mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-05-21 07:26:48 +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:
@@ -26,10 +26,10 @@ func TestWait(t *testing.T) {
|
||||
|
||||
wg.Wait()
|
||||
wg.Add(100)
|
||||
isLeaky(&wait, nil, t)
|
||||
isLeaky(t, &wait, nil)
|
||||
wait.Alert()
|
||||
wg.Wait()
|
||||
isLeaky(&wait, nil, t)
|
||||
isLeaky(t, &wait, nil)
|
||||
|
||||
// use kick
|
||||
ch := make(chan struct{})
|
||||
@@ -46,11 +46,11 @@ func TestWait(t *testing.T) {
|
||||
}
|
||||
wg.Wait()
|
||||
wg.Add(100)
|
||||
isLeaky(&wait, ch, t)
|
||||
isLeaky(t, &wait, ch)
|
||||
close(ch)
|
||||
wg.Wait()
|
||||
ch = make(chan struct{})
|
||||
isLeaky(&wait, ch, t)
|
||||
isLeaky(t, &wait, ch)
|
||||
|
||||
// late receivers
|
||||
wg.Add(100)
|
||||
@@ -70,15 +70,15 @@ func TestWait(t *testing.T) {
|
||||
}
|
||||
wg.Wait()
|
||||
wg.Add(100)
|
||||
isLeaky(&wait, ch, t)
|
||||
isLeaky(t, &wait, ch)
|
||||
wait.Alert()
|
||||
wg.Wait()
|
||||
isLeaky(&wait, ch, t)
|
||||
isLeaky(t, &wait, ch)
|
||||
}
|
||||
|
||||
// isLeaky tests to see if the wait functionality is returning an abnormal
|
||||
// channel that is operational when it shouldn't be.
|
||||
func isLeaky(a *Notice, ch chan struct{}, t *testing.T) {
|
||||
func isLeaky(t *testing.T, a *Notice, ch chan struct{}) {
|
||||
t.Helper()
|
||||
check := a.Wait(ch)
|
||||
time.Sleep(time.Millisecond * 5) // When we call wait a routine for hold is
|
||||
|
||||
@@ -62,8 +62,7 @@ func TestIsValid(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestNew(t *testing.T) {
|
||||
_, err := New("Spota")
|
||||
if err == nil {
|
||||
if _, err := New("Spota"); err == nil {
|
||||
t.Fatal("TestNew returned an unexpected result")
|
||||
}
|
||||
|
||||
|
||||
@@ -374,51 +374,59 @@ func (b *Binance) GetSpotKline(ctx context.Context, arg *KlinesRequestParams) ([
|
||||
|
||||
path := candleStick + "?" + params.Encode()
|
||||
|
||||
if err := b.SendHTTPRequest(ctx,
|
||||
err = b.SendHTTPRequest(ctx,
|
||||
exchange.RestSpotSupplementary,
|
||||
path,
|
||||
spotDefaultRate,
|
||||
&resp); err != nil {
|
||||
return klineData, err
|
||||
&resp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, responseData := range resp.([]interface{}) {
|
||||
responseData, ok := resp.([]interface{})
|
||||
if !ok {
|
||||
return nil, errors.New("unable to type assert responseData")
|
||||
}
|
||||
for x := range responseData {
|
||||
individualData, ok := responseData[x].([]interface{})
|
||||
if !ok {
|
||||
return nil, errors.New("unable to type assert individualData")
|
||||
}
|
||||
if len(individualData) != 12 {
|
||||
return nil, errors.New("unexpected kline data length")
|
||||
}
|
||||
var candle CandleStick
|
||||
for i, individualData := range responseData.([]interface{}) {
|
||||
switch i {
|
||||
case 0:
|
||||
tempTime := individualData.(float64)
|
||||
var err error
|
||||
candle.OpenTime, err = convert.TimeFromUnixTimestampFloat(tempTime)
|
||||
if err != nil {
|
||||
return klineData, err
|
||||
}
|
||||
case 1:
|
||||
candle.Open, _ = strconv.ParseFloat(individualData.(string), 64)
|
||||
case 2:
|
||||
candle.High, _ = strconv.ParseFloat(individualData.(string), 64)
|
||||
case 3:
|
||||
candle.Low, _ = strconv.ParseFloat(individualData.(string), 64)
|
||||
case 4:
|
||||
candle.Close, _ = strconv.ParseFloat(individualData.(string), 64)
|
||||
case 5:
|
||||
candle.Volume, _ = strconv.ParseFloat(individualData.(string), 64)
|
||||
case 6:
|
||||
tempTime := individualData.(float64)
|
||||
var err error
|
||||
candle.CloseTime, err = convert.TimeFromUnixTimestampFloat(tempTime)
|
||||
if err != nil {
|
||||
return klineData, err
|
||||
}
|
||||
case 7:
|
||||
candle.QuoteAssetVolume, _ = strconv.ParseFloat(individualData.(string), 64)
|
||||
case 8:
|
||||
candle.TradeCount = individualData.(float64)
|
||||
case 9:
|
||||
candle.TakerBuyAssetVolume, _ = strconv.ParseFloat(individualData.(string), 64)
|
||||
case 10:
|
||||
candle.TakerBuyQuoteAssetVolume, _ = strconv.ParseFloat(individualData.(string), 64)
|
||||
}
|
||||
if candle.OpenTime, err = convert.TimeFromUnixTimestampFloat(individualData[0]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if candle.Open, err = convert.FloatFromString(individualData[1]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if candle.High, err = convert.FloatFromString(individualData[2]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if candle.Low, err = convert.FloatFromString(individualData[3]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if candle.Close, err = convert.FloatFromString(individualData[4]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if candle.Volume, err = convert.FloatFromString(individualData[5]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if candle.CloseTime, err = convert.TimeFromUnixTimestampFloat(individualData[6]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if candle.QuoteAssetVolume, err = convert.FloatFromString(individualData[7]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if candle.TradeCount, ok = individualData[8].(float64); !ok {
|
||||
return nil, errors.New("unable to type assert trade count")
|
||||
}
|
||||
if candle.TakerBuyAssetVolume, err = convert.FloatFromString(individualData[9]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if candle.TakerBuyQuoteAssetVolume, err = convert.FloatFromString(individualData[10]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
klineData = append(klineData, candle)
|
||||
}
|
||||
@@ -784,7 +792,7 @@ func (b *Binance) SendAuthHTTPRequest(ctx context.Context, ePath exchange.URL, m
|
||||
}
|
||||
|
||||
if params.Get("recvWindow") == "" {
|
||||
params.Set("recvWindow", strconv.FormatInt(convert.RecvWindow(defaultRecvWindow), 10))
|
||||
params.Set("recvWindow", strconv.FormatInt(defaultRecvWindow.Milliseconds(), 10))
|
||||
}
|
||||
|
||||
interim := json.RawMessage{}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
//+build !mock_test_off
|
||||
//go:build !mock_test_off
|
||||
// +build !mock_test_off
|
||||
|
||||
// This will build if build tag mock_test_off is not parsed and will try to mock
|
||||
// all tests in _test.go
|
||||
|
||||
@@ -1622,6 +1622,7 @@ func TestGetAggregatedTradesBatched(t *testing.T) {
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
if tt.mock != mockTests {
|
||||
t.Skip()
|
||||
}
|
||||
@@ -1677,6 +1678,7 @@ func TestGetAggregatedTradesErrors(t *testing.T) {
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := b.GetAggregatedTrades(context.Background(), tt.args)
|
||||
if err == nil {
|
||||
t.Errorf("Binance.GetAggregatedTrades() error = %v, wantErr true", err)
|
||||
@@ -2550,8 +2552,8 @@ func TestWsOrderExecutionReport(t *testing.T) {
|
||||
Side: order.Buy,
|
||||
Status: order.New,
|
||||
AssetType: asset.Spot,
|
||||
Date: time.Unix(0, 1616627567900*int64(time.Millisecond)),
|
||||
LastUpdated: time.Unix(0, 1616627567900*int64(time.Millisecond)),
|
||||
Date: time.UnixMilli(1616627567900),
|
||||
LastUpdated: time.UnixMilli(1616627567900),
|
||||
Pair: currency.NewPair(currency.BTC, currency.USDT),
|
||||
}
|
||||
// empty the channel. otherwise mock_test will fail
|
||||
@@ -2583,8 +2585,7 @@ func TestWsOrderExecutionReport(t *testing.T) {
|
||||
func TestWsOutboundAccountPosition(t *testing.T) {
|
||||
t.Parallel()
|
||||
payload := []byte(`{"stream":"jTfvpakT2yT0hVIo5gYWVihZhdM2PrBgJUZ5PyfZ4EVpCkx4Uoxk5timcrQc","data":{"e":"outboundAccountPosition","E":1616628815745,"u":1616628815745,"B":[{"a":"BTC","f":"0.00225109","l":"0.00123000"},{"a":"BNB","f":"0.00000000","l":"0.00000000"},{"a":"USDT","f":"54.43390661","l":"0.00000000"}]}}`)
|
||||
err := b.wsHandleData(payload)
|
||||
if err != nil {
|
||||
if err := b.wsHandleData(payload); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -371,7 +371,7 @@ func (b *Binance) FetchTradablePairs(ctx context.Context, a asset.Item) ([]strin
|
||||
case asset.CoinMarginedFutures:
|
||||
cInfo, err := b.FuturesExchangeInfo(ctx)
|
||||
if err != nil {
|
||||
return pairs, nil
|
||||
return pairs, err
|
||||
}
|
||||
for z := range cInfo.Symbols {
|
||||
if cInfo.Symbols[z].ContractStatus == "TRADING" {
|
||||
@@ -385,7 +385,7 @@ func (b *Binance) FetchTradablePairs(ctx context.Context, a asset.Item) ([]strin
|
||||
case asset.USDTMarginedFutures:
|
||||
uInfo, err := b.UExchangeInfo(ctx)
|
||||
if err != nil {
|
||||
return pairs, nil
|
||||
return pairs, err
|
||||
}
|
||||
for u := range uInfo.Symbols {
|
||||
if uInfo.Symbols[u].Status == "TRADING" {
|
||||
@@ -751,8 +751,7 @@ func (b *Binance) UpdateAccountInfo(ctx context.Context, assetType asset.Item) (
|
||||
}
|
||||
acc.AssetType = assetType
|
||||
info.Accounts = append(info.Accounts, acc)
|
||||
err := account.Process(&info)
|
||||
if err != nil {
|
||||
if err := account.Process(&info); err != nil {
|
||||
return account.Holdings{}, err
|
||||
}
|
||||
return info, nil
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
)
|
||||
|
||||
func TestRateLimit_Limit(t *testing.T) {
|
||||
t.Parallel()
|
||||
symbol := "BTC-USDT"
|
||||
|
||||
testTable := map[string]struct {
|
||||
@@ -56,6 +57,7 @@ func TestRateLimit_Limit(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestRateLimit_LimitStatic(t *testing.T) {
|
||||
t.Parallel()
|
||||
testTable := map[string]request.EndpointLimit{
|
||||
"Default": spotDefaultRate,
|
||||
"Historical Trades": spotHistoricalTradesRate,
|
||||
|
||||
@@ -4,8 +4,6 @@ import (
|
||||
"encoding/json"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/thrasher-corp/gocryptotrader/common/convert"
|
||||
)
|
||||
|
||||
// binanceTime provides an internal conversion helper
|
||||
@@ -16,7 +14,7 @@ func (t *binanceTime) UnmarshalJSON(data []byte) error {
|
||||
if err := json.Unmarshal(data, ×tamp); err != nil {
|
||||
return err
|
||||
}
|
||||
*t = binanceTime(time.Unix(0, timestamp*int64(time.Millisecond)))
|
||||
*t = binanceTime(time.UnixMilli(timestamp))
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -27,7 +25,7 @@ func (t binanceTime) Time() time.Time {
|
||||
|
||||
// timeString gets the time as Binance timestamp
|
||||
func timeString(t time.Time) string {
|
||||
return strconv.FormatInt(convert.UnixMillis(t), 10)
|
||||
return strconv.FormatInt(t.UnixMilli(), 10)
|
||||
}
|
||||
|
||||
// UnmarshalJSON deserialises the JSON info, including the timestamp
|
||||
@@ -74,11 +72,8 @@ func (a *NewOrderResponse) UnmarshalJSON(data []byte) error {
|
||||
if err := json.Unmarshal(data, &aux); err != nil {
|
||||
return err
|
||||
}
|
||||
// there can be an empty response, then `a` is set to nil
|
||||
if aux != nil {
|
||||
a.TransactionTime = aux.TransactionTime.Time()
|
||||
} else {
|
||||
a = nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -236,7 +236,11 @@ func (b *Bithumb) GetAccountBalance(ctx context.Context, c string) (FullBalance,
|
||||
return fullBalance, err
|
||||
}
|
||||
} else {
|
||||
val = datum.(float64)
|
||||
var ok bool
|
||||
val, ok = datum.(float64)
|
||||
if !ok {
|
||||
return fullBalance, errors.New("unable to type assert datum")
|
||||
}
|
||||
}
|
||||
|
||||
switch splitTag[0] {
|
||||
@@ -529,7 +533,7 @@ func (b *Bithumb) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange.
|
||||
var intermediary json.RawMessage
|
||||
err = b.SendPayload(ctx, request.Auth, func() (*request.Item, error) {
|
||||
// This is time window sensitive
|
||||
tnMS := time.Now().UnixNano() / int64(time.Millisecond)
|
||||
tnMS := time.Now().UnixMilli()
|
||||
n := strconv.FormatInt(tnMS, 10)
|
||||
|
||||
params.Set("endpoint", path)
|
||||
|
||||
@@ -291,8 +291,7 @@ func (b *Bithumb) UpdateTickers(ctx context.Context, a asset.Item) error {
|
||||
|
||||
// UpdateTicker updates and returns the ticker for a currency pair
|
||||
func (b *Bithumb) 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)
|
||||
@@ -818,60 +817,33 @@ func (b *Bithumb) GetHistoricCandles(ctx context.Context, pair currency.Pair, a
|
||||
}
|
||||
|
||||
for x := range candle.Data {
|
||||
if len(candle.Data[x]) < 6 {
|
||||
return kline.Item{}, errors.New("invalid candle length")
|
||||
}
|
||||
var tempCandle kline.Candle
|
||||
|
||||
tempTime := candle.Data[x][0].(float64)
|
||||
timestamp := time.Unix(0, int64(tempTime)*int64(time.Millisecond))
|
||||
if timestamp.Before(start) {
|
||||
if tempCandle.Time, err = convert.TimeFromUnixTimestampFloat(candle.Data[x][0]); err != nil {
|
||||
return kline.Item{}, fmt.Errorf("unable to convert timestamp: %w", err)
|
||||
}
|
||||
if tempCandle.Time.Before(start) {
|
||||
continue
|
||||
}
|
||||
if timestamp.After(end) {
|
||||
if tempCandle.Time.After(end) {
|
||||
break
|
||||
}
|
||||
tempCandle.Time = timestamp
|
||||
|
||||
open, ok := candle.Data[x][1].(string)
|
||||
if !ok {
|
||||
return kline.Item{}, errors.New("open conversion failed")
|
||||
if tempCandle.Open, err = convert.FloatFromString(candle.Data[x][1]); err != nil {
|
||||
return kline.Item{}, fmt.Errorf("kline open conversion failed: %w", err)
|
||||
}
|
||||
tempCandle.Open, err = strconv.ParseFloat(open, 64)
|
||||
if err != nil {
|
||||
return kline.Item{}, err
|
||||
if tempCandle.High, err = convert.FloatFromString(candle.Data[x][2]); err != nil {
|
||||
return kline.Item{}, fmt.Errorf("kline high conversion failed: %w", err)
|
||||
}
|
||||
high, ok := candle.Data[x][2].(string)
|
||||
if !ok {
|
||||
return kline.Item{}, errors.New("high conversion failed")
|
||||
if tempCandle.Low, err = convert.FloatFromString(candle.Data[x][3]); err != nil {
|
||||
return kline.Item{}, fmt.Errorf("kline low conversion failed: %w", err)
|
||||
}
|
||||
tempCandle.High, err = strconv.ParseFloat(high, 64)
|
||||
if err != nil {
|
||||
return kline.Item{}, err
|
||||
if tempCandle.Close, err = convert.FloatFromString(candle.Data[x][4]); err != nil {
|
||||
return kline.Item{}, fmt.Errorf("kline close conversion failed: %w", err)
|
||||
}
|
||||
|
||||
low, ok := candle.Data[x][3].(string)
|
||||
if !ok {
|
||||
return kline.Item{}, errors.New("low conversion failed")
|
||||
}
|
||||
tempCandle.Low, err = strconv.ParseFloat(low, 64)
|
||||
if err != nil {
|
||||
return kline.Item{}, err
|
||||
}
|
||||
|
||||
closeTemp, ok := candle.Data[x][4].(string)
|
||||
if !ok {
|
||||
return kline.Item{}, errors.New("close conversion failed")
|
||||
}
|
||||
tempCandle.Close, err = strconv.ParseFloat(closeTemp, 64)
|
||||
if err != nil {
|
||||
return kline.Item{}, err
|
||||
}
|
||||
|
||||
vol, ok := candle.Data[x][5].(string)
|
||||
if !ok {
|
||||
return kline.Item{}, errors.New("vol conversion failed")
|
||||
}
|
||||
tempCandle.Volume, err = strconv.ParseFloat(vol, 64)
|
||||
if err != nil {
|
||||
return kline.Item{}, err
|
||||
if tempCandle.Volume, err = convert.FloatFromString(candle.Data[x][5]); err != nil {
|
||||
return kline.Item{}, fmt.Errorf("kline volume conversion failed: %w", err)
|
||||
}
|
||||
ret.Candles = append(ret.Candles, tempCandle)
|
||||
}
|
||||
|
||||
@@ -442,7 +442,7 @@ func (b *Bithumb) SeedLocalCacheWithBook(p currency.Pair, o *Orderbook) error {
|
||||
newOrderBook.Pair = p
|
||||
newOrderBook.Asset = asset.Spot
|
||||
newOrderBook.Exchange = b.Name
|
||||
newOrderBook.LastUpdated = time.Unix(0, o.Data.Timestamp*int64(time.Millisecond))
|
||||
newOrderBook.LastUpdated = time.UnixMilli(o.Data.Timestamp)
|
||||
newOrderBook.VerifyOrderbook = b.CanVerifyOrderbook
|
||||
return b.Websocket.Orderbook.LoadSnapshot(&newOrderBook)
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ func TestBithumbTime(t *testing.T) {
|
||||
|
||||
tt := newTime.Time()
|
||||
if tt.UTC().String() != "2021-08-12 03:39:50 +0000 UTC" {
|
||||
t.Fatalf("expected: %s but receieved: %s",
|
||||
t.Fatalf("expected: %s but received: %s",
|
||||
"2021-08-12 03:39:50 +0000 UTC",
|
||||
tt.UTC().String())
|
||||
}
|
||||
|
||||
@@ -320,8 +320,7 @@ func (b *Bitmex) UpdateTickers(ctx context.Context, a asset.Item) error {
|
||||
|
||||
// UpdateTicker updates and returns the ticker for a currency pair
|
||||
func (b *Bitmex) 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
|
||||
}
|
||||
|
||||
|
||||
@@ -370,7 +370,7 @@ func (b *Bittrex) SendAuthHTTPRequest(ctx context.Context, ep exchange.URL, meth
|
||||
}
|
||||
|
||||
newRequest := func() (*request.Item, error) {
|
||||
ts := strconv.FormatInt(time.Now().UnixNano()/1000000, 10)
|
||||
ts := strconv.FormatInt(time.Now().UnixMilli(), 10)
|
||||
path := common.EncodeURLValues(action, params)
|
||||
|
||||
var body io.Reader
|
||||
|
||||
@@ -568,6 +568,7 @@ func TestModifyOrder(t *testing.T) {
|
||||
}
|
||||
|
||||
func WithdrawCryptocurrencyFunds(t *testing.T) {
|
||||
t.Helper()
|
||||
withdrawCryptoRequest := withdraw.Request{
|
||||
Amount: -1,
|
||||
Currency: currency.BTC,
|
||||
|
||||
@@ -156,7 +156,7 @@ func (b *Bittrex) WsAuth() error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
timestamp := strconv.FormatInt(time.Now().UnixNano()/1000000, 10)
|
||||
timestamp := strconv.FormatInt(time.Now().UnixMilli(), 10)
|
||||
hmac, err := crypto.GetHMAC(
|
||||
crypto.HashSHA512,
|
||||
[]byte(timestamp+randomContent.String()),
|
||||
|
||||
@@ -950,8 +950,8 @@ func (b *Bittrex) GetHistoricCandles(ctx context.Context, pair currency.Pair, a
|
||||
year, month, day := start.Date()
|
||||
curYear, curMonth, curDay := time.Now().Date()
|
||||
|
||||
getHistoric := false
|
||||
getRecent := false
|
||||
getHistoric := false // nolint:ifshort,nolintlint // false positive and triggers only on Windows
|
||||
getRecent := false // nolint:ifshort,nolintlint // false positive and triggers only on Windows
|
||||
|
||||
switch interval {
|
||||
case kline.OneMin, kline.FiveMin:
|
||||
|
||||
@@ -704,7 +704,7 @@ func (b *BTCMarkets) SendAuthenticatedRequest(ctx context.Context, method, path
|
||||
|
||||
newRequest := func() (*request.Item, error) {
|
||||
now := time.Now()
|
||||
strTime := strconv.FormatInt(now.UTC().UnixNano()/1000000, 10)
|
||||
strTime := strconv.FormatInt(now.UTC().UnixMilli(), 10)
|
||||
|
||||
var body io.Reader
|
||||
var payload, hmac []byte
|
||||
|
||||
@@ -343,7 +343,7 @@ func (b *BTCMarkets) Subscribe(channelsToSubscribe []stream.ChannelSubscription)
|
||||
if !common.StringDataCompare(payload.Channels, authChannels[i]) {
|
||||
continue
|
||||
}
|
||||
signTime := strconv.FormatInt(time.Now().UTC().UnixNano()/1000000, 10)
|
||||
signTime := strconv.FormatInt(time.Now().UTC().UnixMilli(), 10)
|
||||
strToSign := "/users/self/subscribe" + "\n" + signTime
|
||||
tempSign, err := crypto.GetHMAC(crypto.HashSHA512,
|
||||
[]byte(strToSign),
|
||||
|
||||
@@ -332,8 +332,7 @@ func (b *BTCMarkets) UpdateTickers(ctx context.Context, a asset.Item) error {
|
||||
|
||||
// UpdateTicker updates and returns the ticker for a currency pair
|
||||
func (b *BTCMarkets) 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)
|
||||
|
||||
@@ -477,7 +477,7 @@ func (b *BTSE) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange.URL
|
||||
|
||||
var hmac []byte
|
||||
var body io.Reader
|
||||
nonce := strconv.FormatInt(time.Now().UnixNano()/int64(time.Millisecond), 10)
|
||||
nonce := strconv.FormatInt(time.Now().UnixMilli(), 10)
|
||||
headers := map[string]string{
|
||||
"btse-api": b.API.Credentials.Key,
|
||||
"btse-nonce": nonce,
|
||||
|
||||
@@ -543,12 +543,11 @@ func TestGetFee(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestParseOrderTime(t *testing.T) {
|
||||
expected := int64(1534792846)
|
||||
actual, err := parseOrderTime("2018-08-20 19:20:46")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if expected != actual.Unix() {
|
||||
if expected := int64(1534792846); expected != actual.Unix() {
|
||||
t.Errorf("TestParseOrderTime expected: %d, got %d", expected, actual.Unix())
|
||||
}
|
||||
}
|
||||
@@ -920,8 +919,7 @@ func TestWsLogin(t *testing.T) {
|
||||
func TestWsSubscription(t *testing.T) {
|
||||
t.Parallel()
|
||||
data := []byte(`{"event":"subscribe","channel":["orderBookL2Api:SFI-ETH_0","tradeHistory:SFI-ETH"]}`)
|
||||
err := b.wsHandleData(data)
|
||||
if err != nil {
|
||||
if err := b.wsHandleData(data); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ func (b *BTSE) WsConnect() error {
|
||||
|
||||
// WsAuthenticate Send an authentication message to receive auth data
|
||||
func (b *BTSE) WsAuthenticate() error {
|
||||
nonce := strconv.FormatInt(time.Now().UnixNano()/int64(time.Millisecond), 10)
|
||||
nonce := strconv.FormatInt(time.Now().UnixMilli(), 10)
|
||||
path := "/spotWS" + nonce
|
||||
|
||||
hmac, err := crypto.GetHMAC(crypto.HashSHA512_384,
|
||||
@@ -216,7 +216,7 @@ func (b *BTSE) wsHandleData(respRaw []byte) error {
|
||||
Side: oSide,
|
||||
Status: oStatus,
|
||||
AssetType: a,
|
||||
Date: time.Unix(0, notification.Data[i].Timestamp*int64(time.Millisecond)),
|
||||
Date: time.UnixMilli(notification.Data[i].Timestamp),
|
||||
Pair: p,
|
||||
}
|
||||
}
|
||||
@@ -250,7 +250,7 @@ func (b *BTSE) wsHandleData(respRaw []byte) error {
|
||||
return err
|
||||
}
|
||||
trades = append(trades, trade.Data{
|
||||
Timestamp: time.Unix(0, tradeHistory.Data[x].TransactionTime*int64(time.Millisecond)),
|
||||
Timestamp: time.UnixMilli(tradeHistory.Data[x].TransactionTime),
|
||||
CurrencyPair: p,
|
||||
AssetType: a,
|
||||
Exchange: b.Name,
|
||||
|
||||
@@ -313,8 +313,7 @@ func (b *BTSE) UpdateTickers(ctx context.Context, a asset.Item) error {
|
||||
|
||||
// UpdateTicker updates and returns the ticker for a currency pair
|
||||
func (b *BTSE) 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)
|
||||
@@ -589,7 +588,7 @@ func (b *BTSE) CancelAllOrders(ctx context.Context, orderCancellation *order.Can
|
||||
|
||||
allOrders, err := b.CancelExistingOrder(ctx, "", fPair.String(), "")
|
||||
if err != nil {
|
||||
return resp, nil
|
||||
return resp, err
|
||||
}
|
||||
|
||||
resp.Status = make(map[string]string)
|
||||
|
||||
@@ -432,7 +432,10 @@ func (c *CoinbasePro) UpdateOrderbook(ctx context.Context, p currency.Pair, asse
|
||||
return book, err
|
||||
}
|
||||
|
||||
obNew := orderbookNew.(OrderbookL1L2)
|
||||
obNew, ok := orderbookNew.(OrderbookL1L2)
|
||||
if !ok {
|
||||
return book, errors.New("unable to type assert orderbook data")
|
||||
}
|
||||
for x := range obNew.Bids {
|
||||
book.Bids = append(book.Bids, orderbook.Item{
|
||||
Amount: obNew.Bids[x].Amount,
|
||||
|
||||
@@ -443,8 +443,7 @@ func (c *Coinbene) getCurrencyFromWsTopic(assetType asset.Item, channelTopic str
|
||||
|
||||
// Subscribe sends a websocket message to receive data from the channel
|
||||
func (c *Coinbene) Subscribe(channelsToSubscribe []stream.ChannelSubscription) error {
|
||||
maxSubsPerHour := 240
|
||||
if len(channelsToSubscribe) > maxSubsPerHour {
|
||||
if maxSubsPerHour := 240; len(channelsToSubscribe) > maxSubsPerHour {
|
||||
return fmt.Errorf("channel subscriptions length %d exceeds coinbene's limit of %d, try reducing enabled pairs",
|
||||
len(channelsToSubscribe),
|
||||
maxSubsPerHour)
|
||||
|
||||
@@ -382,8 +382,7 @@ func (c *Coinbene) UpdateTickers(ctx context.Context, a asset.Item) error {
|
||||
|
||||
// UpdateTicker updates and returns the ticker for a currency pair
|
||||
func (c *Coinbene) UpdateTicker(ctx context.Context, p currency.Pair, a asset.Item) (*ticker.Price, error) {
|
||||
err := c.UpdateTickers(ctx, a)
|
||||
if err != nil {
|
||||
if err := c.UpdateTickers(ctx, a); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ticker.GetTicker(c.Name, p, a)
|
||||
@@ -893,11 +892,17 @@ func (c *Coinbene) GetHistoricCandles(ctx context.Context, pair currency.Pair, a
|
||||
}
|
||||
|
||||
for x := range candles.Data {
|
||||
if len(candles.Data[x]) < 6 {
|
||||
return kline.Item{}, errors.New("unexpected candle data length")
|
||||
}
|
||||
var tempCandle kline.Candle
|
||||
tempTime := candles.Data[x][0].(string)
|
||||
tempTime, ok := candles.Data[x][0].(string)
|
||||
if !ok {
|
||||
return kline.Item{}, errors.New("timestamp conversion failed")
|
||||
}
|
||||
timestamp, err := time.Parse(time.RFC3339, tempTime)
|
||||
if err != nil {
|
||||
continue
|
||||
return kline.Item{}, err
|
||||
}
|
||||
tempCandle.Time = timestamp
|
||||
open, ok := candles.Data[x][1].(string)
|
||||
|
||||
@@ -438,8 +438,7 @@ func (i *instrumentMap) Seed(curr string, id int64) {
|
||||
}
|
||||
|
||||
// check to see if the instrument already exists
|
||||
_, ok := i.Instruments[curr]
|
||||
if ok {
|
||||
if _, ok := i.Instruments[curr]; ok {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -59,6 +59,7 @@ func TestMain(m *testing.M) {
|
||||
}
|
||||
|
||||
func setupWSTestAuth(t *testing.T) {
|
||||
t.Helper()
|
||||
if wsSetupRan {
|
||||
return
|
||||
}
|
||||
@@ -430,8 +431,7 @@ func TestGetDepositAddress(t *testing.T) {
|
||||
// TestWsAuthGetAccountBalance dials websocket, retrieves account balance
|
||||
func TestWsAuthGetAccountBalance(t *testing.T) {
|
||||
setupWSTestAuth(t)
|
||||
_, err := c.wsGetAccountBalance()
|
||||
if err != nil {
|
||||
if _, err := c.wsGetAccountBalance(); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
@@ -449,8 +449,7 @@ func TestWsAuthSubmitOrder(t *testing.T) {
|
||||
Price: 1,
|
||||
Side: order.Buy,
|
||||
}
|
||||
_, err := c.wsSubmitOrder(&ord)
|
||||
if err != nil {
|
||||
if _, err := c.wsSubmitOrder(&ord); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -630,18 +630,31 @@ func (c *COINUT) SubmitOrder(ctx context.Context, o *order.Submit) (order.Submit
|
||||
if err != nil {
|
||||
return submitOrderResponse, err
|
||||
}
|
||||
responseMap := APIResponse.(map[string]interface{})
|
||||
switch responseMap["reply"].(string) {
|
||||
responseMap, ok := APIResponse.(map[string]interface{})
|
||||
if !ok {
|
||||
return submitOrderResponse, errors.New("unable to type assert responseMap")
|
||||
}
|
||||
orderType, ok := responseMap["reply"].(string)
|
||||
if !ok {
|
||||
return submitOrderResponse, errors.New("unable to type assert orderType")
|
||||
}
|
||||
switch orderType {
|
||||
case "order_rejected":
|
||||
return submitOrderResponse, fmt.Errorf("clientOrderID: %v was rejected: %v", o.ClientID, responseMap["reasons"])
|
||||
case "order_filled":
|
||||
orderID := responseMap["order_id"].(float64)
|
||||
orderID, ok := responseMap["order_id"].(float64)
|
||||
if !ok {
|
||||
return submitOrderResponse, errors.New("unable to type assert orderID")
|
||||
}
|
||||
submitOrderResponse.OrderID = strconv.FormatFloat(orderID, 'f', -1, 64)
|
||||
submitOrderResponse.IsOrderPlaced = true
|
||||
submitOrderResponse.FullyMatched = true
|
||||
return submitOrderResponse, nil
|
||||
case "order_accepted":
|
||||
orderID := responseMap["order_id"].(float64)
|
||||
orderID, ok := responseMap["order_id"].(float64)
|
||||
if !ok {
|
||||
return submitOrderResponse, errors.New("unable to type assert orderID")
|
||||
}
|
||||
submitOrderResponse.OrderID = strconv.FormatFloat(orderID, 'f', -1, 64)
|
||||
submitOrderResponse.IsOrderPlaced = true
|
||||
return submitOrderResponse, nil
|
||||
|
||||
@@ -409,7 +409,7 @@ func (b *Base) GetPairFormat(assetType asset.Item, requestFormat bool) (currency
|
||||
func (b *Base) GetEnabledPairs(a asset.Item) (currency.Pairs, error) {
|
||||
err := b.CurrencyPairs.IsAssetEnabled(a)
|
||||
if err != nil {
|
||||
return nil, nil
|
||||
return nil, nil // nolint:nilerr // non-fatal error
|
||||
}
|
||||
format, err := b.GetPairFormat(a, false)
|
||||
if err != nil {
|
||||
@@ -1156,7 +1156,7 @@ func (b *Base) FormatExchangeKlineInterval(in kline.Interval) string {
|
||||
// ValidateKline confirms that the requested pair, asset & interval are supported and/or enabled by the requested exchange
|
||||
func (b *Base) ValidateKline(pair currency.Pair, a asset.Item, interval kline.Interval) error {
|
||||
var errorList []string
|
||||
var err kline.ErrorKline
|
||||
var err kline.Error
|
||||
if b.CurrencyPairs.IsAssetEnabled(a) != nil {
|
||||
err.Asset = a
|
||||
errorList = append(errorList, "asset not enabled")
|
||||
@@ -1242,7 +1242,7 @@ func (e *Endpoints) SetRunning(key, val string) error {
|
||||
key,
|
||||
val,
|
||||
e.Exchange)
|
||||
return nil
|
||||
return nil // nolint:nilerr // non-fatal error as we won't update the running URL
|
||||
}
|
||||
e.defaults[key] = val
|
||||
return nil
|
||||
|
||||
@@ -752,8 +752,7 @@ func TestGetName(t *testing.T) {
|
||||
Name: "TESTNAME",
|
||||
}
|
||||
|
||||
name := b.GetName()
|
||||
if name != "TESTNAME" {
|
||||
if name := b.GetName(); name != "TESTNAME" {
|
||||
t.Error("Exchange GetName() returned incorrect name")
|
||||
}
|
||||
}
|
||||
@@ -1167,8 +1166,7 @@ func TestFormatExchangeCurrencies(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Errorf("Exchange TestFormatExchangeCurrencies error %s", err)
|
||||
}
|
||||
expected := "btc~usd^ltc~btc"
|
||||
if actual != expected {
|
||||
if expected := "btc~usd^ltc~btc"; actual != expected {
|
||||
t.Errorf("Exchange TestFormatExchangeCurrencies %s != %s",
|
||||
actual, expected)
|
||||
}
|
||||
@@ -1801,8 +1799,7 @@ func TestGetBase(t *testing.T) {
|
||||
func TestGetAssetType(t *testing.T) {
|
||||
var b Base
|
||||
p := currency.NewPair(currency.BTC, currency.USD)
|
||||
_, err := b.GetPairAssetType(p)
|
||||
if err == nil {
|
||||
if _, err := b.GetPairAssetType(p); err == nil {
|
||||
t.Fatal("error cannot be nil")
|
||||
}
|
||||
b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore)
|
||||
@@ -2410,6 +2407,7 @@ func TestAssetWebsocketFunctionality(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetGetURLTypeFromString(t *testing.T) {
|
||||
t.Parallel()
|
||||
testCases := []struct {
|
||||
Endpoint string
|
||||
Expected URL
|
||||
|
||||
@@ -213,7 +213,11 @@ func (e *EXMO) GetCryptoDepositAddress(ctx context.Context) (map[string]string,
|
||||
case map[string]interface{}:
|
||||
mapString := make(map[string]string)
|
||||
for key, value := range r {
|
||||
mapString[key] = value.(string)
|
||||
v, ok := value.(string)
|
||||
if !ok {
|
||||
return nil, errors.New("unable to type assert value data")
|
||||
}
|
||||
mapString[key] = v
|
||||
}
|
||||
return mapString, nil
|
||||
|
||||
|
||||
@@ -219,8 +219,7 @@ func (e *EXMO) UpdateTickers(ctx context.Context, a asset.Item) error {
|
||||
|
||||
// UpdateTicker updates and returns the ticker for a currency pair
|
||||
func (e *EXMO) UpdateTicker(ctx context.Context, p currency.Pair, a asset.Item) (*ticker.Price, error) {
|
||||
err := e.UpdateTickers(ctx, a)
|
||||
if err != nil {
|
||||
if err := e.UpdateTickers(ctx, a); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ticker.GetTicker(e.Name, p, a)
|
||||
|
||||
@@ -1151,7 +1151,7 @@ func (f *FTX) SendAuthHTTPRequest(ctx context.Context, ep exchange.URL, method,
|
||||
}
|
||||
|
||||
newRequest := func() (*request.Item, error) {
|
||||
ts := strconv.FormatInt(time.Now().UnixNano()/1000000, 10)
|
||||
ts := strconv.FormatInt(time.Now().UnixMilli(), 10)
|
||||
var body io.Reader
|
||||
var hmac, payload []byte
|
||||
|
||||
|
||||
@@ -1364,7 +1364,7 @@ func TestCompatibleOrderVars(t *testing.T) {
|
||||
t.Errorf("received %v expected %v", orderVars.Status, order.Filled)
|
||||
}
|
||||
|
||||
orderVars, err = f.compatibleOrderVars(context.Background(),
|
||||
_, err = f.compatibleOrderVars(context.Background(),
|
||||
"buy",
|
||||
"closed",
|
||||
"limit",
|
||||
@@ -1375,7 +1375,7 @@ func TestCompatibleOrderVars(t *testing.T) {
|
||||
t.Errorf("received %v expected %v", err, errInvalidOrderAmounts)
|
||||
}
|
||||
|
||||
orderVars, err = f.compatibleOrderVars(context.Background(),
|
||||
_, err = f.compatibleOrderVars(context.Background(),
|
||||
"buy",
|
||||
"fake",
|
||||
"limit",
|
||||
|
||||
@@ -77,7 +77,7 @@ func (f *FTX) WsConnect() error {
|
||||
|
||||
// WsAuth sends an authentication message to receive auth data
|
||||
func (f *FTX) WsAuth() error {
|
||||
intNonce := time.Now().UnixNano() / 1000000
|
||||
intNonce := time.Now().UnixMilli()
|
||||
strNonce := strconv.FormatInt(intNonce, 10)
|
||||
hmac, err := crypto.GetHMAC(
|
||||
crypto.HashSHA256,
|
||||
|
||||
@@ -251,8 +251,7 @@ func TestParsingOrders(t *testing.T) {
|
||||
},
|
||||
"type": "update"
|
||||
}`)
|
||||
err := f.wsHandleData(data)
|
||||
if err != nil {
|
||||
if err := f.wsHandleData(data); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
@@ -274,8 +273,7 @@ func TestParsingWSTradesData(t *testing.T) {
|
||||
}
|
||||
]
|
||||
}`)
|
||||
err := f.wsHandleData(data)
|
||||
if err != nil {
|
||||
if err := f.wsHandleData(data); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
@@ -295,8 +293,7 @@ func TestParsingWSTickerData(t *testing.T) {
|
||||
"time": 1589505004.4237103
|
||||
}
|
||||
}`)
|
||||
err := f.wsHandleData(data)
|
||||
if err != nil {
|
||||
if err := f.wsHandleData(data); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
@@ -323,8 +320,7 @@ func TestParsingWSOrdersData(t *testing.T) {
|
||||
},
|
||||
"type": "update"
|
||||
}`)
|
||||
err := f.wsHandleData(data)
|
||||
if err != nil {
|
||||
if err := f.wsHandleData(data); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
@@ -360,8 +356,7 @@ func TestParsingMarketsData(t *testing.T) {
|
||||
"group": "quarterly"}}},
|
||||
"action": "partial"
|
||||
}`)
|
||||
err := f.wsHandleData(data)
|
||||
if err != nil {
|
||||
if err := f.wsHandleData(data); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,9 +52,6 @@ func (g *Gateio) GetSymbols(ctx context.Context) ([]string, error) {
|
||||
var result []string
|
||||
urlPath := fmt.Sprintf("/%s/%s", gateioAPIVersion, gateioSymbol)
|
||||
err := g.SendHTTPRequest(ctx, exchange.RestSpotSupplementary, urlPath, &result)
|
||||
if err != nil {
|
||||
return nil, nil
|
||||
}
|
||||
return result, err
|
||||
}
|
||||
|
||||
@@ -76,9 +73,15 @@ func (g *Gateio) GetMarketInfo(ctx context.Context) (MarketInfoResponse, error)
|
||||
|
||||
result.Result = res.Result
|
||||
for _, v := range res.Pairs {
|
||||
item := v.(map[string]interface{})
|
||||
item, ok := v.(map[string]interface{})
|
||||
if !ok {
|
||||
return result, errors.New("unable to type assert item")
|
||||
}
|
||||
for itemk, itemv := range item {
|
||||
pairv := itemv.(map[string]interface{})
|
||||
pairv, ok := itemv.(map[string]interface{})
|
||||
if !ok {
|
||||
return result, errors.New("unable to type assert pairv")
|
||||
}
|
||||
result.Pairs = append(result.Pairs, MarketInfoPairsResponse{
|
||||
Symbol: itemk,
|
||||
DecimalPlaces: pairv["decimal_places"].(float64),
|
||||
@@ -203,28 +206,27 @@ func (g *Gateio) GetSpotKline(ctx context.Context, arg KlinesRequestParams) (kli
|
||||
arg.GroupSec,
|
||||
arg.HourSize)
|
||||
|
||||
var rawKlines map[string]interface{}
|
||||
err := g.SendHTTPRequest(ctx, exchange.RestSpotSupplementary, urlPath, &rawKlines)
|
||||
if err != nil {
|
||||
resp := struct {
|
||||
Data [][]string `json:"data"`
|
||||
Result string `json:"result"`
|
||||
}{}
|
||||
|
||||
if err := g.SendHTTPRequest(ctx, exchange.RestSpotSupplementary, urlPath, &resp); err != nil {
|
||||
return kline.Item{}, err
|
||||
}
|
||||
if resp.Result != "true" || len(resp.Data) == 0 {
|
||||
return kline.Item{}, errors.New("rawKlines unexpected data returned")
|
||||
}
|
||||
|
||||
result := kline.Item{
|
||||
Exchange: g.Name,
|
||||
}
|
||||
|
||||
if rawKlines == nil || rawKlines["data"] == nil {
|
||||
return kline.Item{}, errors.New("rawKlines is nil")
|
||||
}
|
||||
|
||||
rawKlineDatasString, _ := json.Marshal(rawKlines["data"].([]interface{}))
|
||||
var rawKlineDatas [][]interface{}
|
||||
if err := json.Unmarshal(rawKlineDatasString, &rawKlineDatas); err != nil {
|
||||
return kline.Item{}, fmt.Errorf("rawKlines unmarshal failed. Err: %s", err)
|
||||
}
|
||||
|
||||
for _, k := range rawKlineDatas {
|
||||
otString, err := strconv.ParseFloat(k[0].(string), 64)
|
||||
for x := range resp.Data {
|
||||
if len(resp.Data[x]) < 6 {
|
||||
return kline.Item{}, fmt.Errorf("unexpected kline data length")
|
||||
}
|
||||
otString, err := strconv.ParseFloat(resp.Data[x][0], 64)
|
||||
if err != nil {
|
||||
return kline.Item{}, err
|
||||
}
|
||||
@@ -232,23 +234,23 @@ func (g *Gateio) GetSpotKline(ctx context.Context, arg KlinesRequestParams) (kli
|
||||
if err != nil {
|
||||
return kline.Item{}, fmt.Errorf("cannot parse Kline.OpenTime. Err: %s", err)
|
||||
}
|
||||
_vol, err := convert.FloatFromString(k[1])
|
||||
_vol, err := convert.FloatFromString(resp.Data[x][1])
|
||||
if err != nil {
|
||||
return kline.Item{}, fmt.Errorf("cannot parse Kline.Volume. Err: %s", err)
|
||||
}
|
||||
_close, err := convert.FloatFromString(k[2])
|
||||
_close, err := convert.FloatFromString(resp.Data[x][2])
|
||||
if err != nil {
|
||||
return kline.Item{}, fmt.Errorf("cannot parse Kline.Close. Err: %s", err)
|
||||
}
|
||||
_high, err := convert.FloatFromString(k[3])
|
||||
_high, err := convert.FloatFromString(resp.Data[x][3])
|
||||
if err != nil {
|
||||
return kline.Item{}, fmt.Errorf("cannot parse Kline.High. Err: %s", err)
|
||||
}
|
||||
_low, err := convert.FloatFromString(k[4])
|
||||
_low, err := convert.FloatFromString(resp.Data[x][4])
|
||||
if err != nil {
|
||||
return kline.Item{}, fmt.Errorf("cannot parse Kline.Low. Err: %s", err)
|
||||
}
|
||||
_open, err := convert.FloatFromString(k[5])
|
||||
_open, err := convert.FloatFromString(resp.Data[x][5])
|
||||
if err != nil {
|
||||
return kline.Item{}, fmt.Errorf("cannot parse Kline.Open. Err: %s", err)
|
||||
}
|
||||
|
||||
@@ -544,14 +544,14 @@ func TestWsGetOrderInfo(t *testing.T) {
|
||||
}
|
||||
|
||||
func setupWSTestAuth(t *testing.T) {
|
||||
t.Helper()
|
||||
if wsSetupRan {
|
||||
return
|
||||
}
|
||||
if !g.Websocket.IsEnabled() && !g.API.AuthenticatedWebsocketSupport || !areTestAPIKeysSet() {
|
||||
t.Skip(stream.WebsocketNotEnabled)
|
||||
}
|
||||
err := g.Websocket.Connect()
|
||||
if err != nil {
|
||||
if err := g.Websocket.Connect(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
wsSetupRan = true
|
||||
|
||||
@@ -225,11 +225,22 @@ func (g *Gateio) wsHandleData(respRaw []byte) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
invalidJSON := orderUpdate.Params[1].(map[string]interface{})
|
||||
if len(orderUpdate.Params) < 2 {
|
||||
return errors.New("unexpected orderUpdate.Params data length")
|
||||
}
|
||||
invalidJSON, ok := orderUpdate.Params[1].(map[string]interface{})
|
||||
if !ok {
|
||||
return errors.New("unable to type assert invalidJSON")
|
||||
}
|
||||
oStatus := order.UnknownStatus
|
||||
oType := order.UnknownType
|
||||
oSide := order.UnknownSide
|
||||
switch orderUpdate.Params[0].(float64) {
|
||||
|
||||
orderStatus, ok := orderUpdate.Params[0].(float64)
|
||||
if !ok {
|
||||
return errors.New("unable to type assert orderStatus")
|
||||
}
|
||||
switch orderStatus {
|
||||
case 1:
|
||||
oStatus = order.New
|
||||
case 2:
|
||||
@@ -237,42 +248,57 @@ func (g *Gateio) wsHandleData(respRaw []byte) error {
|
||||
case 3:
|
||||
oStatus = order.Filled
|
||||
}
|
||||
switch invalidJSON["orderType"].(float64) {
|
||||
|
||||
orderType, ok := invalidJSON["orderType"].(float64)
|
||||
if !ok {
|
||||
return errors.New("unable to type assert orderType")
|
||||
}
|
||||
switch orderType {
|
||||
case 1:
|
||||
oType = order.Limit
|
||||
case 2:
|
||||
oType = order.Market
|
||||
}
|
||||
switch invalidJSON["type"].(float64) {
|
||||
|
||||
orderSide, ok := invalidJSON["type"].(float64)
|
||||
if !ok {
|
||||
return errors.New("unable to type assert orderSide")
|
||||
}
|
||||
switch orderSide {
|
||||
case 1:
|
||||
oSide = order.Sell
|
||||
case 2:
|
||||
oSide = order.Buy
|
||||
}
|
||||
|
||||
var price, amount, filledTotal, left, fee float64
|
||||
price, err = strconv.ParseFloat(invalidJSON["price"].(string), 64)
|
||||
price, err = convert.FloatFromString(invalidJSON["price"])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
amount, err = strconv.ParseFloat(invalidJSON["amount"].(string), 64)
|
||||
amount, err = convert.FloatFromString(invalidJSON["amount"])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
filledTotal, err = strconv.ParseFloat(invalidJSON["filledTotal"].(string), 64)
|
||||
filledTotal, err = convert.FloatFromString(invalidJSON["filledTotal"])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
left, err = strconv.ParseFloat(invalidJSON["left"].(string), 64)
|
||||
left, err = convert.FloatFromString(invalidJSON["left"])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fee, err = strconv.ParseFloat(invalidJSON["dealFee"].(string), 64)
|
||||
fee, err = convert.FloatFromString(invalidJSON["dealFee"])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var p currency.Pair
|
||||
p, err = currency.NewPairFromString(invalidJSON["market"].(string))
|
||||
pairStr, ok := invalidJSON["market"].(string)
|
||||
if !ok {
|
||||
return errors.New("unable to type assert market")
|
||||
}
|
||||
p, err = currency.NewPairFromString(pairStr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -270,8 +270,7 @@ func (g *Gateio) UpdateTickers(ctx context.Context, a asset.Item) error {
|
||||
|
||||
// UpdateTicker updates and returns the ticker for a currency pair
|
||||
func (g *Gateio) UpdateTicker(ctx context.Context, p currency.Pair, a asset.Item) (*ticker.Price, error) {
|
||||
err := g.UpdateTickers(ctx, a)
|
||||
if err != nil {
|
||||
if err := g.UpdateTickers(ctx, a); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ticker.GetTicker(g.Name, p, a)
|
||||
@@ -411,8 +410,7 @@ func (g *Gateio) UpdateAccountInfo(ctx context.Context, assetType asset.Item) (a
|
||||
}
|
||||
|
||||
info.Exchange = g.Name
|
||||
err := account.Process(&info)
|
||||
if err != nil {
|
||||
if err := account.Process(&info); err != nil {
|
||||
return account.Holdings{}, err
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
//+build !mock_test_off
|
||||
//go:build !mock_test_off
|
||||
// +build !mock_test_off
|
||||
|
||||
// This will build if build tag mock_test_off is not parsed and will try to mock
|
||||
// all tests in _test.go
|
||||
|
||||
@@ -324,7 +324,7 @@ func (g *Gemini) wsHandleData(respRaw []byte) error {
|
||||
Side: oSide,
|
||||
Status: oStatus,
|
||||
AssetType: asset.Spot,
|
||||
Date: time.Unix(0, result[i].Timestampms*int64(time.Millisecond)),
|
||||
Date: time.UnixMilli(result[i].Timestampms),
|
||||
Pair: pair,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -455,6 +455,7 @@ func TestGetDepositAddress(t *testing.T) {
|
||||
}
|
||||
}
|
||||
func setupWsAuth(t *testing.T) {
|
||||
t.Helper()
|
||||
if wsSetupRan {
|
||||
return
|
||||
}
|
||||
@@ -524,8 +525,7 @@ func TestWsReplaceOrder(t *testing.T) {
|
||||
// TestWsGetActiveOrders dials websocket, sends get active orders request.
|
||||
func TestWsGetActiveOrders(t *testing.T) {
|
||||
setupWsAuth(t)
|
||||
_, err := h.wsGetActiveOrders()
|
||||
if err != nil {
|
||||
if _, err := h.wsGetActiveOrders(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
@@ -533,8 +533,7 @@ func TestWsGetActiveOrders(t *testing.T) {
|
||||
// TestWsGetTradingBalance dials websocket, sends get trading balance request.
|
||||
func TestWsGetTradingBalance(t *testing.T) {
|
||||
setupWsAuth(t)
|
||||
_, err := h.wsGetTradingBalance()
|
||||
if err != nil {
|
||||
if _, err := h.wsGetTradingBalance(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,7 +113,10 @@ func (h *HitBTC) wsGetTableName(respRaw []byte) (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
data := resultType[0].(map[string]interface{})
|
||||
data, ok := resultType[0].(map[string]interface{})
|
||||
if !ok {
|
||||
return "", errors.New("unable to type assert data")
|
||||
}
|
||||
if _, ok := data["clientOrderId"]; ok {
|
||||
return "order", nil
|
||||
} else if _, ok := data["available"]; ok {
|
||||
|
||||
@@ -358,8 +358,7 @@ func (h *HitBTC) UpdateTickers(ctx context.Context, a asset.Item) error {
|
||||
|
||||
// UpdateTicker updates and returns the ticker for a currency pair
|
||||
func (h *HitBTC) UpdateTicker(ctx context.Context, p currency.Pair, a asset.Item) (*ticker.Price, error) {
|
||||
err := h.UpdateTickers(ctx, a)
|
||||
if err != nil {
|
||||
if err := h.UpdateTickers(ctx, a); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ticker.GetTicker(h.Name, p, a)
|
||||
@@ -498,8 +497,8 @@ allTrades:
|
||||
p.String(),
|
||||
"",
|
||||
"",
|
||||
ts.UnixNano()/int64(time.Millisecond),
|
||||
timestampEnd.UnixNano()/int64(time.Millisecond),
|
||||
ts.UnixMilli(),
|
||||
timestampEnd.UnixMilli(),
|
||||
int64(limit),
|
||||
0)
|
||||
if err != nil {
|
||||
|
||||
@@ -57,6 +57,7 @@ func TestMain(m *testing.M) {
|
||||
}
|
||||
|
||||
func setupWsTests(t *testing.T) {
|
||||
t.Helper()
|
||||
if wsSetupRan {
|
||||
return
|
||||
}
|
||||
@@ -2196,8 +2197,7 @@ func TestQueryWithdrawQuota(t *testing.T) {
|
||||
// TestWsGetAccountsList connects to WS, logs in, gets account list
|
||||
func TestWsGetAccountsList(t *testing.T) {
|
||||
setupWsTests(t)
|
||||
_, err := h.wsGetAccountsList()
|
||||
if err != nil {
|
||||
if _, err := h.wsGetAccountsList(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -351,7 +351,7 @@ func (h *HUOBI) wsHandleData(respRaw []byte) error {
|
||||
return err
|
||||
}
|
||||
h.Websocket.DataHandler <- stream.KlineData{
|
||||
Timestamp: time.Unix(0, kline.Timestamp*int64(time.Millisecond)),
|
||||
Timestamp: time.UnixMilli(kline.Timestamp),
|
||||
Exchange: h.Name,
|
||||
AssetType: a,
|
||||
Pair: p,
|
||||
@@ -388,12 +388,11 @@ func (h *HUOBI) wsHandleData(respRaw []byte) error {
|
||||
Exchange: h.Name,
|
||||
AssetType: a,
|
||||
CurrencyPair: p,
|
||||
Timestamp: time.Unix(0,
|
||||
t.Tick.Data[i].Timestamp*int64(time.Millisecond)),
|
||||
Amount: t.Tick.Data[i].Amount,
|
||||
Price: t.Tick.Data[i].Price,
|
||||
Side: side,
|
||||
TID: strconv.FormatFloat(t.Tick.Data[i].TradeID, 'f', -1, 64),
|
||||
Timestamp: time.UnixMilli(t.Tick.Data[i].Timestamp),
|
||||
Amount: t.Tick.Data[i].Amount,
|
||||
Price: t.Tick.Data[i].Price,
|
||||
Side: side,
|
||||
TID: strconv.FormatFloat(t.Tick.Data[i].TradeID, 'f', -1, 64),
|
||||
})
|
||||
}
|
||||
return trade.AddTradesToBuffer(h.Name, trades...)
|
||||
@@ -427,7 +426,7 @@ func (h *HUOBI) wsHandleData(respRaw []byte) error {
|
||||
QuoteVolume: wsTicker.Tick.Volume,
|
||||
High: wsTicker.Tick.High,
|
||||
Low: wsTicker.Tick.Low,
|
||||
LastUpdated: time.Unix(0, wsTicker.Timestamp*int64(time.Millisecond)),
|
||||
LastUpdated: time.UnixMilli(wsTicker.Timestamp),
|
||||
AssetType: a,
|
||||
Pair: p,
|
||||
}
|
||||
|
||||
@@ -793,8 +793,7 @@ func (h *HUOBI) UpdateAccountInfo(ctx context.Context, assetType asset.Item) (ac
|
||||
}
|
||||
acc.AssetType = assetType
|
||||
info.Accounts = append(info.Accounts, acc)
|
||||
err := account.Process(&info)
|
||||
if err != nil {
|
||||
if err := account.Process(&info); err != nil {
|
||||
return info, err
|
||||
}
|
||||
return info, nil
|
||||
@@ -844,7 +843,7 @@ func (h *HUOBI) GetRecentTrades(ctx context.Context, p currency.Pair, assetType
|
||||
Side: side,
|
||||
Price: tradeData[i].Trades[j].Price,
|
||||
Amount: tradeData[i].Trades[j].Amount,
|
||||
Timestamp: time.Unix(0, tradeData[i].Timestamp*int64(time.Millisecond)),
|
||||
Timestamp: time.UnixMilli(tradeData[i].Timestamp),
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1183,7 +1182,7 @@ func (h *HUOBI) GetOrderInfo(ctx context.Context, orderID string, pair currency.
|
||||
Pair: p,
|
||||
Type: orderType,
|
||||
Side: orderSide,
|
||||
Date: time.Unix(0, respData.CreatedAt*int64(time.Millisecond)),
|
||||
Date: time.UnixMilli(respData.CreatedAt),
|
||||
Status: orderStatus,
|
||||
Price: respData.Price,
|
||||
Amount: respData.Amount,
|
||||
@@ -1349,7 +1348,7 @@ func (h *HUOBI) GetActiveOrders(ctx context.Context, req *order.GetOrdersRequest
|
||||
Pair: req.Pairs[i],
|
||||
Type: orderType,
|
||||
Side: orderSide,
|
||||
Date: time.Unix(0, resp.Data[j].CreatedAt*int64(time.Millisecond)),
|
||||
Date: time.UnixMilli(resp.Data[j].CreatedAt),
|
||||
Status: orderStatus,
|
||||
Price: resp.Data[j].Price,
|
||||
Amount: resp.Data[j].OrderAmount,
|
||||
@@ -1377,7 +1376,7 @@ func (h *HUOBI) GetActiveOrders(ctx context.Context, req *order.GetOrdersRequest
|
||||
Pair: req.Pairs[i],
|
||||
Exchange: h.Name,
|
||||
ExecutedAmount: resp[x].FilledAmount,
|
||||
Date: time.Unix(0, resp[x].CreatedAt*int64(time.Millisecond)),
|
||||
Date: time.UnixMilli(resp[x].CreatedAt),
|
||||
Status: order.Status(resp[x].State),
|
||||
AccountID: strconv.FormatInt(resp[x].AccountID, 10),
|
||||
Fee: resp[x].FilledFees,
|
||||
@@ -1389,7 +1388,7 @@ func (h *HUOBI) GetActiveOrders(ctx context.Context, req *order.GetOrdersRequest
|
||||
}
|
||||
case asset.CoinMarginedFutures:
|
||||
for x := range req.Pairs {
|
||||
var currentPage int64 = 0
|
||||
var currentPage int64
|
||||
for done := false; !done; {
|
||||
openOrders, err := h.GetSwapOpenOrders(ctx,
|
||||
req.Pairs[x], currentPage, 50)
|
||||
@@ -1429,7 +1428,7 @@ func (h *HUOBI) GetActiveOrders(ctx context.Context, req *order.GetOrdersRequest
|
||||
}
|
||||
case asset.Futures:
|
||||
for x := range req.Pairs {
|
||||
var currentPage int64 = 0
|
||||
var currentPage int64
|
||||
for done := false; !done; {
|
||||
openOrders, err := h.FGetOpenOrders(ctx,
|
||||
req.Pairs[x].Base, currentPage, 50)
|
||||
@@ -1508,7 +1507,7 @@ func (h *HUOBI) GetOrderHistory(ctx context.Context, req *order.GetOrdersRequest
|
||||
Pair: req.Pairs[i],
|
||||
Exchange: h.Name,
|
||||
ExecutedAmount: resp[x].FilledAmount,
|
||||
Date: time.Unix(0, resp[x].CreatedAt*int64(time.Millisecond)),
|
||||
Date: time.UnixMilli(resp[x].CreatedAt),
|
||||
Status: order.Status(resp[x].State),
|
||||
AccountID: strconv.FormatInt(resp[x].AccountID, 10),
|
||||
Fee: resp[x].FilledFees,
|
||||
@@ -1519,7 +1518,7 @@ func (h *HUOBI) GetOrderHistory(ctx context.Context, req *order.GetOrdersRequest
|
||||
}
|
||||
case asset.CoinMarginedFutures:
|
||||
for x := range req.Pairs {
|
||||
var currentPage int64 = 0
|
||||
var currentPage int64
|
||||
for done := false; !done; {
|
||||
orderHistory, err := h.GetSwapOrderHistory(ctx,
|
||||
req.Pairs[x],
|
||||
@@ -1570,7 +1569,7 @@ func (h *HUOBI) GetOrderHistory(ctx context.Context, req *order.GetOrdersRequest
|
||||
}
|
||||
case asset.Futures:
|
||||
for x := range req.Pairs {
|
||||
var currentPage int64 = 0
|
||||
var currentPage int64
|
||||
for done := false; !done; {
|
||||
openOrders, err := h.FGetOrderHistory(ctx,
|
||||
req.Pairs[x],
|
||||
|
||||
@@ -324,7 +324,7 @@ func (i *ItBit) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange.UR
|
||||
var intermediary json.RawMessage
|
||||
err = i.SendPayload(ctx, request.Unset, func() (*request.Item, error) {
|
||||
n := i.Requester.GetNonce(true).String()
|
||||
timestamp := strconv.FormatInt(time.Now().UnixNano()/1000000, 10)
|
||||
timestamp := strconv.FormatInt(time.Now().UnixMilli(), 10)
|
||||
|
||||
var message []byte
|
||||
message, err = json.Marshal([]string{method, urlPath, string(PayloadJSON), n, timestamp})
|
||||
|
||||
@@ -19,8 +19,7 @@ func CreateKline(trades []order.TradeHistory, interval Interval, p currency.Pair
|
||||
return Item{}, fmt.Errorf("invalid time interval: [%s]", interval)
|
||||
}
|
||||
|
||||
err := validateData(trades)
|
||||
if err != nil {
|
||||
if err := validateData(trades); err != nil {
|
||||
return Item{}, err
|
||||
}
|
||||
|
||||
|
||||
@@ -92,7 +92,7 @@ func TestValidateData(t *testing.T) {
|
||||
|
||||
func TestCreateKline(t *testing.T) {
|
||||
t.Parallel()
|
||||
c, err := CreateKline(nil,
|
||||
_, err := CreateKline(nil,
|
||||
OneMin,
|
||||
currency.NewPair(currency.BTC, currency.USD),
|
||||
asset.Spot,
|
||||
@@ -113,7 +113,7 @@ func TestCreateKline(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
c, err = CreateKline(trades,
|
||||
_, err = CreateKline(trades,
|
||||
0,
|
||||
currency.NewPair(currency.BTC, currency.USD),
|
||||
asset.Spot,
|
||||
@@ -122,7 +122,7 @@ func TestCreateKline(t *testing.T) {
|
||||
t.Fatal("error cannot be nil")
|
||||
}
|
||||
|
||||
c, err = CreateKline(trades,
|
||||
c, err := CreateKline(trades,
|
||||
OneMin,
|
||||
currency.NewPair(currency.BTC, currency.USD),
|
||||
asset.Spot,
|
||||
@@ -251,6 +251,8 @@ func TestDurationToWord(t *testing.T) {
|
||||
for x := range testCases {
|
||||
test := testCases[x]
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
t.Helper()
|
||||
v := durationToWord(test.interval)
|
||||
if !strings.EqualFold(v, test.name) {
|
||||
t.Fatalf("%v: received %v expected %v", test.name, v, test.name)
|
||||
@@ -261,7 +263,7 @@ func TestDurationToWord(t *testing.T) {
|
||||
|
||||
func TestKlineErrors(t *testing.T) {
|
||||
t.Parallel()
|
||||
v := ErrorKline{
|
||||
v := Error{
|
||||
Interval: OneYear,
|
||||
Pair: currency.NewPair(currency.BTC, currency.AUD),
|
||||
Err: errors.New("hello world"),
|
||||
@@ -398,6 +400,7 @@ func TestTotalCandlesPerInterval(t *testing.T) {
|
||||
for x := range testCases {
|
||||
test := testCases[x]
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
v := TotalCandlesPerInterval(start, end, test.interval)
|
||||
if v != test.expected {
|
||||
t.Fatalf("%v: received %v expected %v", test.name, v, test.expected)
|
||||
@@ -506,6 +509,7 @@ func TestItem_SortCandlesByTimestamp(t *testing.T) {
|
||||
}
|
||||
|
||||
func setupTest(t *testing.T) {
|
||||
t.Helper()
|
||||
if verbose {
|
||||
testhelpers.EnableVerboseTestOutput()
|
||||
}
|
||||
|
||||
@@ -128,8 +128,8 @@ type ExchangeCapabilitiesEnabled struct {
|
||||
// Interval type for kline Interval usage
|
||||
type Interval time.Duration
|
||||
|
||||
// ErrorKline struct to hold kline interval errors
|
||||
type ErrorKline struct {
|
||||
// Error struct to hold kline interval errors
|
||||
type Error struct {
|
||||
Asset asset.Item
|
||||
Pair currency.Pair
|
||||
Interval Interval
|
||||
@@ -137,13 +137,13 @@ type ErrorKline struct {
|
||||
}
|
||||
|
||||
// Error returns short interval unsupported message
|
||||
func (k *ErrorKline) Error() string {
|
||||
return k.Err.Error()
|
||||
func (e *Error) Error() string {
|
||||
return e.Err.Error()
|
||||
}
|
||||
|
||||
// Unwrap returns interval unsupported message
|
||||
func (k *ErrorKline) Unwrap() error {
|
||||
return k.Err
|
||||
func (e *Error) Unwrap() error {
|
||||
return e.Err
|
||||
}
|
||||
|
||||
// IntervalRangeHolder holds the entire range of intervals
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -15,6 +15,7 @@ import (
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
gctcrypto "github.com/thrasher-corp/gocryptotrader/common/crypto"
|
||||
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
@@ -114,70 +115,32 @@ func (l *Lbank) GetTrades(ctx context.Context, symbol string, limit, time int64)
|
||||
}
|
||||
|
||||
// GetKlines returns kline data
|
||||
func (l *Lbank) GetKlines(ctx context.Context, symbol, size, klineType, time string) ([]KlineResponse, error) {
|
||||
var klineTemp interface{}
|
||||
var k []KlineResponse
|
||||
func (l *Lbank) GetKlines(ctx context.Context, symbol, size, klineType, tm string) ([]KlineResponse, error) {
|
||||
var klineTemp [][]float64
|
||||
params := url.Values{}
|
||||
params.Set("symbol", symbol)
|
||||
params.Set("size", size)
|
||||
params.Set("type", klineType)
|
||||
params.Set("time", time)
|
||||
params.Set("time", tm)
|
||||
path := fmt.Sprintf("/v%s/%s?%s", lbankAPIVersion, lbankKlines, params.Encode())
|
||||
err := l.SendHTTPRequest(ctx, exchange.RestSpot, path, &klineTemp)
|
||||
if err != nil {
|
||||
return k, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp, ok := klineTemp.([]interface{})
|
||||
if !ok {
|
||||
return nil, errors.New("response received is invalid")
|
||||
}
|
||||
|
||||
for i := range resp {
|
||||
resp2, ok := resp[i].([]interface{})
|
||||
if !ok {
|
||||
return nil, errors.New("response received is invalid")
|
||||
var k []KlineResponse
|
||||
for x := range klineTemp {
|
||||
if len(klineTemp[x]) < 6 {
|
||||
return nil, errors.New("unexpected kline data length")
|
||||
}
|
||||
var tempResp KlineResponse
|
||||
for x := range resp2 {
|
||||
switch x {
|
||||
case 0:
|
||||
tempResp.TimeStamp = int64(resp2[x].(float64))
|
||||
case 1:
|
||||
if val, ok := resp2[x].(int64); ok {
|
||||
tempResp.OpenPrice = float64(val)
|
||||
} else {
|
||||
tempResp.OpenPrice = resp2[x].(float64)
|
||||
}
|
||||
case 2:
|
||||
if val, ok := resp2[x].(int64); ok {
|
||||
tempResp.HigestPrice = float64(val)
|
||||
} else {
|
||||
tempResp.HigestPrice = resp2[x].(float64)
|
||||
}
|
||||
case 3:
|
||||
if val, ok := resp2[x].(int64); ok {
|
||||
tempResp.LowestPrice = float64(val)
|
||||
} else {
|
||||
tempResp.LowestPrice = resp2[x].(float64)
|
||||
}
|
||||
|
||||
case 4:
|
||||
if val, ok := resp2[x].(int64); ok {
|
||||
tempResp.ClosePrice = float64(val)
|
||||
} else {
|
||||
tempResp.ClosePrice = resp2[x].(float64)
|
||||
}
|
||||
|
||||
case 5:
|
||||
if val, ok := resp2[x].(int64); ok {
|
||||
tempResp.TradingVolume = float64(val)
|
||||
} else {
|
||||
tempResp.TradingVolume = resp2[x].(float64)
|
||||
}
|
||||
}
|
||||
}
|
||||
k = append(k, tempResp)
|
||||
k = append(k, KlineResponse{
|
||||
TimeStamp: time.Unix(int64(klineTemp[x][0]), 0).UTC(),
|
||||
OpenPrice: klineTemp[x][1],
|
||||
HigestPrice: klineTemp[x][2],
|
||||
LowestPrice: klineTemp[x][3],
|
||||
ClosePrice: klineTemp[x][4],
|
||||
TradingVolume: klineTemp[x][5],
|
||||
})
|
||||
}
|
||||
return k, nil
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package lbank
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
)
|
||||
@@ -44,12 +45,12 @@ type TradeResponse struct {
|
||||
|
||||
// KlineResponse stores kline info for given currency exchange
|
||||
type KlineResponse struct {
|
||||
TimeStamp int64 `json:"timestamp"`
|
||||
OpenPrice float64 `json:"openprice"`
|
||||
HigestPrice float64 `json:"highestprice"`
|
||||
LowestPrice float64 `json:"lowestprice"`
|
||||
ClosePrice float64 `json:"closeprice"`
|
||||
TradingVolume float64 `json:"tradingvolume"`
|
||||
TimeStamp time.Time `json:"timestamp"`
|
||||
OpenPrice float64 `json:"openprice"`
|
||||
HigestPrice float64 `json:"highestprice"`
|
||||
LowestPrice float64 `json:"lowestprice"`
|
||||
ClosePrice float64 `json:"closeprice"`
|
||||
TradingVolume float64 `json:"tradingvolume"`
|
||||
}
|
||||
|
||||
// InfoResponse stores info
|
||||
|
||||
@@ -224,8 +224,7 @@ func (l *Lbank) UpdateTickers(ctx context.Context, a asset.Item) error {
|
||||
|
||||
// UpdateTicker updates and returns the ticker for a currency pair
|
||||
func (l *Lbank) UpdateTicker(ctx context.Context, p currency.Pair, a asset.Item) (*ticker.Price, error) {
|
||||
err := l.UpdateTickers(ctx, a)
|
||||
if err != nil {
|
||||
if err := l.UpdateTickers(ctx, a); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ticker.GetTicker(l.Name, p, a)
|
||||
@@ -387,12 +386,12 @@ allTrades:
|
||||
tradeData, err = l.GetTrades(ctx,
|
||||
p.String(),
|
||||
int64(limit),
|
||||
ts.UnixNano()/int64(time.Millisecond))
|
||||
ts.UnixMilli())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for i := range tradeData {
|
||||
tradeTime := time.Unix(0, tradeData[i].DateMS*int64(time.Millisecond))
|
||||
tradeTime := time.UnixMilli(tradeData[i].DateMS)
|
||||
if tradeTime.Before(timestampStart) || tradeTime.After(timestampEnd) {
|
||||
break allTrades
|
||||
}
|
||||
@@ -499,7 +498,7 @@ func (l *Lbank) CancelAllOrders(ctx context.Context, o *order.Cancel) (order.Can
|
||||
var resp order.CancelAllResponse
|
||||
orderIDs, err := l.getAllOpenOrderID(ctx)
|
||||
if err != nil {
|
||||
return resp, nil
|
||||
return resp, err
|
||||
}
|
||||
|
||||
for key := range orderIDs {
|
||||
@@ -935,7 +934,7 @@ func (l *Lbank) GetHistoricCandles(ctx context.Context, pair currency.Pair, a as
|
||||
|
||||
for x := range data {
|
||||
ret.Candles = append(ret.Candles, kline.Candle{
|
||||
Time: time.Unix(data[x].TimeStamp, 0),
|
||||
Time: data[x].TimeStamp,
|
||||
Open: data[x].OpenPrice,
|
||||
High: data[x].HigestPrice,
|
||||
Low: data[x].LowestPrice,
|
||||
@@ -981,11 +980,11 @@ func (l *Lbank) GetHistoricCandlesExtended(ctx context.Context, pair currency.Pa
|
||||
return kline.Item{}, err
|
||||
}
|
||||
for i := range data {
|
||||
if data[i].TimeStamp < dates.Ranges[x].Start.Ticks || data[i].TimeStamp > dates.Ranges[x].End.Ticks {
|
||||
if data[i].TimeStamp.Unix() < dates.Ranges[x].Start.Ticks || data[i].TimeStamp.Unix() > dates.Ranges[x].End.Ticks {
|
||||
continue
|
||||
}
|
||||
ret.Candles = append(ret.Candles, kline.Candle{
|
||||
Time: time.Unix(data[i].TimeStamp, 0).UTC(),
|
||||
Time: data[i].TimeStamp,
|
||||
Open: data[i].OpenPrice,
|
||||
High: data[i].HigestPrice,
|
||||
Low: data[i].LowestPrice,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
//+build !mock_test_off
|
||||
//go:build !mock_test_off
|
||||
// +build !mock_test_off
|
||||
|
||||
// This will build if build tag mock_test_off is not parsed and will try to mock
|
||||
// all tests in _test.go
|
||||
|
||||
@@ -199,8 +199,7 @@ func (l *LocalBitcoins) UpdateTickers(ctx context.Context, a asset.Item) error {
|
||||
|
||||
// UpdateTicker updates and returns the ticker for a currency pair
|
||||
func (l *LocalBitcoins) UpdateTicker(ctx context.Context, p currency.Pair, a asset.Item) (*ticker.Price, error) {
|
||||
err := l.UpdateTickers(ctx, a)
|
||||
if err != nil {
|
||||
if err := l.UpdateTickers(ctx, a); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ticker.GetTicker(l.Name, p, a)
|
||||
|
||||
@@ -349,7 +349,10 @@ func CheckJSON(data interface{}, excluded *Exclusion) (interface{}, error) {
|
||||
context[key] = 0.0 // Zero val float
|
||||
}
|
||||
case Slice:
|
||||
slice := val.([]interface{})
|
||||
slice, ok := val.([]interface{})
|
||||
if !ok {
|
||||
return nil, errors.New("unable to type assert slice")
|
||||
}
|
||||
if len(slice) < 1 {
|
||||
// Empty slice found
|
||||
context[key] = slice
|
||||
|
||||
@@ -8,9 +8,7 @@ import (
|
||||
func TestGet(t *testing.T) {
|
||||
var nonce Nonce
|
||||
nonce.Set(112321313)
|
||||
expected := Value(112321313)
|
||||
result := nonce.Get()
|
||||
if expected != result {
|
||||
if expected, result := Value(112321313), nonce.Get(); expected != result {
|
||||
t.Errorf("Expected %d got %d", expected, result)
|
||||
}
|
||||
}
|
||||
@@ -18,9 +16,7 @@ func TestGet(t *testing.T) {
|
||||
func TestGetInc(t *testing.T) {
|
||||
var nonce Nonce
|
||||
nonce.Set(1)
|
||||
expected := Value(2)
|
||||
result := nonce.GetInc()
|
||||
if expected != result {
|
||||
if expected, result := Value(2), nonce.GetInc(); expected != result {
|
||||
t.Errorf("Expected %d got %d", expected, result)
|
||||
}
|
||||
}
|
||||
@@ -28,9 +24,7 @@ func TestGetInc(t *testing.T) {
|
||||
func TestSet(t *testing.T) {
|
||||
var nonce Nonce
|
||||
nonce.Set(1)
|
||||
expected := Value(1)
|
||||
result := nonce.Get()
|
||||
if expected != result {
|
||||
if result, expected := nonce.Get(), Value(1); expected != result {
|
||||
t.Errorf("Expected %d got %d", expected, result)
|
||||
}
|
||||
}
|
||||
@@ -62,9 +56,7 @@ func TestNonceConcurrency(t *testing.T) {
|
||||
|
||||
wg.Wait()
|
||||
|
||||
result := nonce.Get()
|
||||
expected := Value(12312 + 1000)
|
||||
if expected != result {
|
||||
if expected, result := Value(12312+1000), nonce.Get(); expected != result {
|
||||
t.Errorf("Expected %d got %d", expected, result)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -316,8 +316,7 @@ func (o *OKCoin) UpdateTickers(ctx context.Context, a asset.Item) error {
|
||||
|
||||
// UpdateTicker updates and returns the ticker for a currency pair
|
||||
func (o *OKCoin) UpdateTicker(ctx context.Context, p currency.Pair, a asset.Item) (*ticker.Price, error) {
|
||||
err := o.UpdateTickers(ctx, a)
|
||||
if err != nil {
|
||||
if err := o.UpdateTickers(ctx, a); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ticker.GetTicker(o.Name, p, a)
|
||||
|
||||
@@ -187,6 +187,7 @@ func TestGetPerpSwapMarkets(t *testing.T) {
|
||||
}
|
||||
|
||||
func testStandardErrorHandling(t *testing.T, err error) {
|
||||
t.Helper()
|
||||
if !areTestAPIKeysSet() && err == nil {
|
||||
t.Errorf("Expecting an error when no keys are set")
|
||||
}
|
||||
|
||||
@@ -540,8 +540,7 @@ func (o *OKEX) UpdateTickers(ctx context.Context, a asset.Item) error {
|
||||
|
||||
// UpdateTicker updates and returns the ticker for a currency pair
|
||||
func (o *OKEX) UpdateTicker(ctx context.Context, p currency.Pair, a asset.Item) (*ticker.Price, error) {
|
||||
err := o.UpdateTickers(ctx, a)
|
||||
if err != nil {
|
||||
if err := o.UpdateTickers(ctx, a); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ticker.GetTicker(o.Name, p, a)
|
||||
|
||||
@@ -546,11 +546,11 @@ func FormatParameters(request interface{}) (parameters string) {
|
||||
func (o *OKGroup) GetErrorCode(code interface{}) error {
|
||||
var assertedCode string
|
||||
|
||||
switch reflect.TypeOf(code).String() {
|
||||
case "float64":
|
||||
assertedCode = strconv.FormatFloat(code.(float64), 'f', -1, 64)
|
||||
case "string":
|
||||
assertedCode = code.(string)
|
||||
switch d := code.(type) {
|
||||
case float64:
|
||||
assertedCode = strconv.FormatFloat(d, 'f', -1, 64)
|
||||
case string:
|
||||
assertedCode = d
|
||||
default:
|
||||
return errors.New("unusual type returned")
|
||||
}
|
||||
|
||||
@@ -276,8 +276,7 @@ func (o *OKGroup) GetFundingHistory(ctx context.Context) (resp []exchange.FundHi
|
||||
|
||||
// SubmitOrder submits a new order
|
||||
func (o *OKGroup) SubmitOrder(ctx context.Context, s *order.Submit) (order.SubmitResponse, error) {
|
||||
err := s.Validate()
|
||||
if err != nil {
|
||||
if err := s.Validate(); err != nil {
|
||||
return order.SubmitResponse{}, err
|
||||
}
|
||||
|
||||
@@ -625,37 +624,34 @@ func (o *OKGroup) GetHistoricCandles(ctx context.Context, pair currency.Pair, a
|
||||
}
|
||||
|
||||
for x := range candles {
|
||||
t := candles[x].([]interface{})
|
||||
tempCandle := kline.Candle{}
|
||||
t, ok := candles[x].([]interface{})
|
||||
if !ok {
|
||||
return kline.Item{}, errors.New("unable to type asset candle data")
|
||||
}
|
||||
if len(t) < 6 {
|
||||
return kline.Item{}, errors.New("incorrect candles data length")
|
||||
}
|
||||
v, ok := t[0].(string)
|
||||
if !ok {
|
||||
return kline.Item{}, errors.New("unexpected value received")
|
||||
return kline.Item{}, errors.New("unable to type asset time data")
|
||||
}
|
||||
tempCandle.Time, err = time.Parse(time.RFC3339, v)
|
||||
if err != nil {
|
||||
var tempCandle kline.Candle
|
||||
if tempCandle.Time, err = time.Parse(time.RFC3339, v); err != nil {
|
||||
return kline.Item{}, err
|
||||
}
|
||||
tempCandle.Open, err = convert.FloatFromString(t[1])
|
||||
if err != nil {
|
||||
if tempCandle.Open, err = convert.FloatFromString(t[1]); err != nil {
|
||||
return kline.Item{}, err
|
||||
}
|
||||
tempCandle.High, err = convert.FloatFromString(t[2])
|
||||
if err != nil {
|
||||
if tempCandle.High, err = convert.FloatFromString(t[2]); err != nil {
|
||||
return kline.Item{}, err
|
||||
}
|
||||
|
||||
tempCandle.Low, err = convert.FloatFromString(t[3])
|
||||
if err != nil {
|
||||
if tempCandle.Low, err = convert.FloatFromString(t[3]); err != nil {
|
||||
return kline.Item{}, err
|
||||
}
|
||||
|
||||
tempCandle.Close, err = convert.FloatFromString(t[4])
|
||||
if err != nil {
|
||||
if tempCandle.Close, err = convert.FloatFromString(t[4]); err != nil {
|
||||
return kline.Item{}, err
|
||||
}
|
||||
|
||||
tempCandle.Volume, err = convert.FloatFromString(t[5])
|
||||
if err != nil {
|
||||
if tempCandle.Volume, err = convert.FloatFromString(t[5]); err != nil {
|
||||
return kline.Item{}, err
|
||||
}
|
||||
ret.Candles = append(ret.Candles, tempCandle)
|
||||
@@ -703,37 +699,37 @@ func (o *OKGroup) GetHistoricCandlesExtended(ctx context.Context, pair currency.
|
||||
}
|
||||
|
||||
for i := range candles {
|
||||
t := candles[i].([]interface{})
|
||||
tempCandle := kline.Candle{}
|
||||
t, ok := candles[i].([]interface{})
|
||||
if !ok {
|
||||
return kline.Item{}, errors.New("unable to type assert candles data")
|
||||
}
|
||||
if len(t) < 6 {
|
||||
return kline.Item{}, errors.New("candle data length invalid")
|
||||
}
|
||||
v, ok := t[0].(string)
|
||||
if !ok {
|
||||
return kline.Item{}, errors.New("unexpected value received")
|
||||
return kline.Item{}, errors.New("unable to type assert time value")
|
||||
}
|
||||
tempCandle.Time, err = time.Parse(time.RFC3339, v)
|
||||
if err != nil {
|
||||
var tempCandle kline.Candle
|
||||
if tempCandle.Time, err = time.Parse(time.RFC3339, v); err != nil {
|
||||
return kline.Item{}, err
|
||||
}
|
||||
tempCandle.Open, err = convert.FloatFromString(t[1])
|
||||
if err != nil {
|
||||
if tempCandle.Open, err = convert.FloatFromString(t[1]); err != nil {
|
||||
return kline.Item{}, err
|
||||
}
|
||||
tempCandle.High, err = convert.FloatFromString(t[2])
|
||||
if err != nil {
|
||||
if tempCandle.High, err = convert.FloatFromString(t[2]); err != nil {
|
||||
return kline.Item{}, err
|
||||
}
|
||||
|
||||
tempCandle.Low, err = convert.FloatFromString(t[3])
|
||||
if err != nil {
|
||||
if tempCandle.Low, err = convert.FloatFromString(t[3]); err != nil {
|
||||
return kline.Item{}, err
|
||||
}
|
||||
|
||||
tempCandle.Close, err = convert.FloatFromString(t[4])
|
||||
if err != nil {
|
||||
if tempCandle.Close, err = convert.FloatFromString(t[4]); err != nil {
|
||||
return kline.Item{}, err
|
||||
}
|
||||
|
||||
tempCandle.Volume, err = convert.FloatFromString(t[5])
|
||||
if err != nil {
|
||||
if tempCandle.Volume, err = convert.FloatFromString(t[5]); err != nil {
|
||||
return kline.Item{}, err
|
||||
}
|
||||
ret.Candles = append(ret.Candles, tempCandle)
|
||||
|
||||
@@ -40,7 +40,7 @@ func (ll *linkedList) display() {
|
||||
|
||||
func TestLoad(t *testing.T) {
|
||||
list := asks{}
|
||||
Check(list, 0, 0, 0, t)
|
||||
Check(t, list, 0, 0, 0)
|
||||
|
||||
stack := newStack()
|
||||
list.load(Items{
|
||||
@@ -56,7 +56,7 @@ func TestLoad(t *testing.T) {
|
||||
t.Fatalf("incorrect stack count expected: %v received: %v", 0, stack.getCount())
|
||||
}
|
||||
|
||||
Check(list, 6, 36, 6, t)
|
||||
Check(t, list, 6, 36, 6)
|
||||
|
||||
list.load(Items{
|
||||
{Price: 1, Amount: 1},
|
||||
@@ -68,7 +68,7 @@ func TestLoad(t *testing.T) {
|
||||
t.Fatalf("incorrect stack count expected: %v received: %v", 3, stack.getCount())
|
||||
}
|
||||
|
||||
Check(list, 3, 9, 3, t)
|
||||
Check(t, list, 3, 9, 3)
|
||||
|
||||
list.load(Items{
|
||||
{Price: 1, Amount: 1},
|
||||
@@ -81,7 +81,7 @@ func TestLoad(t *testing.T) {
|
||||
t.Fatalf("incorrect stack count expected: %v received: %v", 2, stack.getCount())
|
||||
}
|
||||
|
||||
Check(list, 4, 16, 4, t)
|
||||
Check(t, list, 4, 16, 4)
|
||||
|
||||
// purge entire list
|
||||
list.load(nil, stack)
|
||||
@@ -90,7 +90,7 @@ func TestLoad(t *testing.T) {
|
||||
t.Fatalf("incorrect stack count expected: %v received: %v", 6, stack.getCount())
|
||||
}
|
||||
|
||||
Check(list, 0, 0, 0, t)
|
||||
Check(t, list, 0, 0, 0)
|
||||
}
|
||||
|
||||
// 22222386 57.3 ns/op 0 B/op 0 allocs/op (old)
|
||||
@@ -121,7 +121,7 @@ func TestUpdateInsertByPrice(t *testing.T) {
|
||||
{Price: 1, Amount: 2},
|
||||
}, stack, 0, getNow())
|
||||
|
||||
Check(a, 7, 37, 6, t)
|
||||
Check(t, a, 7, 37, 6)
|
||||
|
||||
if stack.getCount() != 0 {
|
||||
t.Fatalf("incorrect stack count expected: %v received: %v", 0, stack.getCount())
|
||||
@@ -132,7 +132,7 @@ func TestUpdateInsertByPrice(t *testing.T) {
|
||||
{Price: 0.5, Amount: 2},
|
||||
}, stack, 0, getNow())
|
||||
|
||||
Check(a, 9, 38, 7, t)
|
||||
Check(t, a, 9, 38, 7)
|
||||
|
||||
if stack.getCount() != 0 {
|
||||
t.Fatalf("incorrect stack count expected: %v received: %v", 0, stack.getCount())
|
||||
@@ -143,7 +143,7 @@ func TestUpdateInsertByPrice(t *testing.T) {
|
||||
{Price: 12, Amount: 2},
|
||||
}, stack, 0, getNow())
|
||||
|
||||
Check(a, 11, 62, 8, t)
|
||||
Check(t, a, 11, 62, 8)
|
||||
|
||||
if stack.getCount() != 0 {
|
||||
t.Fatalf("incorrect stack count expected: %v received: %v", 0, stack.getCount())
|
||||
@@ -156,7 +156,7 @@ func TestUpdateInsertByPrice(t *testing.T) {
|
||||
{Price: 13, Amount: 2},
|
||||
}, stack, 10, getNow())
|
||||
|
||||
Check(a, 15, 106, 10, t)
|
||||
Check(t, a, 15, 106, 10)
|
||||
|
||||
if stack.getCount() != 1 {
|
||||
t.Fatalf("incorrect stack count expected: %v received: %v", 1, stack.getCount())
|
||||
@@ -167,7 +167,7 @@ func TestUpdateInsertByPrice(t *testing.T) {
|
||||
{Price: 12, Amount: 0},
|
||||
}, stack, 0, getNow())
|
||||
|
||||
Check(a, 13, 82, 9, t)
|
||||
Check(t, a, 13, 82, 9)
|
||||
|
||||
if stack.getCount() != 2 {
|
||||
t.Fatalf("incorrect stack count expected: %v received: %v", 2, stack.getCount())
|
||||
@@ -178,7 +178,7 @@ func TestUpdateInsertByPrice(t *testing.T) {
|
||||
{Price: 7, Amount: 0},
|
||||
}, stack, 0, getNow())
|
||||
|
||||
Check(a, 12, 75, 8, t)
|
||||
Check(t, a, 12, 75, 8)
|
||||
|
||||
if stack.getCount() != 3 {
|
||||
t.Fatalf("incorrect stack count expected: %v received: %v", 3, stack.getCount())
|
||||
@@ -189,7 +189,7 @@ func TestUpdateInsertByPrice(t *testing.T) {
|
||||
{Price: 0.5, Amount: 0},
|
||||
}, stack, 0, getNow())
|
||||
|
||||
Check(a, 10, 74, 7, t)
|
||||
Check(t, a, 10, 74, 7)
|
||||
|
||||
if stack.getCount() != 4 {
|
||||
t.Fatalf("incorrect stack count expected: %v received: %v", 4, stack.getCount())
|
||||
@@ -208,7 +208,7 @@ func TestUpdateInsertByPrice(t *testing.T) {
|
||||
{Price: 11, Amount: 1},
|
||||
}, stack, 0, getNow())
|
||||
|
||||
Check(a, 6, 36, 6, t)
|
||||
Check(t, a, 6, 36, 6)
|
||||
|
||||
if stack.getCount() != 5 {
|
||||
t.Fatalf("incorrect stack count expected: %v received: %v", 4, stack.getCount())
|
||||
@@ -230,7 +230,7 @@ func TestUpdateInsertByPrice(t *testing.T) {
|
||||
{Price: 11, Amount: 2},
|
||||
}, stack, 0, getNow())
|
||||
|
||||
Check(b, 7, 47, 6, t)
|
||||
Check(t, b, 7, 47, 6)
|
||||
|
||||
if stack.getCount() != 0 {
|
||||
t.Fatalf("incorrect stack count expected: %v received: %v", 0, stack.getCount())
|
||||
@@ -241,7 +241,7 @@ func TestUpdateInsertByPrice(t *testing.T) {
|
||||
{Price: 12, Amount: 2},
|
||||
}, stack, 0, getNow())
|
||||
|
||||
Check(b, 9, 71, 7, t)
|
||||
Check(t, b, 9, 71, 7)
|
||||
|
||||
if stack.getCount() != 0 {
|
||||
t.Fatalf("incorrect stack count expected: %v received: %v", 0, stack.getCount())
|
||||
@@ -252,7 +252,7 @@ func TestUpdateInsertByPrice(t *testing.T) {
|
||||
{Price: 0.5, Amount: 2},
|
||||
}, stack, 0, getNow())
|
||||
|
||||
Check(b, 11, 72, 8, t)
|
||||
Check(t, b, 11, 72, 8)
|
||||
|
||||
if stack.getCount() != 0 {
|
||||
t.Fatalf("incorrect stack count expected: %v received: %v", 0, stack.getCount())
|
||||
@@ -265,7 +265,7 @@ func TestUpdateInsertByPrice(t *testing.T) {
|
||||
{Price: 13, Amount: 2},
|
||||
}, stack, 10, getNow())
|
||||
|
||||
Check(b, 15, 141, 10, t)
|
||||
Check(t, b, 15, 141, 10)
|
||||
|
||||
if stack.getCount() != 1 {
|
||||
t.Fatalf("incorrect stack count expected: %v received: %v", 0, stack.getCount())
|
||||
@@ -276,7 +276,7 @@ func TestUpdateInsertByPrice(t *testing.T) {
|
||||
{Price: 1, Amount: 0},
|
||||
}, stack, 0, getNow())
|
||||
|
||||
Check(b, 14, 140, 9, t)
|
||||
Check(t, b, 14, 140, 9)
|
||||
|
||||
if stack.getCount() != 2 {
|
||||
t.Fatalf("incorrect stack count expected: %v received: %v", 2, stack.getCount())
|
||||
@@ -287,7 +287,7 @@ func TestUpdateInsertByPrice(t *testing.T) {
|
||||
{Price: 10.5, Amount: 0},
|
||||
}, stack, 0, getNow())
|
||||
|
||||
Check(b, 12, 119, 8, t)
|
||||
Check(t, b, 12, 119, 8)
|
||||
|
||||
if stack.getCount() != 3 {
|
||||
t.Fatalf("incorrect stack count expected: %v received: %v", 3, stack.getCount())
|
||||
@@ -298,7 +298,7 @@ func TestUpdateInsertByPrice(t *testing.T) {
|
||||
{Price: 13, Amount: 0},
|
||||
}, stack, 0, getNow())
|
||||
|
||||
Check(b, 10, 93, 7, t)
|
||||
Check(t, b, 10, 93, 7)
|
||||
|
||||
if stack.getCount() != 4 {
|
||||
t.Fatalf("incorrect stack count expected: %v received: %v", 4, stack.getCount())
|
||||
@@ -317,7 +317,7 @@ func TestUpdateInsertByPrice(t *testing.T) {
|
||||
{Price: 11, Amount: 1},
|
||||
}, stack, 0, getNow())
|
||||
|
||||
Check(b, 6, 36, 6, t)
|
||||
Check(t, b, 6, 36, 6)
|
||||
|
||||
if stack.getCount() != 5 {
|
||||
t.Fatalf("incorrect stack count expected: %v received: %v", 4, stack.getCount())
|
||||
@@ -338,15 +338,15 @@ func TestCleanup(t *testing.T) {
|
||||
a.load(asksSnapshot, stack)
|
||||
|
||||
a.cleanup(6, stack)
|
||||
Check(a, 6, 36, 6, t)
|
||||
Check(t, a, 6, 36, 6)
|
||||
a.cleanup(5, stack)
|
||||
Check(a, 5, 25, 5, t)
|
||||
Check(t, a, 5, 25, 5)
|
||||
a.cleanup(1, stack)
|
||||
Check(a, 1, 1, 1, t)
|
||||
Check(t, a, 1, 1, 1)
|
||||
a.cleanup(10, stack)
|
||||
Check(a, 1, 1, 1, t)
|
||||
Check(t, a, 1, 1, 1)
|
||||
a.cleanup(0, stack) // will purge, underlying checks are done elseware to prevent this
|
||||
Check(a, 0, 0, 0, t)
|
||||
Check(t, a, 0, 0, 0)
|
||||
}
|
||||
|
||||
// 46154023 24.0 ns/op 0 B/op 0 allocs/op (old)
|
||||
@@ -421,7 +421,7 @@ func TestUpdateByID(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
Check(a, 6, 36, 6, t)
|
||||
Check(t, a, 6, 36, 6)
|
||||
|
||||
err = a.updateByID(Items{
|
||||
{Price: 11, Amount: 1, ID: 1337},
|
||||
@@ -496,7 +496,7 @@ func TestDeleteByID(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
Check(a, 5, 35, 5, t)
|
||||
Check(t, a, 5, 35, 5)
|
||||
|
||||
// Delete at tail
|
||||
err = a.deleteByID(Items{
|
||||
@@ -506,7 +506,7 @@ func TestDeleteByID(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
Check(a, 4, 24, 4, t)
|
||||
Check(t, a, 4, 24, 4)
|
||||
|
||||
// Delete in middle
|
||||
err = a.deleteByID(Items{
|
||||
@@ -516,7 +516,7 @@ func TestDeleteByID(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
Check(a, 3, 19, 3, t)
|
||||
Check(t, a, 3, 19, 3)
|
||||
|
||||
// Intentional error
|
||||
err = a.deleteByID(Items{
|
||||
@@ -556,7 +556,7 @@ func TestUpdateInsertByIDAsk(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
Check(a, 7, 37, 6, t)
|
||||
Check(t, a, 7, 37, 6)
|
||||
|
||||
// Reset
|
||||
a.load(asksSnapshot, s)
|
||||
@@ -574,7 +574,7 @@ func TestUpdateInsertByIDAsk(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
Check(a, 12, 72, 6, t)
|
||||
Check(t, a, 12, 72, 6)
|
||||
|
||||
// Update all instances with matching ID in backwards
|
||||
err = a.updateInsertByID(Items{
|
||||
@@ -589,7 +589,7 @@ func TestUpdateInsertByIDAsk(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
Check(a, 12, 72, 6, t)
|
||||
Check(t, a, 12, 72, 6)
|
||||
|
||||
// Update all instances with matching ID all over the ship
|
||||
err = a.updateInsertByID(Items{
|
||||
@@ -604,7 +604,7 @@ func TestUpdateInsertByIDAsk(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
Check(a, 12, 72, 6, t)
|
||||
Check(t, a, 12, 72, 6)
|
||||
|
||||
// Update all instances move one before ID in middle
|
||||
err = a.updateInsertByID(Items{
|
||||
@@ -619,7 +619,7 @@ func TestUpdateInsertByIDAsk(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
Check(a, 12, 66, 6, t)
|
||||
Check(t, a, 12, 66, 6)
|
||||
|
||||
// Update all instances move one before ID at head
|
||||
err = a.updateInsertByID(Items{
|
||||
@@ -634,7 +634,7 @@ func TestUpdateInsertByIDAsk(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
Check(a, 12, 63, 6, t)
|
||||
Check(t, a, 12, 63, 6)
|
||||
|
||||
// Reset
|
||||
a.load(asksSnapshot, s)
|
||||
@@ -652,7 +652,7 @@ func TestUpdateInsertByIDAsk(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
Check(a, 12, 78, 6, t)
|
||||
Check(t, a, 12, 78, 6)
|
||||
|
||||
// Reset
|
||||
a.load(asksSnapshot, s)
|
||||
@@ -670,7 +670,7 @@ func TestUpdateInsertByIDAsk(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
Check(a, 12, 86, 6, t)
|
||||
Check(t, a, 12, 86, 6)
|
||||
|
||||
// Update all instances then pop new instance
|
||||
err = a.updateInsertByID(Items{
|
||||
@@ -686,7 +686,7 @@ func TestUpdateInsertByIDAsk(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
Check(a, 14, 106, 7, t)
|
||||
Check(t, a, 14, 106, 7)
|
||||
|
||||
// Reset
|
||||
a.load(asksSnapshot, s)
|
||||
@@ -705,7 +705,7 @@ func TestUpdateInsertByIDAsk(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
Check(a, 14, 87, 7, t)
|
||||
Check(t, a, 14, 87, 7)
|
||||
|
||||
// bookmark head and move to mid
|
||||
err = a.updateInsertByID(Items{
|
||||
@@ -715,7 +715,7 @@ func TestUpdateInsertByIDAsk(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
Check(a, 14, 101, 7, t)
|
||||
Check(t, a, 14, 101, 7)
|
||||
|
||||
// bookmark head and move to tail
|
||||
err = a.updateInsertByID(Items{
|
||||
@@ -725,7 +725,7 @@ func TestUpdateInsertByIDAsk(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
Check(a, 14, 124, 7, t)
|
||||
Check(t, a, 14, 124, 7)
|
||||
|
||||
// move tail location to head
|
||||
err = a.updateInsertByID(Items{
|
||||
@@ -735,7 +735,7 @@ func TestUpdateInsertByIDAsk(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
Check(a, 14, 104, 7, t)
|
||||
Check(t, a, 14, 104, 7)
|
||||
|
||||
// move tail location to mid
|
||||
err = a.updateInsertByID(Items{
|
||||
@@ -745,7 +745,7 @@ func TestUpdateInsertByIDAsk(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
Check(a, 14, 96, 7, t)
|
||||
Check(t, a, 14, 96, 7)
|
||||
|
||||
// insert at tail dont match
|
||||
err = a.updateInsertByID(Items{
|
||||
@@ -755,7 +755,7 @@ func TestUpdateInsertByIDAsk(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
Check(a, 16, 156, 8, t)
|
||||
Check(t, a, 16, 156, 8)
|
||||
|
||||
// insert between last and 2nd last
|
||||
err = a.updateInsertByID(Items{
|
||||
@@ -765,7 +765,7 @@ func TestUpdateInsertByIDAsk(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
Check(a, 18, 180, 9, t)
|
||||
Check(t, a, 18, 180, 9)
|
||||
|
||||
// readjust at end
|
||||
err = a.updateInsertByID(Items{
|
||||
@@ -775,7 +775,7 @@ func TestUpdateInsertByIDAsk(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
Check(a, 19, 207, 9, t)
|
||||
Check(t, a, 19, 207, 9)
|
||||
|
||||
// readjust further and decrease price past tail
|
||||
err = a.updateInsertByID(Items{
|
||||
@@ -785,7 +785,7 @@ func TestUpdateInsertByIDAsk(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
Check(a, 19, 213, 9, t)
|
||||
Check(t, a, 19, 213, 9)
|
||||
|
||||
// purge
|
||||
a.load(nil, s)
|
||||
@@ -804,7 +804,7 @@ func TestUpdateInsertByIDAsk(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
Check(a, 14, 87, 7, t)
|
||||
Check(t, a, 14, 87, 7)
|
||||
}
|
||||
|
||||
func TestUpdateInsertByIDBids(t *testing.T) {
|
||||
@@ -828,7 +828,7 @@ func TestUpdateInsertByIDBids(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
Check(b, 7, 37, 6, t)
|
||||
Check(t, b, 7, 37, 6)
|
||||
|
||||
// Reset
|
||||
b.load(bidsSnapshot, s)
|
||||
@@ -846,7 +846,7 @@ func TestUpdateInsertByIDBids(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
Check(b, 12, 72, 6, t)
|
||||
Check(t, b, 12, 72, 6)
|
||||
|
||||
// Update all instances with matching ID in backwards
|
||||
err = b.updateInsertByID(Items{
|
||||
@@ -861,7 +861,7 @@ func TestUpdateInsertByIDBids(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
Check(b, 12, 72, 6, t)
|
||||
Check(t, b, 12, 72, 6)
|
||||
|
||||
// Update all instances with matching ID all over the ship
|
||||
err = b.updateInsertByID(Items{
|
||||
@@ -876,7 +876,7 @@ func TestUpdateInsertByIDBids(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
Check(b, 12, 72, 6, t)
|
||||
Check(t, b, 12, 72, 6)
|
||||
|
||||
// Update all instances move one before ID in middle
|
||||
err = b.updateInsertByID(Items{
|
||||
@@ -891,7 +891,7 @@ func TestUpdateInsertByIDBids(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
Check(b, 12, 66, 6, t)
|
||||
Check(t, b, 12, 66, 6)
|
||||
|
||||
// Update all instances move one before ID at head
|
||||
err = b.updateInsertByID(Items{
|
||||
@@ -906,7 +906,7 @@ func TestUpdateInsertByIDBids(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
Check(b, 12, 63, 6, t)
|
||||
Check(t, b, 12, 63, 6)
|
||||
|
||||
// Reset
|
||||
b.load(bidsSnapshot, s)
|
||||
@@ -924,7 +924,7 @@ func TestUpdateInsertByIDBids(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
Check(b, 12, 78, 6, t)
|
||||
Check(t, b, 12, 78, 6)
|
||||
|
||||
// Reset
|
||||
b.load(bidsSnapshot, s)
|
||||
@@ -942,7 +942,7 @@ func TestUpdateInsertByIDBids(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
Check(b, 12, 86, 6, t)
|
||||
Check(t, b, 12, 86, 6)
|
||||
|
||||
// Update all instances then pop new instance
|
||||
err = b.updateInsertByID(Items{
|
||||
@@ -958,7 +958,7 @@ func TestUpdateInsertByIDBids(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
Check(b, 14, 106, 7, t)
|
||||
Check(t, b, 14, 106, 7)
|
||||
|
||||
// Reset
|
||||
b.load(bidsSnapshot, s)
|
||||
@@ -977,7 +977,7 @@ func TestUpdateInsertByIDBids(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
Check(b, 14, 87, 7, t)
|
||||
Check(t, b, 14, 87, 7)
|
||||
|
||||
// bookmark head and move to mid
|
||||
err = b.updateInsertByID(Items{
|
||||
@@ -987,7 +987,7 @@ func TestUpdateInsertByIDBids(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
Check(b, 14, 82, 7, t)
|
||||
Check(t, b, 14, 82, 7)
|
||||
|
||||
// bookmark head and move to tail
|
||||
err = b.updateInsertByID(Items{
|
||||
@@ -997,7 +997,7 @@ func TestUpdateInsertByIDBids(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
Check(b, 14, 60.5, 7, t)
|
||||
Check(t, b, 14, 60.5, 7)
|
||||
|
||||
// move tail location to head
|
||||
err = b.updateInsertByID(Items{
|
||||
@@ -1007,7 +1007,7 @@ func TestUpdateInsertByIDBids(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
Check(b, 14, 80, 7, t)
|
||||
Check(t, b, 14, 80, 7)
|
||||
|
||||
// move tail location to mid
|
||||
err = b.updateInsertByID(Items{
|
||||
@@ -1017,7 +1017,7 @@ func TestUpdateInsertByIDBids(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
Check(b, 14, 94, 7, t)
|
||||
Check(t, b, 14, 94, 7)
|
||||
|
||||
// insert at head dont match
|
||||
err = b.updateInsertByID(Items{
|
||||
@@ -1027,7 +1027,7 @@ func TestUpdateInsertByIDBids(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
Check(b, 16, 154, 8, t)
|
||||
Check(t, b, 16, 154, 8)
|
||||
|
||||
// insert between last and 2nd last
|
||||
err = b.updateInsertByID(Items{
|
||||
@@ -1036,7 +1036,7 @@ func TestUpdateInsertByIDBids(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
Check(b, 18, 157, 9, t)
|
||||
Check(t, b, 18, 157, 9)
|
||||
|
||||
// readjust at end
|
||||
err = b.updateInsertByID(Items{
|
||||
@@ -1045,7 +1045,7 @@ func TestUpdateInsertByIDBids(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
Check(b, 19, 158, 9, t)
|
||||
Check(t, b, 19, 158, 9)
|
||||
|
||||
// readjust further and decrease price past tail
|
||||
err = b.updateInsertByID(Items{
|
||||
@@ -1054,7 +1054,7 @@ func TestUpdateInsertByIDBids(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
Check(b, 19, 157.7, 9, t)
|
||||
Check(t, b, 19, 157.7, 9)
|
||||
|
||||
// purge
|
||||
b.load(nil, s)
|
||||
@@ -1073,7 +1073,7 @@ func TestUpdateInsertByIDBids(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
Check(b, 14, 87, 7, t)
|
||||
Check(t, b, 14, 87, 7)
|
||||
}
|
||||
|
||||
func TestInsertUpdatesBid(t *testing.T) {
|
||||
@@ -1101,7 +1101,7 @@ func TestInsertUpdatesBid(t *testing.T) {
|
||||
t.Fatalf("expected error %s but received %v", errCollisionDetected, err)
|
||||
}
|
||||
|
||||
Check(b, 6, 36, 6, t)
|
||||
Check(t, b, 6, 36, 6)
|
||||
|
||||
// Insert at head
|
||||
err = b.insertUpdates(Items{
|
||||
@@ -1111,7 +1111,7 @@ func TestInsertUpdatesBid(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
Check(b, 7, 48, 7, t)
|
||||
Check(t, b, 7, 48, 7)
|
||||
|
||||
// Insert at tail
|
||||
err = b.insertUpdates(Items{
|
||||
@@ -1121,7 +1121,7 @@ func TestInsertUpdatesBid(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
Check(b, 8, 48.5, 8, t)
|
||||
Check(t, b, 8, 48.5, 8)
|
||||
|
||||
// Insert at mid
|
||||
err = b.insertUpdates(Items{
|
||||
@@ -1131,7 +1131,7 @@ func TestInsertUpdatesBid(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
Check(b, 9, 54, 9, t)
|
||||
Check(t, b, 9, 54, 9)
|
||||
|
||||
// purge
|
||||
b.load(nil, s)
|
||||
@@ -1144,7 +1144,7 @@ func TestInsertUpdatesBid(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
Check(b, 1, 5.5, 1, t)
|
||||
Check(t, b, 1, 5.5, 1)
|
||||
}
|
||||
|
||||
func TestInsertUpdatesAsk(t *testing.T) {
|
||||
@@ -1172,7 +1172,7 @@ func TestInsertUpdatesAsk(t *testing.T) {
|
||||
t.Fatalf("expected error %s but received %v", errCollisionDetected, err)
|
||||
}
|
||||
|
||||
Check(a, 6, 36, 6, t)
|
||||
Check(t, a, 6, 36, 6)
|
||||
|
||||
// Insert at tail
|
||||
err = a.insertUpdates(Items{
|
||||
@@ -1182,7 +1182,7 @@ func TestInsertUpdatesAsk(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
Check(a, 7, 48, 7, t)
|
||||
Check(t, a, 7, 48, 7)
|
||||
|
||||
// Insert at head
|
||||
err = a.insertUpdates(Items{
|
||||
@@ -1192,7 +1192,7 @@ func TestInsertUpdatesAsk(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
Check(a, 8, 48.5, 8, t)
|
||||
Check(t, a, 8, 48.5, 8)
|
||||
|
||||
// Insert at mid
|
||||
err = a.insertUpdates(Items{
|
||||
@@ -1202,7 +1202,7 @@ func TestInsertUpdatesAsk(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
Check(a, 9, 54, 9, t)
|
||||
Check(t, a, 9, 54, 9)
|
||||
|
||||
// purge
|
||||
a.load(nil, s)
|
||||
@@ -1215,11 +1215,11 @@ func TestInsertUpdatesAsk(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
Check(a, 1, 5.5, 1, t)
|
||||
Check(t, a, 1, 5.5, 1)
|
||||
}
|
||||
|
||||
// check checks depth values after an update has taken place
|
||||
func Check(depth interface{}, liquidity, value float64, nodeCount int, t *testing.T) {
|
||||
func Check(t *testing.T, depth interface{}, liquidity, value float64, nodeCount int) {
|
||||
t.Helper()
|
||||
b, isBid := depth.(bids)
|
||||
a, isAsk := depth.(asks)
|
||||
@@ -1434,7 +1434,7 @@ func TestShiftBookmark(t *testing.T) {
|
||||
t.Fatal("nilBookmark not reassigned")
|
||||
}
|
||||
|
||||
head := bookmarkedNode
|
||||
head := bookmarkedNode // nolint // ifshort false positive
|
||||
bookmarkedNode.Prev = nil
|
||||
bookmarkedNode.Next = originalBookmarkNext
|
||||
tip.Next = nil
|
||||
|
||||
@@ -54,7 +54,6 @@ func getNow() now {
|
||||
func (s *stack) Push(n *Node, tn now) {
|
||||
if !atomic.CompareAndSwapUint32(&s.sema, neutral, active) {
|
||||
// Stack is in use, for now we can dereference pointer
|
||||
n = nil
|
||||
return
|
||||
}
|
||||
// Adds a time when its placed back on to stack.
|
||||
|
||||
@@ -321,8 +321,7 @@ func (b *Base) Process() error {
|
||||
b.LastUpdated = time.Now()
|
||||
}
|
||||
|
||||
err := b.Verify()
|
||||
if err != nil {
|
||||
if err := b.Verify(); err != nil {
|
||||
return err
|
||||
}
|
||||
return service.Update(b)
|
||||
|
||||
@@ -605,9 +605,7 @@ func TestReverse(t *testing.T) {
|
||||
var b Base
|
||||
b.VerifyOrderbook = true
|
||||
|
||||
length := 1000
|
||||
b.Bids = deploySliceOrdered()
|
||||
if len(b.Bids) != length {
|
||||
if b.Bids = deploySliceOrdered(); len(b.Bids) != 1000 {
|
||||
t.Fatal("incorrect length")
|
||||
}
|
||||
|
||||
@@ -637,9 +635,8 @@ func TestReverse(t *testing.T) {
|
||||
|
||||
// 705985 1856 ns/op 0 B/op 0 allocs/op
|
||||
func BenchmarkReverse(b *testing.B) {
|
||||
length := 1000
|
||||
s := deploySliceOrdered()
|
||||
if len(s) != length {
|
||||
if len(s) != 1000 {
|
||||
b.Fatal("incorrect length")
|
||||
}
|
||||
|
||||
|
||||
@@ -246,7 +246,10 @@ func (p *Poloniex) GetBalances(ctx context.Context) (Balance, error) {
|
||||
return Balance{}, err
|
||||
}
|
||||
|
||||
data := result.(map[string]interface{})
|
||||
data, ok := result.(map[string]interface{})
|
||||
if !ok {
|
||||
return Balance{}, errors.New("unable to type assert balance result")
|
||||
}
|
||||
balance := Balance{}
|
||||
balance.Currency = make(map[string]float64)
|
||||
|
||||
@@ -287,7 +290,10 @@ func (p *Poloniex) GetDepositAddresses(ctx context.Context) (DepositAddresses, e
|
||||
}
|
||||
|
||||
for x, y := range data {
|
||||
addresses.Addresses[x] = y.(string)
|
||||
addresses.Addresses[x], ok = y.(string)
|
||||
if !ok {
|
||||
return addresses, errors.New("unable to type assert address to string")
|
||||
}
|
||||
}
|
||||
|
||||
return addresses, nil
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
//+build !mock_test_off
|
||||
//go:build !mock_test_off
|
||||
// +build !mock_test_off
|
||||
|
||||
// This will build if build tag mock_test_off is not parsed and will try to mock
|
||||
// all tests in _test.go
|
||||
|
||||
@@ -270,6 +270,7 @@ func TestGetOrderStatus(t *testing.T) {
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
if tt.mock != mockTests {
|
||||
t.Skip()
|
||||
}
|
||||
@@ -325,6 +326,7 @@ func TestGetOrderTrades(t *testing.T) {
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
if tt.mock != mockTests {
|
||||
t.Skip()
|
||||
}
|
||||
|
||||
@@ -312,8 +312,7 @@ func (p *Poloniex) UpdateTickers(ctx context.Context, a asset.Item) error {
|
||||
|
||||
// UpdateTicker updates and returns the ticker for a currency pair
|
||||
func (p *Poloniex) UpdateTicker(ctx context.Context, currencyPair currency.Pair, a asset.Item) (*ticker.Price, error) {
|
||||
err := p.UpdateTickers(ctx, a)
|
||||
if err != nil {
|
||||
if err := p.UpdateTickers(ctx, a); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ticker.GetTicker(p.Name, currencyPair, a)
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
)
|
||||
|
||||
func TestLinearBackoff(t *testing.T) {
|
||||
t.Parallel()
|
||||
type args struct {
|
||||
Backoff request.Backoff
|
||||
}
|
||||
|
||||
@@ -272,7 +272,7 @@ func (r *Requester) GetNonce(isNano bool) nonce.Value {
|
||||
func (r *Requester) GetNonceMilli() nonce.Value {
|
||||
r.timedLock.LockForDuration()
|
||||
if r.Nonce.Get() == 0 {
|
||||
r.Nonce.Set(time.Now().UnixNano() / int64(time.Millisecond))
|
||||
r.Nonce.Set(time.Now().UnixMilli())
|
||||
return r.Nonce.Get()
|
||||
}
|
||||
return r.Nonce.GetInc()
|
||||
|
||||
@@ -484,18 +484,14 @@ func TestGetNonce(t *testing.T) {
|
||||
new(http.Client),
|
||||
WithLimiter(&globalshell))
|
||||
|
||||
n1 := r.GetNonce(false)
|
||||
n2 := r.GetNonce(false)
|
||||
if n1 == n2 {
|
||||
if n1, n2 := r.GetNonce(false), r.GetNonce(false); n1 == n2 {
|
||||
t.Fatal(unexpected)
|
||||
}
|
||||
|
||||
r2 := New("test",
|
||||
new(http.Client),
|
||||
WithLimiter(&globalshell))
|
||||
n3 := r2.GetNonce(true)
|
||||
n4 := r2.GetNonce(true)
|
||||
if n3 == n4 {
|
||||
if n1, n2 := r2.GetNonce(true), r2.GetNonce(true); n1 == n2 {
|
||||
t.Fatal(unexpected)
|
||||
}
|
||||
}
|
||||
@@ -505,9 +501,7 @@ func TestGetNonceMillis(t *testing.T) {
|
||||
r := New("test",
|
||||
new(http.Client),
|
||||
WithLimiter(&globalshell))
|
||||
m1 := r.GetNonceMilli()
|
||||
m2 := r.GetNonceMilli()
|
||||
if m1 == m2 {
|
||||
if m1, m2 := r.GetNonceMilli(), r.GetNonceMilli(); m1 == m2 {
|
||||
log.Fatal(unexpected)
|
||||
}
|
||||
}
|
||||
@@ -562,7 +556,7 @@ func TestBasicLimiter(t *testing.T) {
|
||||
defer cancel()
|
||||
err = r.SendPayload(ctx, Unset, func() (*Item, error) { return &i, nil })
|
||||
if !errors.Is(err, context.DeadlineExceeded) {
|
||||
t.Fatalf("receieved: %v but expected: %v", err, context.DeadlineExceeded)
|
||||
t.Fatalf("received: %v but expected: %v", err, context.DeadlineExceeded)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
)
|
||||
|
||||
func TestDefaultRetryPolicy(t *testing.T) {
|
||||
t.Parallel()
|
||||
type args struct {
|
||||
Error error
|
||||
Response *http.Response
|
||||
@@ -70,6 +71,7 @@ func TestDefaultRetryPolicy(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestRetryAfter(t *testing.T) {
|
||||
t.Parallel()
|
||||
now := time.Date(2020, time.April, 20, 13, 31, 13, 0, time.UTC)
|
||||
|
||||
type args struct {
|
||||
|
||||
@@ -48,8 +48,7 @@ func (m *Match) IncomingWithData(signature interface{}, data []byte) bool {
|
||||
func (m *Match) set(signature interface{}) (matcher, error) {
|
||||
var ch chan []byte
|
||||
m.Lock()
|
||||
_, ok := m.m[signature]
|
||||
if ok {
|
||||
if _, ok := m.m[signature]; ok {
|
||||
m.Unlock()
|
||||
return matcher{}, errors.New("signature collision")
|
||||
}
|
||||
|
||||
@@ -42,9 +42,8 @@ func TestMatch(t *testing.T) {
|
||||
fmt.Println("should not have been able to match")
|
||||
}
|
||||
|
||||
data := <-m.C
|
||||
if data != nil {
|
||||
t.Fatal("wow")
|
||||
if data := <-m.C; data != nil {
|
||||
t.Fatal("data chan should be nil")
|
||||
}
|
||||
|
||||
m.Cleanup()
|
||||
|
||||
@@ -475,8 +475,7 @@ func (w *Websocket) FlushChannels() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
err := w.Shutdown()
|
||||
if err != nil {
|
||||
if err := w.Shutdown(); err != nil {
|
||||
return err
|
||||
}
|
||||
return w.Connect()
|
||||
@@ -867,8 +866,7 @@ func (w *Websocket) SubscribeToChannels(channels []ChannelSubscription) error {
|
||||
}
|
||||
}
|
||||
}
|
||||
err := w.Subscriber(channels)
|
||||
if err != nil {
|
||||
if err := w.Subscriber(channels); err != nil {
|
||||
return fmt.Errorf("%v %w: %v", w.exchangeName, ErrSubscriptionFailure, err)
|
||||
}
|
||||
return nil
|
||||
|
||||
@@ -167,8 +167,7 @@ func TestSetup(t *testing.T) {
|
||||
func TestTrafficMonitorTimeout(t *testing.T) {
|
||||
t.Parallel()
|
||||
ws := *New()
|
||||
err := ws.Setup(defaultSetup)
|
||||
if err != nil {
|
||||
if err := ws.Setup(defaultSetup); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
ws.trafficTimeout = time.Second * 2
|
||||
@@ -650,6 +649,7 @@ func TestDial(t *testing.T) {
|
||||
for i := range testCases {
|
||||
testData := &testCases[i]
|
||||
t.Run(testData.WC.ExchangeName, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
if testData.WC.ProxyURL != "" && !useProxyTests {
|
||||
t.Skip("Proxy testing not enabled, skipping")
|
||||
}
|
||||
@@ -697,6 +697,7 @@ func TestSendMessage(t *testing.T) {
|
||||
for i := range testCases {
|
||||
testData := &testCases[i]
|
||||
t.Run(testData.WC.ExchangeName, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
if testData.WC.ProxyURL != "" && !useProxyTests {
|
||||
t.Skip("Proxy testing not enabled, skipping")
|
||||
}
|
||||
@@ -737,7 +738,7 @@ func TestSendMessageWithResponse(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
go readMessages(wc, t)
|
||||
go readMessages(t, wc)
|
||||
|
||||
request := testRequest{
|
||||
Event: "subscribe",
|
||||
@@ -755,7 +756,8 @@ func TestSendMessageWithResponse(t *testing.T) {
|
||||
}
|
||||
|
||||
// readMessages helper func
|
||||
func readMessages(wc *WebsocketConnection, t *testing.T) {
|
||||
func readMessages(t *testing.T, wc *WebsocketConnection) {
|
||||
t.Helper()
|
||||
timer := time.NewTimer(20 * time.Second)
|
||||
for {
|
||||
select {
|
||||
|
||||
@@ -222,8 +222,7 @@ func (y *Yobit) UpdateTickers(ctx context.Context, a asset.Item) error {
|
||||
|
||||
// UpdateTicker updates and returns the ticker for a currency pair
|
||||
func (y *Yobit) UpdateTicker(ctx context.Context, p currency.Pair, a asset.Item) (*ticker.Price, error) {
|
||||
err := y.UpdateTickers(ctx, a)
|
||||
if err != nil {
|
||||
if err := y.UpdateTickers(ctx, a); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ticker.GetTicker(y.Name, p, a)
|
||||
|
||||
@@ -227,39 +227,39 @@ func (z *ZB) GetSpotKline(ctx context.Context, arg KlinesRequestParams) (KLineRe
|
||||
urlPath := fmt.Sprintf("/%s/%s/%s?%s", zbData, zbAPIVersion, zbKline, vals.Encode())
|
||||
|
||||
var res KLineResponse
|
||||
var rawKlines map[string]interface{}
|
||||
err := z.SendHTTPRequest(ctx, exchange.RestSpot, urlPath, &rawKlines, klineFunc)
|
||||
resp := struct {
|
||||
Data [][]float64 `json:"data"`
|
||||
MoneyType string `json:"moneyType"`
|
||||
Symbol string `json:"symbol"`
|
||||
}{}
|
||||
err := z.SendHTTPRequest(ctx, exchange.RestSpot, urlPath, &resp, klineFunc)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
if rawKlines == nil || rawKlines["symbol"] == nil {
|
||||
return res, errors.New("zb GetSpotKline rawKlines is nil")
|
||||
if resp.Data == nil || resp.Symbol == "" || resp.MoneyType == "" {
|
||||
return res, errors.New("GetSpotKline received empty data")
|
||||
}
|
||||
res.MoneyType = resp.MoneyType
|
||||
res.Symbol = resp.Symbol
|
||||
|
||||
res.Symbol = rawKlines["symbol"].(string)
|
||||
res.MoneyType = rawKlines["moneyType"].(string)
|
||||
for x := range resp.Data {
|
||||
if len(resp.Data[x]) < 6 {
|
||||
return res, errors.New("unexpected kline data length")
|
||||
}
|
||||
|
||||
rawKlineDatasString, _ := json.Marshal(rawKlines["data"].([]interface{}))
|
||||
var rawKlineDatas [][]interface{}
|
||||
if err := json.Unmarshal(rawKlineDatasString, &rawKlineDatas); err != nil {
|
||||
return res, errors.New("zb rawKlines unmarshal failed")
|
||||
}
|
||||
for _, k := range rawKlineDatas {
|
||||
ot, err := convert.TimeFromUnixTimestampFloat(k[0])
|
||||
ot, err := convert.TimeFromUnixTimestampFloat(resp.Data[x][0])
|
||||
if err != nil {
|
||||
return res, errors.New("zb cannot parse Kline.OpenTime")
|
||||
return res, err
|
||||
}
|
||||
res.Data = append(res.Data, &KLineResponseData{
|
||||
ID: k[0].(float64),
|
||||
KlineTime: ot,
|
||||
Open: k[1].(float64),
|
||||
High: k[2].(float64),
|
||||
Low: k[3].(float64),
|
||||
Close: k[4].(float64),
|
||||
Volume: k[5].(float64),
|
||||
Open: resp.Data[x][1],
|
||||
High: resp.Data[x][2],
|
||||
Low: resp.Data[x][3],
|
||||
Close: resp.Data[x][4],
|
||||
Volume: resp.Data[x][5],
|
||||
})
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
@@ -325,7 +325,7 @@ func (z *ZB) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange.URL,
|
||||
var intermediary json.RawMessage
|
||||
newRequest := func() (*request.Item, error) {
|
||||
now := time.Now()
|
||||
params.Set("reqTime", fmt.Sprintf("%d", convert.UnixMillis(now)))
|
||||
params.Set("reqTime", strconv.FormatInt(now.UnixMilli(), 10))
|
||||
params.Set("sign", fmt.Sprintf("%x", hmac))
|
||||
|
||||
urlPath := fmt.Sprintf("%s/%s?%s",
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
//+build !mock_test_off
|
||||
//go:build !mock_test_off
|
||||
// +build !mock_test_off
|
||||
|
||||
// This will build if build tag mock_test_off is not parsed and will try to mock
|
||||
// all tests in _test.go
|
||||
|
||||
@@ -12,7 +12,6 @@ import (
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"github.com/thrasher-corp/gocryptotrader/common/convert"
|
||||
"github.com/thrasher-corp/gocryptotrader/core"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
@@ -35,6 +34,7 @@ var z ZB
|
||||
var wsSetupRan bool
|
||||
|
||||
func setupWsAuth(t *testing.T) {
|
||||
t.Helper()
|
||||
if wsSetupRan {
|
||||
return
|
||||
}
|
||||
@@ -500,8 +500,7 @@ func TestWsTransferFunds(t *testing.T) {
|
||||
// TestGetSubUserList ws test
|
||||
func TestGetSubUserList(t *testing.T) {
|
||||
setupWsAuth(t)
|
||||
_, err := z.wsGetSubUserList()
|
||||
if err != nil {
|
||||
if _, err := z.wsGetSubUserList(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
@@ -833,7 +832,7 @@ func TestGetSpotKline(t *testing.T) {
|
||||
}
|
||||
if mockTests {
|
||||
startTime := time.Date(2020, 9, 1, 0, 0, 0, 0, time.UTC)
|
||||
arg.Since = convert.UnixMillis(startTime)
|
||||
arg.Since = startTime.UnixMilli()
|
||||
arg.Type = "1day"
|
||||
}
|
||||
|
||||
|
||||
@@ -120,7 +120,6 @@ type KlinesRequestParams struct {
|
||||
|
||||
// KLineResponseData Kline Data
|
||||
type KLineResponseData struct {
|
||||
ID float64 `json:"id"` // K线ID
|
||||
KlineTime time.Time `json:"klineTime"`
|
||||
Open float64 `json:"open"` // 开盘价
|
||||
Close float64 `json:"close"` // 收盘价, 当K线为最晚的一根时, 时最新成交价
|
||||
|
||||
@@ -109,7 +109,7 @@ func (z *ZB) wsHandleData(respRaw []byte) error {
|
||||
Last: wsTicker.Data.Last,
|
||||
Bid: wsTicker.Data.Buy,
|
||||
Ask: wsTicker.Data.Sell,
|
||||
LastUpdated: time.Unix(0, wsTicker.Date*int64(time.Millisecond)),
|
||||
LastUpdated: time.UnixMilli(wsTicker.Date),
|
||||
AssetType: asset.Spot,
|
||||
Pair: p,
|
||||
}
|
||||
|
||||
@@ -11,7 +11,6 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"github.com/thrasher-corp/gocryptotrader/common/convert"
|
||||
"github.com/thrasher-corp/gocryptotrader/config"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
@@ -283,8 +282,7 @@ func (z *ZB) UpdateTickers(ctx context.Context, a asset.Item) error {
|
||||
|
||||
// UpdateTicker updates and returns the ticker for a currency pair
|
||||
func (z *ZB) UpdateTicker(ctx context.Context, p currency.Pair, a asset.Item) (*ticker.Price, error) {
|
||||
err := z.UpdateTickers(ctx, a)
|
||||
if err != nil {
|
||||
if err := z.UpdateTickers(ctx, a); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ticker.GetTicker(z.Name, p, a)
|
||||
@@ -389,8 +387,7 @@ func (z *ZB) UpdateAccountInfo(ctx context.Context, assetType asset.Item) (accou
|
||||
Currencies: balances,
|
||||
})
|
||||
|
||||
err := account.Process(&info)
|
||||
if err != nil {
|
||||
if err := account.Process(&info); err != nil {
|
||||
return account.Holdings{}, err
|
||||
}
|
||||
|
||||
@@ -864,7 +861,7 @@ func (z *ZB) GetHistoricCandles(ctx context.Context, p currency.Pair, a asset.It
|
||||
klineParams := KlinesRequestParams{
|
||||
Type: z.FormatExchangeKlineInterval(interval),
|
||||
Symbol: p.String(),
|
||||
Since: convert.UnixMillis(start),
|
||||
Since: start.UnixMilli(),
|
||||
Size: int64(z.Features.Enabled.Kline.ResultLimit),
|
||||
}
|
||||
var candles KLineResponse
|
||||
@@ -909,7 +906,7 @@ allKlines:
|
||||
klineParams := KlinesRequestParams{
|
||||
Type: z.FormatExchangeKlineInterval(interval),
|
||||
Symbol: p.String(),
|
||||
Since: convert.UnixMillis(startTime),
|
||||
Since: startTime.UnixMilli(),
|
||||
Size: int64(z.Features.Enabled.Kline.ResultLimit),
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user