CI: Bump go version, linters and fix minor issues (#1010)

* Bump golang, golangci-lint versions and fix issues

* Add -fno-stack-protector

* Fix AppVeyor golangci-lint ver

* Nitters

* Nitters round 2
This commit is contained in:
Adrian Gallagher
2022-08-17 11:37:22 +10:00
committed by GitHub
parent 0c9ad9eaa3
commit 68588560e3
85 changed files with 389 additions and 246 deletions

View File

@@ -36,7 +36,7 @@ services:
init:
- set PATH=%POSTGRES_PATH%\bin;%PATH%
- set PATH=C:\go118\bin;%PATH%
- set PATH=C:\go119\bin;%PATH%
install:
- set Path=C:\mingw-w64\x86_64-8.1.0-posix-seh-rt_v6-rev0\mingw64\bin;%Path%
@@ -55,7 +55,7 @@ before_test:
test_script:
# test back-end
- go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.46.2
- go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.48.0
- '%GOPATH%\bin\golangci-lint.exe run --verbose'
- ps: >-
if($env:APPVEYOR_SCHEDULED_BUILD -eq 'true') {

View File

@@ -8,8 +8,8 @@ jobs:
- uses: actions/checkout@v3
- uses: actions/setup-go@v3
with:
go-version: '1.18.x'
go-version: '1.19.x'
- name: golangci-lint
uses: golangci/golangci-lint-action@v3
with:
version: v1.46.2
version: v1.48.0

View File

@@ -12,7 +12,7 @@ jobs:
- name: Setup Go
uses: actions/setup-go@v3
with:
go-version: 1.18.x
go-version: 1.19.x
- name: Setup build depends
run: |

View File

@@ -1,7 +1,7 @@
on: [push, pull_request]
name: CI
env:
GO_VERSION: 1.18.x
GO_VERSION: 1.19.x
jobs:
backend-psql:
name: GoCryptoTrader back-end with PSQL
@@ -115,6 +115,7 @@ jobs:
PSQL_SSLMODE: disable
GOARCH: 386
CGO_ENABLED: 1
CGO_CFLAGS: -fno-stack-protector
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v3

View File

@@ -18,12 +18,12 @@ linters:
- govet
- ineffassign
- staticcheck
- structcheck
- typecheck
# - unused
# - varcheck
# disabled by default linters
# - asasalint
- asciicheck
- bidichk
- bodyclose
@@ -38,8 +38,10 @@ linters:
- errchkjson
- errname
# - errorlint
- execinquery
# - exhaustive
# - exhaustivestruct
# - exhaustivestruct // abandoned by its owner, replaced with exhaustruct
# - exhaustruct
- exportloopref
# - forbidigo
- forcetypeassert
@@ -65,7 +67,7 @@ linters:
- goprintffuncname
- gosec
- grouper
- ifshort
# - ifshort // deprecated by its owner
# - importas
# - interfacer // deprecated by its owner
# - ireturn
@@ -77,9 +79,13 @@ linters:
- nakedret
# - nestif
- nilerr
# - nilnil
# - nlreturn
- noctx
- nolintlint
# - nonamedreturns
# - nosnakecase
- nosprintfhostport
# - paralleltest
- prealloc
- predeclared
@@ -87,14 +93,18 @@ linters:
- revive
- rowserrcheck
# - scopelint // deprecated since v1.39.0, replaced by exportloopref
# - sqlclosecheck
- sqlclosecheck
- structcheck
- stylecheck
# - tagliatelle
- tenv
# - testpackage
- thelper
- tparallel
- unconvert
- unparam
- usestdlibvars
# - varnamelen
- wastedassign
- whitespace
# - wrapcheck
@@ -103,8 +113,6 @@ linters:
linters-settings:
govet:
check-shadowing: true
golint:
min-confidence: 0
goconst:
min-occurrences: 6
depguard:
@@ -139,3 +147,6 @@ issues:
# The following silences false positives in table tests
# https://github.com/kyoh86/scopelint/issues/4
- Using the variable on range scope `ti` in function literal
include:
- EXC0012 # revive: Comment exported (.+) should have comment( \(or a comment on this block\))? or be unexported
- EXC0014 # revive: Comment on exported (.+) should be of the form "(.+)..."

View File

@@ -1,4 +1,4 @@
FROM golang:1.18 as build
FROM golang:1.19 as build
WORKDIR /go/src/github.com/thrasher-corp/gocryptotrader
COPY . .
RUN GO111MODULE=on go mod vendor

View File

@@ -1,6 +1,6 @@
LDFLAGS = -ldflags "-w -s"
GCTPKG = github.com/thrasher-corp/gocryptotrader
LINTPKG = github.com/golangci/golangci-lint/cmd/golangci-lint@v1.46.2
LINTPKG = github.com/golangci/golangci-lint/cmd/golangci-lint@v1.48.0
LINTBIN = $(GOPATH)/bin/golangci-lint
GCTLISTENPORT=9050
GCTPROFILERLISTENPORT=8085

View File

@@ -20,7 +20,8 @@ const (
TradeStr = "trade"
// DataCandle is an int64 representation of a candle data type
DataCandle = iota
DataCandle int64 = iota
// DataTrade is an int64 representation of a trade data type
DataTrade
)

View File

@@ -3,7 +3,6 @@ package config
import (
"encoding/json"
"errors"
"io/ioutil"
"os"
"path/filepath"
"testing"
@@ -458,7 +457,7 @@ func TestValidate(t *testing.T) {
func TestReadConfigFromFile(t *testing.T) {
tempDir := t.TempDir()
passFile, err := ioutil.TempFile(tempDir, "*.start")
passFile, err := os.CreateTemp(tempDir, "*.start")
if err != nil {
t.Fatalf("Problem creating temp file at %v: %s\n", passFile, err)
}

View File

@@ -108,7 +108,7 @@ func main() {
yn := quickParse(reader)
if yn == y || yn == yes {
var fp, wd string
extension := "strat" // nolint:misspell // its shorthand for strategy
extension := "strat" //nolint:misspell // its shorthand for strategy
for {
wd, err = os.Getwd()
if err != nil {
@@ -427,9 +427,9 @@ func parseDatabase(reader *bufio.Reader, cfg *config.Config) error {
}
fmt.Println("What is the database Port? eg 1337")
input = quickParse(reader)
var port float64
var port uint64
if input != "" {
port, err = strconv.ParseFloat(input, 64)
port, err = strconv.ParseUint(input, 10, 16)
if err != nil {
return err
}

View File

@@ -3,7 +3,6 @@ package database
import (
"errors"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"testing"
@@ -39,7 +38,7 @@ func TestMain(m *testing.M) {
var err error
testhelpers.PostgresTestDatabase = testhelpers.GetConnectionDetails()
testhelpers.GetConnectionDetails()
testhelpers.TempDir, err = ioutil.TempDir("", "gct-temp")
testhelpers.TempDir, err = os.MkdirTemp("", "gct-temp")
if err != nil {
fmt.Printf("failed to create temp file: %v", err)
os.Exit(1)
@@ -85,16 +84,7 @@ func TestLoadDataCandles(t *testing.T) {
}
database.MigrationDir = filepath.Join("..", "..", "..", "..", "database", "migrations")
testhelpers.MigrationDir = filepath.Join("..", "..", "..", "..", "database", "migrations")
_, err = testhelpers.ConnectToDatabase(&dbConfg)
if err != nil {
t.Error(err)
}
bot.DatabaseManager, err = engine.SetupDatabaseConnectionManager(&bot.Config.Database)
if err != nil {
t.Error(err)
}
err = bot.DatabaseManager.Start(&bot.ServicesWG)
conn, err := testhelpers.ConnectToDatabase(&dbConfg)
if err != nil {
t.Error(err)
}
@@ -133,6 +123,10 @@ func TestLoadDataCandles(t *testing.T) {
if err != nil {
t.Error(err)
}
if err = conn.SQL.Close(); err != nil {
t.Error(err)
}
}
func TestLoadDataTrades(t *testing.T) {
@@ -165,16 +159,7 @@ func TestLoadDataTrades(t *testing.T) {
}
database.MigrationDir = filepath.Join("..", "..", "..", "..", "database", "migrations")
testhelpers.MigrationDir = filepath.Join("..", "..", "..", "..", "database", "migrations")
_, err = testhelpers.ConnectToDatabase(&dbConfg)
if err != nil {
t.Error(err)
}
bot.DatabaseManager, err = engine.SetupDatabaseConnectionManager(&bot.Config.Database)
if err != nil {
t.Error(err)
}
err = bot.DatabaseManager.Start(&bot.ServicesWG)
conn, err := testhelpers.ConnectToDatabase(&dbConfg)
if err != nil {
t.Error(err)
}
@@ -206,6 +191,10 @@ func TestLoadDataTrades(t *testing.T) {
if err != nil {
t.Error(err)
}
if err = conn.SQL.Close(); err != nil {
t.Error(err)
}
}
func TestLoadDataInvalid(t *testing.T) {

View File

@@ -22,7 +22,7 @@ func EstimateSlippagePercentage(maximumSlippageRate, minimumSlippageRate decimal
// eg 80 means for every dollar, keep 80%
randSeed := int(minimumSlippageRate.IntPart()) - int(maximumSlippageRate.IntPart())
if randSeed > 0 {
result := int64(rand.Intn(randSeed)) // nolint:gosec // basic number generation required, no need for crypto/rand
result := int64(rand.Intn(randSeed)) //nolint:gosec // basic number generation required, no need for crypto/rand
return maximumSlippageRate.Add(decimal.NewFromInt(result)).Div(decimal.NewFromInt(100))
}

View File

@@ -11,7 +11,7 @@ var (
// ErrSimultaneousProcessingOnly is raised when a strategy is improperly configured
ErrSimultaneousProcessingOnly = errors.New("this strategy only supports simultaneous processing")
// ErrStrategyNotFound used when strategy specified in strategy config does not exist
ErrStrategyNotFound = errors.New("not found. Please ensure the strategy-settings field 'name' is spelled properly in your .strat config") // nolint:misspell // its shorthand for strategy
ErrStrategyNotFound = errors.New("not found. Please ensure the strategy-settings field 'name' is spelled properly in your .strat config") //nolint:misspell // its shorthand for strategy
// ErrInvalidCustomSettings used when bad custom settings are found in the strategy config
ErrInvalidCustomSettings = errors.New("invalid custom settings in config")
// ErrTooMuchBadData used when there is too much missing data

View File

@@ -77,6 +77,7 @@ func (b *Base) GetReasons() []string {
return b.Reasons
}
// GetBase returns an event base
func (b *Base) GetBase() *Base {
return b
}

View File

@@ -138,7 +138,7 @@ func (d *Data) enhanceCandles() error {
Asset: lookup.Asset,
Pair: lookup.Pair,
Interval: lookup.Interval,
Watermark: fmt.Sprintf("%s - %s - %s", strings.Title(lookup.Exchange), lookup.Asset.String(), lookup.Pair.Upper()), // nolint // Title usage
Watermark: fmt.Sprintf("%s - %s - %s", strings.Title(lookup.Exchange), lookup.Asset.String(), lookup.Pair.Upper()), //nolint // Title usage
}
statsForCandles :=

View File

@@ -1717,7 +1717,7 @@ func htmlScrapeBitfinex(htmlData *HTMLScrapingData) ([]string, error) {
return resp, nil
}
// htmlScrapeBinance gets checkstring for binance exchange
// htmlScrapeBinance gets checkstring for binance exchange
func htmlScrapeBinance(htmlData *HTMLScrapingData) ([]string, error) {
temp, err := sendHTTPGetRequest(htmlData.Path, nil)
if err != nil {

View File

@@ -486,7 +486,7 @@ func GetPackageName(name string, capital bool) string {
i = len(newStrings) - 1
}
if capital {
return strings.Replace(strings.Title(newStrings[i]), "_", " ", -1) // nolint // ignore staticcheck strings.Title warning
return strings.Replace(strings.Title(newStrings[i]), "_", " ", -1) //nolint // ignore staticcheck strings.Title warning
}
return newStrings[i]
}

View File

@@ -146,7 +146,7 @@ func makeExchange(exchangeDirectory string, configTestFile *config.Config, exch
fmt.Printf("Output directory: %s\n", exchangeDirectory)
exch.CapitalName = strings.Title(exch.Name) // nolint:staticcheck // Ignore Title usage warning
exch.CapitalName = strings.Title(exch.Name) //nolint:staticcheck // Ignore Title usage warning
exch.Variable = exch.Name[0:2]
newExchConfig := &config.Exchange{}
newExchConfig.Name = exch.CapitalName

View File

@@ -878,7 +878,7 @@ func testWrappers(e exchange.IBotExchange, base *exchange.Base, config *Config)
}
func jsonifyInterface(params []interface{}) json.RawMessage {
response, _ := json.MarshalIndent(params, "", " ") // nolint:errchkjson // TODO: ignore this for now
response, _ := json.MarshalIndent(params, "", " ") //nolint:errchkjson // TODO: ignore this for now
return response
}

View File

@@ -5,7 +5,9 @@ import (
"errors"
"fmt"
"log"
"net"
"net/http"
"strconv"
"github.com/gorilla/websocket"
"github.com/thrasher-corp/gocryptotrader/common"
@@ -83,8 +85,8 @@ func main() {
}
listenAddr := cfg.RemoteControl.WebsocketRPC.ListenAddress
wsHost := fmt.Sprintf("ws://%s:%d/ws", common.ExtractHost(listenAddr),
common.ExtractPort(listenAddr))
wsHost := fmt.Sprintf("ws://%s/ws", net.JoinHostPort(common.ExtractHost(listenAddr),
strconv.Itoa(common.ExtractPort(listenAddr))))
log.Printf("Connecting to websocket host: %s", wsHost)
var dialer websocket.Dialer

View File

@@ -5,6 +5,7 @@ import (
"errors"
"fmt"
"io"
"net"
"net/http"
"net/url"
"os"
@@ -305,7 +306,7 @@ func EncodeURLValues(urlPath string, values url.Values) string {
// ExtractHost returns the hostname out of a string
func ExtractHost(address string) string {
host := strings.Split(address, ":")[0]
host, _, _ := net.SplitHostPort(address)
if host == "" {
return "localhost"
}
@@ -314,12 +315,12 @@ func ExtractHost(address string) string {
// ExtractPort returns the port name out of a string
func ExtractPort(host string) int {
portStrs := strings.Split(host, ":")
if len(portStrs) == 1 {
_, port, _ := net.SplitHostPort(host)
if port == "" {
return 80
}
port, _ := strconv.Atoi(portStrs[1])
return port
portInt, _ := strconv.Atoi(port)
return portInt
}
// GetURIPath returns the path of a URL given a URI

View File

@@ -1,6 +1,6 @@
package crypto
// nolint:gosec // md5/sha1 hash functions used by some exchanges
//nolint:gosec // md5/sha1 hash functions used by some exchanges
import (
"crypto/hmac"
"crypto/md5"
@@ -63,7 +63,7 @@ func GetRandomSalt(input []byte, saltLen int) ([]byte, error) {
// GetMD5 returns a MD5 hash of a byte array
func GetMD5(input []byte) ([]byte, error) {
m := md5.New() // nolint:gosec // hash function used by some exchanges
m := md5.New() //nolint:gosec // hash function used by some exchanges
_, err := m.Write(input)
return m.Sum(nil), err
}
@@ -108,7 +108,7 @@ func GetHMAC(hashType int, input, key []byte) ([]byte, error) {
// Sha1ToHex takes a string, sha1 hashes it and return a hex string of the
// result
func Sha1ToHex(data string) (string, error) {
h := sha1.New() // nolint:gosec // hash function used by some exchanges
h := sha1.New() //nolint:gosec // hash function used by some exchanges
_, err := h.Write([]byte(data))
return hex.EncodeToString(h.Sum(nil)), err
}

View File

@@ -33,7 +33,7 @@ func UnZip(src, dest string) (fileList []string, err error) {
}
for x := range z.File {
fPath := filepath.Join(dest, z.File[x].Name) // nolint // We ignore
fPath := filepath.Join(dest, z.File[x].Name) //nolint // We ignore
// gosec linter above because the code below files the file traversal
// bug when extracting archives
if !strings.HasPrefix(fPath, filepath.Clean(dest)+string(os.PathSeparator)) {

View File

@@ -2,7 +2,6 @@ package file
import (
"fmt"
"io/ioutil"
"os"
"path/filepath"
"runtime"
@@ -162,7 +161,7 @@ func TestWriteAsCSV(t *testing.T) {
{"Sup", "bra"},
}
testFile, err := ioutil.TempFile(os.TempDir(), "gct-csv-test.*.csv")
testFile, err := os.CreateTemp(os.TempDir(), "gct-csv-test.*.csv")
if err != nil {
t.Fatal(err)
}

View File

@@ -1771,7 +1771,7 @@ func (c *Config) AssetTypeEnabled(a asset.Item, exch string) (bool, error) {
err = cfg.CurrencyPairs.IsAssetEnabled(a)
if err != nil {
return false, nil // nolint:nilerr // non-fatal error
return false, nil //nolint:nilerr // non-fatal error
}
return true, nil
}

View File

@@ -4,7 +4,6 @@ import (
"bytes"
"fmt"
"io"
"io/ioutil"
"os"
"path/filepath"
"reflect"
@@ -142,7 +141,7 @@ func TestEncryptTwiceReusesSaltButNewCipher(t *testing.T) {
tempDir := t.TempDir()
// Prepare input
passFile, err := ioutil.TempFile(tempDir, "*.pw")
passFile, err := os.CreateTemp(tempDir, "*.pw")
if err != nil {
t.Fatalf("Problem creating temp file at %s: %s\n", tempDir, err)
}
@@ -318,7 +317,7 @@ func TestSaveConfigToFileWithErrorInPasswordPrompt(t *testing.T) {
EncryptConfig: fileEncryptionEnabled,
}
testData := []byte("testdata")
f, err := ioutil.TempFile("", "")
f, err := os.CreateTemp("", "")
if err != nil {
t.Fatal(err)
}
@@ -355,7 +354,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")
responseFile, err := os.CreateTemp("", "*.in")
if err != nil {
return fmt.Errorf("problem creating temp file: %w", err)
}

View File

@@ -2,7 +2,6 @@ package config
import (
"errors"
"io/ioutil"
"os"
"path/filepath"
"runtime"
@@ -1576,7 +1575,7 @@ func TestCheckExchangeConfigValues(t *testing.T) {
}
// Make a sneaky copy for bank account testing
// nolint: gocritic
//nolint: gocritic
cpy := append(cfg.Exchanges[:0:0], cfg.Exchanges...)
// Test empty exchange name for an enabled exchange
@@ -1729,7 +1728,7 @@ func TestSaveConfigToFile(t *testing.T) {
if err != nil {
t.Errorf("TestSaveConfig.LoadConfig: %s", err.Error())
}
f, err := ioutil.TempFile("", "")
f, err := os.CreateTemp("", "")
if err != nil {
t.Errorf("TestSaveConfig create file: %s", err)
}

View File

@@ -114,7 +114,7 @@ var (
BAT = NewCode("BAT")
ETP = NewCode("ETP")
HOT = NewCode("HOT")
STRAT = NewCode("STRAT") // nolint // Cryptocurrency code
STRAT = NewCode("STRAT") //nolint // Cryptocurrency code
GNT = NewCode("GNT")
REP = NewCode("REP")
SNT = NewCode("SNT")
@@ -372,9 +372,9 @@ var (
STQ = NewCode("STQ")
INK = NewCode("INK")
HBZ = NewCode("HBZ")
USDT_ETH = NewCode("USDT_ETH") // nolint // Cryptocurrency code
QTUM_ETH = NewCode("QTUM_ETH") // nolint // Cryptocurrency code
BTM_ETH = NewCode("BTM_ETH") // nolint // Cryptocurrency code
USDT_ETH = NewCode("USDT_ETH") //nolint // Cryptocurrency code
QTUM_ETH = NewCode("QTUM_ETH") //nolint // Cryptocurrency code
BTM_ETH = NewCode("BTM_ETH") //nolint // Cryptocurrency code
FIL = NewCode("FIL")
STX = NewCode("STX")
BOT = NewCode("BOT")
@@ -387,7 +387,7 @@ var (
GOD = NewCode("GOD")
SMT = NewCode("SMT")
BTF = NewCode("BTF")
NAS_ETH = NewCode("NAS_ETH") // nolint // Cryptocurrency code
NAS_ETH = NewCode("NAS_ETH") //nolint // Cryptocurrency code
TSL = NewCode("TSL")
BIFI = NewCode("BIFI")
BNTY = NewCode("BNTY")
@@ -413,7 +413,7 @@ var (
MOBI = NewCode("MOBI")
LEDU = NewCode("LEDU")
DBC = NewCode("DBC")
MKR_OLD = NewCode("MKR_OLD") // nolint // Cryptocurrency code
MKR_OLD = NewCode("MKR_OLD") //nolint // Cryptocurrency code
DPY = NewCode("DPY")
BCDN = NewCode("BCDN")
EOSDAC = NewCode("EOSDAC")
@@ -422,7 +422,7 @@ var (
PPS = NewCode("PPS")
BOE = NewCode("BOE")
MEDX = NewCode("MEDX")
SMT_ETH = NewCode("SMT_ETH") // nolint // Cryptocurrency code
SMT_ETH = NewCode("SMT_ETH") //nolint // Cryptocurrency code
CS = NewCode("CS")
MAN = NewCode("MAN")
REM = NewCode("REM")
@@ -442,7 +442,7 @@ var (
SWTH = NewCode("SWTH")
NKN = NewCode("NKN")
SOUL = NewCode("SOUL")
GALA_NEO = NewCode("GALA_NEO") // nolint // Cryptocurrency code
GALA_NEO = NewCode("GALA_NEO") //nolint // Cryptocurrency code
LRN = NewCode("LRN")
GSE = NewCode("GSE")
RATING = NewCode("RATING")
@@ -1669,7 +1669,7 @@ var (
YER = NewCode("YER")
ZWD = NewCode("ZWD")
XETH = NewCode("XETH")
FX_BTC = NewCode("FX_BTC") // nolint // Cryptocurrency code
FX_BTC = NewCode("FX_BTC") //nolint // Cryptocurrency code
AAVE = NewCode("AAVE")
YFI = NewCode("YFI")
BAL = NewCode("BAL")
@@ -2512,7 +2512,7 @@ var (
NAFT = NewCode("NAFT")
SHIBLITE = NewCode("SHIBLITE")
BHD = NewCode("BHD")
THN = NewCode("THN") // nolint:misspell // false positive
THN = NewCode("THN") //nolint:misspell // false positive
DOGEDASH = NewCode("DOGEDASH")
FARA = NewCode("FARA")
FIL120 = NewCode("FIL120")
@@ -2811,7 +2811,7 @@ var (
SBR = NewCode("SBR")
BMARS = NewCode("BMARS")
GOMI = NewCode("GOMI")
ONOT = NewCode("ONOT") // nolint:misspell // false positive
ONOT = NewCode("ONOT") //nolint:misspell // false positive
GOKU = NewCode("GOKU")
MINTYS = NewCode("MINTYS")
PONYO = NewCode("PONYO")

View File

@@ -130,24 +130,24 @@ func (c *Coinmarketcap) GetCryptocurrencyHistoricalListings() ([]CryptocurrencyH
// Status Status `json:"status"`
// }{}
// nolint:gocritic // unused code, used as example
//nolint:gocritic // unused code, used as example
// err := c.CheckAccountPlan(0)
// if err != nil {
// return resp.Data, err
// }
// nolint:gocritic // unused code, used as example
//nolint:gocritic // unused code, used as example
// err = c.SendHTTPRequest(http.MethodGet, endpointCryptocurrencyHistoricalListings, nil, &resp)
// if err != nil {
// return resp.Data, err
// }
// nolint:gocritic // unused code, used as example
//nolint:gocritic // unused code, used as example
// if resp.Status.ErrorCode != 0 {
// return resp.Data, errors.New(resp.Status.ErrorMessage)
// }
// nolint:gocritic // unused code, used as example
//nolint:gocritic // unused code, used as example
// return resp.Data, nil
}

View File

@@ -240,7 +240,7 @@ func (p Pairs) FindDifferences(pairs Pairs) (newPairs, removedPairs Pairs) {
// GetRandomPair returns a random pair from a list of pairs
func (p Pairs) GetRandomPair() Pair {
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 EMPTYPAIR
}

View File

@@ -3,7 +3,6 @@ package currency
import (
"errors"
"fmt"
"io/ioutil"
"os"
"testing"
@@ -12,7 +11,7 @@ import (
func TestMain(m *testing.M) {
var err error
testhelpers.TempDir, err = ioutil.TempDir("", "gct-temp")
testhelpers.TempDir, err = os.MkdirTemp("", "gct-temp")
if err != nil {
fmt.Printf("failed to create temp file: %v", err)
os.Exit(1)

View File

@@ -3,6 +3,8 @@ package postgres
import (
"database/sql"
"fmt"
"net"
"strconv"
// import go libpq driver package
_ "github.com/lib/pq"
@@ -21,11 +23,11 @@ func Connect(cfg *database.Config) (*database.Instance, error) {
cfg.SSLMode = "disable"
}
configDSN := fmt.Sprintf("postgres://%s:%s@%s:%d/%s?sslmode=%s",
host := net.JoinHostPort(cfg.Host, strconv.FormatUint(uint64(cfg.Port), 10))
configDSN := fmt.Sprintf("postgres://%s:%s@%s/%s?sslmode=%s",
cfg.Username,
cfg.Password,
cfg.Host,
cfg.Port,
host,
cfg.Database,
cfg.SSLMode)

View File

@@ -2,7 +2,6 @@ package audit
import (
"fmt"
"io/ioutil"
"os"
"sync"
"testing"
@@ -16,7 +15,7 @@ import (
func TestMain(m *testing.M) {
var err error
testhelpers.PostgresTestDatabase = testhelpers.GetConnectionDetails()
testhelpers.TempDir, err = ioutil.TempDir("", "gct-temp")
testhelpers.TempDir, err = os.MkdirTemp("", "gct-temp")
if err != nil {
fmt.Printf("failed to create temp file: %v", err)
os.Exit(1)

View File

@@ -3,7 +3,6 @@ package candle
import (
"errors"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"testing"
@@ -39,7 +38,7 @@ func TestMain(m *testing.M) {
var err error
testhelpers.PostgresTestDatabase = testhelpers.GetConnectionDetails()
testhelpers.TempDir, err = ioutil.TempDir("", "gct-temp")
testhelpers.TempDir, err = os.MkdirTemp("", "gct-temp")
if err != nil {
fmt.Printf("failed to create temp file: %v", err)
os.Exit(1)

View File

@@ -3,7 +3,6 @@ package datahistoryjob
import (
"errors"
"fmt"
"io/ioutil"
"log"
"os"
"strings"
@@ -41,7 +40,7 @@ func TestMain(m *testing.M) {
}
var err error
testhelpers.PostgresTestDatabase = testhelpers.GetConnectionDetails()
testhelpers.TempDir, err = ioutil.TempDir("", "gct-temp")
testhelpers.TempDir, err = os.MkdirTemp("", "gct-temp")
if err != nil {
log.Fatal(err)
}

View File

@@ -3,7 +3,6 @@ package datahistoryjobresult
import (
"database/sql"
"fmt"
"io/ioutil"
"log"
"os"
"testing"
@@ -38,7 +37,7 @@ func TestMain(m *testing.M) {
}
var err error
testhelpers.PostgresTestDatabase = testhelpers.GetConnectionDetails()
testhelpers.TempDir, err = ioutil.TempDir("", "gct-temp")
testhelpers.TempDir, err = os.MkdirTemp("", "gct-temp")
if err != nil {
log.Fatal(err)
}

View File

@@ -2,7 +2,6 @@ package exchange
import (
"fmt"
"io/ioutil"
"os"
"path/filepath"
"testing"
@@ -39,7 +38,7 @@ func TestMain(m *testing.M) {
var err error
testhelpers.PostgresTestDatabase = testhelpers.GetConnectionDetails()
testhelpers.TempDir, err = ioutil.TempDir("", "gct-temp")
testhelpers.TempDir, err = os.MkdirTemp("", "gct-temp")
if err != nil {
fmt.Printf("failed to create temp file: %v", err)
os.Exit(1)

View File

@@ -2,7 +2,6 @@ package script
import (
"fmt"
"io/ioutil"
"os"
"sync"
"testing"
@@ -21,7 +20,7 @@ var (
func TestMain(m *testing.M) {
var err error
testhelpers.PostgresTestDatabase = testhelpers.GetConnectionDetails()
testhelpers.TempDir, err = ioutil.TempDir("", "gct-temp")
testhelpers.TempDir, err = os.MkdirTemp("", "gct-temp")
if err != nil {
fmt.Printf("failed to create temp file: %v", err)
os.Exit(1)

View File

@@ -2,7 +2,6 @@ package trade
import (
"fmt"
"io/ioutil"
"log"
"os"
"testing"
@@ -41,11 +40,16 @@ func TestMain(m *testing.M) {
}
var err error
testhelpers.PostgresTestDatabase = testhelpers.GetConnectionDetails()
testhelpers.TempDir, err = ioutil.TempDir("", "gct-temp")
testhelpers.TempDir, err = os.MkdirTemp("", "gct-temp")
if err != nil {
log.Fatal(err)
}
os.Exit(m.Run())
exitCode := m.Run()
if err = os.RemoveAll(testhelpers.TempDir); err != nil {
fmt.Printf("failed to remove temp dir: %s", err)
}
os.Exit(exitCode)
}
func TestTrades(t *testing.T) {

View File

@@ -3,7 +3,6 @@ package withdraw
import (
"errors"
"fmt"
"io/ioutil"
"math/rand"
"os"
"testing"
@@ -38,7 +37,7 @@ func TestMain(m *testing.M) {
var err error
testhelpers.PostgresTestDatabase = testhelpers.GetConnectionDetails()
testhelpers.TempDir, err = ioutil.TempDir("", "gct-temp")
testhelpers.TempDir, err = os.MkdirTemp("", "gct-temp")
if err != nil {
fmt.Printf("failed to create temp file: %v", err)
os.Exit(1)
@@ -139,7 +138,7 @@ func seedWithdrawData() {
},
},
}
rnd := rand.Intn(2) // nolint:gosec // used for generating test data, no need to import crypo/rand
rnd := rand.Intn(2) //nolint:gosec // used for generating test data, no need to import crypo/rand
if rnd == 0 {
resp.RequestDetails.Currency = currency.AUD
resp.RequestDetails.Type = 1

View File

@@ -2,7 +2,6 @@ package testhelpers
import (
"fmt"
"io/ioutil"
"os"
"path/filepath"
"testing"
@@ -14,7 +13,7 @@ import (
func TestMain(m *testing.M) {
var err error
PostgresTestDatabase = GetConnectionDetails()
TempDir, err = ioutil.TempDir("", "gct-temp")
TempDir, err = os.MkdirTemp("", "gct-temp")
if err != nil {
fmt.Printf("failed to create temp file: %v", err)
os.Exit(1)

View File

@@ -169,8 +169,9 @@ func (m *apiServerManager) StartRESTServer() error {
m.restRouter = m.newRouter(true)
if m.restHTTPServer == nil {
m.restHTTPServer = &http.Server{
Addr: m.restListenAddress,
Handler: m.restRouter,
Addr: m.restListenAddress,
Handler: m.restRouter,
ReadHeaderTimeout: time.Minute,
}
}
m.wgRest.Add(1)
@@ -429,8 +430,9 @@ func (m *apiServerManager) StartWebsocketServer() error {
m.websocketRouter = m.newRouter(false)
if m.websocketHTTPServer == nil {
m.websocketHTTPServer = &http.Server{
Addr: m.websocketListenAddress,
Handler: m.websocketRouter,
Addr: m.websocketListenAddress,
Handler: m.websocketRouter,
ReadHeaderTimeout: time.Minute,
}
}

View File

@@ -710,7 +710,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 // nolint:nilerr // error is returned in the job result
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 {
@@ -759,13 +759,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 // nolint:nilerr // error is returned in the job result
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 // nolint:nilerr // error is returned in the job result
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 {
@@ -826,13 +826,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 // nolint:nilerr // error is returned in the job result
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 // nolint:nilerr // error is returned in the job result
return r, nil //nolint:nilerr // error is returned in the job result
}
candles.SourceJobID = job.ID
err = m.saveCandlesInBatches(job, &candles, r)
@@ -865,13 +865,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 // nolint:nilerr // error is returned in the job result
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 // nolint:nilerr // error is returned in the job result
return r, nil //nolint:nilerr // error is returned in the job result
}
newCandles.SourceJobID = job.ID
err = m.saveCandlesInBatches(job, &candles, r)
@@ -913,14 +913,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 // nolint:nilerr // error is returned in the job result
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 // nolint:nilerr // error is returned in the job result
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)

View File

@@ -654,7 +654,7 @@ func TestCompareJobsToData(t *testing.T) {
}
}
func TestRunJob(t *testing.T) { // nolint // TO-DO: Fix race t.Parallel() usage
func TestRunJob(t *testing.T) { //nolint // TO-DO: Fix race t.Parallel() usage
testCases := []*DataHistoryJob{
{
Nickname: "TestRunJobDataHistoryCandleDataType",

View File

@@ -118,7 +118,7 @@ func TestGetRPCEndpoints(t *testing.T) {
}
}
func TestSetSubsystem(t *testing.T) { // nolint // TO-DO: Fix race t.Parallel() usage
func TestSetSubsystem(t *testing.T) { //nolint // TO-DO: Fix race t.Parallel() usage
testCases := []struct {
Subsystem string
Engine *Engine

View File

@@ -2579,7 +2579,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
//nolint:nilerr // error is returned in the GCTScriptQueryResponse
return &gctrpc.GCTScriptQueryResponse{Status: MsgStatusError, Data: err.Error()}, nil
}
@@ -2626,7 +2626,7 @@ func (s *RPCServer) GCTScriptExecute(_ context.Context, r *gctrpc.GCTScriptExecu
script := filepath.Join(r.Script.Path, r.Script.Name)
if err := gctVM.Load(script); err != nil {
return &gctrpc.GenericResponse{ // nolint:nilerr // error is returned in the generic response
return &gctrpc.GenericResponse{ //nolint:nilerr // error is returned in the generic response
Status: MsgStatusError,
Data: err.Error(),
}, nil
@@ -2648,7 +2648,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 // nolint:nilerr // error is returned in the generic response
return &gctrpc.GenericResponse{Status: MsgStatusError, Data: err.Error()}, nil //nolint:nilerr // error is returned in the generic response
}
v, f := gctscript.AllVMSync.Load(UUID)
@@ -2818,7 +2818,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 // nolint:nilerr // error is returned in the generic response
return &gctrpc.GenericResponse{Status: "error", Data: err.Error()}, nil //nolint:nilerr // error is returned in the generic response
}
return &gctrpc.GenericResponse{
@@ -2836,7 +2836,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
//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
@@ -2844,7 +2844,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 // nolint:nilerr // error is returned in the generic response
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
}

View File

@@ -22,14 +22,17 @@ const (
// changed while the same keys can be used.
ContextSubAccountFlag contextCredential = "subaccountoverride"
apiKeyDisplaySize = 16
)
// Default credential values
const (
Key = "key"
Secret = "secret"
SubAccountSTR = "subaccount"
ClientID = "clientid"
OneTimePassword = "otp"
PEMKey = "pemkey"
apiKeyDisplaySize = 16
)
var (

View File

@@ -13,7 +13,9 @@ const (
alerting
dataToActuatorDefaultBuffer = 1
PreAllocCommsDefaultBuffer = 5
// PreAllocCommsDefaultBuffer is the default buffer size for comms
PreAllocCommsDefaultBuffer = 5
)
var (

View File

@@ -101,8 +101,10 @@ func BenchmarkAlert(b *testing.B) {
}
}
// 150352 9916 ns/op 681 B/op 4 allocs/op // PREV
// 87436 14724 ns/op 682 B/op 4 allocs/op // CURRENT
// BenchmarkWait benchmark
//
// 150352 9916 ns/op 681 B/op 4 allocs/op // PREV
// 87436 14724 ns/op 682 B/op 4 allocs/op // CURRENT
func BenchmarkWait(b *testing.B) {
n := Notice{}
for x := 0; x < b.N; x++ {

View File

@@ -62,7 +62,7 @@ func Supported() Items {
return supportedList
}
// returns an Item to string
// String converts an Item to its string representation
func (a Item) String() string {
switch a {
case Spot:

View File

@@ -775,8 +775,9 @@ func (bi *Binanceus) GetTradeFee(ctx context.Context, recvWindow uint, symbol st
// GetAssetDistributionHistory this endpoint to query
// asset distribution records, including for staking, referrals and airdrops etc.
//
// INPUTS:
// asset: string , startTime & endTime unix time in Milli seconds, recvWindow(duration in milli seconds > 2000 to < 6000)
// asset: string , startTime & endTime unix time in Milli seconds, recvWindow(duration in milli seconds > 2000 to < 6000)
func (bi *Binanceus) GetAssetDistributionHistory(ctx context.Context, asset string, startTime, endTime uint64, recvWindow uint) (*AssetDistributionHistories, error) {
params := url.Values{}
timestamp := time.Now().UnixMilli()

View File

@@ -309,7 +309,7 @@ func (b *Bitflyer) SendHTTPRequest(ctx context.Context, ep exchange.URL, path st
// if you have access and update the authenticated requests
// TODO: Fill out this function once API access is obtained
func (b *Bitflyer) SendAuthHTTPRequest() {
// nolint:gocritic // code example
//nolint:gocritic // code example
// headers := make(map[string]string)
// headers["ACCESS-KEY"] = b.API.Credentials.Key
// headers["ACCESS-TIMESTAMP"] = strconv.FormatInt(time.Now().UnixNano(), 10)

View File

@@ -254,14 +254,7 @@ func TestMarketSellOrder(t *testing.T) {
func TestUpdateTicker(t *testing.T) {
t.Parallel()
cp := currency.NewPair(currency.QTUM, currency.KRW)
_, err := b.UpdateTicker(context.Background(), cp, asset.Spot)
if err != nil {
t.Fatal(err)
}
cp = currency.NewPair(currency.BTC, currency.KRW)
_, err = b.UpdateTicker(context.Background(), cp, asset.Spot)
if err != nil {
if _, err := b.UpdateTicker(context.Background(), cp, asset.Spot); err != nil {
t.Fatal(err)
}
}

View File

@@ -58,8 +58,8 @@ const (
// Authenticated endpoints
bitmexEndpointAPIkeys = "/apiKey"
bitmexEndpointDisableAPIkey = "/apiKey/disable" // nolint:gosec // false positive
bitmexEndpointEnableAPIkey = "/apiKey/enable" // nolint:gosec // false positive
bitmexEndpointDisableAPIkey = "/apiKey/disable" //nolint:gosec // false positive
bitmexEndpointEnableAPIkey = "/apiKey/enable" //nolint:gosec // false positive
bitmexEndpointTrollboxSend = "/chat"
bitmexEndpointExecution = "/execution"
bitmexEndpointExecutionTradeHistory = "/execution/tradeHistory"

View File

@@ -783,7 +783,7 @@ func TestWithdraw(t *testing.T) {
Amount: -1,
Currency: currency.BTC,
Description: "WITHDRAW IT ALL",
OneTimePassword: 000000, // nolint // gocritic false positive
OneTimePassword: 000000, //nolint // gocritic false positive
}
if areTestAPIKeysSet() && !canManipulateRealOrders {

View File

@@ -17,7 +17,9 @@ import (
"github.com/thrasher-corp/gocryptotrader/currency"
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
"github.com/thrasher-corp/gocryptotrader/log"
)
const (
@@ -654,3 +656,12 @@ func (b *Bitstamp) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange
func parseTime(dateTime string) (time.Time, error) {
return time.Parse(bitstampTimeLayout, dateTime)
}
func filterOrderbookZeroBidPrice(ob *orderbook.Base) {
if len(ob.Bids) == 0 || ob.Bids[len(ob.Bids)-1].Price != 0 {
return
}
log.Warnf(log.ExchangeSys, "%s %s %s orderbook has zero bid price, filtering.", ob.Exchange, ob.Pair, ob.Asset)
ob.Bids = ob.Bids[0 : len(ob.Bids)-1]
}

View File

@@ -14,6 +14,7 @@ import (
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
"github.com/thrasher-corp/gocryptotrader/exchanges/kline"
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
"github.com/thrasher-corp/gocryptotrader/portfolio/banking"
"github.com/thrasher-corp/gocryptotrader/portfolio/withdraw"
)
@@ -757,3 +758,37 @@ func TestGetHistoricTrades(t *testing.T) {
t.Error(err)
}
}
func TestOrderbookZeroBidPrice(t *testing.T) {
t.Parallel()
ob := &orderbook.Base{
Exchange: "Bitstamp",
Pair: currency.NewPair(currency.BTC, currency.USD),
Asset: asset.Spot,
}
filterOrderbookZeroBidPrice(ob)
ob.Bids = orderbook.Items{
{Price: 69, Amount: 1337},
{Price: 0, Amount: 69},
}
filterOrderbookZeroBidPrice(ob)
if ob.Bids[0].Price != 69 || ob.Bids[0].Amount != 1337 || len(ob.Bids) != 1 {
t.Error("invalid orderbook bid values")
}
ob.Bids = orderbook.Items{
{Price: 59, Amount: 1337},
{Price: 42, Amount: 8595},
}
filterOrderbookZeroBidPrice(ob)
if ob.Bids[0].Price != 59 || ob.Bids[0].Amount != 1337 ||
ob.Bids[1].Price != 42 || ob.Bids[1].Amount != 8595 || len(ob.Bids) != 2 {
t.Error("invalid orderbook bid values")
}
}

View File

@@ -21,7 +21,7 @@ import (
)
const (
bitstampWSURL = "wss://ws.bitstamp.net" // nolint // gosec false positive
bitstampWSURL = "wss://ws.bitstamp.net" //nolint // gosec false positive
)
// WsConnect connects to a websocket feed
@@ -118,7 +118,7 @@ func (b *Bitstamp) wsHandleData(respRaw []byte) error {
return err
}
err = b.wsUpdateOrderbook(wsOrderBookTemp.Data, p, asset.Spot)
err = b.wsUpdateOrderbook(&wsOrderBookTemp.Data, p, asset.Spot)
if err != nil {
return err
}
@@ -251,12 +251,21 @@ func (b *Bitstamp) Unsubscribe(channelsToUnsubscribe []stream.ChannelSubscriptio
return nil
}
func (b *Bitstamp) wsUpdateOrderbook(update websocketOrderBook, p currency.Pair, assetType asset.Item) error {
func (b *Bitstamp) wsUpdateOrderbook(update *websocketOrderBook, p currency.Pair, assetType asset.Item) error {
if len(update.Asks) == 0 && len(update.Bids) == 0 {
return errors.New("no orderbook data")
}
asks := make([]orderbook.Item, len(update.Asks))
bids := make([]orderbook.Item, len(update.Bids))
obUpdate := &orderbook.Base{
Bids: make(orderbook.Items, len(update.Bids)),
Asks: make(orderbook.Items, len(update.Asks)),
Pair: p,
LastUpdated: time.Unix(update.Timestamp, 0),
Asset: assetType,
Exchange: b.Name,
VerifyOrderbook: b.CanVerifyOrderbook,
}
for i := range update.Asks {
target, err := strconv.ParseFloat(update.Asks[i][0], 64)
if err != nil {
@@ -266,7 +275,7 @@ func (b *Bitstamp) wsUpdateOrderbook(update websocketOrderBook, p currency.Pair,
if err != nil {
return err
}
asks[i] = orderbook.Item{Price: target, Amount: amount}
obUpdate.Asks[i] = orderbook.Item{Price: target, Amount: amount}
}
for i := range update.Bids {
target, err := strconv.ParseFloat(update.Bids[i][0], 64)
@@ -277,17 +286,10 @@ func (b *Bitstamp) wsUpdateOrderbook(update websocketOrderBook, p currency.Pair,
if err != nil {
return err
}
bids[i] = orderbook.Item{Price: target, Amount: amount}
obUpdate.Bids[i] = orderbook.Item{Price: target, Amount: amount}
}
return b.Websocket.Orderbook.LoadSnapshot(&orderbook.Base{
Bids: bids,
Asks: asks,
Pair: p,
LastUpdated: time.Unix(update.Timestamp, 0),
Asset: assetType,
Exchange: b.Name,
VerifyOrderbook: b.CanVerifyOrderbook,
})
filterOrderbookZeroBidPrice(obUpdate)
return b.Websocket.Orderbook.LoadSnapshot(obUpdate)
}
func (b *Bitstamp) seedOrderBook(ctx context.Context) error {
@@ -306,27 +308,31 @@ func (b *Bitstamp) seedOrderBook(ctx context.Context) error {
return err
}
var newOrderBook orderbook.Base
newOrderBook.Asks = make(orderbook.Items, len(orderbookSeed.Asks))
newOrderBook := &orderbook.Base{
Pair: p[x],
Asset: asset.Spot,
Exchange: b.Name,
VerifyOrderbook: b.CanVerifyOrderbook,
Bids: make(orderbook.Items, len(orderbookSeed.Bids)),
Asks: make(orderbook.Items, len(orderbookSeed.Asks)),
}
for i := range orderbookSeed.Asks {
newOrderBook.Asks[i] = orderbook.Item{
Price: orderbookSeed.Asks[i].Price,
Amount: orderbookSeed.Asks[i].Amount,
}
}
newOrderBook.Bids = make(orderbook.Items, len(orderbookSeed.Bids))
for i := range orderbookSeed.Bids {
newOrderBook.Bids[i] = orderbook.Item{
Price: orderbookSeed.Bids[i].Price,
Amount: orderbookSeed.Bids[i].Amount,
}
}
newOrderBook.Pair = p[x]
newOrderBook.Asset = asset.Spot
newOrderBook.Exchange = b.Name
newOrderBook.VerifyOrderbook = b.CanVerifyOrderbook
err = b.Websocket.Orderbook.LoadSnapshot(&newOrderBook)
filterOrderbookZeroBidPrice(newOrderBook)
err = b.Websocket.Orderbook.LoadSnapshot(newOrderBook)
if err != nil {
return err
}

View File

@@ -414,6 +414,8 @@ func (b *Bitstamp) UpdateOrderbook(ctx context.Context, p currency.Pair, assetTy
}
}
filterOrderbookZeroBidPrice(book)
book.Asks = make(orderbook.Items, len(orderbookNew.Asks))
for x := range orderbookNew.Asks {
book.Asks[x] = orderbook.Item{
@@ -421,6 +423,7 @@ func (b *Bitstamp) UpdateOrderbook(ctx context.Context, p currency.Pair, assetTy
Price: orderbookNew.Asks[x].Price,
}
}
err = book.Process()
if err != nil {
return book, err

View File

@@ -379,7 +379,7 @@ func (b *BTSE) UpdateOrderbook(ctx context.Context, p currency.Pair, assetType a
Amount: a.SellQuote[x].Size,
})
}
book.Asks.Reverse() // Reverse asks for correct alignment
book.Asks.SortAsks() // Sort asks for correct alignment
book.Pair = p
book.Exchange = b.Name
book.Asset = assetType

View File

@@ -370,11 +370,13 @@ type orderbookResponse struct {
Error
}
// DepositWalletInfo stores wallet deposit info
type DepositWalletInfo struct {
Coin string `json:"coin"`
Chains []ChainInfo `json:"chains"`
}
// ChainInfo stores a coins chain info
type ChainInfo struct {
ChainType string `json:"chain_type"`
DepositAddress string `json:"address_deposit"`

View File

@@ -497,5 +497,5 @@ func (i *instrumentMap) GetInstrumentIDs() []int64 {
}
func getNonce() int64 {
return rand.Int63n(coinutMaxNonce-1) + 1 // nolint:gosec // basic number generation required, no need for crypo/rand
return rand.Int63n(coinutMaxNonce-1) + 1 //nolint:gosec // basic number generation required, no need for crypo/rand
}

View File

@@ -28,7 +28,7 @@ import (
)
const (
warningBase64DecryptSecretKeyFailed = "exchange %s unable to base64 decode secret key.. Disabling Authenticated API support" // nolint // False positive (G101: Potential hardcoded credentials)
warningBase64DecryptSecretKeyFailed = "exchange %s unable to base64 decode secret key.. Disabling Authenticated API support" //nolint // False positive (G101: Potential hardcoded credentials)
// DefaultHTTPTimeout is the default HTTP/HTTPS Timeout for exchange requests
DefaultHTTPTimeout = time.Second * 15
// DefaultWebsocketResponseCheckTimeout is the default delay in checking for an expected websocket response
@@ -330,7 +330,7 @@ func (b *Base) GetPairFormat(assetType asset.Item, requestFormat bool) (currency
func (b *Base) GetEnabledPairs(a asset.Item) (currency.Pairs, error) {
err := b.CurrencyPairs.IsAssetEnabled(a)
if err != nil {
return nil, nil // nolint:nilerr // non-fatal error
return nil, nil //nolint:nilerr // non-fatal error
}
format, err := b.GetPairFormat(a, false)
if err != nil {
@@ -1117,7 +1117,7 @@ func (e *Endpoints) SetRunning(key, val string) error {
key,
val,
e.Exchange)
return nil // nolint:nilerr // non-fatal error as we won't update the running URL
return nil //nolint:nilerr // non-fatal error as we won't update the running URL
}
e.defaults[key] = val
return nil

View File

@@ -133,11 +133,17 @@ func (g *Gemini) GetAuction(ctx context.Context, currencyPair string) (Auction,
//
// currencyPair - example "btcusd"
// params -- [optional]
// since - [timestamp] Only returns auction events after the specified
//
// since - [timestamp] Only returns auction events after the specified
//
// timestamp.
// limit_auction_results - [integer] The maximum number of auction
//
// limit_auction_results - [integer] The maximum number of auction
//
// events to return.
// include_indicative - [bool] Whether to include publication of
//
// include_indicative - [bool] Whether to include publication of
//
// indicative prices and quantities.
func (g *Gemini) GetAuctionHistory(ctx context.Context, currencyPair string, params url.Values) ([]AuctionHistory, error) {
path := common.EncodeURLValues(fmt.Sprintf("/v%s/%s/%s/%s", geminiAPIVersion, geminiAuction, currencyPair, geminiAuctionHistory), params)

View File

@@ -42,7 +42,7 @@ const (
huobiBasisData = "/index/market/history/swap_basis"
huobiSwapAccInfo = "/swap-api/v1/swap_account_info"
huobiSwapPosInfo = "/swap-api/v1/swap_position_info"
huobiSwapAssetsAndPos = "/swap-api/v1/swap_account_position_info" // nolint // false positive gosec
huobiSwapAssetsAndPos = "/swap-api/v1/swap_account_position_info" //nolint // false positive gosec
huobiSwapSubAccList = "/swap-api/v1/swap_sub_account_list"
huobiSwapSubAccInfo = "/swap-api/v1/swap_sub_account_info"
huobiSwapSubAccPosInfo = "/swap-api/v1/swap_sub_position_info"

View File

@@ -75,8 +75,9 @@ func (i *ItBit) GetTradeHistory(ctx context.Context, currencyPair, tradeID strin
// GetWallets returns information about all wallets associated with the account.
//
// params --
// page - [optional] page to return example 1. default 1
// perPage - [optional] items per page example 50, default 50 max 50
//
// page - [optional] page to return example 1. default 1
// perPage - [optional] items per page example 50, default 50 max 50
func (i *ItBit) GetWallets(ctx context.Context, params url.Values) ([]Wallet, error) {
creds, err := i.GetCredentials(ctx)
if err != nil {

View File

@@ -3,7 +3,6 @@ package kline
import (
"errors"
"fmt"
"io/ioutil"
"math/rand"
"os"
"path/filepath"
@@ -106,11 +105,11 @@ func TestCreateKline(t *testing.T) {
rand.Seed(time.Now().Unix())
for i := 0; i < 24000; i++ {
trades = append(trades, order.TradeHistory{
Timestamp: time.Now().Add((time.Duration(rand.Intn(10)) * time.Minute) + // nolint:gosec // no need to import crypo/rand for testing
(time.Duration(rand.Intn(10)) * time.Second)), // nolint:gosec // no need to import crypo/rand for testing
Timestamp: time.Now().Add((time.Duration(rand.Intn(10)) * time.Minute) + //nolint:gosec // no need to import crypo/rand for testing
(time.Duration(rand.Intn(10)) * time.Second)), //nolint:gosec // no need to import crypo/rand for testing
TID: crypto.HexEncodeToString([]byte(string(rune(i)))),
Amount: float64(rand.Intn(20)) + 1, // nolint:gosec // no need to import crypo/rand for testing
Price: 1000 + float64(rand.Intn(1000)), // nolint:gosec // no need to import crypo/rand for testing
Amount: float64(rand.Intn(20)) + 1, //nolint:gosec // no need to import crypo/rand for testing
Price: 1000 + float64(rand.Intn(1000)), //nolint:gosec // no need to import crypo/rand for testing
})
}
@@ -461,7 +460,7 @@ func TestItem_SortCandlesByTimestamp(t *testing.T) {
}
for x := 0; x < 100; x++ {
y := rand.Float64() // nolint:gosec // used for generating test data, no need to import crypo/rand
y := rand.Float64() //nolint:gosec // used for generating test data, no need to import crypo/rand
tempKline.Candles = append(tempKline.Candles,
Candle{
Time: time.Now().AddDate(0, 0, -x),
@@ -497,7 +496,7 @@ func setupTest(t *testing.T) {
var err error
testhelpers.MigrationDir = filepath.Join("..", "..", "database", "migrations")
testhelpers.PostgresTestDatabase = testhelpers.GetConnectionDetails()
testhelpers.TempDir, err = ioutil.TempDir("", "gct-temp")
testhelpers.TempDir, err = os.MkdirTemp("", "gct-temp")
if err != nil {
t.Fatalf("failed to create temp file: %v", err)
}
@@ -857,7 +856,7 @@ func BenchmarkJustifyIntervalTimeStoringUnixValues1(b *testing.B) {
tt2 := time.Now().Add(-time.Hour)
tt3 := time.Now().Add(time.Hour)
for i := 0; i < b.N; i++ {
if tt1.Unix() == tt2.Unix() || // nolint:staticcheck // it is a benchmark to demonstrate inefficiency in calling
if tt1.Unix() == tt2.Unix() || //nolint:staticcheck // it is a benchmark to demonstrate inefficiency in calling
(tt1.Unix() > tt2.Unix() && tt1.Unix() < tt3.Unix()) {
}
@@ -873,7 +872,7 @@ func BenchmarkJustifyIntervalTimeStoringUnixValues2(b *testing.B) {
tt2 := time.Now().Add(-time.Hour).Unix()
tt3 := time.Now().Add(time.Hour).Unix()
for i := 0; i < b.N; i++ {
if tt1 >= tt2 && tt1 <= tt3 { // nolint:staticcheck // it is a benchmark to demonstrate inefficiency in calling
if tt1 >= tt2 && tt1 <= tt3 { //nolint:staticcheck // it is a benchmark to demonstrate inefficiency in calling
}
}

View File

@@ -185,7 +185,7 @@ func (o *OHLC) GetSimpleMovingAverage(option []float64, period int64) ([]float64
}
// GetExponentialMovingAverageOnClose returns the EMA on the close price set for
// the given period.
// the given period.
func (k *Item) GetExponentialMovingAverageOnClose(period int64) ([]float64, error) {
ohlc := k.GetOHLC()
return ohlc.GetExponentialMovingAverage(ohlc.Close, period)

View File

@@ -977,11 +977,12 @@ func (k *Kraken) CancelExistingOrder(ctx context.Context, txid string) (CancelOr
return response.Result, GetError(response.Error)
}
// GetError parse Exchange errors in response and return the first one
// GetError parse Exchange errors in response and return the first one.
//
// Error format from API doc:
// error = array of error messages in the format of:
// <char-severity code><string-error category>:<string-error type>[:<string-extra info>]
// severity code can be E for error or W for warning
// - error = array of error messages in the format of:
// <char-severity code><string-error category>:<string-error type>[:<string-extra info>]
// severity code can be E for error or W for warning
func GetError(apiErrors []string) error {
const exchangeName = "Kraken"
for _, e := range apiErrors {

View File

@@ -475,6 +475,7 @@ func TestGetHistoricCandlesExtended(t *testing.T) {
}
func Test_FormatExchangeKlineInterval(t *testing.T) {
t.Parallel()
testCases := []struct {
name string
interval kline.Interval
@@ -511,6 +512,7 @@ func Test_FormatExchangeKlineInterval(t *testing.T) {
test := testCases[x]
t.Run(test.name, func(t *testing.T) {
t.Parallel()
ret := l.FormatExchangeKlineInterval(test.interval)
if ret != test.output {

View File

@@ -404,7 +404,9 @@ var filterOrdersByTypeBenchmark = &[]Detail{
{Type: Limit},
}
// 392455 3226 ns/op 15840 B/op 5 allocs/op // PREV
// BenchmarkFilterOrdersByType benchmark
//
// 392455 3226 ns/op 15840 B/op 5 allocs/op // PREV
// 9486490 109.5 ns/op 0 B/op 0 allocs/op // CURRENT
func BenchmarkFilterOrdersByType(b *testing.B) {
for x := 0; x < b.N; x++ {
@@ -454,7 +456,9 @@ var filterOrdersBySideBenchmark = &[]Detail{
{Side: Ask},
}
// 372594 3049 ns/op 15840 B/op 5 allocs/op // PREV
// BenchmarkFilterOrdersBySide benchmark
//
// 372594 3049 ns/op 15840 B/op 5 allocs/op // PREV
// 7412187 148.8 ns/op 0 B/op 0 allocs/op // CURRENT
func BenchmarkFilterOrdersBySide(b *testing.B) {
for x := 0; x < b.N; x++ {
@@ -537,7 +541,9 @@ var filterOrdersByTimeRangeBenchmark = &[]Detail{
{Date: time.Unix(100, 0)},
}
// 390822 3335 ns/op 15840 B/op 5 allocs/op // PREV
// BenchmarkFilterOrdersByTimeRange benchmark
//
// 390822 3335 ns/op 15840 B/op 5 allocs/op // PREV
// 6201034 172.1 ns/op 0 B/op 0 allocs/op // CURRENT
func BenchmarkFilterOrdersByTimeRange(b *testing.B) {
for x := 0; x < b.N; x++ {
@@ -615,7 +621,9 @@ var filterOrdersByPairsBenchmark = &[]Detail{
{Pair: currency.NewPair(currency.BTC, currency.USD)},
}
// 400032 2977 ns/op 15840 B/op 5 allocs/op // PREV
// BenchmarkFilterOrdersByPairs benchmark
//
// 400032 2977 ns/op 15840 B/op 5 allocs/op // PREV
// 6977242 172.8 ns/op 0 B/op 0 allocs/op // CURRENT
func BenchmarkFilterOrdersByPairs(b *testing.B) {
pairs := []currency.Pair{currency.NewPair(currency.BTC, currency.USD)}

View File

@@ -622,7 +622,7 @@ func (t Type) Lower() string {
// Title returns the type titleized, eg "Limit"
func (t Type) Title() string {
return strings.Title(strings.ToLower(t.String())) // nolint:staticcheck // Ignore Title usage warning
return strings.Title(strings.ToLower(t.String())) //nolint:staticcheck // Ignore Title usage warning
}
// String implements the stringer interface
@@ -675,7 +675,7 @@ func (s Side) Lower() string {
// Title returns the side titleized, eg "Buy"
func (s Side) Title() string {
return strings.Title(strings.ToLower(s.String())) // nolint:staticcheck // Ignore Title usage warning
return strings.Title(strings.ToLower(s.String())) //nolint:staticcheck // Ignore Title usage warning
}
// IsShort returns if the side is short

View File

@@ -62,7 +62,7 @@ func (s *stack) Display() {
fmt.Println("TOTAL COUNT:", s.getCount())
}
// 158 9,521,717 ns/op 9600104 B/op 100001 allocs/op
// 158 9,521,717 ns/op 9600104 B/op 100001 allocs/op
func BenchmarkWithoutStack(b *testing.B) {
var n *Node
b.ReportAllocs()

View File

@@ -492,12 +492,12 @@ func TestProcessOrderbook(t *testing.T) {
m.Unlock()
wg.Add(1)
go func() {
newName := "Exchange" + strconv.FormatInt(rand.Int63(), 10) // nolint:gosec // no need to import crypo/rand for testing
newName := "Exchange" + strconv.FormatInt(rand.Int63(), 10) //nolint:gosec // no need to import crypo/rand for testing
newPairs := currency.NewPair(currency.NewCode("BTC"+strconv.FormatInt(rand.Int63(), 10)),
currency.NewCode("USD"+strconv.FormatInt(rand.Int63(), 10))) // nolint:gosec // no need to import crypo/rand for testing
currency.NewCode("USD"+strconv.FormatInt(rand.Int63(), 10))) //nolint:gosec // no need to import crypo/rand for testing
asks := []Item{{Price: rand.Float64(), Amount: rand.Float64()}} // nolint:gosec // no need to import crypo/rand for testing
bids := []Item{{Price: rand.Float64(), Amount: rand.Float64()}} // nolint:gosec // no need to import crypo/rand for testing
asks := []Item{{Price: rand.Float64(), Amount: rand.Float64()}} //nolint:gosec // no need to import crypo/rand for testing
bids := []Item{{Price: rand.Float64(), Amount: rand.Float64()}} //nolint:gosec // no need to import crypo/rand for testing
base := &Base{
Pair: newPairs,
Asks: asks,
@@ -558,7 +558,7 @@ func deployUnorderedSlice() Items {
var items []Item
rand.Seed(time.Now().UnixNano())
for i := 0; i < 1000; i++ {
items = append(items, Item{Amount: 1, Price: rand.Float64(), ID: rand.Int63()}) // nolint:gosec // Not needed in tests
items = append(items, Item{Amount: 1, Price: rand.Float64(), ID: rand.Int63()}) //nolint:gosec // Not needed in tests
}
return items
}
@@ -596,7 +596,7 @@ func deploySliceOrdered() Items {
rand.Seed(time.Now().UnixNano())
var items []Item
for i := 0; i < 1000; i++ {
items = append(items, Item{Amount: 1, Price: float64(i + 1), ID: rand.Int63()}) // nolint:gosec // Not needed in tests
items = append(items, Item{Amount: 1, Price: float64(i + 1), ID: rand.Int63()}) //nolint:gosec // Not needed in tests
}
return items
}
@@ -620,7 +620,7 @@ func TestReverse(t *testing.T) {
t.Fatal(err)
}
b.Asks = append(b.Bids[:0:0], b.Bids...) // nolint:gocritic // Short hand
b.Asks = append(b.Bids[:0:0], b.Bids...) //nolint:gocritic // Short hand
err = b.Verify()
if !errors.Is(err, errPriceOutOfOrder) {
t.Fatalf("error expected %v received %v", errPriceOutOfOrder, err)
@@ -645,11 +645,11 @@ func BenchmarkReverse(b *testing.B) {
}
}
// 20209 56385 ns/op 49189 B/op 2 allocs/op
// 20209 56385 ns/op 49189 B/op 2 allocs/op
func BenchmarkSortAsksDecending(b *testing.B) {
s := deploySliceOrdered()
for i := 0; i < b.N; i++ {
// nolint: gocritic
//nolint: gocritic
ts := append(s[:0:0], s...)
ts.SortAsks()
}
@@ -660,7 +660,7 @@ func BenchmarkSortBidsAscending(b *testing.B) {
s := deploySliceOrdered()
s.Reverse()
for i := 0; i < b.N; i++ {
// nolint: gocritic
//nolint: gocritic
ts := append(s[:0:0], s...)
ts.SortBids()
}
@@ -670,7 +670,7 @@ func BenchmarkSortBidsAscending(b *testing.B) {
func BenchmarkSortAsksStandard(b *testing.B) {
s := deployUnorderedSlice()
for i := 0; i < b.N; i++ {
// nolint: gocritic
//nolint: gocritic
ts := append(s[:0:0], s...)
ts.SortAsks()
}
@@ -680,7 +680,7 @@ func BenchmarkSortAsksStandard(b *testing.B) {
func BenchmarkSortBidsStandard(b *testing.B) {
s := deployUnorderedSlice()
for i := 0; i < b.N; i++ {
// nolint: gocritic
//nolint: gocritic
ts := append(s[:0:0], s...)
ts.SortBids()
}
@@ -690,7 +690,7 @@ func BenchmarkSortBidsStandard(b *testing.B) {
func BenchmarkSortAsksAscending(b *testing.B) {
s := deploySliceOrdered()
for i := 0; i < b.N; i++ {
// nolint: gocritic
//nolint: gocritic
ts := append(s[:0:0], s...)
ts.SortAsks()
}
@@ -701,7 +701,7 @@ func BenchmarkSortBidsDescending(b *testing.B) {
s := deploySliceOrdered()
s.Reverse()
for i := 0; i < b.N; i++ {
// nolint: gocritic
//nolint: gocritic
ts := append(s[:0:0], s...)
ts.SortBids()
}

View File

@@ -25,7 +25,7 @@ func TestUnsafe(t *testing.T) {
ob2 := &externalBook{}
ob.Lock()
ob.Unlock() // nolint:staticcheck, gocritic // Not needed in test
ob.Unlock() //nolint:staticcheck, gocritic // Not needed in test
ob.LockWith(ob2)
ob.UnlockWith(ob2)
}

View File

@@ -20,268 +20,335 @@ import (
"github.com/thrasher-corp/gocryptotrader/portfolio/withdraw"
)
// CustomEx creates a mock custom exchange
type CustomEx struct {
exchange.Base
}
// Setup is a mock method for CustomEx
func (c *CustomEx) Setup(exch *config.Exchange) error {
return nil
}
// Start is a mock method for CustomEx
func (c *CustomEx) Start(wg *sync.WaitGroup) error {
return nil
}
// SetDefaults is a mock method for CustomEx
func (c *CustomEx) SetDefaults() {
}
// GetName is a mock method for CustomEx
func (c *CustomEx) GetName() string {
return "customex"
}
// IsEnabled is a mock method for CustomEx
func (c *CustomEx) IsEnabled() bool {
return true
}
// SetEnabled is a mock method for CustomEx
func (c *CustomEx) SetEnabled(bool) {
}
// ValidateCredentials is a mock method for CustomEx
func (c *CustomEx) ValidateCredentials(ctx context.Context, a asset.Item) error {
return nil
}
// FetchTicker is a mock method for CustomEx
func (c *CustomEx) FetchTicker(ctx context.Context, p currency.Pair, a asset.Item) (*ticker.Price, error) {
return nil, nil
}
// UpdateTickers is a mock method for CustomEx
func (c *CustomEx) UpdateTickers(ctx context.Context, a asset.Item) error {
return nil
}
// UpdateTicker is a mock method for CustomEx
func (c *CustomEx) UpdateTicker(ctx context.Context, p currency.Pair, a asset.Item) (*ticker.Price, error) {
return nil, nil
}
// FetchOrderbook is a mock method for CustomEx
func (c *CustomEx) FetchOrderbook(ctx context.Context, p currency.Pair, a asset.Item) (*orderbook.Base, error) {
return nil, nil
}
// UpdateOrderbook is a mock method for CustomEx
func (c *CustomEx) UpdateOrderbook(ctx context.Context, p currency.Pair, a asset.Item) (*orderbook.Base, error) {
return nil, nil
}
// FetchTradablePairs is a mock method for CustomEx
func (c *CustomEx) FetchTradablePairs(ctx context.Context, a asset.Item) ([]string, error) {
return nil, nil
}
// UpdateTradablePairs is a mock method for CustomEx
func (c *CustomEx) UpdateTradablePairs(ctx context.Context, forceUpdate bool) error {
return nil
}
// GetEnabledPairs is a mock method for CustomEx
func (c *CustomEx) GetEnabledPairs(a asset.Item) (currency.Pairs, error) {
return nil, nil
}
// GetAvailablePairs is a mock method for CustomEx
func (c *CustomEx) GetAvailablePairs(a asset.Item) (currency.Pairs, error) {
return nil, nil
}
// FetchAccountInfo is a mock method for CustomEx
func (c *CustomEx) FetchAccountInfo(ctx context.Context, a asset.Item) (account.Holdings, error) {
return account.Holdings{}, nil
}
// UpdateAccountInfo is a mock method for CustomEx
func (c *CustomEx) UpdateAccountInfo(ctx context.Context, a asset.Item) (account.Holdings, error) {
return account.Holdings{}, nil
}
// SetPairs is a mock method for CustomEx
func (c *CustomEx) SetPairs(pairs currency.Pairs, a asset.Item, enabled bool) error {
return nil
}
// GetAssetTypes is a mock method for CustomEx
func (c *CustomEx) GetAssetTypes(enabled bool) asset.Items {
return nil
}
// GetRecentTrades is a mock method for CustomEx
func (c *CustomEx) GetRecentTrades(ctx context.Context, p currency.Pair, a asset.Item) ([]trade.Data, error) {
return nil, nil
}
// GetHistoricTrades is a mock method for CustomEx
func (c *CustomEx) GetHistoricTrades(ctx context.Context, p currency.Pair, a asset.Item, startTime, endTime time.Time) ([]trade.Data, error) {
return nil, nil
}
// SupportsAutoPairUpdates is a mock method for CustomEx
func (c *CustomEx) SupportsAutoPairUpdates() bool {
return false
}
// SupportsRESTTickerBatchUpdates is a mock method for CustomEx
func (c *CustomEx) SupportsRESTTickerBatchUpdates() bool {
return false
}
// GetFeeByType is a mock method for CustomEx
func (c *CustomEx) GetFeeByType(ctx context.Context, f *exchange.FeeBuilder) (float64, error) {
return 0.0, nil
}
// GetLastPairsUpdateTime is a mock method for CustomEx
func (c *CustomEx) GetLastPairsUpdateTime() int64 {
return 0
}
// GetWithdrawPermissions is a mock method for CustomEx
func (c *CustomEx) GetWithdrawPermissions() uint32 {
return 0
}
// FormatWithdrawPermissions is a mock method for CustomEx
func (c *CustomEx) FormatWithdrawPermissions() string {
return ""
}
// SupportsWithdrawPermissions is a mock method for CustomEx
func (c *CustomEx) SupportsWithdrawPermissions(permissions uint32) bool {
return false
}
// GetFundingHistory is a mock method for CustomEx
func (c *CustomEx) GetFundingHistory(ctx context.Context) ([]exchange.FundHistory, error) {
return nil, nil
}
// SubmitOrder is a mock method for CustomEx
func (c *CustomEx) SubmitOrder(ctx context.Context, s *order.Submit) (*order.SubmitResponse, error) {
return nil, nil
}
// ModifyOrder is a mock method for CustomEx
func (c *CustomEx) ModifyOrder(_ context.Context, _ *order.Modify) (*order.ModifyResponse, error) {
return nil, nil
}
// CancelOrder is a mock method for CustomEx
func (c *CustomEx) CancelOrder(ctx context.Context, o *order.Cancel) error {
return nil
}
// CancelBatchOrders is a mock method for CustomEx
func (c *CustomEx) CancelBatchOrders(ctx context.Context, o []order.Cancel) (order.CancelBatchResponse, error) {
return order.CancelBatchResponse{}, nil
}
// CancelAllOrders is a mock method for CustomEx
func (c *CustomEx) CancelAllOrders(ctx context.Context, orders *order.Cancel) (order.CancelAllResponse, error) {
return order.CancelAllResponse{}, nil
}
// GetOrderInfo is a mock method for CustomEx
func (c *CustomEx) GetOrderInfo(ctx context.Context, orderID string, pair currency.Pair, assetType asset.Item) (order.Detail, error) {
return order.Detail{}, nil
}
// GetDepositAddress is a mock method for CustomEx
func (c *CustomEx) GetDepositAddress(ctx context.Context, cryptocurrency currency.Code, accountID, chain string) (*deposit.Address, error) {
return nil, nil
}
// GetOrderHistory is a mock method for CustomEx
func (c *CustomEx) GetOrderHistory(ctx context.Context, getOrdersRequest *order.GetOrdersRequest) ([]order.Detail, error) {
return nil, nil
}
// GetWithdrawalsHistory is a mock method for CustomEx
func (c *CustomEx) GetWithdrawalsHistory(ctx context.Context, code currency.Code, a asset.Item) ([]exchange.WithdrawalHistory, error) {
return []exchange.WithdrawalHistory{}, nil
}
// GetActiveOrders is a mock method for CustomEx
func (c *CustomEx) GetActiveOrders(ctx context.Context, getOrdersRequest *order.GetOrdersRequest) ([]order.Detail, error) {
return []order.Detail{}, nil
}
// WithdrawCryptocurrencyFunds is a mock method for CustomEx
func (c *CustomEx) WithdrawCryptocurrencyFunds(ctx context.Context, withdrawRequest *withdraw.Request) (*withdraw.ExchangeResponse, error) {
return nil, nil
}
// WithdrawFiatFunds is a mock method for CustomEx
func (c *CustomEx) WithdrawFiatFunds(ctx context.Context, withdrawRequest *withdraw.Request) (*withdraw.ExchangeResponse, error) {
return nil, nil
}
// WithdrawFiatFundsToInternationalBank is a mock method for CustomEx
func (c *CustomEx) WithdrawFiatFundsToInternationalBank(ctx context.Context, withdrawRequest *withdraw.Request) (*withdraw.ExchangeResponse, error) {
return nil, nil
}
// SetHTTPClientUserAgent is a mock method for CustomEx
func (c *CustomEx) SetHTTPClientUserAgent(ua string) error {
return nil
}
// GetHTTPClientUserAgent is a mock method for CustomEx
func (c *CustomEx) GetHTTPClientUserAgent() (string, error) {
return "", nil
}
// SetClientProxyAddress is a mock method for CustomEx
func (c *CustomEx) SetClientProxyAddress(addr string) error {
return nil
}
// SupportsREST is a mock method for CustomEx
func (c *CustomEx) SupportsREST() bool {
return true
}
// GetSubscriptions is a mock method for CustomEx
func (c *CustomEx) GetSubscriptions() ([]stream.ChannelSubscription, error) {
return nil, nil
}
// GetDefaultConfig is a mock method for CustomEx
func (c *CustomEx) GetDefaultConfig() (*config.Exchange, error) {
return nil, nil
}
// GetBase is a mock method for CustomEx
func (c *CustomEx) GetBase() *exchange.Base {
return nil
}
// SupportsAsset is a mock method for CustomEx
func (c *CustomEx) SupportsAsset(assetType asset.Item) bool {
return false
}
// GetHistoricCandles is a mock method for CustomEx
func (c *CustomEx) GetHistoricCandles(ctx context.Context, p currency.Pair, a asset.Item, timeStart, timeEnd time.Time, interval kline.Interval) (kline.Item, error) {
return kline.Item{}, nil
}
// GetHistoricCandlesExtended is a mock method for CustomEx
func (c *CustomEx) GetHistoricCandlesExtended(ctx context.Context, p currency.Pair, a asset.Item, timeStart, timeEnd time.Time, interval kline.Interval) (kline.Item, error) {
return kline.Item{}, nil
}
// DisableRateLimiter is a mock method for CustomEx
func (c *CustomEx) DisableRateLimiter() error {
return nil
}
// EnableRateLimiter is a mock method for CustomEx
func (c *CustomEx) EnableRateLimiter() error {
return nil
}
// GetWebsocket is a mock method for CustomEx
func (c *CustomEx) GetWebsocket() (*stream.Websocket, error) {
return nil, nil
}
// IsWebsocketEnabled is a mock method for CustomEx
func (c *CustomEx) IsWebsocketEnabled() bool {
return false
}
// SupportsWebsocket is a mock method for CustomEx
func (c *CustomEx) SupportsWebsocket() bool {
return false
}
// SubscribeToWebsocketChannels is a mock method for CustomEx
func (c *CustomEx) SubscribeToWebsocketChannels(channels []stream.ChannelSubscription) error {
return nil
}
// UnsubscribeToWebsocketChannels is a mock method for CustomEx
func (c *CustomEx) UnsubscribeToWebsocketChannels(channels []stream.ChannelSubscription) error {
return nil
}
// IsAssetWebsocketSupported is a mock method for CustomEx
func (c *CustomEx) IsAssetWebsocketSupported(aType asset.Item) bool {
return false
}
// FlushWebsocketChannels is a mock method for CustomEx
func (c *CustomEx) FlushWebsocketChannels() error {
return nil
}
// AuthenticateWebsocket is a mock method for CustomEx
func (c *CustomEx) AuthenticateWebsocket(ctx context.Context) error {
return nil
}
// GetOrderExecutionLimits is a mock method for CustomEx
func (c *CustomEx) GetOrderExecutionLimits(a asset.Item, cp currency.Pair) (order.MinMaxLevel, error) {
return order.MinMaxLevel{}, nil
}
// CheckOrderExecutionLimits is a mock method for CustomEx
func (c *CustomEx) CheckOrderExecutionLimits(a asset.Item, cp currency.Pair, price, amount float64, orderType order.Type) error {
return nil
}
// UpdateOrderExecutionLimits is a mock method for CustomEx
func (c *CustomEx) UpdateOrderExecutionLimits(ctx context.Context, a asset.Item) error {
return nil
}

View File

@@ -63,12 +63,12 @@ func bidAskGenerator() []orderbook.Item {
var response []orderbook.Item
randIterator := 100
for i := 0; i < randIterator; i++ {
price := float64(rand.Intn(1000)) // nolint:gosec // no need to import crypo/rand for testing
price := float64(rand.Intn(1000)) //nolint:gosec // no need to import crypo/rand for testing
if price == 0 {
price = 1
}
response = append(response, orderbook.Item{
Amount: float64(rand.Intn(10)), // nolint:gosec // no need to import crypo/rand for testing
Amount: float64(rand.Intn(10)), //nolint:gosec // no need to import crypo/rand for testing
Price: price,
ID: int64(i),
})
@@ -134,7 +134,7 @@ func BenchmarkBufferPerformance(b *testing.B) {
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
randomIndex := rand.Intn(4) // nolint:gosec // no need to import crypo/rand for testing
randomIndex := rand.Intn(4) //nolint:gosec // no need to import crypo/rand for testing
update.Asks = itemArray[randomIndex]
update.Bids = itemArray[randomIndex]
err = holder.Update(update)
@@ -145,7 +145,8 @@ func BenchmarkBufferPerformance(b *testing.B) {
}
// BenchmarkBufferSortingPerformance benchmark
// 613964 2093 ns/op 440 B/op 4 allocs/op
//
// 613964 2093 ns/op 440 B/op 4 allocs/op
func BenchmarkBufferSortingPerformance(b *testing.B) {
holder, asks, bids, err := createSnapshot()
if err != nil {
@@ -162,7 +163,7 @@ func BenchmarkBufferSortingPerformance(b *testing.B) {
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
randomIndex := rand.Intn(4) // nolint:gosec // no need to import crypo/rand for testing
randomIndex := rand.Intn(4) //nolint:gosec // no need to import crypo/rand for testing
update.Asks = itemArray[randomIndex]
update.Bids = itemArray[randomIndex]
err = holder.Update(update)
@@ -191,7 +192,7 @@ func BenchmarkBufferSortingByIDPerformance(b *testing.B) {
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
randomIndex := rand.Intn(4) // nolint:gosec // no need to import crypo/rand for testing
randomIndex := rand.Intn(4) //nolint:gosec // no need to import crypo/rand for testing
update.Asks = itemArray[randomIndex]
update.Bids = itemArray[randomIndex]
err = holder.Update(update)
@@ -221,7 +222,7 @@ func BenchmarkNoBufferPerformance(b *testing.B) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
randomIndex := rand.Intn(4) // nolint:gosec // no need to import crypo/rand for testing
randomIndex := rand.Intn(4) //nolint:gosec // no need to import crypo/rand for testing
update.Asks = itemArray[randomIndex]
update.Bids = itemArray[randomIndex]
err = obl.Update(update)
@@ -897,7 +898,7 @@ func deploySliceOrdered(size int) orderbook.Items {
rand.Seed(time.Now().UnixNano())
var items []orderbook.Item
for i := 0; i < size; i++ {
items = append(items, orderbook.Item{Amount: 1, Price: rand.Float64() + float64(i), ID: rand.Int63()}) // nolint:gosec // Not needed for tests
items = append(items, orderbook.Item{Amount: 1, Price: rand.Float64() + float64(i), ID: rand.Int63()}) //nolint:gosec // Not needed for tests
}
return items
}
@@ -907,7 +908,7 @@ func TestUpdateByIDAndAction(t *testing.T) {
holder := orderbookHolder{}
asks := deploySliceOrdered(100)
// nolint: gocritic
//nolint: gocritic
bids := append(asks[:0:0], asks...)
bids.Reverse()
@@ -1053,7 +1054,7 @@ func TestUpdateByIDAndAction(t *testing.T) {
t.Fatal("did not adjust ask item placement and details")
}
book.LoadSnapshot(append(bids[:0:0], bids...), append(bids[:0:0], bids...), 0, time.Time{}, true) // nolint:gocritic
book.LoadSnapshot(append(bids[:0:0], bids...), append(bids[:0:0], bids...), 0, time.Time{}, true) //nolint:gocritic
// Delete - not found
err = holder.updateByIDAndAction(&orderbook.Update{
Action: orderbook.Delete,
@@ -1069,7 +1070,7 @@ func TestUpdateByIDAndAction(t *testing.T) {
t.Fatalf("received: '%v' but expected: '%v'", err, errDeleteFailure)
}
book.LoadSnapshot(append(bids[:0:0], bids...), append(bids[:0:0], bids...), 0, time.Time{}, true) // nolint:gocritic
book.LoadSnapshot(append(bids[:0:0], bids...), append(bids[:0:0], bids...), 0, time.Time{}, true) //nolint:gocritic
// Delete - found
err = holder.updateByIDAndAction(&orderbook.Update{
Action: orderbook.Delete,

View File

@@ -180,7 +180,7 @@ func (s *Service) update(p *Price) error {
}
t.Price = *p
// nolint: gocritic
//nolint: gocritic
ids := append(t.Assoc, t.Main)
s.mu.Unlock()
return s.mux.Publish(p, ids...)

View File

@@ -342,17 +342,17 @@ func TestProcessTicker(t *testing.T) { // non-appending function to tickers
wg.Add(1)
go func() {
// nolint:gosec // no need to import crypo/rand for testing
//nolint:gosec // no need to import crypo/rand for testing
newName := "Exchange" + strconv.FormatInt(rand.Int63(), 10)
newPairs, err := currency.NewPairFromStrings("BTC"+strconv.FormatInt(rand.Int63(), 10), // nolint:gosec // no need to import crypo/rand for testing
"USD"+strconv.FormatInt(rand.Int63(), 10)) // nolint:gosec // no need to import crypo/rand for testing
newPairs, err := currency.NewPairFromStrings("BTC"+strconv.FormatInt(rand.Int63(), 10), //nolint:gosec // no need to import crypo/rand for testing
"USD"+strconv.FormatInt(rand.Int63(), 10)) //nolint:gosec // no need to import crypo/rand for testing
if err != nil {
log.Fatal(err)
}
tp := Price{
Pair: newPairs,
Last: rand.Float64(), // nolint:gosec // no need to import crypo/rand for testing
Last: rand.Float64(), //nolint:gosec // no need to import crypo/rand for testing
ExchangeName: newName,
AssetType: asset.Spot,
}

View File

@@ -129,7 +129,7 @@ func (p *Processor) Run(wg *sync.WaitGroup) {
for {
<-ticker.C
p.mutex.Lock()
// nolint: gocritic
//nolint: gocritic
bufferCopy := append(p.buffer[:0:0], p.buffer...)
p.buffer = nil
p.mutex.Unlock()

View File

@@ -23,7 +23,7 @@ var (
func TestMain(m *testing.M) {
for x := 0; x < 100; x++ {
v := rand.Float64() // nolint:gosec // no need to import crypo/rand for testing
v := rand.Float64() //nolint:gosec // no need to import crypo/rand for testing
candle := &objects.Array{}
candle.Value = append(candle.Value, &objects.Time{Value: time.Now()},
&objects.Float{Value: v},

View File

@@ -25,7 +25,7 @@ const (
// Wrapper instance of GCT to use for modules
var Wrapper GCTExchange
// Exchange interface requirements
// GCTExchange interface requirements
type GCTExchange interface {
Exchanges(enabledOnly bool) []string
IsEnabled(exch string) bool

View File

@@ -263,7 +263,7 @@ func (w Wrapper) OHLCV(ctx context.Context, exch string, p currency.Pair, a asse
})
for x := 1; x < 200; x++ {
r := validatorLow + rand.Float64()*(validatorHigh-validatorLow) // nolint:gosec // no need to import crypo/rand
r := validatorLow + rand.Float64()*(validatorHigh-validatorLow) //nolint:gosec // no need to import crypo/rand
candle := kline.Candle{
Time: candles[x-1].Time.Add(-i.Duration()),
Open: r,

View File

@@ -4,7 +4,6 @@ import (
"bytes"
"errors"
"io"
"io/ioutil"
"log"
"os"
"strings"
@@ -18,7 +17,7 @@ func TestMain(m *testing.M) {
if err != nil {
log.Fatal("cannot set up test loggers", err)
}
tempDir, err := ioutil.TempDir(os.TempDir(), "")
tempDir, err := os.MkdirTemp(os.TempDir(), "")
if err != nil {
log.Fatal("Cannot create temporary file", err)
}

View File

@@ -591,8 +591,8 @@
],
"pairs": {
"spot": {
"enabled": "BTCKRW,ETHKRW,LTCKRW,ETCKRW,XRPKRW,BCHKRW,QTUMKRW,BTGKRW,EOSKRW",
"available": "BHPKRW,STEEMKRW,GTOKRW,ETCKRW,STRATKRW,FXKRW,LTCKRW,MIXKRW,THETAKRW,QTUMKRW,ADAKRW,MCOKRW,INSKRW,RDNKRW,CONKRW,FABKRW,ETHKRW,HDACKRW,BTCKRW,POWRKRW,CMTKRW,LBAKRW,ETHOSKRW,HCKRW,ETZKRW,PPTKRW,XVGKRW,WTCKRW,TMTGKRW,LOOMKRW,WETKRW,ABTKRW,ITCKRW,GXCKRW,ORBSKRW,ICXKRW,BSVKRW,MXCKRW,MITHKRW,AEKRW,SALTKRW,ARNKRW,TRUEKRW,ENJKRW,GNTKRW,PLYKRW,REPKRW,ZRXKRW,BTGKRW,APISKRW,QKCKRW,LRCKRW,DVPKRW,DADKRW,CHRKRW,BCHKRW,NPXSKRW,PIVXKRW,AMOKRW,RNTKRW,XEMKRW,FCTKRW,WOMKRW,WAXPKRW,DACKRW,OMGKRW,PCMKRW,CROKRW,FNBKRW,ANKRKRW,EOSKRW,KNCKRW,OCNKRW,MTLKRW,XSRKRW,VALORKRW,TRVKRW,AUTOKRW,HYCKRW,AOAKRW,BTTKRW,MBLKRW,VETKRW,XRPKRW,ZILKRW,ELFKRW,LAMBKRW,POLYKRW,IOSTKRW,BZNTKRW,CTXCKRW,BATKRW,FZZKRW,PAYKRW,BCDKRW,SNTKRW,WAVESKRW,XLMKRW,LINKKRW,OGOKRW,WICCKRW,TRXKRW"
"enabled": "BTCKRW,ETHKRW,ETCKRW,XRPKRW,BCHKRW,QTUMKRW,BTGKRW,EOSKRW",
"available": "BHPKRW,STEEMKRW,GTOKRW,ETCKRW,STRATKRW,FXKRW,MIXKRW,THETAKRW,QTUMKRW,ADAKRW,MCOKRW,INSKRW,RDNKRW,CONKRW,FABKRW,ETHKRW,HDACKRW,BTCKRW,POWRKRW,CMTKRW,LBAKRW,ETHOSKRW,HCKRW,ETZKRW,PPTKRW,XVGKRW,WTCKRW,TMTGKRW,LOOMKRW,WETKRW,ABTKRW,ITCKRW,GXCKRW,ORBSKRW,ICXKRW,BSVKRW,MXCKRW,MITHKRW,AEKRW,SALTKRW,ARNKRW,TRUEKRW,ENJKRW,GNTKRW,PLYKRW,REPKRW,ZRXKRW,BTGKRW,APISKRW,QKCKRW,LRCKRW,DVPKRW,DADKRW,CHRKRW,BCHKRW,NPXSKRW,PIVXKRW,AMOKRW,RNTKRW,XEMKRW,FCTKRW,WOMKRW,WAXPKRW,DACKRW,OMGKRW,PCMKRW,CROKRW,FNBKRW,ANKRKRW,EOSKRW,KNCKRW,OCNKRW,MTLKRW,XSRKRW,VALORKRW,TRVKRW,AUTOKRW,HYCKRW,AOAKRW,BTTKRW,MBLKRW,VETKRW,XRPKRW,ZILKRW,ELFKRW,LAMBKRW,POLYKRW,IOSTKRW,BZNTKRW,CTXCKRW,BATKRW,FZZKRW,PAYKRW,BCDKRW,SNTKRW,WAVESKRW,XLMKRW,LINKKRW,OGOKRW,WICCKRW,TRXKRW"
}
}
},