mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-05-16 23:16: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:
@@ -1,5 +1,7 @@
|
||||
build: off
|
||||
|
||||
image: Visual Studio 2019
|
||||
|
||||
clone_folder: c:\gopath\src\github.com\thrasher-corp\gocryptotrader
|
||||
|
||||
cache:
|
||||
@@ -26,7 +28,7 @@ environment:
|
||||
PSQL_SSLMODE: disable
|
||||
PSQL_SKIPSQLCMD: true
|
||||
PSQL_TESTDBNAME: gct_dev_ci
|
||||
stack: go 1.16.x
|
||||
stack: go 1.17.x
|
||||
|
||||
services:
|
||||
- postgresql96
|
||||
@@ -45,11 +47,13 @@ build_script:
|
||||
|
||||
before_test:
|
||||
- cd c:\gopath\src\github.com\thrasher-corp\gocryptotrader
|
||||
- go get
|
||||
- go env
|
||||
- go version
|
||||
- go install
|
||||
|
||||
test_script:
|
||||
# test back-end
|
||||
- go get github.com/golangci/golangci-lint/cmd/golangci-lint@v1.31.0
|
||||
- go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.42.1
|
||||
- '%GOPATH%\bin\golangci-lint.exe run --verbose'
|
||||
- ps: >-
|
||||
if($env:APPVEYOR_SCHEDULED_BUILD -eq 'true') {
|
||||
|
||||
2
.github/workflows/linter.yml
vendored
2
.github/workflows/linter.yml
vendored
@@ -9,4 +9,4 @@ jobs:
|
||||
- name: golangci-lint
|
||||
uses: golangci/golangci-lint-action@v2
|
||||
with:
|
||||
version: v1.31
|
||||
version: v1.42.1
|
||||
|
||||
2
.github/workflows/tests.yml
vendored
2
.github/workflows/tests.yml
vendored
@@ -1,7 +1,7 @@
|
||||
on: [push, pull_request]
|
||||
name: CI
|
||||
env:
|
||||
GO_VERSION: 1.16.x
|
||||
GO_VERSION: 1.17.x
|
||||
jobs:
|
||||
backend-psql:
|
||||
name: GoCryptoTrader back-end with PSQL
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
run:
|
||||
timeout: 2m30s
|
||||
timeout: 3m
|
||||
issues-exit-code: 1
|
||||
tests: true
|
||||
skip-dirs:
|
||||
@@ -25,11 +25,18 @@ linters:
|
||||
# disabled by default linters
|
||||
- asciicheck
|
||||
- bodyclose
|
||||
# - cyclop
|
||||
- depguard
|
||||
- dogsled
|
||||
# - dupl
|
||||
- durationcheck
|
||||
- errname
|
||||
# - errorlint
|
||||
# - exhaustive
|
||||
# - exhaustivestruct
|
||||
- exportloopref
|
||||
# - forbidigo
|
||||
- forcetypeassert
|
||||
# - funlen
|
||||
- gci
|
||||
# - gochecknoglobals
|
||||
@@ -43,31 +50,45 @@ linters:
|
||||
# - goerr113
|
||||
- gofmt
|
||||
# - gofumpt
|
||||
- goheader
|
||||
# - goheader
|
||||
- goimports
|
||||
- golint
|
||||
# - golint // deprecated since 1.41.0, replaced by revive
|
||||
# - gomnd
|
||||
- gomoddirectives
|
||||
- gomodguard
|
||||
- goprintffuncname
|
||||
- gosec
|
||||
# - interfacer
|
||||
# - lll
|
||||
- ifshort
|
||||
# - importas
|
||||
# - interfacer // deprecated by its owner
|
||||
# - lll
|
||||
- makezero
|
||||
# - maligned
|
||||
- misspell
|
||||
- nakedret
|
||||
# - nestif
|
||||
- nilerr
|
||||
# - nlreturn
|
||||
- noctx
|
||||
- nolintlint
|
||||
# - paralleltest
|
||||
# - prealloc
|
||||
- predeclared
|
||||
# - promlinter
|
||||
- revive
|
||||
- rowserrcheck
|
||||
- scopelint
|
||||
- sqlclosecheck
|
||||
# - scopelint // deprecated since v1.39.0, replaced by exportloopref
|
||||
# - sqlclosecheck
|
||||
- stylecheck
|
||||
# - tagliatelle
|
||||
# - testpackage
|
||||
- thelper
|
||||
- tparallel
|
||||
- unconvert
|
||||
- unparam
|
||||
- wastedassign
|
||||
- whitespace
|
||||
# - wrapcheck
|
||||
# - wsl
|
||||
|
||||
linters-settings:
|
||||
|
||||
@@ -18,7 +18,7 @@ matrix:
|
||||
dist: xenial
|
||||
name: 'GoCryptoTrader [back-end] [linux] [64-bit]'
|
||||
go:
|
||||
- 1.15.x
|
||||
- 1.17.x
|
||||
env:
|
||||
- GO111MODULE=on
|
||||
- PSQL_USER=postgres
|
||||
@@ -43,7 +43,7 @@ matrix:
|
||||
dist: xenial
|
||||
name: 'GoCryptoTrader [back-end] [linux] [32-bit]'
|
||||
go:
|
||||
- 1.15.x
|
||||
- 1.17.x
|
||||
env:
|
||||
- GO111MODULE=on
|
||||
- NO_RACE_TEST=1
|
||||
@@ -72,7 +72,7 @@ matrix:
|
||||
os: osx
|
||||
name: 'GoCryptoTrader [back-end] [darwin]'
|
||||
go:
|
||||
- 1.15.x
|
||||
- 1.17.x
|
||||
env:
|
||||
- GO111MODULE=on
|
||||
- PSQL_USER=postgres
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM golang:1.15 as build
|
||||
FROM golang:1.17 as build
|
||||
WORKDIR /go/src/github.com/thrasher-corp/gocryptotrader
|
||||
COPY . .
|
||||
RUN GO111MODULE=on go mod vendor
|
||||
|
||||
18
Makefile
18
Makefile
@@ -1,6 +1,6 @@
|
||||
LDFLAGS = -ldflags "-w -s"
|
||||
GCTPKG = github.com/thrasher-corp/gocryptotrader
|
||||
LINTPKG = github.com/golangci/golangci-lint/cmd/golangci-lint@v1.31.0
|
||||
LINTPKG = github.com/golangci/golangci-lint/cmd/golangci-lint@v1.42.1
|
||||
LINTBIN = $(GOPATH)/bin/golangci-lint
|
||||
GCTLISTENPORT=9050
|
||||
GCTPROFILERLISTENPORT=8085
|
||||
@@ -14,11 +14,11 @@ CONFIG_FLAG = $(if $(CONFIG),-config $(CONFIG),)
|
||||
all: check build
|
||||
|
||||
get:
|
||||
GO111MODULE=on go get $(GCTPKG)
|
||||
go install $(GCTPKG)
|
||||
|
||||
linter:
|
||||
GO111MODULE=on go get $(GCTPKG)
|
||||
GO111MODULE=on go get $(LINTPKG)
|
||||
go install $(GCTPKG)
|
||||
go install $(LINTPKG)
|
||||
test -z "$$($(LINTBIN) run --verbose | tee /dev/stderr)"
|
||||
|
||||
check: linter test
|
||||
@@ -31,19 +31,19 @@ else
|
||||
endif
|
||||
|
||||
build:
|
||||
GO111MODULE=on go build $(LDFLAGS)
|
||||
go build $(LDFLAGS)
|
||||
|
||||
install:
|
||||
GO111MODULE=on go install $(LDFLAGS)
|
||||
go install $(LDFLAGS)
|
||||
|
||||
fmt:
|
||||
gofmt -l -w -s $(shell find . -type f -name '*.go')
|
||||
|
||||
update_deps:
|
||||
GO111MODULE=on go mod verify
|
||||
GO111MODULE=on go mod tidy
|
||||
go mod verify
|
||||
go mod tidy
|
||||
rm -rf vendor
|
||||
GO111MODULE=on go mod vendor
|
||||
go mod vendor
|
||||
|
||||
.PHONY: profile_heap
|
||||
profile_heap:
|
||||
|
||||
@@ -1208,8 +1208,7 @@ func TestValidate(t *testing.T) {
|
||||
},
|
||||
},
|
||||
}
|
||||
err := c.Validate()
|
||||
if !errors.Is(err, nil) {
|
||||
if err := c.Validate(); !errors.Is(err, nil) {
|
||||
t.Errorf("received %v expected %v", err, nil)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -399,8 +399,7 @@ func parseDatabase(reader *bufio.Reader, cfg *config.Config) error {
|
||||
}
|
||||
|
||||
fmt.Printf("What is the end date? Leave blank for \"%v\"\n", defaultStart.Format(gctcommon.SimpleTimeFormat))
|
||||
endDate := quickParse(reader)
|
||||
if endDate != "" {
|
||||
if endDate := quickParse(reader); endDate != "" {
|
||||
cfg.DataSettings.DatabaseData.EndDate, err = time.Parse(endDate, gctcommon.SimpleTimeFormat)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -19,8 +19,7 @@ type fakeDataHandler struct {
|
||||
func TestBaseDataFunctions(t *testing.T) {
|
||||
t.Parallel()
|
||||
var d Base
|
||||
latest := d.Latest()
|
||||
if latest != nil {
|
||||
if latest := d.Latest(); latest != nil {
|
||||
t.Error("expected nil")
|
||||
}
|
||||
d.Next()
|
||||
@@ -37,17 +36,14 @@ func TestBaseDataFunctions(t *testing.T) {
|
||||
if o != 0 {
|
||||
t.Error("expected 0")
|
||||
}
|
||||
list := d.List()
|
||||
if list != nil {
|
||||
if list := d.List(); list != nil {
|
||||
t.Error("expected nil")
|
||||
}
|
||||
history := d.History()
|
||||
if history != nil {
|
||||
if history := d.History(); history != nil {
|
||||
t.Error("expected nil")
|
||||
}
|
||||
d.SetStream(nil)
|
||||
st := d.GetStream()
|
||||
if st != nil {
|
||||
if st := d.GetStream(); st != nil {
|
||||
t.Error("expected nil")
|
||||
}
|
||||
d.Reset()
|
||||
@@ -91,24 +87,24 @@ func TestStream(t *testing.T) {
|
||||
|
||||
d.SortStream()
|
||||
|
||||
f = d.Next().(fakeDataHandler)
|
||||
if f.time != 1 {
|
||||
f, ok := d.Next().(fakeDataHandler)
|
||||
if f.time != 1 || !ok {
|
||||
t.Error("expected 1")
|
||||
}
|
||||
f = d.Next().(fakeDataHandler)
|
||||
if f.time != 2 {
|
||||
f, ok = d.Next().(fakeDataHandler)
|
||||
if f.time != 2 || !ok {
|
||||
t.Error("expected 2")
|
||||
}
|
||||
f = d.Next().(fakeDataHandler)
|
||||
if f.time != 4 {
|
||||
f, ok = d.Next().(fakeDataHandler)
|
||||
if f.time != 4 || !ok {
|
||||
t.Error("expected 4")
|
||||
}
|
||||
f = d.Next().(fakeDataHandler)
|
||||
if f.time != 10 {
|
||||
f, ok = d.Next().(fakeDataHandler)
|
||||
if f.time != 10 || !ok {
|
||||
t.Error("expected 10")
|
||||
}
|
||||
f = d.Next().(fakeDataHandler)
|
||||
if f.time != 20 {
|
||||
f, ok = d.Next().(fakeDataHandler)
|
||||
if f.time != 20 || !ok {
|
||||
t.Error("expected 20")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,8 +81,7 @@ func TestHasDataAtTime(t *testing.T) {
|
||||
},
|
||||
},
|
||||
}
|
||||
err := d.Load()
|
||||
if err != nil {
|
||||
if err := d.Load(); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
|
||||
@@ -28,8 +28,7 @@ func TestAppendEvent(t *testing.T) {
|
||||
func TestNextEvent(t *testing.T) {
|
||||
t.Parallel()
|
||||
e := Holder{Queue: []common.EventHandler{}}
|
||||
ev := e.NextEvent()
|
||||
if ev != nil {
|
||||
if ev := e.NextEvent(); ev != nil {
|
||||
t.Error("expected not ok")
|
||||
}
|
||||
|
||||
|
||||
@@ -58,8 +58,7 @@ func (h *Holding) HasFunds() bool {
|
||||
|
||||
func (h *Holding) update(e fill.Event, f funding.IPairReader) {
|
||||
direction := e.GetDirection()
|
||||
o := e.GetOrder()
|
||||
if o != nil {
|
||||
if o := e.GetOrder(); o != nil {
|
||||
amount := decimal.NewFromFloat(o.Amount)
|
||||
fee := decimal.NewFromFloat(o.Fee)
|
||||
price := decimal.NewFromFloat(o.Price)
|
||||
|
||||
@@ -60,7 +60,7 @@ func TestUpdate(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
t1 := h.Timestamp
|
||||
t1 := h.Timestamp // nolint:ifshort,nolintlint // false positive and triggers only on Windows
|
||||
h.Update(&fill.Fill{
|
||||
Base: event.Base{
|
||||
Time: time.Now(),
|
||||
|
||||
@@ -262,8 +262,7 @@ func (p *Portfolio) addComplianceSnapshot(fillEvent fill.Event) error {
|
||||
return err
|
||||
}
|
||||
prevSnap := complianceManager.GetLatestSnapshot()
|
||||
fo := fillEvent.GetOrder()
|
||||
if fo != nil {
|
||||
if fo := fillEvent.GetOrder(); fo != nil {
|
||||
price := decimal.NewFromFloat(fo.Price)
|
||||
amount := decimal.NewFromFloat(fo.Amount)
|
||||
fee := decimal.NewFromFloat(fo.Fee)
|
||||
|
||||
@@ -376,8 +376,7 @@ func TestAddComplianceSnapshotForTime(t *testing.T) {
|
||||
func TestSerialise(t *testing.T) {
|
||||
t.Parallel()
|
||||
s := Statistic{}
|
||||
_, err := s.Serialise()
|
||||
if err != nil {
|
||||
if _, err := s.Serialise(); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,8 +21,7 @@ import (
|
||||
|
||||
func TestName(t *testing.T) {
|
||||
d := Strategy{}
|
||||
n := d.Name()
|
||||
if n != Name {
|
||||
if n := d.Name(); n != Name {
|
||||
t.Errorf("expected %v", Name)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,9 +55,8 @@ func (s *Strategy) OnSignal(d data.Handler, _ funding.IFundTransferer) (signal.E
|
||||
return nil, err
|
||||
}
|
||||
es.SetPrice(d.Latest().ClosePrice())
|
||||
offset := d.Offset()
|
||||
|
||||
if offset <= int(s.rsiPeriod.IntPart()) {
|
||||
if offset := d.Offset(); offset <= int(s.rsiPeriod.IntPart()) {
|
||||
es.AppendReason("Not enough data for signal generation")
|
||||
es.SetDirection(common.DoNothing)
|
||||
return &es, nil
|
||||
|
||||
@@ -22,8 +22,7 @@ import (
|
||||
func TestName(t *testing.T) {
|
||||
t.Parallel()
|
||||
d := Strategy{}
|
||||
n := d.Name()
|
||||
if n != Name {
|
||||
if n := d.Name(); n != Name {
|
||||
t.Errorf("expected %v", Name)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,8 +23,7 @@ import (
|
||||
func TestName(t *testing.T) {
|
||||
t.Parallel()
|
||||
d := Strategy{}
|
||||
n := d.Name()
|
||||
if n != Name {
|
||||
if n := d.Name(); n != Name {
|
||||
t.Errorf("expected %v", Name)
|
||||
}
|
||||
}
|
||||
@@ -94,8 +93,7 @@ func TestSetCustomSettings(t *testing.T) {
|
||||
func TestOnSignal(t *testing.T) {
|
||||
t.Parallel()
|
||||
s := Strategy{}
|
||||
_, err := s.OnSignal(nil, nil)
|
||||
if !errors.Is(err, errStrategyOnlySupportsSimultaneousProcessing) {
|
||||
if _, err := s.OnSignal(nil, nil); !errors.Is(err, errStrategyOnlySupportsSimultaneousProcessing) {
|
||||
t.Errorf("received: %v, expected: %v", err, errStrategyOnlySupportsSimultaneousProcessing)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,8 +25,7 @@ func TestEvent_GetAssetType(t *testing.T) {
|
||||
e := &Base{
|
||||
AssetType: asset.Spot,
|
||||
}
|
||||
y := e.GetAssetType()
|
||||
if y != asset.Spot {
|
||||
if y := e.GetAssetType(); y != asset.Spot {
|
||||
t.Error("expected spot")
|
||||
}
|
||||
}
|
||||
@@ -36,8 +35,7 @@ func TestEvent_GetExchange(t *testing.T) {
|
||||
e := &Base{
|
||||
Exchange: "test",
|
||||
}
|
||||
y := e.GetExchange()
|
||||
if y != "test" {
|
||||
if y := e.GetExchange(); y != "test" {
|
||||
t.Error("expected test")
|
||||
}
|
||||
}
|
||||
@@ -47,8 +45,7 @@ func TestEvent_GetInterval(t *testing.T) {
|
||||
e := &Base{
|
||||
Interval: gctkline.OneMin,
|
||||
}
|
||||
y := e.GetInterval()
|
||||
if y != gctkline.OneMin {
|
||||
if y := e.GetInterval(); y != gctkline.OneMin {
|
||||
t.Error("expected one minute")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -565,7 +565,10 @@ func addExch(exchName, checkType string, data interface{}, isUpdate bool) error
|
||||
func fillData(exchName, checkType string, data interface{}) (ExchangeInfo, error) {
|
||||
switch checkType {
|
||||
case github:
|
||||
tempData := data.(GithubData)
|
||||
tempData, ok := data.(GithubData)
|
||||
if !ok {
|
||||
return ExchangeInfo{}, errors.New("unable to type assert GithubData")
|
||||
}
|
||||
tempSha, err := getSha(path)
|
||||
if err != nil {
|
||||
return ExchangeInfo{}, err
|
||||
@@ -579,7 +582,10 @@ func fillData(exchName, checkType string, data interface{}) (ExchangeInfo, error
|
||||
},
|
||||
}, nil
|
||||
case htmlScrape:
|
||||
tempData := data.(HTMLScrapingData)
|
||||
tempData, ok := data.(HTMLScrapingData)
|
||||
if !ok {
|
||||
return ExchangeInfo{}, errors.New("unable to type assert HTMLScrapingData")
|
||||
}
|
||||
checkStr, err := checkChangeLog(&tempData)
|
||||
if err != nil {
|
||||
return ExchangeInfo{}, err
|
||||
|
||||
@@ -142,8 +142,7 @@ func TestCheckChangeLog(t *testing.T) {
|
||||
DateFormat: "2006/01/02",
|
||||
RegExp: `^20(\d){2}/(\d){2}/(\d){2}$`,
|
||||
Path: "https://docs.gemini.com/rest-api/#revision-history"}
|
||||
_, err := checkChangeLog(&data)
|
||||
if err != nil {
|
||||
if _, err := checkChangeLog(&data); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
@@ -236,8 +235,7 @@ func TestHTMLScrapeBitmex(t *testing.T) {
|
||||
DateFormat: "Jan-2-2006",
|
||||
RegExp: `([A-Z]{1}[a-z]{2}-\d{1,2}-2\d{3})`,
|
||||
Path: "https://www.bitmex.com/static/md/en-US/apiChangelog"}
|
||||
_, err := htmlScrapeBitmex(&data)
|
||||
if err != nil {
|
||||
if _, err := htmlScrapeBitmex(&data); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
@@ -246,8 +244,7 @@ func TestHTMLScrapeHitBTC(t *testing.T) {
|
||||
t.Parallel()
|
||||
data := HTMLScrapingData{RegExp: `newest version \d{1}.\d{1}`,
|
||||
Path: "https://api.hitbtc.com/"}
|
||||
_, err := htmlScrapeHitBTC(&data)
|
||||
if err != nil {
|
||||
if _, err := htmlScrapeHitBTC(&data); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
@@ -273,8 +270,7 @@ func TestHTMLScrapeBTSE(t *testing.T) {
|
||||
t.Parallel()
|
||||
data := HTMLScrapingData{RegExp: `^version: \d{1}.\d{1}.\d{1}`,
|
||||
Path: "https://api.btcmarkets.net/openapi/info/index.yaml"}
|
||||
_, err := htmlScrapeBTSE(&data)
|
||||
if err != nil {
|
||||
if _, err := htmlScrapeBTSE(&data); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
@@ -283,8 +279,7 @@ func TestHTMLScrapeBTCMarkets(t *testing.T) {
|
||||
t.Parallel()
|
||||
data := HTMLScrapingData{RegExp: `^version: \d{1}.\d{1}.\d{1}`,
|
||||
Path: "https://api.btcmarkets.net/openapi/info/index.yaml"}
|
||||
_, err := htmlScrapeBTCMarkets(&data)
|
||||
if err != nil {
|
||||
if _, err := htmlScrapeBTCMarkets(&data); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
@@ -296,8 +291,7 @@ func TestHTMLScrapeBitflyer(t *testing.T) {
|
||||
TextTokenData: "code",
|
||||
RegExp: `^https://api.bitflyer.com/v\d{1}/$`,
|
||||
Path: "https://lightning.bitflyer.com/docs?lang=en"}
|
||||
_, err := htmlScrapeBitflyer(&data)
|
||||
if err != nil {
|
||||
if _, err := htmlScrapeBitflyer(&data); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
@@ -306,8 +300,7 @@ func TestHTMLScrapeANX(t *testing.T) {
|
||||
t.Parallel()
|
||||
data := HTMLScrapingData{RegExp: `ANX Exchange API v\d{1}`,
|
||||
Path: "https://anxv3.docs.apiary.io/#reference/quickstart-catalog"}
|
||||
_, err := htmlScrapeANX(&data)
|
||||
if err != nil {
|
||||
if _, err := htmlScrapeANX(&data); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
@@ -322,8 +315,7 @@ func TestHTMLPoloniex(t *testing.T) {
|
||||
DateFormat: "2006-01-02",
|
||||
RegExp: `(2\d{3}-\d{1,2}-\d{1,2})`,
|
||||
Path: "https://docs.poloniex.com/#changelog"}
|
||||
_, err := htmlScrapePoloniex(&data)
|
||||
if err != nil {
|
||||
if _, err := htmlScrapePoloniex(&data); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
@@ -338,8 +330,7 @@ func TestHTMLItBit(t *testing.T) {
|
||||
DateFormat: "2006-01-02",
|
||||
RegExp: `^https://api.itbit.com/v\d{1}/$`,
|
||||
Path: "https://api.itbit.com/docs"}
|
||||
_, err := htmlScrapeItBit(&data)
|
||||
if err != nil {
|
||||
if _, err := htmlScrapeItBit(&data); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
@@ -348,8 +339,7 @@ func TestHTMLScrapeExmo(t *testing.T) {
|
||||
t.Parallel()
|
||||
data := HTMLScrapingData{RegExp: `Last updated on [\s\S]*, 20\d{2}`,
|
||||
Path: "https://exmo.com/en/api/"}
|
||||
_, err := htmlScrapeExmo(&data)
|
||||
if err != nil {
|
||||
if _, err := htmlScrapeExmo(&data); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
@@ -358,8 +348,7 @@ func TestHTMLBitstamp(t *testing.T) {
|
||||
t.Parallel()
|
||||
data := HTMLScrapingData{RegExp: `refer to the v\d{1} API for future references.`,
|
||||
Path: "https://www.bitstamp.net/api/"}
|
||||
_, err := htmlScrapeBitstamp(&data)
|
||||
if err != nil {
|
||||
if _, err := htmlScrapeBitstamp(&data); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
@@ -371,8 +360,7 @@ func TestHTMLKraken(t *testing.T) {
|
||||
TextTokenData: "p",
|
||||
RegExp: `URL: https://api.kraken.com/\d{1}/private/Balance`,
|
||||
Path: "https://www.kraken.com/features/api"}
|
||||
_, err := htmlScrapeKraken(&data)
|
||||
if err != nil {
|
||||
if _, err := htmlScrapeKraken(&data); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
@@ -386,8 +374,7 @@ func TestHTMLAlphaPoint(t *testing.T) {
|
||||
TextTokenData: "h3",
|
||||
RegExp: `revised-calls-\d{1}-\d{1}-\d{1}-gt-\d{1}-\d{1}-\d{1}`,
|
||||
Path: "https://alphapoint.github.io/slate/#introduction"}
|
||||
_, err := htmlScrapeAlphaPoint(&data)
|
||||
if err != nil {
|
||||
if _, err := htmlScrapeAlphaPoint(&data); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
@@ -397,8 +384,7 @@ func TestHTMLYobit(t *testing.T) {
|
||||
data := HTMLScrapingData{TokenData: "h2",
|
||||
Key: "id",
|
||||
Path: "https://www.yobit.net/en/api/"}
|
||||
_, err := htmlScrapeYobit(&data)
|
||||
if err != nil {
|
||||
if _, err := htmlScrapeYobit(&data); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
@@ -408,8 +394,7 @@ func TestHTMLScrapeLocalBitcoins(t *testing.T) {
|
||||
data := HTMLScrapingData{TokenData: "div",
|
||||
RegExp: `col-md-12([\s\S]*?)clearfix`,
|
||||
Path: "https://localbitcoins.com/api-docs/"}
|
||||
_, err := htmlScrapeLocalBitcoins(&data)
|
||||
if err != nil {
|
||||
if _, err := htmlScrapeLocalBitcoins(&data); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
@@ -422,8 +407,7 @@ func TestHTMLScrapeOk(t *testing.T) {
|
||||
TokenDataEnd: "./#change-",
|
||||
RegExp: `./#change-\d{8}`,
|
||||
Path: "https://www.okex.com/docs/en/"}
|
||||
_, err := htmlScrapeOk(&data)
|
||||
if err != nil {
|
||||
if _, err := htmlScrapeOk(&data); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
@@ -547,8 +531,7 @@ func TestTrelloGetLists(t *testing.T) {
|
||||
if !areTestAPIKeysSet() {
|
||||
t.Skip()
|
||||
}
|
||||
_, err := trelloGetLists()
|
||||
if err != nil {
|
||||
if _, err := trelloGetLists(); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
@@ -557,8 +540,7 @@ func TestGetAllCards(t *testing.T) {
|
||||
if !areTestAPIKeysSet() {
|
||||
t.Skip()
|
||||
}
|
||||
_, err := trelloGetAllCards()
|
||||
if err != nil {
|
||||
if _, err := trelloGetAllCards(); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
@@ -567,8 +549,7 @@ func TestGetAllChecklists(t *testing.T) {
|
||||
if !areTestAPIKeysSet() {
|
||||
t.Skip()
|
||||
}
|
||||
_, err := trelloGetAllChecklists()
|
||||
if err != nil {
|
||||
if _, err := trelloGetAllChecklists(); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
@@ -580,8 +561,7 @@ func TestTrelloGetAllBoards(t *testing.T) {
|
||||
if trelloBoardID != "" || testBoardName != "" {
|
||||
t.Skip()
|
||||
}
|
||||
_, err := trelloGetBoardID()
|
||||
if err != nil {
|
||||
if _, err := trelloGetBoardID(); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
@@ -590,8 +570,7 @@ func TestCreateNewList(t *testing.T) {
|
||||
if !areTestAPIKeysSet() {
|
||||
t.Skip()
|
||||
}
|
||||
err := trelloCreateNewList()
|
||||
if err != nil {
|
||||
if err := trelloCreateNewList(); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
@@ -600,8 +579,7 @@ func TestTrelloCreateNewCard(t *testing.T) {
|
||||
if !areTestAPIKeysSet() {
|
||||
t.Skip()
|
||||
}
|
||||
err := trelloCreateNewCard()
|
||||
if err != nil {
|
||||
if err := trelloCreateNewCard(); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
@@ -610,8 +588,7 @@ func TestCreateNewChecklist(t *testing.T) {
|
||||
if !areTestAPIKeysSet() {
|
||||
t.Skip()
|
||||
}
|
||||
err := trelloCreateNewChecklist()
|
||||
if err != nil {
|
||||
if err := trelloCreateNewChecklist(); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
@@ -619,8 +596,7 @@ func TestCreateNewChecklist(t *testing.T) {
|
||||
func TestWriteAuthVars(t *testing.T) {
|
||||
if canTestMainFile {
|
||||
trelloCardID = "jdsfl"
|
||||
err := writeAuthVars(testMode)
|
||||
if err != nil {
|
||||
if err := writeAuthVars(testMode); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,8 +38,7 @@ func TestLoad(t *testing.T) {
|
||||
fs := &flag.FlagSet{}
|
||||
fs.String("config", testConfig, "")
|
||||
newCtx := cli.NewContext(testApp, fs, &cli.Context{})
|
||||
err := load(newCtx)
|
||||
if err != nil {
|
||||
if err := load(newCtx); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -951,12 +951,10 @@ func outputToConsole(exchangeResponses []ExchangeResponses) {
|
||||
// disruptFormatting adds in an unused delimiter and strange casing features to
|
||||
// ensure format currency pair is used throughout the code base.
|
||||
func disruptFormatting(p currency.Pair) (currency.Pair, error) {
|
||||
base := p.Base.String()
|
||||
if base == "" {
|
||||
if p.Base.IsEmpty() {
|
||||
return currency.Pair{}, errors.New("cannot disrupt formatting as base is not populated")
|
||||
}
|
||||
quote := p.Quote.String()
|
||||
if quote == "" {
|
||||
if p.Quote.IsEmpty() {
|
||||
return currency.Pair{}, errors.New("cannot disrupt formatting as quote is not populated")
|
||||
}
|
||||
|
||||
|
||||
@@ -24,8 +24,7 @@ func clearScreen() error {
|
||||
}
|
||||
|
||||
func closeConn(conn *grpc.ClientConn, cancel context.CancelFunc) {
|
||||
err := conn.Close()
|
||||
if err != nil {
|
||||
if err := conn.Close(); err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
if cancel != nil {
|
||||
|
||||
6
common/cache/cache_test.go
vendored
6
common/cache/cache_test.go
vendored
@@ -130,16 +130,14 @@ func TestRemove(t *testing.T) {
|
||||
|
||||
func TestGetNewest(t *testing.T) {
|
||||
lruCache := New(2)
|
||||
k, _ := lruCache.getNewest()
|
||||
if k != nil {
|
||||
if k, _ := lruCache.getNewest(); k != nil {
|
||||
t.Fatal("expected GetNewest() on empty cache to return nil")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetOldest(t *testing.T) {
|
||||
lruCache := New(2)
|
||||
k, _ := lruCache.getOldest()
|
||||
if k != nil {
|
||||
if k, _ := lruCache.getOldest(); k != nil {
|
||||
t.Fatal("expected GetOldest() on empty cache to return nil")
|
||||
}
|
||||
}
|
||||
|
||||
9
common/cache/lru.go
vendored
9
common/cache/lru.go
vendored
@@ -47,8 +47,7 @@ func (l *LRU) Get(key interface{}) interface{} {
|
||||
|
||||
// GetOldest returns the oldest entry
|
||||
func (l *LRU) getOldest() (key, value interface{}) {
|
||||
x := l.l.Back()
|
||||
if x != nil {
|
||||
if x := l.l.Back(); x != nil {
|
||||
return x.Value.(*item).key, x.Value.(*item).value
|
||||
}
|
||||
return
|
||||
@@ -56,8 +55,7 @@ func (l *LRU) getOldest() (key, value interface{}) {
|
||||
|
||||
// GetNewest returns the newest entry
|
||||
func (l *LRU) getNewest() (key, value interface{}) {
|
||||
x := l.l.Front()
|
||||
if x != nil {
|
||||
if x := l.l.Front(); x != nil {
|
||||
return x.Value.(*item).key, x.Value.(*item).value
|
||||
}
|
||||
return
|
||||
@@ -93,8 +91,7 @@ func (l *LRU) Len() uint64 {
|
||||
|
||||
// removeOldest removes the oldest item from the cache.
|
||||
func (l *LRU) removeOldestEntry() {
|
||||
i := l.l.Back()
|
||||
if i != nil {
|
||||
if i := l.l.Back(); i != nil {
|
||||
l.removeElement(i)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -248,15 +248,13 @@ func TestStringDataContains(t *testing.T) {
|
||||
originalHaystack := []string{"hello", "world", "USDT", "Contains", "string"}
|
||||
originalNeedle := "USD"
|
||||
anotherNeedle := "thing"
|
||||
expectedOutput := true
|
||||
expectedOutputTwo := false
|
||||
actualResult := StringDataContains(originalHaystack, originalNeedle)
|
||||
if actualResult != expectedOutput {
|
||||
if expectedOutput := true; actualResult != expectedOutput {
|
||||
t.Errorf("Expected '%v'. Actual '%v'",
|
||||
expectedOutput, actualResult)
|
||||
}
|
||||
actualResult = StringDataContains(originalHaystack, anotherNeedle)
|
||||
if actualResult != expectedOutputTwo {
|
||||
if expectedOutput := false; actualResult != expectedOutput {
|
||||
t.Errorf("Expected '%v'. Actual '%v'",
|
||||
expectedOutput, actualResult)
|
||||
}
|
||||
@@ -267,15 +265,13 @@ func TestStringDataCompare(t *testing.T) {
|
||||
originalHaystack := []string{"hello", "WoRld", "USDT", "Contains", "string"}
|
||||
originalNeedle := "WoRld"
|
||||
anotherNeedle := "USD"
|
||||
expectedOutput := true
|
||||
expectedOutputTwo := false
|
||||
actualResult := StringDataCompare(originalHaystack, originalNeedle)
|
||||
if actualResult != expectedOutput {
|
||||
if expectedOutput := true; actualResult != expectedOutput {
|
||||
t.Errorf("Expected '%v'. Actual '%v'",
|
||||
expectedOutput, actualResult)
|
||||
}
|
||||
actualResult = StringDataCompare(originalHaystack, anotherNeedle)
|
||||
if actualResult != expectedOutputTwo {
|
||||
if expectedOutput := false; actualResult != expectedOutput {
|
||||
t.Errorf("Expected '%v'. Actual '%v'",
|
||||
expectedOutput, actualResult)
|
||||
}
|
||||
@@ -286,16 +282,14 @@ func TestStringDataCompareUpper(t *testing.T) {
|
||||
originalHaystack := []string{"hello", "WoRld", "USDT", "Contains", "string"}
|
||||
originalNeedle := "WoRld"
|
||||
anotherNeedle := "WoRldD"
|
||||
expectedOutput := true
|
||||
expectedOutputTwo := false
|
||||
actualResult := StringDataCompareInsensitive(originalHaystack, originalNeedle)
|
||||
if actualResult != expectedOutput {
|
||||
if expectedOutput := true; actualResult != expectedOutput {
|
||||
t.Errorf("Expected '%v'. Actual '%v'",
|
||||
expectedOutput, actualResult)
|
||||
}
|
||||
|
||||
actualResult = StringDataCompareInsensitive(originalHaystack, anotherNeedle)
|
||||
if actualResult != expectedOutputTwo {
|
||||
if expectedOutput := false; actualResult != expectedOutput {
|
||||
t.Errorf("Expected '%v'. Actual '%v'",
|
||||
expectedOutput, actualResult)
|
||||
}
|
||||
@@ -306,15 +300,13 @@ func TestStringDataContainsUpper(t *testing.T) {
|
||||
originalHaystack := []string{"bLa", "BrO", "sUp"}
|
||||
originalNeedle := "Bla"
|
||||
anotherNeedle := "ning"
|
||||
expectedOutput := true
|
||||
expectedOutputTwo := false
|
||||
actualResult := StringDataContainsInsensitive(originalHaystack, originalNeedle)
|
||||
if actualResult != expectedOutput {
|
||||
if expectedOutput := true; actualResult != expectedOutput {
|
||||
t.Errorf("Expected '%v'. Actual '%v'",
|
||||
expectedOutput, actualResult)
|
||||
}
|
||||
actualResult = StringDataContainsInsensitive(originalHaystack, anotherNeedle)
|
||||
if actualResult != expectedOutputTwo {
|
||||
if expectedOutput := false; actualResult != expectedOutput {
|
||||
t.Errorf("Expected '%v'. Actual '%v'",
|
||||
expectedOutput, actualResult)
|
||||
}
|
||||
@@ -410,8 +402,7 @@ func TestGetURIPath(t *testing.T) {
|
||||
|
||||
func TestGetExecutablePath(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := GetExecutablePath()
|
||||
if err != nil {
|
||||
if _, err := GetExecutablePath(); err != nil {
|
||||
t.Errorf("Common GetExecutablePath. Error: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ func TimeFromUnixTimestampFloat(raw interface{}) (time.Time, error) {
|
||||
if !ok {
|
||||
return time.Time{}, fmt.Errorf("unable to parse, value not float64: %T", raw)
|
||||
}
|
||||
return time.Unix(0, int64(ts)*int64(time.Millisecond)), nil
|
||||
return time.UnixMilli(int64(ts)), nil
|
||||
}
|
||||
|
||||
// TimeFromUnixTimestampDecimal converts a unix timestamp in decimal form to
|
||||
@@ -76,23 +76,8 @@ func UnixTimestampStrToTime(timeStr string) (time.Time, error) {
|
||||
return time.Unix(i, 0), nil
|
||||
}
|
||||
|
||||
// UnixMillis converts a UnixNano timestamp to milliseconds
|
||||
func UnixMillis(t time.Time) int64 {
|
||||
return t.UnixNano() / int64(time.Millisecond)
|
||||
}
|
||||
|
||||
// RecvWindow converts a supplied time.Duration to milliseconds
|
||||
func RecvWindow(d time.Duration) int64 {
|
||||
return int64(d) / int64(time.Millisecond)
|
||||
}
|
||||
|
||||
// BoolPtr takes in boolen condition and returns pointer version of it
|
||||
func BoolPtr(condition bool) *bool {
|
||||
b := condition
|
||||
return &b
|
||||
}
|
||||
|
||||
// UnixMillisToNano converts Unix milli time to UnixNano
|
||||
func UnixMillisToNano(milli int64) int64 {
|
||||
return milli * int64(time.Millisecond)
|
||||
}
|
||||
|
||||
@@ -32,10 +32,8 @@ func TestFloatFromString(t *testing.T) {
|
||||
func TestIntFromString(t *testing.T) {
|
||||
t.Parallel()
|
||||
testString := "1337"
|
||||
expectedOutput := 1337
|
||||
|
||||
actualOutput, err := IntFromString(testString)
|
||||
if actualOutput != expectedOutput || err != nil {
|
||||
if expectedOutput := 1337; actualOutput != expectedOutput || err != nil {
|
||||
t.Errorf("Common IntFromString. Expected '%v'. Actual '%v'. Error: %s",
|
||||
expectedOutput, actualOutput, err)
|
||||
}
|
||||
@@ -136,33 +134,9 @@ func TestUnixTimestampStrToTime(t *testing.T) {
|
||||
t.Errorf(
|
||||
"Expected '%s'. Actual '%s'.", expectedOutput, actualResult)
|
||||
}
|
||||
actualResult, err = UnixTimestampStrToTime(incorrectTime)
|
||||
_, err = UnixTimestampStrToTime(incorrectTime)
|
||||
if err == nil {
|
||||
t.Error("Common UnixTimestampStrToTime error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnixMillis(t *testing.T) {
|
||||
t.Parallel()
|
||||
testTime := time.Date(2014, time.October, 28, 0, 32, 0, 0, time.UTC)
|
||||
expectedOutput := int64(1414456320000)
|
||||
|
||||
actualOutput := UnixMillis(testTime)
|
||||
if actualOutput != expectedOutput {
|
||||
t.Errorf("Common UnixMillis. Expected '%d'. Actual '%d'.",
|
||||
expectedOutput, actualOutput)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRecvWindow(t *testing.T) {
|
||||
t.Parallel()
|
||||
testTime := time.Duration(24760000)
|
||||
expectedOutput := int64(24)
|
||||
|
||||
actualOutput := RecvWindow(testTime)
|
||||
if actualOutput != expectedOutput {
|
||||
t.Errorf("Common RecvWindow. Expected '%d'. Actual '%d'",
|
||||
expectedOutput, actualOutput)
|
||||
t.Error("should throw an error")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -176,10 +150,3 @@ func TestBoolPtr(t *testing.T) {
|
||||
t.Fatal("false expected received true")
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnixMillisToNano(t *testing.T) {
|
||||
v := UnixMillisToNano(1588653603424)
|
||||
if v != 1588653603424000000 {
|
||||
t.Fatalf("unexpected result received %v", v)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,9 +35,8 @@ func TestBase64Decode(t *testing.T) {
|
||||
func TestBase64Encode(t *testing.T) {
|
||||
t.Parallel()
|
||||
originalInput := []byte("hello")
|
||||
expectedOutput := "aGVsbG8="
|
||||
actualResult := Base64Encode(originalInput)
|
||||
if actualResult != expectedOutput {
|
||||
if expectedOutput := "aGVsbG8="; actualResult != expectedOutput {
|
||||
t.Errorf("Expected '%s'. Actual '%s'",
|
||||
expectedOutput, actualResult)
|
||||
}
|
||||
|
||||
@@ -80,8 +80,7 @@ func TestZip(t *testing.T) {
|
||||
if filepath.Base(o[0]) != "binance.json" || filepath.Base(o[4]) != "localbitcoins.json" {
|
||||
t.Fatal("unexpected archive result received")
|
||||
}
|
||||
expected := 7
|
||||
if len(o) != expected {
|
||||
if expected := 7; len(o) != expected {
|
||||
t.Fatalf("expected %v files to be extracted received: %v ", expected, len(o))
|
||||
}
|
||||
|
||||
|
||||
@@ -116,8 +116,7 @@ func WriteAsCSV(filename string, records [][]string) error {
|
||||
|
||||
w.Flush()
|
||||
|
||||
err := w.Error()
|
||||
if err != nil {
|
||||
if err := w.Error(); err != nil {
|
||||
return err
|
||||
}
|
||||
return Write(filename, buf.Bytes())
|
||||
|
||||
@@ -12,9 +12,7 @@ func TestCalculateFee(t *testing.T) {
|
||||
t.Parallel()
|
||||
originalInput := float64(1)
|
||||
fee := float64(1)
|
||||
expectedOutput := 0.01
|
||||
actualResult := CalculateFee(originalInput, fee)
|
||||
if expectedOutput != actualResult {
|
||||
if expectedOutput, actualResult := 0.01, CalculateFee(originalInput, fee); expectedOutput != actualResult {
|
||||
t.Errorf(
|
||||
"Expected '%f'. Actual '%f'.", expectedOutput, actualResult)
|
||||
}
|
||||
@@ -24,9 +22,7 @@ func TestCalculateAmountWithFee(t *testing.T) {
|
||||
t.Parallel()
|
||||
originalInput := float64(1)
|
||||
fee := float64(1)
|
||||
expectedOutput := 1.01
|
||||
actualResult := CalculateAmountWithFee(originalInput, fee)
|
||||
if expectedOutput != actualResult {
|
||||
if actualResult, expectedOutput := CalculateAmountWithFee(originalInput, fee), 1.01; expectedOutput != actualResult {
|
||||
t.Errorf(
|
||||
"Expected '%f'. Actual '%f'.", expectedOutput, actualResult)
|
||||
}
|
||||
@@ -62,9 +58,8 @@ func TestCalculateNetProfit(t *testing.T) {
|
||||
priceThen := float64(1)
|
||||
priceNow := float64(10)
|
||||
costs := float64(1)
|
||||
expectedOutput := float64(44)
|
||||
actualResult := CalculateNetProfit(amount, priceThen, priceNow, costs)
|
||||
if expectedOutput != actualResult {
|
||||
if expectedOutput := float64(44); expectedOutput != actualResult {
|
||||
t.Errorf(
|
||||
"Expected '%f'. Actual '%f'.", expectedOutput, actualResult)
|
||||
}
|
||||
@@ -164,8 +159,7 @@ func TestSortinoRatio(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
rr := math.Round(r*10) / 10
|
||||
if rr != 0.2 {
|
||||
if rr := math.Round(r*10) / 10; rr != 0.2 {
|
||||
t.Errorf("expected 0.2, received %v", rr)
|
||||
}
|
||||
}
|
||||
@@ -538,8 +532,7 @@ func TestDecimalSortinoRatio(t *testing.T) {
|
||||
if err != nil && !errors.Is(err, ErrInexactConversion) {
|
||||
t.Error(err)
|
||||
}
|
||||
rr := r.Round(1)
|
||||
if !rr.Equal(decimal.NewFromFloat(0.2)) {
|
||||
if rr := r.Round(1); !rr.Equal(decimal.NewFromFloat(0.2)) {
|
||||
t.Errorf("expected 0.2, received %v", rr)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,7 +100,6 @@ func (t *TimePeriodCalculator) calculateRanges() {
|
||||
}
|
||||
tr.HasDataInRange = t.TimePeriods[len(t.TimePeriods)-1].dataInRange
|
||||
t.TimeRanges = append(t.TimeRanges, tr)
|
||||
tr = TimeRange{}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,8 +8,7 @@ import (
|
||||
|
||||
func TestNewComm(t *testing.T) {
|
||||
var cfg base.CommunicationsConfig
|
||||
_, err := NewComm(&cfg)
|
||||
if err == nil {
|
||||
if _, err := NewComm(&cfg); err == nil {
|
||||
t.Error("NewComm should have failed on no enabled communication mediums")
|
||||
}
|
||||
|
||||
|
||||
@@ -67,8 +67,7 @@ func (s *Slack) Setup(cfg *base.CommunicationsConfig) {
|
||||
|
||||
// Connect connects to the service
|
||||
func (s *Slack) Connect() error {
|
||||
err := s.NewConnection()
|
||||
if err != nil {
|
||||
if err := s.NewConnection(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
@@ -25,8 +25,7 @@ func TestSetup(t *testing.T) {
|
||||
func TestConnect(t *testing.T) {
|
||||
t.Parallel()
|
||||
var s Slack
|
||||
err := s.Connect()
|
||||
if err == nil {
|
||||
if err := s.Connect(); err == nil {
|
||||
t.Error("slack Connect() error cannot be nil")
|
||||
}
|
||||
}
|
||||
@@ -43,8 +42,7 @@ func TestPushEvent(t *testing.T) {
|
||||
func TestBuildURL(t *testing.T) {
|
||||
t.Parallel()
|
||||
var s Slack
|
||||
v := s.BuildURL("lol123")
|
||||
if v != "https://slack.com/api/rtm.start?token=lol123" {
|
||||
if v := s.BuildURL("lol123"); v != "https://slack.com/api/rtm.start?token=lol123" {
|
||||
t.Error("slack BuildURL() error")
|
||||
}
|
||||
}
|
||||
@@ -183,8 +181,7 @@ func TestGetUsersInGroup(t *testing.T) {
|
||||
func TestNewConnection(t *testing.T) {
|
||||
t.Parallel()
|
||||
var s Slack
|
||||
err := s.NewConnection()
|
||||
if err == nil {
|
||||
if err := s.NewConnection(); err == nil {
|
||||
t.Error("slack NewConnection() error")
|
||||
}
|
||||
}
|
||||
@@ -192,8 +189,7 @@ func TestNewConnection(t *testing.T) {
|
||||
func TestWebsocketConnect(t *testing.T) {
|
||||
t.Parallel()
|
||||
var s Slack
|
||||
err := s.WebsocketConnect()
|
||||
if err == nil {
|
||||
if err := s.WebsocketConnect(); err == nil {
|
||||
t.Error("slack WebsocketConnect() error")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,9 +18,8 @@ func TestSetup(t *testing.T) {
|
||||
func TestConnect(t *testing.T) {
|
||||
t.Parallel()
|
||||
var s SMSGlobal
|
||||
err := s.Connect()
|
||||
if err != nil {
|
||||
t.Error("SMSGlobal Connect() error", err)
|
||||
if err := s.Connect(); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,9 +42,8 @@ func TestGetEnabledContacts(t *testing.T) {
|
||||
},
|
||||
},
|
||||
}
|
||||
v := s.GetEnabledContacts()
|
||||
if v != 1 {
|
||||
t.Error("SMSGlobal GetEnabledContacts() error")
|
||||
if v := s.GetEnabledContacts(); v != 1 {
|
||||
t.Error("expected one enabled contact")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,8 +17,7 @@ func TestSetup(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestConnect(t *testing.T) {
|
||||
err := s.Connect()
|
||||
if err != nil {
|
||||
if err := s.Connect(); err != nil {
|
||||
t.Error("smtpservice Connect() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,9 +36,8 @@ func TestSetup(t *testing.T) {
|
||||
func TestConnect(t *testing.T) {
|
||||
t.Parallel()
|
||||
var T Telegram
|
||||
err := T.Connect()
|
||||
if err == nil {
|
||||
t.Error("telegram Connect() error")
|
||||
if err := T.Connect(); err == nil {
|
||||
t.Error("expected error")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,8 +90,7 @@ func TestHandleMessages(t *testing.T) {
|
||||
func TestGetUpdates(t *testing.T) {
|
||||
t.Parallel()
|
||||
var T Telegram
|
||||
_, err := T.GetUpdates()
|
||||
if err != nil {
|
||||
if _, err := T.GetUpdates(); err != nil {
|
||||
t.Error("telegram GetUpdates() error", err)
|
||||
}
|
||||
}
|
||||
@@ -100,10 +98,8 @@ func TestGetUpdates(t *testing.T) {
|
||||
func TestTestConnection(t *testing.T) {
|
||||
t.Parallel()
|
||||
var T Telegram
|
||||
err := T.TestConnection()
|
||||
if err.Error() != testErrNotFound {
|
||||
t.Errorf("telegram TestConnection() error, expected 'Not found' got '%s'",
|
||||
err)
|
||||
if err := T.TestConnection(); err.Error() != testErrNotFound {
|
||||
t.Errorf("received %s, expected: %s", err, testErrNotFound)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1870,7 +1870,7 @@ func (c *Config) AssetTypeEnabled(a asset.Item, exch string) (bool, error) {
|
||||
|
||||
err = cfg.CurrencyPairs.IsAssetEnabled(a)
|
||||
if err != nil {
|
||||
return false, nil
|
||||
return false, nil // nolint:nilerr // non-fatal error
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
@@ -34,8 +34,7 @@ func promptForConfigEncryption() (bool, error) {
|
||||
log.Println("Would you like to encrypt your config file (y/n)?")
|
||||
|
||||
input := ""
|
||||
_, err := fmt.Scanln(&input)
|
||||
if err != nil {
|
||||
if _, err := fmt.Scanln(&input); err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
@@ -194,8 +193,7 @@ func ConfirmECS(file []byte) bool {
|
||||
// or errors, if the prefix wasn't found
|
||||
func skipECS(file io.Reader) error {
|
||||
buf := make([]byte, len(EncryptConfirmString))
|
||||
_, err := io.ReadFull(file, buf)
|
||||
if err != nil {
|
||||
if _, err := io.ReadFull(file, buf); err != nil {
|
||||
return err
|
||||
}
|
||||
if string(buf) != EncryptConfirmString {
|
||||
|
||||
@@ -130,8 +130,7 @@ func TestRemoveECS(t *testing.T) {
|
||||
func TestMakeNewSessionDK(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
_, _, err := makeNewSessionDK(nil)
|
||||
if err == nil {
|
||||
if _, _, err := makeNewSessionDK(nil); err == nil {
|
||||
t.Fatal("makeNewSessionDK passed with nil key")
|
||||
}
|
||||
}
|
||||
@@ -238,6 +237,7 @@ func TestSaveAndReopenEncryptedConfig(t *testing.T) {
|
||||
// setAnswersFile sets the given file as the current stdin
|
||||
// returns the close function to defer for reverting the stdin
|
||||
func setAnswersFile(t *testing.T, answerFile string) func() {
|
||||
t.Helper()
|
||||
oldIn := os.Stdin
|
||||
|
||||
inputFile, err := os.Open(answerFile)
|
||||
@@ -359,6 +359,7 @@ func TestSaveConfigToFileWithErrorInPasswordPrompt(t *testing.T) {
|
||||
}
|
||||
|
||||
func withInteractiveResponse(t *testing.T, response string, body func() error) error {
|
||||
t.Helper()
|
||||
// Answers to the prompt
|
||||
responseFile, err := ioutil.TempFile("", "*.in")
|
||||
if err != nil {
|
||||
|
||||
@@ -35,8 +35,7 @@ func TestGetNonExistentDefaultFilePathDoesNotCreateDefaultDir(t *testing.T) {
|
||||
if file.Exists(dir) {
|
||||
t.Skip("The default directory already exists before running the test")
|
||||
}
|
||||
_, _, err := GetFilePath("")
|
||||
if err != nil {
|
||||
if _, _, err := GetFilePath(""); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if file.Exists(dir) {
|
||||
@@ -921,7 +920,7 @@ func TestSupportsPair(t *testing.T) {
|
||||
},
|
||||
},
|
||||
}
|
||||
assetType := asset.Spot
|
||||
assetType := asset.Spot // nolint // ifshort false positive
|
||||
if cfg.SupportsPair("asdf",
|
||||
currency.NewPair(currency.BTC, currency.USD), assetType) {
|
||||
t.Error(
|
||||
@@ -1284,7 +1283,7 @@ func TestGetForexProviders(t *testing.T) {
|
||||
|
||||
func TestGetPrimaryForexProvider(t *testing.T) {
|
||||
t.Parallel()
|
||||
fxr := "Fixer"
|
||||
fxr := "Fixer" // nolint:ifshort,nolintlint // false positive and triggers only on Windows
|
||||
cfg := &Config{
|
||||
Currency: CurrencyConfig{
|
||||
ForexProviders: []currency.FXSettings{
|
||||
@@ -1937,8 +1936,7 @@ func TestCheckConfig(t *testing.T) {
|
||||
},
|
||||
},
|
||||
}
|
||||
err := cfg.CheckConfig()
|
||||
if err != nil {
|
||||
if err := cfg.CheckConfig(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
@@ -2209,6 +2207,7 @@ func TestRemoveExchange(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetDataPath(t *testing.T) {
|
||||
t.Parallel()
|
||||
tests := []struct {
|
||||
name string
|
||||
dir string
|
||||
@@ -2238,6 +2237,7 @@ func TestGetDataPath(t *testing.T) {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
t.Helper()
|
||||
c := &Config{
|
||||
DataDirectory: tt.dir,
|
||||
}
|
||||
@@ -2278,6 +2278,7 @@ func TestMigrateConfig(t *testing.T) {
|
||||
{
|
||||
name: "source present, no target dir",
|
||||
setup: func(t *testing.T) {
|
||||
t.Helper()
|
||||
test, err := os.Create("test.json")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -2285,6 +2286,7 @@ func TestMigrateConfig(t *testing.T) {
|
||||
test.Close()
|
||||
},
|
||||
cleanup: func(t *testing.T) {
|
||||
t.Helper()
|
||||
os.Remove("test.json")
|
||||
},
|
||||
args: args{
|
||||
@@ -2297,6 +2299,7 @@ func TestMigrateConfig(t *testing.T) {
|
||||
{
|
||||
name: "source same as target",
|
||||
setup: func(t *testing.T) {
|
||||
t.Helper()
|
||||
err := file.Write(filepath.Join(dir, File), nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -2312,6 +2315,7 @@ func TestMigrateConfig(t *testing.T) {
|
||||
{
|
||||
name: "source and target present",
|
||||
setup: func(t *testing.T) {
|
||||
t.Helper()
|
||||
err := file.Write(filepath.Join(dir, File), nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
||||
@@ -48,8 +48,7 @@ func New(dnsList, domainList []string, checkInterval time.Duration) (*Checker, e
|
||||
c.CheckInterval = checkInterval
|
||||
}
|
||||
|
||||
err := c.initialCheck()
|
||||
if err != nil {
|
||||
if err := c.initialCheck(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
||||
@@ -51,8 +51,7 @@ func TestRoleMarshalJSON(t *testing.T) {
|
||||
t.Error("Role MarshalJSON() error", err)
|
||||
}
|
||||
|
||||
expected := `"fiatCurrency"`
|
||||
if string(d) != expected {
|
||||
if expected := `"fiatCurrency"`; string(d) != expected {
|
||||
t.Errorf("Role MarshalJSON() error expected %s but received %s",
|
||||
expected,
|
||||
string(d))
|
||||
@@ -337,18 +336,14 @@ func TestBaseCode(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCodeString(t *testing.T) {
|
||||
expected := "TEST"
|
||||
cc := NewCode("TEST")
|
||||
if cc.String() != expected {
|
||||
if cc, expected := NewCode("TEST"), "TEST"; cc.String() != expected {
|
||||
t.Errorf("Currency Code String() error expected %s but received %s",
|
||||
expected, cc)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCodeLower(t *testing.T) {
|
||||
expected := "test"
|
||||
cc := NewCode("TEST")
|
||||
if cc.Lower().String() != expected {
|
||||
if cc, expected := NewCode("TEST"), "test"; cc.Lower().String() != expected {
|
||||
t.Errorf("Currency Code Lower() error expected %s but received %s",
|
||||
expected,
|
||||
cc.Lower())
|
||||
@@ -356,9 +351,7 @@ func TestCodeLower(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCodeUpper(t *testing.T) {
|
||||
expected := "TEST"
|
||||
cc := NewCode("test")
|
||||
if cc.Upper().String() != expected {
|
||||
if cc, expected := NewCode("test"), "TEST"; cc.Upper().String() != expected {
|
||||
t.Errorf("Currency Code Upper() error expected %s but received %s",
|
||||
expected,
|
||||
cc.Upper())
|
||||
|
||||
@@ -33,14 +33,13 @@ func TestNewConversionFromString(t *testing.T) {
|
||||
func TestNewConversionFromStrings(t *testing.T) {
|
||||
from := "AUD"
|
||||
to := "USD"
|
||||
expected := "AUDUSD"
|
||||
|
||||
conv, err := NewConversionFromStrings(from, to)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if conv.String() != expected {
|
||||
if expected := "AUDUSD"; conv.String() != expected {
|
||||
t.Errorf("NewConversion() error expected %s but received %s",
|
||||
expected,
|
||||
conv)
|
||||
@@ -50,14 +49,13 @@ func TestNewConversionFromStrings(t *testing.T) {
|
||||
func TestNewConversion(t *testing.T) {
|
||||
from := NewCode("AUD")
|
||||
to := NewCode("USD")
|
||||
expected := "AUDUSD"
|
||||
|
||||
conv, err := NewConversion(from, to)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if conv.String() != expected {
|
||||
if expected := "AUDUSD"; conv.String() != expected {
|
||||
t.Errorf("NewConversion() error expected %s but received %s",
|
||||
expected,
|
||||
conv)
|
||||
@@ -79,8 +77,7 @@ func TestConversionIsInvalid(t *testing.T) {
|
||||
}
|
||||
|
||||
to = AUD
|
||||
conv, err = NewConversion(from, to)
|
||||
if err == nil {
|
||||
if _, err = NewConversion(from, to); err == nil {
|
||||
t.Error("Expected error")
|
||||
}
|
||||
}
|
||||
@@ -100,8 +97,7 @@ func TestConversionIsFiatPair(t *testing.T) {
|
||||
}
|
||||
|
||||
to = LTC
|
||||
conv, err = NewConversion(from, to)
|
||||
if err == nil {
|
||||
if _, err = NewConversion(from, to); err == nil {
|
||||
t.Error("Expected error")
|
||||
}
|
||||
}
|
||||
@@ -159,17 +155,16 @@ func TestConversionsRatesSystem(t *testing.T) {
|
||||
p := SuperDuperConversionSystem.m[USD.Item][AUD.Item]
|
||||
// inverse * to a rate
|
||||
pi := SuperDuperConversionSystem.m[AUD.Item][USD.Item]
|
||||
r := *p * 1000
|
||||
|
||||
expectedRate := 1396.9317581
|
||||
if r != expectedRate {
|
||||
if r := *p * 1000; r != expectedRate {
|
||||
t.Errorf("Convert() error expected %.13f but received %.13f",
|
||||
expectedRate,
|
||||
r)
|
||||
}
|
||||
|
||||
inverseR := *pi * expectedRate
|
||||
expectedInverseRate := float64(1000)
|
||||
if inverseR != expectedInverseRate {
|
||||
if inverseR := *pi * expectedRate; inverseR != expectedInverseRate {
|
||||
t.Errorf("Convert() error expected %.13f but received %.13f",
|
||||
expectedInverseRate,
|
||||
inverseR)
|
||||
|
||||
@@ -93,7 +93,7 @@ func CopyPairFormat(p Pair, pairs []Pair, exact bool) Pair {
|
||||
return pairs[x]
|
||||
}
|
||||
}
|
||||
return Pair{Base: NewCode(""), Quote: NewCode("")}
|
||||
return Pair{}
|
||||
}
|
||||
|
||||
// FormatPairs formats a string array to a list of currency pairs with the
|
||||
|
||||
@@ -63,8 +63,7 @@ func (c *CurrencyConverter) GetRates(baseCurrency, symbols string) (map[string]f
|
||||
}
|
||||
|
||||
currLen := len(completedStrings)
|
||||
mod := currLen % 2
|
||||
if mod == 0 {
|
||||
if mod := currLen % 2; mod == 0 {
|
||||
processBatch(currLen)
|
||||
return rates, nil
|
||||
}
|
||||
|
||||
@@ -74,8 +74,7 @@ func TestConvert(t *testing.T) {
|
||||
t.Skip()
|
||||
}
|
||||
|
||||
_, err := c.Convert("AUD", "USD")
|
||||
if err != nil {
|
||||
if _, err := c.Convert("AUD", "USD"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
@@ -96,8 +95,7 @@ func TestGetCountries(t *testing.T) {
|
||||
t.Skip()
|
||||
}
|
||||
|
||||
_, err := c.GetCountries()
|
||||
if err != nil {
|
||||
if _, err := c.GetCountries(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -211,8 +211,7 @@ func TestGetRates(t *testing.T) {
|
||||
t.Skip("API key not set, skipping test")
|
||||
}
|
||||
|
||||
_, err := e.GetRates("EUR", "")
|
||||
if err != nil {
|
||||
if _, err := e.GetRates("EUR", ""); err != nil {
|
||||
t.Fatalf("failed to GetRates. Err: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ var f Fixer
|
||||
var isSetup bool
|
||||
|
||||
func setup(t *testing.T) {
|
||||
t.Helper()
|
||||
if !isSetup {
|
||||
err := f.Setup(base.Settings{})
|
||||
if err != nil {
|
||||
|
||||
@@ -88,8 +88,7 @@ func TestGetOHLC(t *testing.T) {
|
||||
|
||||
func TestGetUsageStats(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := o.GetUsageStats(false)
|
||||
if err == nil {
|
||||
if _, err := o.GetUsageStats(false); err == nil {
|
||||
t.Error("GetUsageStats() Expected error")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
var p PairsManager
|
||||
|
||||
func initTest(t *testing.T) {
|
||||
t.Helper()
|
||||
spotAvailable, err := NewPairsFromStrings([]string{"BTC-USD", "LTC-USD"})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
||||
@@ -16,13 +16,11 @@ func TestLower(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
actual := pair.Lower()
|
||||
expected, err := NewPairFromString(defaultPair)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if actual.String() != expected.Lower().String() {
|
||||
if actual := pair.Lower(); actual.String() != expected.Lower().String() {
|
||||
t.Errorf("Lower(): %s was not equal to expected value: %s",
|
||||
actual,
|
||||
expected.Lower())
|
||||
@@ -35,12 +33,11 @@ func TestUpper(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
actual := pair.Upper()
|
||||
expected, err := NewPairFromString(defaultPair)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if actual.String() != expected.String() {
|
||||
if actual := pair.Upper(); actual.String() != expected.String() {
|
||||
t.Errorf("Upper(): %s was not equal to expected value: %s",
|
||||
actual, expected)
|
||||
}
|
||||
@@ -126,9 +123,7 @@ func TestIsFiatPair(t *testing.T) {
|
||||
func TestString(t *testing.T) {
|
||||
t.Parallel()
|
||||
pair := NewPair(BTC, USD)
|
||||
actual := defaultPair
|
||||
expected := pair.String()
|
||||
if actual != expected {
|
||||
if actual, expected := defaultPair, pair.String(); actual != expected {
|
||||
t.Errorf("String(): %s was not equal to expected value: %s",
|
||||
actual, expected)
|
||||
}
|
||||
@@ -137,9 +132,7 @@ func TestString(t *testing.T) {
|
||||
func TestFirstCurrency(t *testing.T) {
|
||||
t.Parallel()
|
||||
pair := NewPair(BTC, USD)
|
||||
actual := pair.Base
|
||||
expected := BTC
|
||||
if actual != expected {
|
||||
if actual, expected := pair.Base, BTC; actual != expected {
|
||||
t.Errorf(
|
||||
"GetFirstCurrency(): %s was not equal to expected value: %s",
|
||||
actual, expected,
|
||||
@@ -150,9 +143,7 @@ func TestFirstCurrency(t *testing.T) {
|
||||
func TestSecondCurrency(t *testing.T) {
|
||||
t.Parallel()
|
||||
pair := NewPair(BTC, USD)
|
||||
actual := pair.Quote
|
||||
expected := USD
|
||||
if actual != expected {
|
||||
if actual, expected := pair.Quote, USD; actual != expected {
|
||||
t.Errorf(
|
||||
"GetSecondCurrency(): %s was not equal to expected value: %s",
|
||||
actual, expected,
|
||||
@@ -163,9 +154,7 @@ func TestSecondCurrency(t *testing.T) {
|
||||
func TestPair(t *testing.T) {
|
||||
t.Parallel()
|
||||
pair := NewPair(BTC, USD)
|
||||
actual := pair.String()
|
||||
expected := defaultPair
|
||||
if actual != expected {
|
||||
if actual, expected := pair.String(), defaultPair; actual != expected {
|
||||
t.Errorf(
|
||||
"Pair(): %s was not equal to expected value: %s",
|
||||
actual, expected,
|
||||
@@ -282,9 +271,7 @@ func TestEqualIncludeReciprocal(t *testing.T) {
|
||||
func TestSwap(t *testing.T) {
|
||||
t.Parallel()
|
||||
pair := NewPair(BTC, USD)
|
||||
actual := pair.Swap().String()
|
||||
expected := "USDBTC"
|
||||
if actual != expected {
|
||||
if actual, expected := pair.Swap().String(), "USDBTC"; actual != expected {
|
||||
t.Errorf(
|
||||
"TestSwap: %s was not equal to expected value: %s",
|
||||
actual, expected,
|
||||
@@ -308,9 +295,7 @@ func TestEmpty(t *testing.T) {
|
||||
func TestNewPair(t *testing.T) {
|
||||
t.Parallel()
|
||||
pair := NewPair(BTC, USD)
|
||||
actual := pair.String()
|
||||
expected := defaultPair
|
||||
if actual != expected {
|
||||
if expected, actual := defaultPair, pair.String(); actual != expected {
|
||||
t.Errorf(
|
||||
"Pair(): %s was not equal to expected value: %s",
|
||||
actual, expected,
|
||||
|
||||
@@ -185,11 +185,8 @@ func (p Pairs) FindDifferences(pairs Pairs) (newPairs, removedPairs Pairs) {
|
||||
|
||||
// GetRandomPair returns a random pair from a list of pairs
|
||||
func (p Pairs) GetRandomPair() Pair {
|
||||
pairsLen := len(p)
|
||||
|
||||
if pairsLen == 0 {
|
||||
return Pair{Base: NewCode(""), Quote: NewCode("")}
|
||||
if pairsLen := len(p); pairsLen != 0 {
|
||||
return p[rand.Intn(pairsLen)] // nolint:gosec // basic number generation required, no need for crypo/rand
|
||||
}
|
||||
|
||||
return p[rand.Intn(pairsLen)] // nolint:gosec // basic number generation required, no need for crypo/rand
|
||||
return Pair{}
|
||||
}
|
||||
|
||||
@@ -82,7 +82,6 @@ func (s *Storage) RunUpdater(overrides BotOverrides, settings *MainConfiguration
|
||||
if err != nil {
|
||||
log.Errorf(log.Global,
|
||||
"Unable to setup CoinMarketCap analysis. Error: %s", err)
|
||||
c = nil
|
||||
settings.CryptocurrencyProvider.Enabled = false
|
||||
} else {
|
||||
s.currencyAnalysis = c
|
||||
|
||||
@@ -3,13 +3,12 @@ package currency
|
||||
import "testing"
|
||||
|
||||
func TestGetSymbolByCurrencyName(t *testing.T) {
|
||||
expected := "₩"
|
||||
actual, err := GetSymbolByCurrencyName(KPW)
|
||||
if err != nil {
|
||||
t.Errorf("TestGetSymbolByCurrencyName error: %s", err)
|
||||
}
|
||||
|
||||
if actual != expected {
|
||||
if expected := "₩"; actual != expected {
|
||||
t.Errorf("TestGetSymbolByCurrencyName differing values")
|
||||
}
|
||||
|
||||
|
||||
@@ -30,17 +30,17 @@ Join our slack to discuss all things related to GoCryptoTrader! [GoCryptoTrader
|
||||
|
||||
[SQLBoiler](https://github.com/thrasher-corp/sqlboiler)
|
||||
```shell script
|
||||
go get -u github.com/thrasher-corp/sqlboiler
|
||||
go install github.com/thrasher-corp/sqlboiler
|
||||
```
|
||||
|
||||
[Postgres Driver](https://github.com/thrasher-corp/sqlboiler/drivers/sqlboiler-psql)
|
||||
```shell script
|
||||
go get -u github.com/thrasher-corp/sqlboiler/drivers/sqlboiler-psql
|
||||
go install github.com/thrasher-corp/sqlboiler/drivers/sqlboiler-psql
|
||||
```
|
||||
|
||||
[SQLite Driver](https://github.com/thrasher-corp/sqlboiler-sqlite3)
|
||||
```shell script
|
||||
go get -u github.com/thrasher-corp/sqlboiler-sqlite3
|
||||
go install github.com/thrasher-corp/sqlboiler-sqlite3
|
||||
```
|
||||
|
||||
##### Configuration
|
||||
|
||||
@@ -241,25 +241,19 @@ func TestSeries(t *testing.T) {
|
||||
t.Errorf("unexpected number of results received: %v", len(ret.Candles))
|
||||
}
|
||||
|
||||
ret, err = Series("", "", "", 0, "", start, end)
|
||||
_, err = Series("", "", "", 0, "", start, end)
|
||||
if !errors.Is(err, errInvalidInput) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
ret, err = Series(testExchanges[0].Name,
|
||||
_, err = Series(testExchanges[0].Name,
|
||||
"BTC", "MOON",
|
||||
864000, "spot",
|
||||
start, end)
|
||||
if err != nil {
|
||||
if !errors.Is(err, errInvalidInput) {
|
||||
if !errors.Is(err, ErrNoCandleDataFound) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
if err != nil && !errors.Is(err, errInvalidInput) && !errors.Is(err, ErrNoCandleDataFound) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = testhelpers.CloseDatabase(dbConn)
|
||||
if err != nil {
|
||||
if err = testhelpers.CloseDatabase(dbConn); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
})
|
||||
|
||||
@@ -177,8 +177,7 @@ func seed() error {
|
||||
|
||||
func TestLoadCSV(t *testing.T) {
|
||||
testData := filepath.Join("..", "..", "..", "testdata", "exchangelist.csv")
|
||||
_, err := LoadCSV(testData)
|
||||
if err != nil {
|
||||
if _, err := LoadCSV(testData); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,6 +97,7 @@ func TestTrades(t *testing.T) {
|
||||
}
|
||||
|
||||
func tradeSQLTester(t *testing.T) {
|
||||
t.Helper()
|
||||
var trades, trades2 []Data
|
||||
firstTime := time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC)
|
||||
for i := 0; i < 20; i++ {
|
||||
|
||||
@@ -151,6 +151,7 @@ func seedWithdrawData() {
|
||||
}
|
||||
}
|
||||
func withdrawHelper(t *testing.T) {
|
||||
t.Helper()
|
||||
seedWithdrawData()
|
||||
|
||||
_, err := GetEventByUUID(withdraw.DryRunID.String())
|
||||
|
||||
@@ -292,7 +292,10 @@ func (d *Dispatcher) subscribe(id uuid.UUID) (chan interface{}, error) {
|
||||
}
|
||||
|
||||
// Get an unused channel from the channel pool
|
||||
unusedChan := d.outbound.Get().(chan interface{})
|
||||
unusedChan, ok := d.outbound.Get().(chan interface{})
|
||||
if !ok {
|
||||
return nil, errors.New("unable to type assert unusedChan")
|
||||
}
|
||||
|
||||
// Lock for writing to the route list
|
||||
d.rMtx.Lock()
|
||||
@@ -356,11 +359,11 @@ func (d *Dispatcher) getNewID() (uuid.UUID, error) {
|
||||
|
||||
// Check to see if it already exists
|
||||
d.rMtx.RLock()
|
||||
_, ok := d.routes[newID]
|
||||
d.rMtx.RUnlock()
|
||||
if ok {
|
||||
if _, ok := d.routes[newID]; ok {
|
||||
d.rMtx.RUnlock()
|
||||
return newID, errors.New("dispatcher collision detected, uuid already exists")
|
||||
}
|
||||
d.rMtx.RUnlock()
|
||||
|
||||
// Write the key into system
|
||||
d.rMtx.Lock()
|
||||
|
||||
@@ -462,7 +462,7 @@ func (f *FTX) SendAuthHTTPRequest(ctx context.Context, method, path string, data
|
||||
// within time receive windows. NOTE: This is not always necessary and the above
|
||||
// SendHTTPRequest example will suffice.
|
||||
generate := 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
|
||||
var err error
|
||||
@@ -1028,8 +1028,7 @@ https://docs.ftx.com/#private-channels
|
||||
```go
|
||||
// WsAuth sends an authentication message to receive auth data
|
||||
func (f *FTX) WsAuth() error {
|
||||
intNonce := time.Now().UnixNano() / 1000000
|
||||
strNonce := strconv.FormatInt(intNonce, 10)
|
||||
strNonce := strconv.FormatInt(time.Now().UnixMilli(), 10)
|
||||
hmac := crypto.GetHMAC(
|
||||
crypto.HashSHA256,
|
||||
[]byte(strNonce+"websocket_login"),
|
||||
|
||||
@@ -234,6 +234,7 @@ func TestGetAllActiveAccounts(t *testing.T) {
|
||||
}
|
||||
|
||||
func makeHTTPGetRequest(t *testing.T, response interface{}) *http.Response {
|
||||
t.Helper()
|
||||
w := httptest.NewRecorder()
|
||||
|
||||
err := writeResponse(w, response)
|
||||
|
||||
@@ -51,8 +51,7 @@ func SetupDatabaseConnectionManager(cfg *database.Config) (*DatabaseConnectionMa
|
||||
cfg: *cfg,
|
||||
dbConn: database.DB,
|
||||
}
|
||||
err := m.dbConn.SetConfig(cfg)
|
||||
if err != nil {
|
||||
if err := m.dbConn.SetConfig(cfg); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -177,8 +176,7 @@ func (m *DatabaseConnectionManager) checkConnection() error {
|
||||
return database.ErrNoDatabaseProvided
|
||||
}
|
||||
|
||||
err := m.dbConn.Ping()
|
||||
if err != nil {
|
||||
if err := m.dbConn.Ping(); err != nil {
|
||||
m.dbConn.SetConnected(false)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -455,7 +455,7 @@ ranges:
|
||||
lookup = append(lookup, *result)
|
||||
job.Results[result.IntervalStartDate] = lookup
|
||||
}
|
||||
completed := true
|
||||
completed := true // nolint:ifshort,nolintlint // false positive and triggers only on Windows
|
||||
allResultsSuccessful := true
|
||||
allResultsFailed := true
|
||||
completionCheck:
|
||||
@@ -553,7 +553,7 @@ timesToFetch:
|
||||
job.Results[result.IntervalStartDate] = lookup
|
||||
}
|
||||
|
||||
completed := true
|
||||
completed := true // nolint:ifshort,nolintlint // false positive and triggers only on Windows
|
||||
allResultsSuccessful := true
|
||||
allResultsFailed := true
|
||||
completionCheck:
|
||||
@@ -709,7 +709,7 @@ func (m *DataHistoryManager) processCandleData(job *DataHistoryJob, exch exchang
|
||||
if err != nil {
|
||||
r.Result += "could not get candles: " + err.Error() + ". "
|
||||
r.Status = dataHistoryStatusFailed
|
||||
return r, nil
|
||||
return r, nil // nolint:nilerr // error is returned in the job result
|
||||
}
|
||||
job.rangeHolder.SetHasDataFromCandles(candles.Candles)
|
||||
for i := range job.rangeHolder.Ranges[intervalIndex].Intervals {
|
||||
@@ -758,13 +758,13 @@ func (m *DataHistoryManager) processTradeData(job *DataHistoryJob, exch exchange
|
||||
if err != nil {
|
||||
r.Result += "could not get trades: " + err.Error() + ". "
|
||||
r.Status = dataHistoryStatusFailed
|
||||
return r, nil
|
||||
return r, nil // nolint:nilerr // error is returned in the job result
|
||||
}
|
||||
candles, err := trade.ConvertTradesToCandles(job.Interval, trades...)
|
||||
if err != nil {
|
||||
r.Result += "could not convert candles to trades: " + err.Error() + ". "
|
||||
r.Status = dataHistoryStatusFailed
|
||||
return r, nil
|
||||
return r, nil // nolint:nilerr // error is returned in the job result
|
||||
}
|
||||
job.rangeHolder.SetHasDataFromCandles(candles.Candles)
|
||||
for i := range job.rangeHolder.Ranges[intervalIndex].Intervals {
|
||||
@@ -825,13 +825,13 @@ func (m *DataHistoryManager) convertTradesToCandles(job *DataHistoryJob, startRa
|
||||
if err != nil {
|
||||
r.Result = "could not get trades in range: " + err.Error()
|
||||
r.Status = dataHistoryStatusFailed
|
||||
return r, nil
|
||||
return r, nil // nolint:nilerr // error is returned in the job result
|
||||
}
|
||||
candles, err := trade.ConvertTradesToCandles(job.Interval, trades...)
|
||||
if err != nil {
|
||||
r.Result = "could not convert trades in range: " + err.Error()
|
||||
r.Status = dataHistoryStatusFailed
|
||||
return r, nil
|
||||
return r, nil // nolint:nilerr // error is returned in the job result
|
||||
}
|
||||
candles.SourceJobID = job.ID
|
||||
err = m.saveCandlesInBatches(job, &candles, r)
|
||||
@@ -864,13 +864,13 @@ func (m *DataHistoryManager) convertCandleData(job *DataHistoryJob, startRange,
|
||||
if err != nil {
|
||||
r.Result = "could not get candles in range: " + err.Error()
|
||||
r.Status = dataHistoryStatusFailed
|
||||
return r, nil
|
||||
return r, nil // nolint:nilerr // error is returned in the job result
|
||||
}
|
||||
newCandles, err := kline.ConvertToNewInterval(&candles, job.ConversionInterval)
|
||||
if err != nil {
|
||||
r.Result = "could not convert candles in range: " + err.Error()
|
||||
r.Status = dataHistoryStatusFailed
|
||||
return r, nil
|
||||
return r, nil // nolint:nilerr // error is returned in the job result
|
||||
}
|
||||
newCandles.SourceJobID = job.ID
|
||||
err = m.saveCandlesInBatches(job, &candles, r)
|
||||
@@ -912,14 +912,14 @@ func (m *DataHistoryManager) validateCandles(job *DataHistoryJob, exch exchange.
|
||||
if err != nil {
|
||||
r.Result = "could not get API candles: " + err.Error()
|
||||
r.Status = dataHistoryStatusFailed
|
||||
return r, nil
|
||||
return r, nil // nolint:nilerr // error is returned in the job result
|
||||
}
|
||||
apiCandles.ValidationJobID = job.ID
|
||||
dbCandles, err := m.candleLoader(job.Exchange, job.Pair, job.Asset, job.Interval, startRange, endRange)
|
||||
if err != nil {
|
||||
r.Result = "could not get database candles: " + err.Error()
|
||||
r.Status = dataHistoryStatusFailed
|
||||
return r, nil
|
||||
return r, nil // nolint:nilerr // error is returned in the job result
|
||||
}
|
||||
if len(dbCandles.Candles) == 0 {
|
||||
r.Result = fmt.Sprintf("missing database candles for period %v-%v", startRange, endRange)
|
||||
|
||||
@@ -655,6 +655,7 @@ func TestCompareJobsToData(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestRunJob(t *testing.T) {
|
||||
t.Parallel()
|
||||
testCases := []*DataHistoryJob{
|
||||
{
|
||||
Nickname: "TestRunJobDataHistoryCandleDataType",
|
||||
@@ -923,6 +924,7 @@ func TestConverters(t *testing.T) {
|
||||
|
||||
// test helper functions
|
||||
func createDHM(t *testing.T) (*DataHistoryManager, *datahistoryjob.DataHistoryJob) {
|
||||
t.Helper()
|
||||
em := SetupExchangeManager()
|
||||
exch, err := em.NewExchangeByName(testExchange)
|
||||
if !errors.Is(err, nil) {
|
||||
|
||||
@@ -708,8 +708,7 @@ func (bot *Engine) Stop() {
|
||||
|
||||
// Wait for services to gracefully shutdown
|
||||
bot.ServicesWG.Wait()
|
||||
err := gctlog.CloseLogger()
|
||||
if err != nil {
|
||||
if err := gctlog.CloseLogger(); err != nil {
|
||||
log.Printf("Failed to close logger. Error: %v\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ import (
|
||||
var testExchange = "Bitstamp"
|
||||
|
||||
func CreateTestBot(t *testing.T) *Engine {
|
||||
t.Helper()
|
||||
cFormat := ¤cy.PairFormat{Uppercase: true}
|
||||
cp1 := currency.NewPair(currency.BTC, currency.USD)
|
||||
cp2 := currency.NewPair(currency.BTC, currency.USDT)
|
||||
@@ -86,11 +87,9 @@ func CreateTestBot(t *testing.T) *Engine {
|
||||
},
|
||||
},
|
||||
}}}
|
||||
err := bot.LoadExchange(testExchange, nil)
|
||||
if err != nil {
|
||||
if err := bot.LoadExchange(testExchange, nil); err != nil {
|
||||
t.Fatalf("SetupTest: Failed to load exchange: %s", err)
|
||||
}
|
||||
|
||||
return bot
|
||||
}
|
||||
|
||||
@@ -117,6 +116,7 @@ func TestGetRPCEndpoints(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSetSubsystem(t *testing.T) {
|
||||
t.Parallel()
|
||||
testCases := []struct {
|
||||
Subsystem string
|
||||
Engine *Engine
|
||||
|
||||
@@ -182,6 +182,7 @@ func TestOrderManagerStop(t *testing.T) {
|
||||
}
|
||||
|
||||
func OrdersSetup(t *testing.T) *OrderManager {
|
||||
t.Helper()
|
||||
var wg sync.WaitGroup
|
||||
em := SetupExchangeManager()
|
||||
exch, err := em.NewExchangeByName(testExchange)
|
||||
@@ -377,8 +378,7 @@ func TestExists(t *testing.T) {
|
||||
Exchange: testExchange,
|
||||
ID: "TestExists",
|
||||
}
|
||||
err := m.orderStore.add(o)
|
||||
if err != nil {
|
||||
if err := m.orderStore.add(o); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
b := m.orderStore.exists(o)
|
||||
@@ -551,8 +551,7 @@ func TestCancelAllOrders(t *testing.T) {
|
||||
ID: "TestCancelAllOrders",
|
||||
Status: order.New,
|
||||
}
|
||||
err := m.orderStore.add(o)
|
||||
if err != nil {
|
||||
if err := m.orderStore.add(o); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
|
||||
@@ -109,8 +109,7 @@ func (s *RPCServer) authenticateClient(ctx context.Context) (context.Context, er
|
||||
// StartRPCServer starts a gRPC server with TLS auth
|
||||
func StartRPCServer(engine *Engine) {
|
||||
targetDir := utils.GetTLSDir(engine.Settings.DataDir)
|
||||
err := checkCerts(targetDir)
|
||||
if err != nil {
|
||||
if err := checkCerts(targetDir); err != nil {
|
||||
log.Errorf(log.GRPCSys, "gRPC checkCerts failed. err: %s\n", err)
|
||||
return
|
||||
}
|
||||
@@ -678,7 +677,15 @@ func (s *RPCServer) GetAccountInfoStream(r *gctrpc.GetAccountInfoRequest, stream
|
||||
return errDispatchSystem
|
||||
}
|
||||
|
||||
acc := (*data.(*interface{})).(account.Holdings)
|
||||
d := *data.(*interface{})
|
||||
if d == nil {
|
||||
return errors.New("unable to type assert data")
|
||||
}
|
||||
|
||||
acc, ok := d.(account.Holdings)
|
||||
if !ok {
|
||||
return errors.New("unable to type assert account holdings data")
|
||||
}
|
||||
|
||||
var accounts []*gctrpc.Account
|
||||
for x := range acc.Accounts {
|
||||
@@ -1977,7 +1984,16 @@ func (s *RPCServer) GetExchangeOrderbookStream(r *gctrpc.GetExchangeOrderbookStr
|
||||
return errDispatchSystem
|
||||
}
|
||||
|
||||
ob := (*data.(*interface{})).(orderbook.Base)
|
||||
d := *data.(*interface{})
|
||||
if d == nil {
|
||||
return errors.New("unable to type assert data")
|
||||
}
|
||||
|
||||
ob, ok := d.(orderbook.Base)
|
||||
if !ok {
|
||||
return errors.New("unable to type assert orderbook data")
|
||||
}
|
||||
|
||||
bids := make([]*gctrpc.OrderbookItem, len(ob.Bids))
|
||||
for i := range ob.Bids {
|
||||
bids[i] = &gctrpc.OrderbookItem{
|
||||
@@ -2050,7 +2066,16 @@ func (s *RPCServer) GetTickerStream(r *gctrpc.GetTickerStreamRequest, stream gct
|
||||
if !ok {
|
||||
return errDispatchSystem
|
||||
}
|
||||
t := (*data.(*interface{})).(ticker.Price)
|
||||
|
||||
d := *data.(*interface{})
|
||||
if d == nil {
|
||||
return errors.New("unable to type assert data")
|
||||
}
|
||||
|
||||
t, ok := d.(ticker.Price)
|
||||
if !ok {
|
||||
return errors.New("unable to type assert ticker data")
|
||||
}
|
||||
|
||||
err := stream.Send(&gctrpc.TickerResponse{
|
||||
Pair: &gctrpc.CurrencyPair{
|
||||
@@ -2099,7 +2124,16 @@ func (s *RPCServer) GetExchangeTickerStream(r *gctrpc.GetExchangeTickerStreamReq
|
||||
if !ok {
|
||||
return errDispatchSystem
|
||||
}
|
||||
t := (*data.(*interface{})).(ticker.Price)
|
||||
|
||||
d := *data.(*interface{})
|
||||
if d == nil {
|
||||
return errors.New("unable to type assert data")
|
||||
}
|
||||
|
||||
t, ok := d.(ticker.Price)
|
||||
if !ok {
|
||||
return errors.New("unable to type assert ticker data")
|
||||
}
|
||||
|
||||
err := stream.Send(&gctrpc.TickerResponse{
|
||||
Pair: &gctrpc.CurrencyPair{
|
||||
@@ -2355,7 +2389,11 @@ func (s *RPCServer) GCTScriptStatus(_ context.Context, _ *gctrpc.GCTScriptStatus
|
||||
}
|
||||
|
||||
gctscript.AllVMSync.Range(func(k, v interface{}) bool {
|
||||
vm := v.(*gctscript.VM)
|
||||
vm, ok := v.(*gctscript.VM)
|
||||
if !ok {
|
||||
log.Errorf(log.GRPCSys, "Unable to type assert gctscript.VM")
|
||||
return false
|
||||
}
|
||||
resp.Scripts = append(resp.Scripts, &gctrpc.GCTScript{
|
||||
UUID: vm.ID.String(),
|
||||
Name: vm.ShortName(),
|
||||
@@ -2376,6 +2414,7 @@ func (s *RPCServer) GCTScriptQuery(_ context.Context, r *gctrpc.GCTScriptQueryRe
|
||||
|
||||
UUID, err := uuid.FromString(r.Script.UUID)
|
||||
if err != nil {
|
||||
// nolint:nilerr // error is returned in the GCTScriptQueryResponse
|
||||
return &gctrpc.GCTScriptQueryResponse{Status: MsgStatusError, Data: err.Error()}, nil
|
||||
}
|
||||
|
||||
@@ -2415,9 +2454,8 @@ func (s *RPCServer) GCTScriptExecute(_ context.Context, r *gctrpc.GCTScriptExecu
|
||||
}
|
||||
|
||||
script := filepath.Join(r.Script.Path, r.Script.Name)
|
||||
err := gctVM.Load(script)
|
||||
if err != nil {
|
||||
return &gctrpc.GenericResponse{
|
||||
if err := gctVM.Load(script); err != nil {
|
||||
return &gctrpc.GenericResponse{ // nolint:nilerr // error is returned in the generic response
|
||||
Status: MsgStatusError,
|
||||
Data: err.Error(),
|
||||
}, nil
|
||||
@@ -2439,7 +2477,7 @@ func (s *RPCServer) GCTScriptStop(_ context.Context, r *gctrpc.GCTScriptStopRequ
|
||||
|
||||
UUID, err := uuid.FromString(r.Script.UUID)
|
||||
if err != nil {
|
||||
return &gctrpc.GenericResponse{Status: MsgStatusError, Data: err.Error()}, nil
|
||||
return &gctrpc.GenericResponse{Status: MsgStatusError, Data: err.Error()}, nil // nolint:nilerr // error is returned in the generic response
|
||||
}
|
||||
|
||||
if v, f := gctscript.AllVMSync.Load(UUID); f {
|
||||
@@ -2603,7 +2641,7 @@ func (s *RPCServer) GCTScriptStopAll(context.Context, *gctrpc.GCTScriptStopAllRe
|
||||
|
||||
err := s.gctScriptManager.ShutdownAll()
|
||||
if err != nil {
|
||||
return &gctrpc.GenericResponse{Status: "error", Data: err.Error()}, nil
|
||||
return &gctrpc.GenericResponse{Status: "error", Data: err.Error()}, nil // nolint:nilerr // error is returned in the generic response
|
||||
}
|
||||
|
||||
return &gctrpc.GenericResponse{
|
||||
@@ -2621,6 +2659,7 @@ func (s *RPCServer) GCTScriptAutoLoadToggle(_ context.Context, r *gctrpc.GCTScri
|
||||
if r.Status {
|
||||
err := s.gctScriptManager.Autoload(r.Script, true)
|
||||
if err != nil {
|
||||
// nolint:nilerr // error is returned in the generic response
|
||||
return &gctrpc.GenericResponse{Status: "error", Data: err.Error()}, nil
|
||||
}
|
||||
return &gctrpc.GenericResponse{Status: "success", Data: "script " + r.Script + " removed from autoload list"}, nil
|
||||
@@ -2628,7 +2667,7 @@ func (s *RPCServer) GCTScriptAutoLoadToggle(_ context.Context, r *gctrpc.GCTScri
|
||||
|
||||
err := s.gctScriptManager.Autoload(r.Script, false)
|
||||
if err != nil {
|
||||
return &gctrpc.GenericResponse{Status: "error", Data: err.Error()}, nil
|
||||
return &gctrpc.GenericResponse{Status: "error", Data: err.Error()}, nil // nolint:nilerr // error is returned in the generic response
|
||||
}
|
||||
return &gctrpc.GenericResponse{Status: "success", Data: "script " + r.Script + " added to autoload list"}, nil
|
||||
}
|
||||
@@ -2726,7 +2765,7 @@ func (s *RPCServer) UpdateExchangeSupportedPairs(ctx context.Context, r *gctrpc.
|
||||
return nil, err
|
||||
}
|
||||
|
||||
base := exch.GetBase()
|
||||
base := exch.GetBase() // nolint:ifshort,nolintlint // false positive and triggers only on Windows
|
||||
if base == nil {
|
||||
return nil, errExchangeBaseNotFound
|
||||
}
|
||||
|
||||
@@ -1557,8 +1557,7 @@ func TestGetActiveDataHistoryJobs(t *testing.T) {
|
||||
Interval: kline.OneMin,
|
||||
}
|
||||
|
||||
err := m.UpsertJob(dhj, false)
|
||||
if !errors.Is(err, nil) {
|
||||
if err := m.UpsertJob(dhj, false); !errors.Is(err, nil) {
|
||||
t.Fatalf("received %v, expected %v", err, nil)
|
||||
}
|
||||
|
||||
|
||||
@@ -98,8 +98,7 @@ func (m *WithdrawManager) WithdrawalEventByID(id string) (*withdraw.Response, er
|
||||
if m == nil {
|
||||
return nil, ErrNilSubsystem
|
||||
}
|
||||
v := withdraw.Cache.Get(id)
|
||||
if v != nil {
|
||||
if v := withdraw.Cache.Get(id); v != nil {
|
||||
return v.(*withdraw.Response), nil
|
||||
}
|
||||
|
||||
|
||||
@@ -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),
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user