linter: Enable error checking linter (#766)

* golangci: Enable err checking linter to expose unchecked errors.

* gct: handle errors across the board

* gct: handle errors NOTE: Found bug in FTX (WIP)

* linter: fix issues

* ftx/exchanges: fix bug where error was being returned when setting pair management variables to an already enabled state

* bitmex: fix bug where a dangly supported asset in config danglied up the place.

* linter: fix more linter issues

* linter: fix my terrible spelling.

* currency: fix test

* exchanges: fix tests

* logger: fix test

* exchanges: fix tests

* glorious: nits

* vm: revert rm variable and instigate test
This commit is contained in:
Ryan O'Hara-Reid
2021-08-30 14:06:40 +10:00
committed by GitHub
parent c9ab0b1164
commit 8020e1ec6a
99 changed files with 814 additions and 293 deletions

View File

@@ -12,7 +12,7 @@ linters:
enable:
# defaults
# - deadcode
# - errcheck
- errcheck
- gosimple
- govet
- ineffassign

View File

@@ -1137,7 +1137,10 @@ func htmlScrapeLocalBitcoins(htmlData *HTMLScrapingData) ([]string, error) {
return nil, err
}
str := r.FindString(string(a))
sha := crypto.GetSHA256([]byte(str))
sha, err := crypto.GetSHA256([]byte(str))
if err != nil {
return nil, err
}
var resp []string
resp = append(resp, crypto.HexEncodeToString(sha))
return resp, nil

View File

@@ -2953,8 +2953,7 @@ var withdrawalRequestCommand = &cli.Command{
func withdrawlRequestByID(c *cli.Context) error {
if c.NArg() == 0 && c.NumFlags() == 0 {
cli.ShowSubcommandHelp(c)
return nil
return cli.ShowSubcommandHelp(c)
}
var ID string
@@ -2990,8 +2989,7 @@ func withdrawlRequestByID(c *cli.Context) error {
func withdrawlRequestByExchangeID(c *cli.Context) error {
if c.NArg() == 0 && c.NumFlags() == 0 {
cli.ShowSubcommandHelp(c)
return nil
return cli.ShowSubcommandHelp(c)
}
var exchange, currency string
@@ -3058,8 +3056,7 @@ func withdrawlRequestByExchangeID(c *cli.Context) error {
func withdrawlRequestByDate(c *cli.Context) error {
if c.NArg() == 0 && c.NumFlags() == 0 {
cli.ShowSubcommandHelp(c)
return nil
return cli.ShowSubcommandHelp(c)
}
var exchange string
@@ -3842,8 +3839,7 @@ var gctScriptCommand = &cli.Command{
func gctScriptAutoload(c *cli.Context) error {
if c.NArg() == 0 && c.NumFlags() == 0 {
_ = cli.ShowSubcommandHelp(c)
return nil
return cli.ShowSubcommandHelp(c)
}
var command, script string
@@ -3866,8 +3862,7 @@ func gctScriptAutoload(c *cli.Context) error {
case "remove":
status = true
default:
_ = cli.ShowSubcommandHelp(c)
return nil
return cli.ShowSubcommandHelp(c)
}
conn, err := setupClient()
@@ -3893,8 +3888,7 @@ func gctScriptAutoload(c *cli.Context) error {
func gctScriptExecute(c *cli.Context) error {
if c.NArg() == 0 && c.NumFlags() == 0 {
_ = cli.ShowSubcommandHelp(c)
return nil
return cli.ShowSubcommandHelp(c)
}
if !c.IsSet("filename") {
@@ -3973,8 +3967,7 @@ func gctScriptList(c *cli.Context) error {
func gctScriptStop(c *cli.Context) error {
if c.NArg() == 0 && c.NumFlags() == 0 {
_ = cli.ShowSubcommandHelp(c)
return nil
return cli.ShowSubcommandHelp(c)
}
if !c.IsSet("uuid") {
@@ -4024,8 +4017,7 @@ func gctScriptStopAll(c *cli.Context) error {
func gctScriptRead(c *cli.Context) error {
if c.NArg() == 0 && c.NumFlags() == 0 {
_ = cli.ShowSubcommandHelp(c)
return nil
return cli.ShowSubcommandHelp(c)
}
if !c.IsSet("name") {
@@ -4058,8 +4050,7 @@ func gctScriptRead(c *cli.Context) error {
func gctScriptQuery(c *cli.Context) error {
if c.NArg() == 0 && c.NumFlags() == 0 {
_ = cli.ShowSubcommandHelp(c)
return nil
return cli.ShowSubcommandHelp(c)
}
if !c.IsSet("uuid") {
@@ -4093,8 +4084,7 @@ func gctScriptQuery(c *cli.Context) error {
func gctScriptUpload(c *cli.Context) error {
if c.NArg() == 0 && c.NumFlags() == 0 {
_ = cli.ShowSubcommandHelp(c)
return nil
return cli.ShowSubcommandHelp(c)
}
var overwrite bool

View File

@@ -89,7 +89,12 @@ func main() {
Subtotal float64
}
cfg.RetrieveConfigCurrencyPairs(true, asset.Spot)
err = cfg.RetrieveConfigCurrencyPairs(true, asset.Spot)
if err != nil {
log.Printf("Failed to retrieve config currency pairs %v\n", err)
os.Exit(1)
}
portfolioMap := make(map[currency.Code]PortfolioTemp)
total := float64(0)

View File

@@ -97,11 +97,17 @@ func main() {
resp.Body.Close()
log.Println("Connected to websocket!")
hash, err := crypto.GetSHA256([]byte(cfg.RemoteControl.Password))
if err != nil {
log.Println("Unable to generate SHA256 hash from remote control password:", err)
return
}
log.Println("Authenticating..")
var wsResp WebsocketEventResponse
reqData := WebsocketAuth{
Username: cfg.RemoteControl.Username,
Password: crypto.HexEncodeToString(crypto.GetSHA256([]byte(cfg.RemoteControl.Password))),
Password: crypto.HexEncodeToString(hash),
}
err = SendWebsocketEvent("auth", reqData, &wsResp)
if err != nil {

View File

@@ -62,29 +62,29 @@ func GetRandomSalt(input []byte, saltLen int) ([]byte, error) {
}
// GetMD5 returns a MD5 hash of a byte array
func GetMD5(input []byte) []byte {
func GetMD5(input []byte) ([]byte, error) {
m := md5.New() // nolint:gosec // hash function used by some exchanges
m.Write(input)
return m.Sum(nil)
_, err := m.Write(input)
return m.Sum(nil), err
}
// GetSHA512 returns a SHA512 hash of a byte array
func GetSHA512(input []byte) []byte {
func GetSHA512(input []byte) ([]byte, error) {
sha := sha512.New()
sha.Write(input)
return sha.Sum(nil)
_, err := sha.Write(input)
return sha.Sum(nil), err
}
// GetSHA256 returns a SHA256 hash of a byte array
func GetSHA256(input []byte) []byte {
func GetSHA256(input []byte) ([]byte, error) {
sha := sha256.New()
sha.Write(input)
return sha.Sum(nil)
_, err := sha.Write(input)
return sha.Sum(nil), err
}
// GetHMAC returns a keyed-hash message authentication code using the desired
// hashtype
func GetHMAC(hashType int, input, key []byte) []byte {
func GetHMAC(hashType int, input, key []byte) ([]byte, error) {
var hasher func() hash.Hash
switch hashType {
@@ -101,14 +101,14 @@ func GetHMAC(hashType int, input, key []byte) []byte {
}
h := hmac.New(hasher, key)
h.Write(input)
return h.Sum(nil)
_, err := h.Write(input)
return h.Sum(nil), err
}
// Sha1ToHex takes a string, sha1 hashes it and return a hex string of the
// result
func Sha1ToHex(data string) string {
func Sha1ToHex(data string) (string, error) {
h := sha1.New() // nolint:gosec // hash function used by some exchanges
h.Write([]byte(data))
return hex.EncodeToString(h.Sum(nil))
_, err := h.Write([]byte(data))
return hex.EncodeToString(h.Sum(nil)), err
}

View File

@@ -74,7 +74,10 @@ func TestGetMD5(t *testing.T) {
t.Parallel()
var originalString = []byte("I am testing the MD5 function in common!")
var expectedOutput = []byte("18fddf4a41ba90a7352765e62e7a8744")
actualOutput := GetMD5(originalString)
actualOutput, err := GetMD5(originalString)
if err != nil {
t.Fatal(err)
}
actualStr := HexEncodeToString(actualOutput)
if !bytes.Equal(expectedOutput, []byte(actualStr)) {
t.Errorf("Expected '%s'. Actual '%s'",
@@ -88,7 +91,10 @@ func TestGetSHA512(t *testing.T) {
var expectedOutput = []byte(
`a2273f492ea73fddc4f25c267b34b3b74998bd8a6301149e1e1c835678e3c0b90859fce22e4e7af33bde1711cbb924809aedf5d759d648d61774b7185c5dc02b`,
)
actualOutput := GetSHA512(originalString)
actualOutput, err := GetSHA512(originalString)
if err != nil {
t.Fatal(err)
}
actualStr := HexEncodeToString(actualOutput)
if !bytes.Equal(expectedOutput, []byte(actualStr)) {
t.Errorf("Expected '%x'. Actual '%x'",
@@ -102,7 +108,11 @@ func TestGetSHA256(t *testing.T) {
var expectedOutput = []byte(
"0962813d7a9f739cdcb7f0c0be0c2a13bd630167e6e54468266e4af6b1ad9303",
)
actualOutput := GetSHA256(originalString)
actualOutput, err := GetSHA256(originalString)
if err != nil {
t.Fatal(err)
}
actualStr := HexEncodeToString(actualOutput)
if !bytes.Equal(expectedOutput, []byte(actualStr)) {
t.Errorf("Expected '%x'. Actual '%x'", expectedOutput,
@@ -135,31 +145,46 @@ func TestGetHMAC(t *testing.T) {
113, 64, 132, 129, 213, 68, 231, 99, 252, 15, 175, 109, 198, 132, 139, 39,
}
sha1 := GetHMAC(HashSHA1, []byte("Hello,World"), []byte("1234"))
sha1, err := GetHMAC(HashSHA1, []byte("Hello,World"), []byte("1234"))
if err != nil {
t.Fatal(err)
}
if string(sha1) != string(expectedSha1) {
t.Errorf("Common GetHMAC error: Expected '%x'. Actual '%x'",
expectedSha1, sha1,
)
}
sha256 := GetHMAC(HashSHA256, []byte("Hello,World"), []byte("1234"))
sha256, err := GetHMAC(HashSHA256, []byte("Hello,World"), []byte("1234"))
if err != nil {
t.Fatal(err)
}
if string(sha256) != string(expectedsha256) {
t.Errorf("Common GetHMAC error: Expected '%x'. Actual '%x'",
expectedsha256, sha256,
)
}
sha512 := GetHMAC(HashSHA512, []byte("Hello,World"), []byte("1234"))
sha512, err := GetHMAC(HashSHA512, []byte("Hello,World"), []byte("1234"))
if err != nil {
t.Fatal(err)
}
if string(sha512) != string(expectedsha512) {
t.Errorf("Common GetHMAC error: Expected '%x'. Actual '%x'",
expectedsha512, sha512,
)
}
sha512384 := GetHMAC(HashSHA512_384, []byte("Hello,World"), []byte("1234"))
sha512384, err := GetHMAC(HashSHA512_384, []byte("Hello,World"), []byte("1234"))
if err != nil {
t.Fatal(err)
}
if string(sha512384) != string(expectedsha512384) {
t.Errorf("Common GetHMAC error: Expected '%x'. Actual '%x'",
expectedsha512384, sha512384,
)
}
md5 := GetHMAC(HashMD5, []byte("Hello World"), []byte("1234"))
md5, err := GetHMAC(HashMD5, []byte("Hello World"), []byte("1234"))
if err != nil {
t.Fatal(err)
}
if string(md5) != string(expectedmd5) {
t.Errorf("Common GetHMAC error: Expected '%x'. Actual '%x'",
expectedmd5, md5,
@@ -170,7 +195,10 @@ func TestGetHMAC(t *testing.T) {
func TestSha1Tohex(t *testing.T) {
t.Parallel()
expectedResult := "fcfbfcd7d31d994ef660f6972399ab5d7a890149"
actualResult := Sha1ToHex("Testing Sha1ToHex")
actualResult, err := Sha1ToHex("Testing Sha1ToHex")
if err != nil {
t.Fatal(err)
}
if actualResult != expectedResult {
t.Errorf("Expected '%s'. Actual '%s'",
expectedResult, actualResult)

View File

@@ -35,7 +35,10 @@ func TestGetNonExistentDefaultFilePathDoesNotCreateDefaultDir(t *testing.T) {
if file.Exists(dir) {
t.Skip("The default directory already exists before running the test")
}
GetFilePath("")
_, _, err := GetFilePath("")
if err != nil {
t.Fatal(err)
}
if file.Exists(dir) {
t.Fatalf("The target directory was created in %s", dir)
}

View File

@@ -245,12 +245,15 @@ func TestBaseCode(t *testing.T) {
true)
}
main.LoadItem(&Item{
err = main.LoadItem(&Item{
ID: 0,
FullName: "Cardano",
Role: Cryptocurrency,
Symbol: "ADA",
})
if err != nil {
t.Fatal(err)
}
full, err := main.GetFullCurrencyData()
if err != nil {

View File

@@ -1,6 +1,7 @@
package exchangeratehost
import (
"log"
"os"
"testing"
"time"
@@ -14,9 +15,12 @@ var (
)
func TestMain(t *testing.M) {
e.Setup(base.Settings{
err := e.Setup(base.Settings{
Name: "ExchangeRateHost",
})
if err != nil {
log.Fatal(err)
}
os.Exit(t.Run())
}

View File

@@ -16,10 +16,12 @@ import (
"github.com/thrasher-corp/gocryptotrader/log"
)
var errAPIKeyNotSet = errors.New("API key must be set")
// Setup sets appropriate values for CurrencyLayer
func (e *ExchangeRates) Setup(config base.Settings) error {
if config.APIKey == "" {
return errors.New("API key must be set")
return errAPIKeyNotSet
}
e.Name = config.Name
e.Enabled = config.Enabled

View File

@@ -2,6 +2,7 @@ package exchangerates
import (
"errors"
"log"
"os"
"testing"
"time"
@@ -17,11 +18,14 @@ const (
)
func TestMain(t *testing.M) {
e.Setup(base.Settings{
err := e.Setup(base.Settings{
Name: "ExchangeRates",
APIKey: apiKey,
APIKeyLvl: apiKeyLevel,
})
if err != nil && !errors.Is(err, errAPIKeyNotSet) {
log.Fatal(err)
}
os.Exit(t.Run())
}

View File

@@ -88,8 +88,10 @@ func StartFXService(fxProviders []base.Settings) (*ForexProviders, error) {
return nil, err
}
handler.SetProvider(provider)
err = handler.SetProvider(provider)
if err != nil {
return nil, err
}
case fxProviders[i].Name == "CurrencyLayer" && fxProviders[i].Enabled:
provider := new(currencylayer.CurrencyLayer)
err := provider.Setup(fxProviders[i])
@@ -97,8 +99,10 @@ func StartFXService(fxProviders []base.Settings) (*ForexProviders, error) {
return nil, err
}
handler.SetProvider(provider)
err = handler.SetProvider(provider)
if err != nil {
return nil, err
}
case fxProviders[i].Name == "ExchangeRates" && fxProviders[i].Enabled:
provider := new(exchangerates.ExchangeRates)
err := provider.Setup(fxProviders[i])
@@ -106,8 +110,10 @@ func StartFXService(fxProviders []base.Settings) (*ForexProviders, error) {
return nil, err
}
handler.SetProvider(provider)
err = handler.SetProvider(provider)
if err != nil {
return nil, err
}
case fxProviders[i].Name == "Fixer" && fxProviders[i].Enabled:
provider := new(fixer.Fixer)
err := provider.Setup(fxProviders[i])
@@ -115,8 +121,10 @@ func StartFXService(fxProviders []base.Settings) (*ForexProviders, error) {
return nil, err
}
handler.SetProvider(provider)
err = handler.SetProvider(provider)
if err != nil {
return nil, err
}
case fxProviders[i].Name == "OpenExchangeRates" && fxProviders[i].Enabled:
provider := new(openexchangerates.OXR)
err := provider.Setup(fxProviders[i])
@@ -124,7 +132,10 @@ func StartFXService(fxProviders []base.Settings) (*ForexProviders, error) {
return nil, err
}
handler.SetProvider(provider)
err = handler.SetProvider(provider)
if err != nil {
return nil, err
}
}
}

View File

@@ -1,6 +1,8 @@
package openexchangerates
import (
"log"
"os"
"testing"
"github.com/thrasher-corp/gocryptotrader/currency/forexprovider/base"
@@ -15,20 +17,21 @@ const (
var o OXR
var initialSetup bool
func setup() {
o.Setup(base.Settings{
Name: "OpenExchangeRates",
Enabled: true,
func TestMain(m *testing.M) {
err := o.Setup(base.Settings{
Name: "OpenExchangeRates",
Enabled: true,
APIKey: apikey,
APIKeyLvl: apilvl,
})
initialSetup = true
if err != nil {
log.Fatal(err)
}
os.Exit(m.Run())
}
func TestGetRates(t *testing.T) {
if !initialSetup {
setup()
}
t.Parallel()
_, err := o.GetRates("USD", "AUD")
if err == nil {
t.Error("GetRates() Expected error")
@@ -36,9 +39,7 @@ func TestGetRates(t *testing.T) {
}
func TestGetLatest(t *testing.T) {
if !initialSetup {
setup()
}
t.Parallel()
_, err := o.GetLatest("USD", "AUD", false, false)
if err == nil {
t.Error("GetLatest() Expected error")
@@ -46,9 +47,7 @@ func TestGetLatest(t *testing.T) {
}
func TestGetHistoricalRates(t *testing.T) {
if !initialSetup {
setup()
}
t.Parallel()
_, err := o.GetHistoricalRates("2017-12-01", "USD", []string{"CNH", "AUD", "ANG"}, false, false)
if err == nil {
t.Error("GetRates() Expected error")
@@ -56,9 +55,7 @@ func TestGetHistoricalRates(t *testing.T) {
}
func TestGetCurrencies(t *testing.T) {
if !initialSetup {
setup()
}
t.Parallel()
_, err := o.GetCurrencies(true, true, true)
if err != nil {
t.Error("GetCurrencies() error", err)
@@ -66,9 +63,7 @@ func TestGetCurrencies(t *testing.T) {
}
func TestGetTimeSeries(t *testing.T) {
if !initialSetup {
setup()
}
t.Parallel()
_, err := o.GetTimeSeries("USD", "2017-12-01", "2017-12-02", []string{"CNH", "AUD", "ANG"}, false, false)
if err == nil {
t.Error("GetTimeSeries() Expected error")
@@ -76,9 +71,7 @@ func TestGetTimeSeries(t *testing.T) {
}
func TestConvertCurrency(t *testing.T) {
if !initialSetup {
setup()
}
t.Parallel()
_, err := o.ConvertCurrency(1337, "USD", "AUD")
if err == nil {
t.Error("ConvertCurrency() Expected error")
@@ -86,9 +79,7 @@ func TestConvertCurrency(t *testing.T) {
}
func TestGetOHLC(t *testing.T) {
if !initialSetup {
setup()
}
t.Parallel()
_, err := o.GetOHLC("2017-07-17T08:30:00Z", "1m", "USD", []string{"AUD"}, false)
if err == nil {
t.Error("GetOHLC() Expected error")
@@ -96,9 +87,7 @@ func TestGetOHLC(t *testing.T) {
}
func TestGetUsageStats(t *testing.T) {
if !initialSetup {
setup()
}
t.Parallel()
_, err := o.GetUsageStats(false)
if err == nil {
t.Error("GetUsageStats() Expected error")

View File

@@ -8,6 +8,10 @@ import (
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
)
// ErrAssetAlreadyEnabled defines an error for the pairs management system
// that declares the asset is already enabled.
var ErrAssetAlreadyEnabled = errors.New("asset already enabled")
// GetAssetTypes returns a list of stored asset types
func (p *PairsManager) GetAssetTypes(enabled bool) asset.Items {
p.m.RLock()
@@ -185,7 +189,7 @@ func (p *PairsManager) SetAssetEnabled(a asset.Item, enabled bool) error {
if !*c.AssetEnabled && !enabled {
return errors.New("asset already disabled")
} else if *c.AssetEnabled && enabled {
return errors.New("asset already enabled")
return ErrAssetAlreadyEnabled
}
*c.AssetEnabled = enabled

View File

@@ -539,9 +539,7 @@ func (s *Storage) SetupCryptoProvider(settings coinmarketcap.Settings) error {
s.currencyAnalysis = new(coinmarketcap.Coinmarketcap)
s.currencyAnalysis.SetDefaults()
s.currencyAnalysis.Setup(settings)
return nil
return s.currencyAnalysis.Setup(settings)
}
// GetTotalMarketCryptocurrencies returns the total seeded market

View File

@@ -686,7 +686,12 @@ func wsAuth(client *websocketClient, data interface{}) error {
return err
}
hashPW := crypto.HexEncodeToString(crypto.GetSHA256([]byte(client.password)))
hash, err := crypto.GetSHA256([]byte(client.password))
if err != nil {
return err
}
hashPW := crypto.HexEncodeToString(hash)
if auth.Username == client.username && auth.Password == hashPW {
client.Authenticated = true
wsResp.Data = WebsocketResponseSuccess

View File

@@ -1779,7 +1779,7 @@ func TestRPCServer_GetTicker_LastUpdatedNanos(t *testing.T) {
// Push a mock-up ticker.
now := time.Now()
ticker.ProcessTicker(&ticker.Price{
err = ticker.ProcessTicker(&ticker.Price{
ExchangeName: testExchange,
Pair: pair,
AssetType: asset.Spot,
@@ -1790,6 +1790,9 @@ func TestRPCServer_GetTicker_LastUpdatedNanos(t *testing.T) {
Low: 169,
Close: 196,
})
if err != nil {
t.Fatal(err)
}
// Prepare a ticker request.
request := &gctrpc.GetTickerRequest{

View File

@@ -567,9 +567,14 @@ func (a *Alphapoint) SendAuthenticatedHTTPRequest(ep exchange.URL, method, path
headers["Content-Type"] = "application/json"
data["apiKey"] = a.API.Credentials.Key
data["apiNonce"] = n
hmac := crypto.GetHMAC(crypto.HashSHA256,
hmac, err := crypto.GetHMAC(crypto.HashSHA256,
[]byte(n.String()+a.API.Credentials.ClientID+a.API.Credentials.Key),
[]byte(a.API.Credentials.Secret))
if err != nil {
return err
}
data["apiSig"] = strings.ToUpper(crypto.HexEncodeToString(hmac))
path = fmt.Sprintf("%s/ajax/v%s/%s", endpoint, alphapointAPIVersion, path)

View File

@@ -743,7 +743,13 @@ func (b *Binance) SendAuthHTTPRequest(ePath exchange.URL, method, path string, p
fullPath := endpointPath + path
params.Set("timestamp", strconv.FormatInt(time.Now().Unix()*1000, 10))
signature := params.Encode()
hmacSigned := crypto.GetHMAC(crypto.HashSHA256, []byte(signature), []byte(b.API.Credentials.Secret))
var hmacSigned []byte
hmacSigned, err = crypto.GetHMAC(crypto.HashSHA256,
[]byte(signature),
[]byte(b.API.Credentials.Secret))
if err != nil {
return nil, err
}
hmacSignedStr := crypto.HexEncodeToString(hmacSigned)
headers := make(map[string]string)
headers["X-MBX-APIKEY"] = b.API.Credentials.Key

View File

@@ -1331,7 +1331,10 @@ func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
t.Parallel()
var feeBuilder = setFeeBuilder()
b.GetFeeByType(feeBuilder)
_, err := b.GetFeeByType(feeBuilder)
if err != nil {
t.Fatal(err)
}
if !areTestAPIKeysSet() || mockTests {
if feeBuilder.FeeType != exchange.OfflineTradeFee {
t.Errorf("Expected %v, received %v", exchange.OfflineTradeFee, feeBuilder.FeeType)

View File

@@ -1542,9 +1542,12 @@ func (b *Bitfinex) SendAuthenticatedHTTPRequest(ep exchange.URL, method, path st
}
PayloadBase64 := crypto.Base64Encode(PayloadJSON)
hmac := crypto.GetHMAC(crypto.HashSHA512_384,
hmac, err := crypto.GetHMAC(crypto.HashSHA512_384,
[]byte(PayloadBase64),
[]byte(b.API.Credentials.Secret))
if err != nil {
return nil, err
}
headers := make(map[string]string)
headers["X-BFX-APIKEY"] = b.API.Credentials.Key
headers["X-BFX-PAYLOAD"] = PayloadBase64
@@ -1594,11 +1597,14 @@ func (b *Bitfinex) SendAuthenticatedHTTPRequestV2(ep exchange.URL, method, path
headers["bfx-nonce"] = n
strPath := "/api" + bitfinexAPIVersion2 + path + string(payload)
signStr := strPath + n
hmac := crypto.GetHMAC(
hmac, err := crypto.GetHMAC(
crypto.HashSHA512_384,
[]byte(signStr),
[]byte(b.API.Credentials.Secret),
)
if err != nil {
return nil, err
}
headers["bfx-signature"] = crypto.HexEncodeToString(hmac)
return &request.Item{

View File

@@ -723,7 +723,10 @@ func setFeeBuilder() *exchange.FeeBuilder {
// TestGetFeeByTypeOfflineTradeFee logic test
func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
var feeBuilder = setFeeBuilder()
b.GetFeeByType(feeBuilder)
_, err := b.GetFeeByType(feeBuilder)
if err != nil {
t.Fatal(err)
}
if !areTestAPIKeysSet() {
if feeBuilder.FeeType != exchange.OfflineTradeFee {
t.Errorf("Expected %v, received %v", exchange.OfflineTradeFee, feeBuilder.FeeType)

View File

@@ -1167,19 +1167,25 @@ func (b *Bitfinex) WsSendAuth() error {
return fmt.Errorf("%v AuthenticatedWebsocketAPISupport not enabled",
b.Name)
}
nonce := strconv.FormatInt(time.Now().Unix(), 10)
payload := "AUTH" + nonce
hmac, err := crypto.GetHMAC(crypto.HashSHA512_384,
[]byte(payload),
[]byte(b.API.Credentials.Secret))
if err != nil {
return err
}
request := WsAuthRequest{
Event: "auth",
APIKey: b.API.Credentials.Key,
AuthPayload: payload,
AuthSig: crypto.HexEncodeToString(crypto.GetHMAC(crypto.HashSHA512_384,
[]byte(payload),
[]byte(b.API.Credentials.Secret))),
Event: "auth",
APIKey: b.API.Credentials.Key,
AuthPayload: payload,
AuthSig: crypto.HexEncodeToString(hmac),
AuthNonce: nonce,
DeadManSwitch: 0,
}
err := b.Websocket.AuthConn.SendJSONMessage(request)
err = b.Websocket.AuthConn.SendJSONMessage(request)
if err != nil {
b.Websocket.SetCanUseAuthenticatedEndpoints(false)
return err

View File

@@ -187,7 +187,10 @@ func setFeeBuilder() *exchange.FeeBuilder {
// TestGetFeeByTypeOfflineTradeFee logic test
func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
var feeBuilder = setFeeBuilder()
b.GetFeeByType(feeBuilder)
_, err := b.GetFeeByType(feeBuilder)
if err != nil {
t.Fatal(err)
}
if !areTestAPIKeysSet() {
if feeBuilder.FeeType != exchange.OfflineTradeFee {
t.Errorf("Expected %v, received %v", exchange.OfflineTradeFee, feeBuilder.FeeType)

View File

@@ -500,9 +500,14 @@ func (b *Bithumb) SendAuthenticatedHTTPRequest(ep exchange.URL, path string, par
payload := params.Encode()
hmacPayload := path + string('\x00') + payload + string('\x00') + n
hmac := crypto.GetHMAC(crypto.HashSHA512,
var hmac []byte
hmac, err = crypto.GetHMAC(crypto.HashSHA512,
[]byte(hmacPayload),
[]byte(b.API.Credentials.Secret))
if err != nil {
return nil, err
}
hmacStr := crypto.HexEncodeToString(hmac)
headers := make(map[string]string)

View File

@@ -261,7 +261,10 @@ func setFeeBuilder() *exchange.FeeBuilder {
// TestGetFeeByTypeOfflineTradeFee logic test
func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
var feeBuilder = setFeeBuilder()
b.GetFeeByType(feeBuilder)
_, err := b.GetFeeByType(feeBuilder)
if err != nil {
t.Fatal(err)
}
if !areTestAPIKeysSet() {
if feeBuilder.FeeType != exchange.OfflineTradeFee {
t.Errorf("Expected %v, received %v", exchange.OfflineTradeFee, feeBuilder.FeeType)

View File

@@ -868,9 +868,13 @@ func (b *Bitmex) SendAuthenticatedHTTPRequest(ep exchange.URL, verb, path string
payload = string(data)
}
hmac := crypto.GetHMAC(crypto.HashSHA256,
var hmac []byte
hmac, err = crypto.GetHMAC(crypto.HashSHA256,
[]byte(verb+"/api/v1"+path+timestampNew+payload),
[]byte(b.API.Credentials.Secret))
if err != nil {
return nil, err
}
headers["api-signature"] = crypto.HexEncodeToString(hmac)

View File

@@ -500,7 +500,10 @@ func setFeeBuilder() *exchange.FeeBuilder {
func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
t.Parallel()
var feeBuilder = setFeeBuilder()
b.GetFeeByType(feeBuilder)
_, err := b.GetFeeByType(feeBuilder)
if err != nil {
t.Fatal(err)
}
if !areTestAPIKeysSet() {
if feeBuilder.FeeType != exchange.OfflineTradeFee {
t.Errorf("Expected %v, received %v", exchange.OfflineTradeFee, feeBuilder.FeeType)

View File

@@ -666,16 +666,19 @@ func (b *Bitmex) websocketSendAuth() error {
b.Websocket.SetCanUseAuthenticatedEndpoints(true)
timestamp := time.Now().Add(time.Hour * 1).Unix()
newTimestamp := strconv.FormatInt(timestamp, 10)
hmac := crypto.GetHMAC(crypto.HashSHA256,
hmac, err := crypto.GetHMAC(crypto.HashSHA256,
[]byte("GET/realtime"+newTimestamp),
[]byte(b.API.Credentials.Secret))
if err != nil {
return err
}
signature := crypto.HexEncodeToString(hmac)
var sendAuth WebsocketRequest
sendAuth.Command = "authKeyExpires"
sendAuth.Arguments = append(sendAuth.Arguments, b.API.Credentials.Key, timestamp,
signature)
err := b.Websocket.Conn.SendJSONMessage(sendAuth)
err = b.Websocket.Conn.SendJSONMessage(sendAuth)
if err != nil {
b.Websocket.SetCanUseAuthenticatedEndpoints(false)
return err

View File

@@ -631,9 +631,15 @@ func (b *Bitstamp) SendAuthenticatedHTTPRequest(ep exchange.URL, path string, v2
values.Set("key", b.API.Credentials.Key)
values.Set("nonce", n)
hmac := crypto.GetHMAC(crypto.HashSHA256,
var hmac []byte
hmac, err = crypto.GetHMAC(crypto.HashSHA256,
[]byte(n+b.API.Credentials.ClientID+b.API.Credentials.Key),
[]byte(b.API.Credentials.Secret))
if err != nil {
return nil, err
}
values.Set("signature", strings.ToUpper(crypto.HexEncodeToString(hmac)))
var fullPath string

View File

@@ -44,7 +44,10 @@ func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
t.Parallel()
var feeBuilder = setFeeBuilder()
b.GetFeeByType(feeBuilder)
_, err := b.GetFeeByType(feeBuilder)
if err != nil {
t.Fatal(err)
}
if !areTestAPIKeysSet() {
if feeBuilder.FeeType != exchange.OfflineTradeFee {
t.Errorf("Expected %v, received %v",

View File

@@ -81,7 +81,12 @@ func (b *Bitstamp) wsHandleData(respRaw []byte) error {
if b.Verbose {
log.Debugf(log.ExchangeSys, "%v - Websocket reconnection request received", b.Name)
}
go b.Websocket.Shutdown() // Connection monitor will reconnect
go func() {
err := b.Websocket.Shutdown()
if err != nil {
log.Errorf(log.WebsocketMgr, "%s failed to shutdown websocket: %v", b.Name, err)
}
}() // Connection monitor will reconnect
case "data":
wsOrderBookTemp := websocketOrderBookResponse{}
err := json.Unmarshal(respRaw, &wsOrderBookTemp)

View File

@@ -386,9 +386,18 @@ func (b *Bittrex) SendAuthHTTPRequest(ep exchange.URL, method, action string, pa
}
}
body = bytes.NewBuffer(payload)
contentHash = crypto.HexEncodeToString(crypto.GetSHA512(payload))
hash, err := crypto.GetSHA512(payload)
if err != nil {
return nil, err
}
contentHash = crypto.HexEncodeToString(hash)
sigPayload := ts + endpoint + path + method + contentHash
hmac = crypto.GetHMAC(crypto.HashSHA512, []byte(sigPayload), []byte(b.API.Credentials.Secret))
hmac, err = crypto.GetHMAC(crypto.HashSHA512,
[]byte(sigPayload),
[]byte(b.API.Credentials.Secret))
if err != nil {
return nil, err
}
headers := make(map[string]string)
headers["Api-Key"] = b.API.Credentials.Key

View File

@@ -339,7 +339,10 @@ func setFeeBuilder() *exchange.FeeBuilder {
// TestGetFeeByTypeOfflineTradeFee logic test
func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
var feeBuilder = setFeeBuilder()
b.GetFeeByType(feeBuilder)
_, err := b.GetFeeByType(feeBuilder)
if err != nil {
t.Fatal(err)
}
if !areTestAPIKeysSet() {
if feeBuilder.FeeType != exchange.OfflineTradeFee {
t.Errorf("Expected %v, received %v", exchange.OfflineTradeFee, feeBuilder.FeeType)

View File

@@ -155,11 +155,15 @@ func (b *Bittrex) WsAuth() error {
return err
}
timestamp := strconv.FormatInt(time.Now().UnixNano()/1000000, 10)
hmac := crypto.GetHMAC(
hmac, err := crypto.GetHMAC(
crypto.HashSHA512,
[]byte(timestamp+randomContent.String()),
[]byte(b.API.Credentials.Secret),
)
if err != nil {
return err
}
signature := crypto.HexEncodeToString(hmac)
req := WsEventRequest{

View File

@@ -144,7 +144,10 @@ func (b *Bittrex) Setup(exch *config.ExchangeConfig) error {
return nil
}
b.SetupDefaults(exch)
err := b.SetupDefaults(exch)
if err != nil {
return err
}
wsRunningEndpoint, err := b.API.Endpoints.GetURL(exchange.WebsocketSpot)
if err != nil {

View File

@@ -166,7 +166,10 @@ func (b *Bittrex) applyBufferUpdate(pair currency.Pair) error {
"%s error processing update - initiating new orderbook sync via REST: %s\n",
b.Name,
err)
b.obm.setNeedsFetchingBook(pair)
err = b.obm.setNeedsFetchingBook(pair)
if err != nil {
return err
}
}
}
return nil

View File

@@ -716,13 +716,20 @@ func (b *BTCMarkets) SendAuthenticatedRequest(method, path string, data, result
}
body = bytes.NewBuffer(payload)
strMsg := method + btcMarketsAPIVersion + path + strTime + string(payload)
hmac = crypto.GetHMAC(crypto.HashSHA512,
[]byte(strMsg), []byte(b.API.Credentials.Secret))
hmac, err = crypto.GetHMAC(crypto.HashSHA512,
[]byte(strMsg),
[]byte(b.API.Credentials.Secret))
if err != nil {
return nil, err
}
default:
strArray := strings.Split(path, "?")
hmac = crypto.GetHMAC(crypto.HashSHA512,
hmac, err = crypto.GetHMAC(crypto.HashSHA512,
[]byte(method+btcMarketsAPIVersion+strArray[0]+strTime),
[]byte(b.API.Credentials.Secret))
if err != nil {
return nil, err
}
}
headers := make(map[string]string)

View File

@@ -1,12 +1,9 @@
package btcmarkets
import (
"errors"
"time"
)
var errInvalidTimeInterval = errors.New("invalid time interval")
// Market holds a tradable market instrument
type Market struct {
MarketID string `json:"marketId"`

View File

@@ -344,9 +344,12 @@ func (b *BTCMarkets) Subscribe(channelsToSubscribe []stream.ChannelSubscription)
}
signTime := strconv.FormatInt(time.Now().UTC().UnixNano()/1000000, 10)
strToSign := "/users/self/subscribe" + "\n" + signTime
tempSign := crypto.GetHMAC(crypto.HashSHA512,
tempSign, err := crypto.GetHMAC(crypto.HashSHA512,
[]byte(strToSign),
[]byte(b.API.Credentials.Secret))
if err != nil {
return err
}
sign := crypto.Base64Encode(tempSign)
payload.Key = b.API.Credentials.Key
payload.Signature = sign

View File

@@ -483,23 +483,30 @@ func (b *BTSE) SendAuthenticatedHTTPRequest(ep exchange.URL, method, endpoint st
"btse-nonce": nonce,
}
if req != nil {
reqPayload, err := json.Marshal(req)
var reqPayload []byte
reqPayload, err = json.Marshal(req)
if err != nil {
return nil, err
}
body = bytes.NewBuffer(reqPayload)
hmac = crypto.GetHMAC(
hmac, err = crypto.GetHMAC(
crypto.HashSHA512_384,
[]byte((expandedEndpoint + nonce + string(reqPayload))),
[]byte(b.API.Credentials.Secret),
)
if err != nil {
return nil, err
}
headers["Content-Type"] = "application/json"
} else {
hmac = crypto.GetHMAC(
hmac, err = crypto.GetHMAC(
crypto.HashSHA512_384,
[]byte((expandedEndpoint + nonce)),
[]byte(b.API.Credentials.Secret),
)
if err != nil {
return nil, err
}
if len(values) > 0 {
host += "?" + values.Encode()
}

View File

@@ -466,7 +466,10 @@ func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
PurchasePrice: 1000,
}
b.GetFeeByType(feeBuilder)
_, err := b.GetFeeByType(feeBuilder)
if err != nil {
t.Fatal(err)
}
if !areTestAPIKeysSet() {
if feeBuilder.FeeType != exchange.OfflineTradeFee {
t.Errorf("Expected %v, received %v", exchange.OfflineTradeFee, feeBuilder.FeeType)

View File

@@ -57,10 +57,15 @@ func (b *BTSE) WsConnect() error {
func (b *BTSE) WsAuthenticate() error {
nonce := strconv.FormatInt(time.Now().UnixNano()/int64(time.Millisecond), 10)
path := "/spotWS" + nonce
hmac := crypto.GetHMAC(crypto.HashSHA512_384,
hmac, err := crypto.GetHMAC(crypto.HashSHA512_384,
[]byte((path)),
[]byte(b.API.Credentials.Secret),
)
if err != nil {
return err
}
sign := crypto.HexEncodeToString(hmac)
req := wsSub{
Operation: "authKeyExpires",

View File

@@ -28,11 +28,6 @@ import (
"github.com/thrasher-corp/gocryptotrader/portfolio/withdraw"
)
const (
spotURL = "spotURL"
spotWSURL = "websocketURL"
)
// GetDefaultConfig returns a default exchange config
func (b *BTSE) GetDefaultConfig() (*config.ExchangeConfig, error) {
b.SetDefaults()

View File

@@ -722,7 +722,14 @@ func (c *CoinbasePro) SendAuthenticatedHTTPRequest(ep exchange.URL, method, path
now := time.Now()
n := strconv.FormatInt(now.Unix(), 10)
message := n + method + "/" + path + string(payload)
hmac := crypto.GetHMAC(crypto.HashSHA256, []byte(message), []byte(c.API.Credentials.Secret))
hmac, err := crypto.GetHMAC(crypto.HashSHA256,
[]byte(message),
[]byte(c.API.Credentials.Secret))
if err != nil {
return nil, err
}
headers := make(map[string]string)
headers["CB-ACCESS-SIGN"] = crypto.Base64Encode(hmac)
headers["CB-ACCESS-TIMESTAMP"] = n

View File

@@ -214,7 +214,10 @@ func setFeeBuilder() *exchange.FeeBuilder {
// TestGetFeeByTypeOfflineTradeFee logic test
func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
var feeBuilder = setFeeBuilder()
c.GetFeeByType(feeBuilder)
_, err := c.GetFeeByType(feeBuilder)
if err != nil {
t.Fatal(err)
}
if !areTestAPIKeysSet() {
if feeBuilder.FeeType != exchange.OfflineTradeFee {
t.Errorf("Expected %v, received %v", exchange.OfflineTradeFee, feeBuilder.FeeType)

View File

@@ -416,8 +416,12 @@ subscriptions:
channelsToSubscribe[i].Channel == "full" {
n := strconv.FormatInt(time.Now().Unix(), 10)
message := n + http.MethodGet + "/users/self/verify"
hmac := crypto.GetHMAC(crypto.HashSHA256, []byte(message),
hmac, err := crypto.GetHMAC(crypto.HashSHA256,
[]byte(message),
[]byte(c.API.Credentials.Secret))
if err != nil {
return err
}
subscribe.Signature = crypto.Base64Encode(hmac)
subscribe.Key = c.API.Credentials.Key
subscribe.Passphrase = c.API.Credentials.ClientID

View File

@@ -1166,9 +1166,13 @@ func (c *Coinbene) SendAuthHTTPRequest(ep exchange.URL, method, path, epPath str
default:
preSign = timestamp + method + authPath + epPath
}
tempSign := crypto.GetHMAC(crypto.HashSHA256,
tempSign, err := crypto.GetHMAC(crypto.HashSHA256,
[]byte(preSign),
[]byte(c.API.Credentials.Secret))
if err != nil {
return nil, err
}
headers := make(map[string]string)
headers["Content-Type"] = "application/json"
headers["ACCESS-KEY"] = c.API.Credentials.Key

View File

@@ -502,9 +502,14 @@ func (c *Coinbene) Login() error {
var sub WsSub
expTime := time.Now().Add(time.Minute * 10).Format("2006-01-02T15:04:05Z")
signMsg := expTime + http.MethodGet + "/login"
tempSign := crypto.GetHMAC(crypto.HashSHA256,
tempSign, err := crypto.GetHMAC(crypto.HashSHA256,
[]byte(signMsg),
[]byte(c.API.Credentials.Secret))
if err != nil {
return err
}
sign := crypto.HexEncodeToString(tempSign)
sub.Operation = "login"
sub.Arguments = []string{c.API.Credentials.Key, expTime, sign}

View File

@@ -44,10 +44,7 @@ const (
wsRateLimitInMilliseconds = 33
)
var (
errLookupInstrumentID = errors.New("unable to lookup instrument ID")
errLookupInstrumentCurrency = errors.New("unable to lookup instrument")
)
var errLookupInstrumentID = errors.New("unable to lookup instrument ID")
// COINUT is the overarching type across the coinut package
type COINUT struct {
@@ -174,11 +171,6 @@ func (c *COINUT) CancelExistingOrder(instrumentID, orderID int64) (bool, error)
func (c *COINUT) CancelOrders(orders []CancelOrders) (CancelOrdersResponse, error) {
var result CancelOrdersResponse
params := make(map[string]interface{})
type Request struct {
InstrumentID int `json:"inst_id"`
OrderID int `json:"order_id"`
}
var entries []CancelOrders
entries = append(entries, orders...)
params["entries"] = entries
@@ -288,7 +280,13 @@ func (c *COINUT) SendHTTPRequest(ep exchange.URL, apiRequest string, params map[
headers := make(map[string]string)
if authenticated {
headers["X-USER"] = c.API.Credentials.ClientID
hmac := crypto.GetHMAC(crypto.HashSHA256, payload, []byte(c.API.Credentials.Key))
var hmac []byte
hmac, err = crypto.GetHMAC(crypto.HashSHA256,
payload,
[]byte(c.API.Credentials.Key))
if err != nil {
return nil, err
}
headers["X-SIGNATURE"] = crypto.HexEncodeToString(hmac)
}
headers["Content-Type"] = "application/json"

View File

@@ -117,7 +117,10 @@ func setFeeBuilder() *exchange.FeeBuilder {
// TestGetFeeByTypeOfflineTradeFee logic test
func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
var feeBuilder = setFeeBuilder()
c.GetFeeByType(feeBuilder)
_, err := c.GetFeeByType(feeBuilder)
if err != nil {
t.Fatal(err)
}
if apiKey == "" {
if feeBuilder.FeeType != exchange.OfflineTradeFee {
t.Errorf("Expected %v, received %v", exchange.OfflineTradeFee, feeBuilder.FeeType)

View File

@@ -690,9 +690,14 @@ func (c *COINUT) wsAuthenticate() error {
payload := c.API.Credentials.ClientID + "|" +
strconv.FormatInt(timestamp, 10) + "|" +
strconv.FormatInt(nonce, 10)
hmac := crypto.GetHMAC(crypto.HashSHA256,
hmac, err := crypto.GetHMAC(crypto.HashSHA256,
[]byte(payload),
[]byte(c.API.Credentials.Key))
if err != nil {
return err
}
loginRequest := struct {
Request string `json:"request"`
Username string `json:"username"`

View File

@@ -37,8 +37,11 @@ const (
DefaultWebsocketOrderbookBufferLimit = 5
)
// ErrAuthenticatedRequestWithoutCredentialsSet error message for authenticated request without credentials set
var ErrAuthenticatedRequestWithoutCredentialsSet = errors.New("authenticated HTTP request called but not supported due to unset/default API keys")
var (
// ErrAuthenticatedRequestWithoutCredentialsSet error message for authenticated request without credentials set
ErrAuthenticatedRequestWithoutCredentialsSet = errors.New("authenticated HTTP request called but not supported due to unset/default API keys")
errTransportNotSet = errors.New("transport not set, cannot set timeout")
)
func (b *Base) checkAndInitRequester() {
if b.Requester == nil {
@@ -54,7 +57,7 @@ func (b *Base) SetHTTPClientTimeout(t time.Duration) error {
b.Requester.HTTPClient.Timeout = t
tr, ok := b.Requester.HTTPClient.Transport.(*http.Transport)
if !ok {
return errors.New("transport not set, cannot set timeout")
return errTransportNotSet
}
tr.IdleConnTimeout = t
return nil
@@ -294,6 +297,7 @@ func (b *Base) SetConfigPairs() error {
"%s exchange asset type %s unsupported, please manually remove from configuration",
b.Name,
assetTypes[x])
continue // If there are unsupported assets contained in config, skip.
}
cfgPS, err := b.Config.CurrencyPairs.Get(assetTypes[x])
if err != nil {
@@ -304,7 +308,14 @@ func (b *Base) SetConfigPairs() error {
if b.Config.CurrencyPairs.IsAssetEnabled(assetTypes[x]) == nil {
enabledAsset = true
}
b.CurrencyPairs.SetAssetEnabled(assetTypes[x], enabledAsset)
err = b.CurrencyPairs.SetAssetEnabled(assetTypes[x], enabledAsset)
// Suppress error when assets are enabled by default and they are being
// enabled by config. A check for the inverse
// e.g. currency.ErrAssetAlreadyDisabled is not needed.
if err != nil && err != currency.ErrAssetAlreadyEnabled {
return err
}
if b.Config.CurrencyPairs.UseGlobalFormat {
b.CurrencyPairs.StorePairs(assetTypes[x], cfgPS.Available, false)

View File

@@ -111,10 +111,13 @@ func TestGetURL(t *testing.T) {
Name: "HELAAAAAOOOOOOOOO",
}
b.API.Endpoints = b.NewEndpoints()
b.API.Endpoints.SetDefaultEndpoints(map[URL]string{
err := b.API.Endpoints.SetDefaultEndpoints(map[URL]string{
EdgeCase1: "http://test1.com/",
EdgeCase2: "http://test2.com/",
})
if err != nil {
t.Fatal(err)
}
getVal, err := b.API.Endpoints.GetURL(EdgeCase1)
if err != nil {
t.Error(err)
@@ -189,7 +192,10 @@ func TestSetDefaultEndpoints(t *testing.T) {
func TestHTTPClient(t *testing.T) {
t.Parallel()
r := Base{Name: "asdf"}
r.SetHTTPClientTimeout(time.Second * 5)
err := r.SetHTTPClientTimeout(time.Second * 5)
if err != nil {
t.Fatal(err)
}
if r.GetHTTPClient().Timeout != time.Second*5 {
t.Fatalf("TestHTTPClient unexpected value")
@@ -210,10 +216,19 @@ func TestHTTPClient(t *testing.T) {
}
b := Base{Name: "RAWR"}
b.Requester = request.New(b.Name,
new(http.Client))
b.SetHTTPClientTimeout(time.Second * 5)
b.Requester = request.New(b.Name, new(http.Client))
err = b.SetHTTPClientTimeout(time.Second * 5)
if !errors.Is(err, errTransportNotSet) {
t.Fatalf("received: %v but expected: %v", err, errTransportNotSet)
}
b.Requester = request.New(b.Name, &http.Client{Transport: new(http.Transport)})
err = b.SetHTTPClientTimeout(time.Second * 5)
if err != nil {
t.Fatal(err)
}
if b.GetHTTPClient().Timeout != time.Second*5 {
t.Fatalf("TestHTTPClient unexpected value")
}
@@ -656,7 +671,10 @@ func TestLoadConfigPairs(t *testing.T) {
b.Config.CurrencyPairs.UseGlobalFormat = false
b.CurrencyPairs.UseGlobalFormat = false
b.SetConfigPairs()
err = b.SetConfigPairs()
if err != nil {
t.Fatal(err)
}
// Test four things:
// 1) XRP-USD is set
// 2) pair format is set for RequestFormat
@@ -1286,7 +1304,10 @@ func TestSetupDefaults(t *testing.T) {
},
},
)
b.SetupDefaults(&cfg)
err = b.SetupDefaults(&cfg)
if err != nil {
t.Fatal(err)
}
ps, err := cfg.CurrencyPairs.Get(asset.Spot)
if err != nil {
t.Fatal(err)
@@ -1298,7 +1319,6 @@ func TestSetupDefaults(t *testing.T) {
// Test websocket support
b.Websocket = stream.New()
b.Features.Supports.Websocket = true
b.SetupDefaults(&cfg)
err = b.Websocket.Setup(&stream.WebsocketSetup{
Enabled: false,
WebsocketTimeout: time.Second * 30,

View File

@@ -336,9 +336,12 @@ func (e *EXMO) SendAuthenticatedHTTPRequest(epath exchange.URL, method, endpoint
vals.Set("nonce", n)
payload := vals.Encode()
hash := crypto.GetHMAC(crypto.HashSHA512,
hash, err := crypto.GetHMAC(crypto.HashSHA512,
[]byte(payload),
[]byte(e.API.Credentials.Secret))
if err != nil {
return nil, err
}
headers := make(map[string]string)
headers["Key"] = e.API.Credentials.Key

View File

@@ -126,7 +126,10 @@ func setFeeBuilder() *exchange.FeeBuilder {
// TestGetFeeByTypeOfflineTradeFee logic test
func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
var feeBuilder = setFeeBuilder()
e.GetFeeByType(feeBuilder)
_, err := e.GetFeeByType(feeBuilder)
if err != nil {
t.Fatal(err)
}
if !areTestAPIKeysSet() {
if feeBuilder.FeeType != exchange.OfflineTradeFee {
t.Errorf("Expected %v, received %v", exchange.OfflineTradeFee, feeBuilder.FeeType)

View File

@@ -1153,18 +1153,24 @@ func (f *FTX) SendAuthHTTPRequest(ep exchange.URL, method, path string, data, re
ts := strconv.FormatInt(time.Now().UnixNano()/1000000, 10)
var body io.Reader
var hmac, payload []byte
sigPayload := ts + method + "/api" + path
if data != nil {
payload, err = json.Marshal(data)
if err != nil {
return nil, err
}
body = bytes.NewBuffer(payload)
sigPayload := ts + method + "/api" + path + string(payload)
hmac = crypto.GetHMAC(crypto.HashSHA256, []byte(sigPayload), []byte(f.API.Credentials.Secret))
} else {
sigPayload := ts + method + "/api" + path
hmac = crypto.GetHMAC(crypto.HashSHA256, []byte(sigPayload), []byte(f.API.Credentials.Secret))
sigPayload += string(payload)
}
hmac, err = crypto.GetHMAC(crypto.HashSHA256,
[]byte(sigPayload),
[]byte(f.API.Credentials.Secret))
if err != nil {
return nil, err
}
headers := make(map[string]string)
headers["FTX-KEY"] = f.API.Credentials.Key
headers["FTX-SIGN"] = crypto.HexEncodeToString(hmac)

View File

@@ -76,11 +76,14 @@ func (f *FTX) WsConnect() error {
func (f *FTX) WsAuth() error {
intNonce := time.Now().UnixNano() / 1000000
strNonce := strconv.FormatInt(intNonce, 10)
hmac := crypto.GetHMAC(
hmac, err := crypto.GetHMAC(
crypto.HashSHA256,
[]byte(strNonce+"websocket_login"),
[]byte(f.API.Credentials.Secret),
)
if err != nil {
return err
}
sign := crypto.HexEncodeToString(hmac)
req := Authenticate{Operation: "login",
Args: AuthenticationData{

View File

@@ -399,7 +399,7 @@ func (g *Gateio) GetTradeHistory(symbol string) (TradHistoryResponse, error) {
}
// GenerateSignature returns hash for authenticated requests
func (g *Gateio) GenerateSignature(message string) []byte {
func (g *Gateio) GenerateSignature(message string) ([]byte, error) {
return crypto.GetHMAC(crypto.HashSHA512, []byte(message),
[]byte(g.API.Credentials.Secret))
}
@@ -418,7 +418,11 @@ func (g *Gateio) SendAuthenticatedHTTPRequest(ep exchange.URL, method, endpoint,
headers["Content-Type"] = "application/x-www-form-urlencoded"
headers["key"] = g.API.Credentials.Key
hmac := g.GenerateSignature(param)
hmac, err := g.GenerateSignature(param)
if err != nil {
return err
}
headers["sign"] = crypto.HexEncodeToString(hmac)
urlPath := fmt.Sprintf("%s/%s/%s", ePoint, gateioAPIVersion, endpoint)

View File

@@ -186,7 +186,10 @@ func TestGetTradeHistory(t *testing.T) {
// TestGetFeeByTypeOfflineTradeFee logic test
func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
var feeBuilder = setFeeBuilder()
g.GetFeeByType(feeBuilder)
_, err := g.GetFeeByType(feeBuilder)
if err != nil {
t.Fatal(err)
}
if !areTestAPIKeysSet() {
if feeBuilder.FeeType != exchange.OfflineTradeFee {
t.Errorf("Expected %v, received %v", exchange.OfflineTradeFee, feeBuilder.FeeType)

View File

@@ -67,7 +67,10 @@ func (g *Gateio) WsConnect() error {
func (g *Gateio) wsServerSignIn() error {
nonce := int(time.Now().Unix() * 1000)
sigTemp := g.GenerateSignature(strconv.Itoa(nonce))
sigTemp, err := g.GenerateSignature(strconv.Itoa(nonce))
if err != nil {
return err
}
signature := crypto.Base64Encode(sigTemp)
signinWsRequest := WebsocketRequest{
ID: g.Websocket.Conn.GenerateMessageID(false),

View File

@@ -41,13 +41,6 @@ const (
geminiWithdraw = "withdraw/"
geminiHeartbeat = "heartbeat"
geminiVolume = "notionalvolume"
// Too many requests returns this
geminiRateError = "429"
// Assigned API key roles on creation
geminiRoleTrader = "trader"
geminiRoleFundManager = "fundmanager"
)
// Gemini is the overarching type across the Gemini package, create multiple
@@ -392,7 +385,12 @@ func (g *Gemini) SendAuthenticatedHTTPRequest(ep exchange.URL, method, path stri
}
PayloadBase64 := crypto.Base64Encode(PayloadJSON)
hmac := crypto.GetHMAC(crypto.HashSHA512_384, []byte(PayloadBase64), []byte(g.API.Credentials.Secret))
hmac, err := crypto.GetHMAC(crypto.HashSHA512_384,
[]byte(PayloadBase64),
[]byte(g.API.Credentials.Secret))
if err != nil {
return nil, err
}
headers := make(map[string]string)
headers["Content-Length"] = "0"

View File

@@ -241,8 +241,10 @@ func setFeeBuilder() *exchange.FeeBuilder {
func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
t.Parallel()
var feeBuilder = setFeeBuilder()
g.GetFeeByType(feeBuilder)
_, err := g.GetFeeByType(feeBuilder)
if err != nil {
t.Fatal(err)
}
if !areTestAPIKeysSet() {
if feeBuilder.FeeType != exchange.OfflineTradeFee {
t.Errorf("Expected %v, received %v",

View File

@@ -193,7 +193,13 @@ func (g *Gemini) WsAuth(dialer *websocket.Dialer) error {
}
endpoint := wsEndpoint + geminiWsOrderEvents
PayloadBase64 := crypto.Base64Encode(PayloadJSON)
hmac := crypto.GetHMAC(crypto.HashSHA512_384, []byte(PayloadBase64), []byte(g.API.Credentials.Secret))
hmac, err := crypto.GetHMAC(crypto.HashSHA512_384,
[]byte(PayloadBase64),
[]byte(g.API.Credentials.Secret))
if err != nil {
return err
}
headers := http.Header{}
headers.Add("Content-Length", "0")
headers.Add("Content-Type", "text/plain")

View File

@@ -132,7 +132,10 @@ func setFeeBuilder() *exchange.FeeBuilder {
// TestGetFeeByTypeOfflineTradeFee logic test
func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
var feeBuilder = setFeeBuilder()
h.GetFeeByType(feeBuilder)
_, err := h.GetFeeByType(feeBuilder)
if err != nil {
t.Fatal(err)
}
if !areTestAPIKeysSet() {
if feeBuilder.FeeType != exchange.OfflineTradeFee {
t.Errorf("Expected %v, received %v", exchange.OfflineTradeFee, feeBuilder.FeeType)
@@ -453,7 +456,10 @@ func setupWsAuth(t *testing.T) {
t.Fatal(err)
}
go h.wsReadData()
h.wsLogin()
err = h.wsLogin()
if err != nil {
t.Fatal(err)
}
timer := time.NewTimer(time.Second)
select {
case loginError := <-h.Websocket.DataHandler:

View File

@@ -15,7 +15,6 @@ import (
"github.com/thrasher-corp/gocryptotrader/currency"
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
"github.com/thrasher-corp/gocryptotrader/exchanges/nonce"
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
"github.com/thrasher-corp/gocryptotrader/exchanges/stream"
@@ -32,8 +31,6 @@ const (
errAuthFailed = 1002
)
var requestID nonce.Nonce
// WsConnect starts a new connection with the websocket API
func (h *HitBTC) WsConnect() error {
if !h.Websocket.IsEnabled() || !h.IsEnabled() {
@@ -564,7 +561,13 @@ func (h *HitBTC) wsLogin() error {
}
h.Websocket.SetCanUseAuthenticatedEndpoints(true)
n := strconv.FormatInt(time.Now().Unix(), 10)
hmac := crypto.GetHMAC(crypto.HashSHA256, []byte(n), []byte(h.API.Credentials.Secret))
hmac, err := crypto.GetHMAC(crypto.HashSHA256,
[]byte(n),
[]byte(h.API.Credentials.Secret))
if err != nil {
return err
}
request := WsLoginRequest{
Method: "login",
Params: WsLoginData{
@@ -576,7 +579,7 @@ func (h *HitBTC) wsLogin() error {
ID: h.Websocket.Conn.GenerateMessageID(false),
}
err := h.Websocket.Conn.SendJSONMessage(request)
err = h.Websocket.Conn.SendJSONMessage(request)
if err != nil {
h.Websocket.SetCanUseAuthenticatedEndpoints(false)
return err

View File

@@ -859,7 +859,14 @@ func (h *HUOBI) SendAuthenticatedHTTPRequest(ep exchange.URL, method, endpoint s
headers["Content-Type"] = "application/json"
}
hmac := crypto.GetHMAC(crypto.HashSHA256, []byte(payload), []byte(h.API.Credentials.Secret))
var hmac []byte
hmac, err = crypto.GetHMAC(crypto.HashSHA256,
[]byte(payload),
[]byte(h.API.Credentials.Secret))
if err != nil {
return nil, err
}
values.Set("Signature", crypto.Base64Encode(hmac))
urlPath := ePoint + common.EncodeURLValues(endpoint, values)

View File

@@ -1134,7 +1134,14 @@ func (h *HUOBI) FuturesAuthenticatedHTTPRequest(ep exchange.URL, method, endpoin
} else {
headers["Content-Type"] = "application/json"
}
hmac := crypto.GetHMAC(crypto.HashSHA256, []byte(sigPath), []byte(h.API.Credentials.Secret))
var hmac []byte
hmac, err = crypto.GetHMAC(crypto.HashSHA256,
[]byte(sigPath),
[]byte(h.API.Credentials.Secret))
if err != nil {
return nil, err
}
sigValues := url.Values{}
sigValues.Add("Signature", crypto.Base64Encode(hmac))
urlPath :=

View File

@@ -1840,7 +1840,10 @@ func setFeeBuilder() *exchange.FeeBuilder {
// TestGetFeeByTypeOfflineTradeFee logic test
func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
var feeBuilder = setFeeBuilder()
h.GetFeeByType(feeBuilder)
_, err := h.GetFeeByType(feeBuilder)
if err != nil {
t.Fatal(err)
}
if !areTestAPIKeysSet() {
if feeBuilder.FeeType != exchange.OfflineTradeFee {
t.Errorf("Expected %v, received %v", exchange.OfflineTradeFee, feeBuilder.FeeType)

View File

@@ -564,7 +564,7 @@ func (h *HUOBI) Unsubscribe(channelsToUnsubscribe []stream.ChannelSubscription)
return nil
}
func (h *HUOBI) wsGenerateSignature(timestamp, endpoint string) []byte {
func (h *HUOBI) wsGenerateSignature(timestamp, endpoint string) ([]byte, error) {
values := url.Values{}
values.Set("AccessKeyId", h.API.Credentials.Key)
values.Set("SignatureMethod", signatureMethod)
@@ -589,9 +589,12 @@ func (h *HUOBI) wsLogin() error {
SignatureVersion: signatureVersion,
Timestamp: timestamp,
}
hmac := h.wsGenerateSignature(timestamp, wsAccountsOrdersEndPoint)
hmac, err := h.wsGenerateSignature(timestamp, wsAccountsOrdersEndPoint)
if err != nil {
return err
}
request.Signature = crypto.Base64Encode(hmac)
err := h.Websocket.AuthConn.SendJSONMessage(request)
err = h.Websocket.AuthConn.SendJSONMessage(request)
if err != nil {
h.Websocket.SetCanUseAuthenticatedEndpoints(false)
return err
@@ -611,7 +614,10 @@ func (h *HUOBI) wsAuthenticatedSubscribe(operation, endpoint, topic string) erro
Timestamp: timestamp,
Topic: topic,
}
hmac := h.wsGenerateSignature(timestamp, endpoint)
hmac, err := h.wsGenerateSignature(timestamp, endpoint)
if err != nil {
return err
}
request.Signature = crypto.Base64Encode(hmac)
return h.Websocket.AuthConn.SendJSONMessage(request)
}
@@ -629,7 +635,10 @@ func (h *HUOBI) wsGetAccountsList() (*WsAuthenticatedAccountsListResponse, error
Timestamp: timestamp,
Topic: wsAccountsList,
}
hmac := h.wsGenerateSignature(timestamp, wsAccountListEndpoint)
hmac, err := h.wsGenerateSignature(timestamp, wsAccountListEndpoint)
if err != nil {
return nil, err
}
request.Signature = crypto.Base64Encode(hmac)
request.ClientID = h.Websocket.AuthConn.GenerateMessageID(true)
resp, err := h.Websocket.AuthConn.SendMessageReturnResponse(request.ClientID, request)
@@ -672,7 +681,10 @@ func (h *HUOBI) wsGetOrdersList(accountID int64, pair currency.Pair) (*WsAuthent
States: "submitted,partial-filled",
}
hmac := h.wsGenerateSignature(timestamp, wsOrdersListEndpoint)
hmac, err := h.wsGenerateSignature(timestamp, wsOrdersListEndpoint)
if err != nil {
return nil, err
}
request.Signature = crypto.Base64Encode(hmac)
request.ClientID = h.Websocket.AuthConn.GenerateMessageID(true)
@@ -708,7 +720,10 @@ func (h *HUOBI) wsGetOrderDetails(orderID string) (*WsAuthenticatedOrderDetailRe
Topic: wsOrdersDetail,
OrderID: orderID,
}
hmac := h.wsGenerateSignature(timestamp, wsOrdersDetailEndpoint)
hmac, err := h.wsGenerateSignature(timestamp, wsOrdersDetailEndpoint)
if err != nil {
return nil, err
}
request.Signature = crypto.Base64Encode(hmac)
request.ClientID = h.Websocket.AuthConn.GenerateMessageID(true)
resp, err := h.Websocket.AuthConn.SendMessageReturnResponse(request.ClientID, request)

View File

@@ -332,8 +332,18 @@ func (i *ItBit) SendAuthenticatedHTTPRequest(ep exchange.URL, method, path strin
return nil, err
}
hash := crypto.GetSHA256([]byte(n + string(message)))
hmac := crypto.GetHMAC(crypto.HashSHA512, []byte(urlPath+string(hash)), []byte(i.API.Credentials.Secret))
var hash []byte
hash, err = crypto.GetSHA256([]byte(n + string(message)))
if err != nil {
return nil, err
}
var hmac []byte
hmac, err = crypto.GetHMAC(crypto.HashSHA512,
[]byte(urlPath+string(hash)),
[]byte(i.API.Credentials.Secret))
if err != nil {
return nil, err
}
signature := crypto.Base64Encode(hmac)
headers := make(map[string]string)

View File

@@ -171,7 +171,10 @@ func setFeeBuilder() *exchange.FeeBuilder {
// TestGetFeeByTypeOfflineTradeFee logic test
func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
var feeBuilder = setFeeBuilder()
i.GetFeeByType(feeBuilder)
_, err := i.GetFeeByType(feeBuilder)
if err != nil {
t.Fatal(err)
}
if !areTestAPIKeysSet() {
if feeBuilder.FeeType != exchange.OfflineTradeFee {
t.Errorf("Expected %v, received %v", exchange.OfflineTradeFee, feeBuilder.FeeType)

View File

@@ -988,10 +988,21 @@ func (k *Kraken) SendAuthenticatedHTTPRequest(ep exchange.URL, method string, pa
nonce := k.Requester.GetNonce(true).String()
params.Set("nonce", nonce)
encoded := params.Encode()
shasum := crypto.GetSHA256([]byte(nonce + encoded))
signature := crypto.Base64Encode(crypto.GetHMAC(crypto.HashSHA512,
var shasum []byte
shasum, err = crypto.GetSHA256([]byte(nonce + encoded))
if err != nil {
return nil, err
}
var hmac []byte
hmac, err = crypto.GetHMAC(crypto.HashSHA512,
append([]byte(path), shasum...),
[]byte(k.API.Credentials.Secret)))
[]byte(k.API.Credentials.Secret))
if err != nil {
return nil, err
}
signature := crypto.Base64Encode(hmac)
headers := make(map[string]string)
headers["API-Key"] = k.API.Credentials.Key

View File

@@ -249,11 +249,19 @@ func (k *Kraken) GetFuturesAccountData() (FuturesAccountsData, error) {
return resp, k.SendFuturesAuthRequest(http.MethodGet, futuresAccountData, nil, nil, &resp)
}
func (k *Kraken) signFuturesRequest(endpoint, nonce, data string) string {
func (k *Kraken) signFuturesRequest(endpoint, nonce, data string) (string, error) {
message := data + nonce + endpoint
hash := crypto.GetSHA256([]byte(message))
hc := crypto.GetHMAC(crypto.HashSHA512, hash, []byte(k.API.Credentials.Secret))
return base64.StdEncoding.EncodeToString(hc)
hash, err := crypto.GetSHA256([]byte(message))
if err != nil {
return "", err
}
hc, err := crypto.GetHMAC(crypto.HashSHA512,
hash,
[]byte(k.API.Credentials.Secret))
if err != nil {
return "", err
}
return base64.StdEncoding.EncodeToString(hc), nil
}
// SendFuturesAuthRequest will send an auth req
@@ -277,7 +285,10 @@ func (k *Kraken) SendFuturesAuthRequest(method, path string, postData url.Values
postData.Set("json", string(temp))
reqData = "json=" + string(temp)
}
sig := k.signFuturesRequest(path, nonce, reqData)
sig, err := k.signFuturesRequest(path, nonce, reqData)
if err != nil {
return nil, err
}
headers := map[string]string{
"APIKey": k.API.Credentials.Key,
"Authent": sig,

View File

@@ -1,6 +1,7 @@
package kraken
import (
"fmt"
"log"
"net/http"
"os"
@@ -687,7 +688,10 @@ func setFeeBuilder() *exchange.FeeBuilder {
func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
t.Parallel()
var feeBuilder = setFeeBuilder()
k.GetFeeByType(feeBuilder)
_, err := k.GetFeeByType(feeBuilder)
if err != nil {
t.Fatal(err)
}
if !areTestAPIKeysSet() {
if feeBuilder.FeeType != exchange.OfflineTradeFee {
t.Errorf("Expected %v, received %v", exchange.OfflineTradeFee, feeBuilder.FeeType)
@@ -1127,7 +1131,12 @@ func setupWsTests(t *testing.T) {
go k.wsFunnelConnectionData(k.Websocket.Conn, comms)
go k.wsFunnelConnectionData(k.Websocket.AuthConn, comms)
go k.wsReadData(comms)
go k.wsPingHandler()
go func() {
err := k.wsPingHandler()
if err != nil {
fmt.Println("error:", err)
}
}()
wsSetupRan = true
}

View File

@@ -548,9 +548,15 @@ func (l *Lbank) sign(data string) (string, error) {
if l.privateKey == nil {
return "", errors.New("private key not loaded")
}
md5hash := gctcrypto.GetMD5([]byte(data))
md5hash, err := gctcrypto.GetMD5([]byte(data))
if err != nil {
return "", err
}
m := strings.ToUpper(gctcrypto.HexEncodeToString(md5hash))
s := gctcrypto.GetSHA256([]byte(m))
s, err := gctcrypto.GetSHA256([]byte(m))
if err != nil {
return "", err
}
r, err := rsa.SignPKCS1v15(rand.Reader, l.privateKey, crypto.SHA256, s)
if err != nil {
return "", err

View File

@@ -297,8 +297,11 @@ func TestSign(t *testing.T) {
t.Skip("API keys required but not set, skipping test")
}
l.API.Credentials.Secret = testAPISecret
l.loadPrivKey()
_, err := l.sign("hello123")
err := l.loadPrivKey()
if err != nil {
t.Fatal(err)
}
_, err = l.sign("hello123")
if err != nil {
t.Error(err)
}

View File

@@ -761,7 +761,12 @@ func (l *LocalBitcoins) SendAuthenticatedHTTPRequest(ep exchange.URL, method, pa
fullPath := "/api/" + path
encoded := params.Encode()
message := n + l.API.Credentials.Key + fullPath + encoded
hmac := crypto.GetHMAC(crypto.HashSHA256, []byte(message), []byte(l.API.Credentials.Secret))
hmac, err := crypto.GetHMAC(crypto.HashSHA256,
[]byte(message),
[]byte(l.API.Credentials.Secret))
if err != nil {
return nil, err
}
headers := make(map[string]string)
headers["Apiauth-Key"] = l.API.Credentials.Key
headers["Apiauth-Nonce"] = n

View File

@@ -121,7 +121,10 @@ func TestGetOrderbook(t *testing.T) {
func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
t.Parallel()
var feeBuilder = setFeeBuilder()
l.GetFeeByType(feeBuilder)
_, err := l.GetFeeByType(feeBuilder)
if err != nil {
t.Fatal(err)
}
if !areTestAPIKeysSet() {
if feeBuilder.FeeType != exchange.OfflineTradeFee {
t.Errorf("Expected %v, received %v", exchange.OfflineTradeFee, feeBuilder.FeeType)

View File

@@ -228,7 +228,10 @@ func MessageWriteJSON(w http.ResponseWriter, status int, data interface{}) {
err := json.NewEncoder(w).Encode(data)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte(err.Error()))
_, wErr := w.Write([]byte(err.Error()))
if wErr != nil {
log.Println("Mock Test Failure - Writing to HTTP connection", wErr)
}
log.Fatal("Mock Test Failure - JSON encode error", err)
}
}

View File

@@ -879,7 +879,10 @@ func setFeeBuilder() *exchange.FeeBuilder {
// TestGetFeeByTypeOfflineTradeFee logic test
func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
var feeBuilder = setFeeBuilder()
o.GetFeeByType(feeBuilder)
_, err := o.GetFeeByType(feeBuilder)
if err != nil {
t.Fatal(err)
}
if !areTestAPIKeysSet() {
if feeBuilder.FeeType != exchange.OfflineTradeFee {
t.Errorf("Expected %v, received %v", exchange.OfflineTradeFee, feeBuilder.FeeType)

View File

@@ -58,7 +58,10 @@ func (o *OKCoin) SetDefaults() {
requestFmt := &currency.PairFormat{Uppercase: true, Delimiter: currency.DashDelimiter}
configFmt := &currency.PairFormat{Uppercase: true, Delimiter: currency.DashDelimiter}
o.SetGlobalPairsManager(requestFmt, configFmt, asset.Spot, asset.Margin)
err := o.SetGlobalPairsManager(requestFmt, configFmt, asset.Spot, asset.Margin)
if err != nil {
log.Errorln(log.ExchangeSys, err)
}
o.Features = exchange.Features{
Supports: exchange.FeaturesSupported{
@@ -135,7 +138,7 @@ func (o *OKCoin) SetDefaults() {
request.WithLimiter(request.NewBasicRateLimit(okCoinRateInterval, okCoinStandardRequestRate)),
)
o.API.Endpoints = o.NewEndpoints()
err := o.API.Endpoints.SetDefaultEndpoints(map[exchange.URL]string{
err = o.API.Endpoints.SetDefaultEndpoints(map[exchange.URL]string{
exchange.RestSpot: okCoinAPIURL,
exchange.WebsocketSpot: okCoinWebsocketURL,
})

View File

@@ -1699,7 +1699,10 @@ func setFeeBuilder() *exchange.FeeBuilder {
// TestGetFeeByTypeOfflineTradeFee logic test
func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
var feeBuilder = setFeeBuilder()
o.GetFeeByType(feeBuilder)
_, err := o.GetFeeByType(feeBuilder)
if err != nil {
t.Fatal(err)
}
if !areTestAPIKeysSet() {
if feeBuilder.FeeType != exchange.OfflineTradeFee {
t.Errorf("Expected %v, received %v", exchange.OfflineTradeFee, feeBuilder.FeeType)

View File

@@ -22,8 +22,6 @@ import (
)
const (
okGroupAuthRate = 0
okGroupUnauthRate = 0
// OKGroupAPIPath const to help with api url formatting
OKGroupAPIPath = "api/"
// API subsections
@@ -83,8 +81,6 @@ const (
okGroupGetRepayment = "repayment"
)
var errMissValue = errors.New("warning - resp value is missing from exchange")
// OKGroup is the overaching type across the all of OKEx's exchange methods
type OKGroup struct {
exchange.Base
@@ -596,9 +592,14 @@ func (o *OKGroup) SendHTTPRequest(ep exchange.URL, httpMethod, requestType, requ
if authenticated {
signPath := fmt.Sprintf("/%v%v%v%v", OKGroupAPIPath,
requestType, o.APIVersion, requestPath)
hmac := crypto.GetHMAC(crypto.HashSHA256,
var hmac []byte
hmac, err = crypto.GetHMAC(crypto.HashSHA256,
[]byte(utcTime+httpMethod+signPath+string(payload)),
[]byte(o.API.Credentials.Secret))
if err != nil {
return nil, err
}
headers["OK-ACCESS-KEY"] = o.API.Credentials.Key
headers["OK-ACCESS-SIGN"] = crypto.Base64Encode(hmac)
headers["OK-ACCESS-TIMESTAMP"] = utcTime

View File

@@ -211,10 +211,13 @@ func (o *OKGroup) WsLogin() error {
o.Websocket.SetCanUseAuthenticatedEndpoints(true)
unixTime := time.Now().UTC().Unix()
signPath := "/users/self/verify"
hmac := crypto.GetHMAC(crypto.HashSHA256,
hmac, err := crypto.GetHMAC(crypto.HashSHA256,
[]byte(strconv.FormatInt(unixTime, 10)+http.MethodGet+signPath),
[]byte(o.API.Credentials.Secret),
)
if err != nil {
return err
}
base64 := crypto.Base64Encode(hmac)
request := WebsocketEventRequest{
Operation: "login",
@@ -225,7 +228,7 @@ func (o *OKGroup) WsLogin() error {
base64,
},
}
_, err := o.Websocket.Conn.SendMessageReturnResponse("login", request)
_, err = o.Websocket.Conn.SendMessageReturnResponse("login", request)
if err != nil {
o.Websocket.SetCanUseAuthenticatedEndpoints(false)
return err

View File

@@ -866,9 +866,12 @@ func (p *Poloniex) SendAuthenticatedHTTPRequest(ep exchange.URL, method, endpoin
values.Set("nonce", strconv.FormatInt(time.Now().UnixNano(), 10))
values.Set("command", endpoint)
hmac := crypto.GetHMAC(crypto.HashSHA512,
hmac, err := crypto.GetHMAC(crypto.HashSHA512,
[]byte(values.Encode()),
[]byte(p.API.Credentials.Secret))
if err != nil {
return nil, err
}
headers["Sign"] = crypto.HexEncodeToString(hmac)
path := fmt.Sprintf("%s/%s", ePoint, poloniexAPITradingEndpoint)

View File

@@ -108,7 +108,10 @@ func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
t.Parallel()
var feeBuilder = setFeeBuilder()
p.GetFeeByType(feeBuilder)
_, err := p.GetFeeByType(feeBuilder)
if err != nil {
t.Fatal(err)
}
if !areTestAPIKeysSet() {
if feeBuilder.FeeType != exchange.OfflineTradeFee {
t.Errorf("Expected %v, received %v",

View File

@@ -616,9 +616,12 @@ channels:
func (p *Poloniex) wsSendAuthorisedCommand(command string) error {
nonce := fmt.Sprintf("nonce=%v", time.Now().UnixNano())
hmac := crypto.GetHMAC(crypto.HashSHA512,
hmac, err := crypto.GetHMAC(crypto.HashSHA512,
[]byte(nonce),
[]byte(p.API.Credentials.Secret))
if err != nil {
return err
}
request := WsAuthorisationRequest{
Command: command,
Channel: 1000,

View File

@@ -33,11 +33,17 @@ func TestMain(m *testing.M) {
sm := http.NewServeMux()
sm.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
w.Header().Set("Content-Type", "application/json")
io.WriteString(w, `{"response":true}`)
_, err := io.WriteString(w, `{"response":true}`)
if err != nil {
log.Fatal(err)
}
})
sm.HandleFunc("/error", func(w http.ResponseWriter, req *http.Request) {
w.WriteHeader(http.StatusBadRequest)
io.WriteString(w, `{"error":true}`)
_, err := io.WriteString(w, `{"error":true}`)
if err != nil {
log.Fatal(err)
}
})
sm.HandleFunc("/timeout", func(w http.ResponseWriter, req *http.Request) {
time.Sleep(time.Millisecond * 100)
@@ -48,10 +54,16 @@ func TestMain(m *testing.M) {
http.Error(w,
http.StatusText(http.StatusTooManyRequests),
http.StatusTooManyRequests)
io.WriteString(w, `{"response":false}`)
_, err := io.WriteString(w, `{"response":false}`)
if err != nil {
log.Fatal(err)
}
return
}
io.WriteString(w, `{"response":true}`)
_, err := io.WriteString(w, `{"response":true}`)
if err != nil {
log.Fatal(err)
}
})
sm.HandleFunc("/rate-retry", func(w http.ResponseWriter, req *http.Request) {
if !serverLimitRetry.Allow() {
@@ -59,15 +71,24 @@ func TestMain(m *testing.M) {
http.Error(w,
http.StatusText(http.StatusTooManyRequests),
http.StatusTooManyRequests)
io.WriteString(w, `{"response":false}`)
_, err := io.WriteString(w, `{"response":false}`)
if err != nil {
log.Fatal(err)
}
return
}
io.WriteString(w, `{"response":true}`)
_, err := io.WriteString(w, `{"response":true}`)
if err != nil {
log.Fatal(err)
}
})
sm.HandleFunc("/always-retry", func(w http.ResponseWriter, req *http.Request) {
w.Header().Add("Retry-After", time.Now().Format(time.RFC1123))
w.WriteHeader(http.StatusTooManyRequests)
io.WriteString(w, `{"response":false}`)
_, err := io.WriteString(w, `{"response":false}`)
if err != nil {
log.Fatal(err)
}
})
server := httptest.NewServer(sm)

View File

@@ -150,7 +150,11 @@ func TestAdd(t *testing.T) {
if err != nil {
t.Fatal(err)
}
Add(testExchange, p, asset.Spot, 300, 1000)
err = Add(testExchange, p, asset.Spot, 300, 1000)
if err != nil {
t.Fatal(err)
}
if Items[2].Pair.String() != "ETHUSD" {
t.Fatal("stats Add did not add exchange info.")

View File

@@ -303,7 +303,12 @@ func (y *Yobit) SendAuthenticatedHTTPRequest(ep exchange.URL, path string, param
params.Set("method", path)
encoded := params.Encode()
hmac := crypto.GetHMAC(crypto.HashSHA512, []byte(encoded), []byte(y.API.Credentials.Secret))
hmac, err := crypto.GetHMAC(crypto.HashSHA512,
[]byte(encoded),
[]byte(y.API.Credentials.Secret))
if err != nil {
return nil, err
}
headers := make(map[string]string)
headers["Key"] = y.API.Credentials.Key

View File

@@ -169,7 +169,10 @@ func setFeeBuilder() *exchange.FeeBuilder {
// TestGetFeeByTypeOfflineTradeFee logic test
func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
var feeBuilder = setFeeBuilder()
y.GetFeeByType(feeBuilder)
_, err := y.GetFeeByType(feeBuilder)
if err != nil {
t.Fatal(err)
}
if !areTestAPIKeysSet() {
if feeBuilder.FeeType != exchange.OfflineTradeFee {
t.Errorf("Expected %v, received %v", exchange.OfflineTradeFee, feeBuilder.FeeType)

View File

@@ -311,9 +311,17 @@ func (z *ZB) SendAuthenticatedHTTPRequest(ep exchange.URL, httpMethod string, pa
}
params.Set("accesskey", z.API.Credentials.Key)
hmac := crypto.GetHMAC(crypto.HashMD5,
hex, err := crypto.Sha1ToHex(z.API.Credentials.Secret)
if err != nil {
return err
}
hmac, err := crypto.GetHMAC(crypto.HashMD5,
[]byte(params.Encode()),
[]byte(crypto.Sha1ToHex(z.API.Credentials.Secret)))
[]byte(hex))
if err != nil {
return err
}
var intermediary json.RawMessage
newRequest := func() (*request.Item, error) {

View File

@@ -141,7 +141,10 @@ func setFeeBuilder() *exchange.FeeBuilder {
func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
t.Parallel()
var feeBuilder = setFeeBuilder()
z.GetFeeByType(feeBuilder)
_, err := z.GetFeeByType(feeBuilder)
if err != nil {
t.Fatal(err)
}
if !z.ValidateAPICredentials() {
if feeBuilder.FeeType != exchange.OfflineTradeFee {
t.Errorf("Expected %v, received %v", exchange.OfflineTradeFee, feeBuilder.FeeType)

View File

@@ -21,7 +21,6 @@ import (
"github.com/thrasher-corp/gocryptotrader/exchanges/stream"
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
"github.com/thrasher-corp/gocryptotrader/exchanges/trade"
"github.com/thrasher-corp/gocryptotrader/log"
)
const (
@@ -301,16 +300,22 @@ func (z *ZB) Subscribe(channelsToSubscribe []stream.ChannelSubscription) error {
return nil
}
func (z *ZB) wsGenerateSignature(request interface{}) string {
func (z *ZB) wsGenerateSignature(request interface{}) (string, error) {
jsonResponse, err := json.Marshal(request)
if err != nil {
log.Error(log.ExchangeSys, err)
return ""
return "", err
}
hmac := crypto.GetHMAC(crypto.HashMD5,
hex, err := crypto.Sha1ToHex(z.API.Credentials.Secret)
if err != nil {
return "", err
}
hmac, err := crypto.GetHMAC(crypto.HashMD5,
jsonResponse,
[]byte(crypto.Sha1ToHex(z.API.Credentials.Secret)))
return fmt.Sprintf("%x", hmac)
[]byte(hex))
if err != nil {
return "", err
}
return fmt.Sprintf("%x", hmac), nil
}
func (z *ZB) wsFixInvalidJSON(json []byte) []byte {
@@ -340,7 +345,12 @@ func (z *ZB) wsAddSubUser(username, password string) (*WsGetSubUserListResponse,
request.Event = zWebsocketAddChannel
request.Accesskey = z.API.Credentials.Key
request.No = z.Websocket.Conn.GenerateMessageID(true)
request.Sign = z.wsGenerateSignature(request)
var err error
request.Sign, err = z.wsGenerateSignature(request)
if err != nil {
return nil, err
}
resp, err := z.Websocket.Conn.SendMessageReturnResponse(request.No, request)
if err != nil {
return nil, err
@@ -375,7 +385,12 @@ func (z *ZB) wsGetSubUserList() (*WsGetSubUserListResponse, error) {
request.Event = zWebsocketAddChannel
request.Accesskey = z.API.Credentials.Key
request.No = z.Websocket.Conn.GenerateMessageID(true)
request.Sign = z.wsGenerateSignature(request)
var err error
request.Sign, err = z.wsGenerateSignature(request)
if err != nil {
return nil, err
}
resp, err := z.Websocket.Conn.SendMessageReturnResponse(request.No, request)
if err != nil {
@@ -411,7 +426,12 @@ func (z *ZB) wsDoTransferFunds(pair currency.Code, amount float64, fromUserName,
request.Channel = "doTransferFunds"
request.Event = zWebsocketAddChannel
request.Accesskey = z.API.Credentials.Key
request.Sign = z.wsGenerateSignature(request)
var err error
request.Sign, err = z.wsGenerateSignature(request)
if err != nil {
return nil, err
}
resp, err := z.Websocket.Conn.SendMessageReturnResponse(request.No, request)
if err != nil {
@@ -449,7 +469,12 @@ func (z *ZB) wsCreateSubUserKey(assetPerm, entrustPerm, leverPerm, moneyPerm boo
request.Channel = "createSubUserKey"
request.Event = zWebsocketAddChannel
request.Accesskey = z.API.Credentials.Key
request.Sign = z.wsGenerateSignature(request)
var err error
request.Sign, err = z.wsGenerateSignature(request)
if err != nil {
return nil, err
}
resp, err := z.Websocket.Conn.SendMessageReturnResponse(request.No, request)
if err != nil {
@@ -484,7 +509,12 @@ func (z *ZB) wsSubmitOrder(pair currency.Pair, amount, price float64, tradeType
request.Channel = pair.String() + "_order"
request.Event = zWebsocketAddChannel
request.Accesskey = z.API.Credentials.Key
request.Sign = z.wsGenerateSignature(request)
var err error
request.Sign, err = z.wsGenerateSignature(request)
if err != nil {
return nil, err
}
resp, err := z.Websocket.Conn.SendMessageReturnResponse(request.No, request)
if err != nil {
@@ -517,7 +547,12 @@ func (z *ZB) wsCancelOrder(pair currency.Pair, orderID int64) (*WsCancelOrderRes
request.Channel = pair.String() + "_cancelorder"
request.Event = zWebsocketAddChannel
request.Accesskey = z.API.Credentials.Key
request.Sign = z.wsGenerateSignature(request)
var err error
request.Sign, err = z.wsGenerateSignature(request)
if err != nil {
return nil, err
}
resp, err := z.Websocket.Conn.SendMessageReturnResponse(request.No, request)
if err != nil {
@@ -550,7 +585,12 @@ func (z *ZB) wsGetOrder(pair currency.Pair, orderID int64) (*WsGetOrderResponse,
request.Channel = pair.String() + "_getorder"
request.Event = zWebsocketAddChannel
request.Accesskey = z.API.Credentials.Key
request.Sign = z.wsGenerateSignature(request)
var err error
request.Sign, err = z.wsGenerateSignature(request)
if err != nil {
return nil, err
}
resp, err := z.Websocket.Conn.SendMessageReturnResponse(request.No, request)
if err != nil {
@@ -584,7 +624,13 @@ func (z *ZB) wsGetOrders(pair currency.Pair, pageIndex, tradeType int64) (*WsGet
request.Channel = pair.String() + "_getorders"
request.Event = zWebsocketAddChannel
request.Accesskey = z.API.Credentials.Key
request.Sign = z.wsGenerateSignature(request)
var err error
request.Sign, err = z.wsGenerateSignature(request)
if err != nil {
return nil, err
}
resp, err := z.Websocket.Conn.SendMessageReturnResponse(request.No, request)
if err != nil {
return nil, err
@@ -617,7 +663,12 @@ func (z *ZB) wsGetOrdersIgnoreTradeType(pair currency.Pair, pageIndex, pageSize
request.Channel = pair.String() + "_getordersignoretradetype"
request.Event = zWebsocketAddChannel
request.Accesskey = z.API.Credentials.Key
request.Sign = z.wsGenerateSignature(request)
var err error
request.Sign, err = z.wsGenerateSignature(request)
if err != nil {
return nil, err
}
resp, err := z.Websocket.Conn.SendMessageReturnResponse(request.No, request)
if err != nil {
@@ -649,7 +700,12 @@ func (z *ZB) wsGetAccountInfoRequest() (*WsGetAccountInfoResponse, error) {
Accesskey: z.API.Credentials.Key,
No: z.Websocket.Conn.GenerateMessageID(true),
}
request.Sign = z.wsGenerateSignature(request)
var err error
request.Sign, err = z.wsGenerateSignature(request)
if err != nil {
return nil, err
}
resp, err := z.Websocket.Conn.SendMessageReturnResponse(request.No, request)
if err != nil {

View File

@@ -288,7 +288,11 @@ func (vm *VM) getHash() string {
log.Errorln(log.GCTScriptMgr, err)
}
contents = append(contents, vm.ShortName()...)
return hex.EncodeToString(crypto.GetSHA256(contents))
hash, err := crypto.GetSHA256(contents)
if err != nil {
log.Errorln(log.GCTScriptMgr, err)
}
return hex.EncodeToString(hash)
}
func (vmc *vmscount) add() {

View File

@@ -25,8 +25,8 @@ var (
testBrokenScript = filepath.Join("..", "..", "testdata", "gctscript", "broken.gct")
testScriptRunner = filepath.Join("..", "..", "testdata", "gctscript", "timer.gct")
testScriptRunner1s = filepath.Join("..", "..", "testdata", "gctscript", "1s_timer.gct")
testScriptRunnerInvalid = filepath.Join("..", "..", "testdata", "gctscript", "invalid_timer.gct")
testScriptRunnerNegative = filepath.Join("..", "..", "testdata", "gctscript", "negative_timer.gct")
testScriptRunnerInvalid = filepath.Join("..", "..", "testdata", "gctscript", "invalid_timer.gct")
)
func TestMain(m *testing.M) {
@@ -325,6 +325,34 @@ func TestVMWithRunnerNegativeTimer(t *testing.T) {
}
}
func TestVMWithRunnerInvalidTimer(t *testing.T) {
manager := GctScriptManager{
config: configHelper(true, true, maxTestVirtualMachines),
started: 1,
}
vmCount := VMSCount.Len()
VM := manager.New()
if VM == nil {
t.Fatal("Failed to allocate new VM exiting")
}
err := VM.Load(testScriptRunnerInvalid)
if err != nil {
t.Fatal(err)
}
if VMSCount.Len() == vmCount {
t.Fatal("expected VM count to increase")
}
VM.CompileAndRun()
err = VM.Shutdown()
if err == nil {
t.Fatal("VM should not be running with invalid timer")
}
if VMSCount.Len() == vmCount-1 {
t.Fatal("expected VM count to decrease")
}
}
func TestShutdownAll(t *testing.T) {
manager := GctScriptManager{
config: configHelper(true, true, maxTestVirtualMachines),

View File

@@ -210,13 +210,16 @@ func BenchmarkInfoln(b *testing.B) {
func TestNewLogEvent(t *testing.T) {
w := &bytes.Buffer{}
logger.newLogEvent("out", "header", "SUBLOGGER", w)
err := logger.newLogEvent("out", "header", "SUBLOGGER", w)
if err != nil {
t.Fatal(err)
}
if w.String() == "" {
t.Error("newLogEvent() failed expected output got empty string")
}
err := logger.newLogEvent("out", "header", "SUBLOGGER", nil)
err = logger.newLogEvent("out", "header", "SUBLOGGER", nil)
if err == nil {
t.Error("Error expected with output is set to nil")
}
@@ -225,23 +228,24 @@ func TestNewLogEvent(t *testing.T) {
func TestInfo(t *testing.T) {
w := &bytes.Buffer{}
tempSL := SubLogger{
"TESTYMCTESTALOT",
splitLevel("INFO|WARN|DEBUG|ERROR"),
w,
}
sl := registerNewSubLogger("TESTYMCTESTALOT")
sl.Levels = splitLevel("INFO|WARN|DEBUG|ERROR")
sl.output = w
Info(&tempSL, "Hello")
Info(sl, "Hello")
if w.String() == "" {
t.Error("expected Info() to write output to buffer")
}
tempSL.output = nil
sl.output = nil
w.Reset()
SetLevel("TESTYMCTESTALOT", "INFO")
Debug(&tempSL, "HelloHello")
_, err := SetLevel("TESTYMCTESTALOT", "INFO")
if err != nil {
t.Fatal(err)
}
Debug(sl, "HelloHello")
if w.String() != "" {
t.Error("Expected output buffer to be empty but Debug wrote to output")
@@ -251,14 +255,20 @@ func TestInfo(t *testing.T) {
func TestSubLoggerName(t *testing.T) {
w := &bytes.Buffer{}
registerNewSubLogger("sublogger")
logger.newLogEvent("out", "header", "SUBLOGGER", w)
err := logger.newLogEvent("out", "header", "SUBLOGGER", w)
if err != nil {
t.Fatal(err)
}
if !strings.Contains(w.String(), "SUBLOGGER") {
t.Error("Expected SUBLOGGER in output")
}
logger.ShowLogSystemName = false
w.Reset()
logger.newLogEvent("out", "header", "SUBLOGGER", w)
err = logger.newLogEvent("out", "header", "SUBLOGGER", w)
if err != nil {
t.Fatal(err)
}
if strings.Contains(w.String(), "SUBLOGGER") {
t.Error("Unexpected SUBLOGGER in output")
}