Exchange: Pair formatting/loading/SetDefaults improvements (#396)

* Improve exchange pair loading/setting/formatting

* Update configs

* Link up forceUpdate for OKEX

* Fix linter issues

* Rearrange exchPS

* Fix typerino

* Config updates
This commit is contained in:
Adrian Gallagher
2019-12-13 13:10:17 +11:00
committed by GitHub
parent bab4cd98be
commit 25e290563c
18 changed files with 270 additions and 150 deletions

File diff suppressed because one or more lines are too long

View File

@@ -571,7 +571,7 @@ func (e *ExchangeCurrencyPairSyncer) Start() {
if atomic.CompareAndSwapInt32(&e.initSyncCompleted, 0, 1) {
log.Debugf(log.SyncMgr, "Exchange CurrencyPairSyncer initial sync is complete.\n")
completedTime := time.Now()
log.Debugf(log.SyncMgr, "Exchange CurrencyPairSyncer initiial sync took %v [%v sync items].\n",
log.Debugf(log.SyncMgr, "Exchange CurrencyPairSyncer initial sync took %v [%v sync items].\n",
completedTime.Sub(e.initSyncStartTime), createdCounter)
if !e.Cfg.SyncContinuously {

View File

@@ -147,12 +147,14 @@ func (a *ANX) Run() {
}
forceUpdate := false
if !common.StringDataContains(a.GetEnabledPairs(asset.Spot).Strings(), "_") ||
!common.StringDataContains(a.GetAvailablePairs(asset.Spot).Strings(), "_") {
enabledPairs := currency.NewPairsFromStrings([]string{"BTC_USD,BTC_HKD,BTC_EUR,BTC_CAD,BTC_AUD,BTC_SGD,BTC_JPY,BTC_GBP,BTC_NZD,LTC_BTC,DOG_EBTC,STR_BTC,XRP_BTC"})
delim := a.GetPairFormat(asset.Spot, false).Delimiter
if !common.StringDataContains(a.GetEnabledPairs(asset.Spot).Strings(), delim) ||
!common.StringDataContains(a.GetAvailablePairs(asset.Spot).Strings(), delim) {
enabledPairs := currency.NewPairsFromStrings(
[]string{currency.BTC.String() + delim + currency.USD.String()},
)
log.Warn(log.ExchangeSys,
"Enabled pairs for ANX reset due to config upgrade, please enable the ones you would like again.")
forceUpdate = true
err := a.UpdatePairs(enabledPairs, asset.Spot, true, true)
if err != nil {

View File

@@ -2,7 +2,6 @@ package binance
import (
"errors"
"fmt"
"strconv"
"strings"
"sync"
@@ -192,9 +191,12 @@ func (b *Binance) Run() {
}
forceUpdate := false
if !common.StringDataContains(b.GetEnabledPairs(asset.Spot).Strings(), b.GetPairFormat(asset.Spot, false).Delimiter) ||
!common.StringDataContains(b.GetAvailablePairs(asset.Spot).Strings(), b.GetPairFormat(asset.Spot, false).Delimiter) {
enabledPairs := currency.NewPairsFromStrings([]string{fmt.Sprintf("BTC%vUSDT", b.GetPairFormat(asset.Spot, false).Delimiter)})
delim := b.GetPairFormat(asset.Spot, false).Delimiter
if !common.StringDataContains(b.GetEnabledPairs(asset.Spot).Strings(), delim) ||
!common.StringDataContains(b.GetAvailablePairs(asset.Spot).Strings(), delim) {
enabledPairs := currency.NewPairsFromStrings(
[]string{currency.BTC.String() + delim + currency.USDT.String()},
)
log.Warn(log.ExchangeSys,
"Available pairs for Binance reset due to config upgrade, please enable the ones you would like to use again")
forceUpdate = true

View File

@@ -60,7 +60,6 @@ func (b *Bitmex) SetDefaults() {
asset.DownsideProfitContract,
asset.UpsideProfitContract,
},
UseGlobalFormat: false,
}
// Same format used for perpetual contracts and futures

View File

@@ -132,13 +132,19 @@ func (b *Bittrex) Run() {
}
forceUpdate := false
if !common.StringDataContains(b.GetEnabledPairs(asset.Spot).Strings(), "-") ||
!common.StringDataContains(b.GetAvailablePairs(asset.Spot).Strings(), "-") {
delim := b.GetPairFormat(asset.Spot, false).Delimiter
if !common.StringDataContains(b.GetEnabledPairs(asset.Spot).Strings(), delim) ||
!common.StringDataContains(b.GetAvailablePairs(asset.Spot).Strings(), delim) {
forceUpdate = true
enabledPairs := []string{"USDT-BTC"}
log.Warn(log.ExchangeSys, "Available pairs for Bittrex reset due to config upgrade, please enable the ones you would like again")
err := b.UpdatePairs(currency.NewPairsFromStrings(enabledPairs), asset.Spot, true, true)
err := b.UpdatePairs(currency.NewPairsFromStrings(
[]string{currency.USDT.String() + delim + currency.BTC.String()},
),
asset.Spot,
true,
true,
)
if err != nil {
log.Errorf(log.ExchangeSys,
"%s failed to update currencies. Err: %s\n",

View File

@@ -181,8 +181,9 @@ func (b *BTCMarkets) Run() {
b.PrintEnabledPairs()
}
forceUpdate := false
if !common.StringDataContains(b.GetEnabledPairs(asset.Spot).Strings(), "-") ||
!common.StringDataContains(b.GetAvailablePairs(asset.Spot).Strings(), "-") {
delim := b.GetPairFormat(asset.Spot, false).Delimiter
if !common.StringDataContains(b.GetEnabledPairs(asset.Spot).Strings(), delim) ||
!common.StringDataContains(b.GetAvailablePairs(asset.Spot).Strings(), delim) {
log.Warnln(log.ExchangeSys, "Available pairs for BTC Markets reset due to config upgrade, please enable the pairs you would like again.")
forceUpdate = true
}
@@ -190,7 +191,7 @@ func (b *BTCMarkets) Run() {
enabledPairs := currency.Pairs{currency.Pair{
Base: currency.BTC.Lower(),
Quote: currency.AUD.Lower(),
Delimiter: "-",
Delimiter: delim,
},
}
err := b.UpdatePairs(enabledPairs, asset.Spot, true, true)

View File

@@ -203,7 +203,7 @@ func (c *CoinbasePro) Run() {
!common.StringDataContains(c.CurrencyPairs.GetPairs(asset.Spot,
false).Strings(), delim) {
enabledPairs := currency.NewPairsFromStrings(
[]string{fmt.Sprintf("BTC%sUSD", delim)},
[]string{currency.BTC.String() + delim + currency.USD.String()},
)
log.Warn(log.ExchangeSys,
"Enabled pairs for CoinbasePro reset due to config upgrade, please enable the ones you would like to use again")

View File

@@ -199,7 +199,7 @@ func (c *COINUT) Run() {
!common.StringDataContains(c.CurrencyPairs.GetPairs(asset.Spot,
false).Strings(), delim) {
enabledPairs := currency.NewPairsFromStrings(
[]string{fmt.Sprintf("LTC%sUSDT", delim)},
[]string{currency.LTC.String() + delim + currency.USDT.String()},
)
log.Warn(log.ExchangeSys,
"Enabled pairs for Coinut reset due to config upgrade, please enable the ones you would like to use again")

View File

@@ -255,7 +255,7 @@ func (e *Base) GetExchangeBankAccounts(exchangeName, depositCurrency string) (co
}
// SetCurrencyPairFormat checks the exchange request and config currency pair
// formats and sets it to a default setting if it doesn't exist
// formats and syncs it with the exchanges SetDefault settings
func (e *Base) SetCurrencyPairFormat() {
if e.Config.CurrencyPairs == nil {
e.Config.CurrencyPairs = new(currency.PairsManager)
@@ -263,12 +263,8 @@ func (e *Base) SetCurrencyPairFormat() {
e.Config.CurrencyPairs.UseGlobalFormat = e.CurrencyPairs.UseGlobalFormat
if e.Config.CurrencyPairs.UseGlobalFormat {
if e.Config.CurrencyPairs.ConfigFormat == nil {
e.Config.CurrencyPairs.ConfigFormat = e.CurrencyPairs.ConfigFormat
}
if e.Config.CurrencyPairs.RequestFormat == nil {
e.Config.CurrencyPairs.RequestFormat = e.CurrencyPairs.RequestFormat
}
e.Config.CurrencyPairs.RequestFormat = e.CurrencyPairs.RequestFormat
e.Config.CurrencyPairs.ConfigFormat = e.CurrencyPairs.ConfigFormat
return
}
@@ -291,6 +287,27 @@ func (e *Base) SetCurrencyPairFormat() {
}
}
// SetConfigPairs sets the exchanges currency pairs to the pairs set in the config
func (e *Base) SetConfigPairs() {
assetTypes := e.GetAssetTypes()
for x := range assetTypes {
cfgPS := e.Config.CurrencyPairs.Get(assetTypes[x])
if cfgPS == nil {
continue
}
if e.Config.CurrencyPairs.UseGlobalFormat {
e.CurrencyPairs.StorePairs(assetTypes[x], cfgPS.Available, false)
e.CurrencyPairs.StorePairs(assetTypes[x], cfgPS.Enabled, true)
continue
}
exchPS := e.CurrencyPairs.Get(assetTypes[x])
cfgPS.ConfigFormat = exchPS.ConfigFormat
cfgPS.RequestFormat = exchPS.RequestFormat
e.CurrencyPairs.StorePairs(assetTypes[x], cfgPS.Available, false)
e.CurrencyPairs.StorePairs(assetTypes[x], cfgPS.Enabled, true)
}
}
// GetAuthenticatedAPISupport returns whether the exchange supports
// authenticated API requests
func (e *Base) GetAuthenticatedAPISupport(endpoint uint8) bool {
@@ -443,6 +460,7 @@ func (e *Base) SetupDefaults(exch *config.ExchangeConfig) error {
e.SetHTTPRateLimiter()
e.SetAssetTypes()
e.SetCurrencyPairFormat()
e.SetConfigPairs()
e.SetFeatureDefaults()
e.SetAPIURL()
e.SetAPICredentialDefaults()
@@ -451,14 +469,6 @@ func (e *Base) SetupDefaults(exch *config.ExchangeConfig) error {
e.BaseCurrencies = exch.BaseCurrencies
assetTypes := e.GetAssetTypes()
for x := range assetTypes {
p := exch.CurrencyPairs.Get(assetTypes[x])
if p != nil {
e.CurrencyPairs.Store(assetTypes[x], *p)
}
}
if e.Features.Supports.Websocket {
return e.Websocket.Initialise()
}

View File

@@ -440,6 +440,127 @@ func TestSetCurrencyPairFormat(t *testing.T) {
}
}
func TestLoadConfigPairs(t *testing.T) {
t.Parallel()
pairs := currency.Pairs{
currency.Pair{Base: currency.BTC, Quote: currency.USD},
currency.Pair{Base: currency.LTC, Quote: currency.USD},
}
b := Base{
CurrencyPairs: currency.PairsManager{
UseGlobalFormat: true,
AssetTypes: asset.Items{asset.Spot},
RequestFormat: &currency.PairFormat{
Delimiter: ">",
Uppercase: false,
},
ConfigFormat: &currency.PairFormat{
Delimiter: "^",
Uppercase: true,
},
Pairs: map[asset.Item]*currency.PairStore{
asset.Spot: {
RequestFormat: &currency.PairFormat{},
ConfigFormat: &currency.PairFormat{},
},
},
},
Config: &config.ExchangeConfig{
CurrencyPairs: &currency.PairsManager{},
},
}
// Test a nil PairsManager
b.SetConfigPairs()
// Now setup a proper PairsManager
b.Config.CurrencyPairs = &currency.PairsManager{
UseGlobalFormat: true,
RequestFormat: &currency.PairFormat{
Delimiter: "!",
Uppercase: true,
},
ConfigFormat: &currency.PairFormat{
Delimiter: "!",
Uppercase: true,
},
AssetTypes: asset.Items{asset.Spot},
Pairs: map[asset.Item]*currency.PairStore{
asset.Spot: {
Enabled: pairs,
Available: pairs,
RequestFormat: &currency.PairFormat{},
ConfigFormat: &currency.PairFormat{},
},
},
}
// Test UseGlobalFormat setting of pairs
b.SetCurrencyPairFormat()
b.SetConfigPairs()
// Test four things:
// 1) Config pairs are set
// 2) pair format is set for RequestFormat
// 3) pair format is set for ConfigFormat
// 4) Config global format delimiter is updated based off exchange.Base
pFmt := b.GetPairFormat(asset.Spot, false)
p := b.GetEnabledPairs(asset.Spot)[0].Format(pFmt.Delimiter,
pFmt.Uppercase).String()
if p != "BTC^USD" {
t.Errorf("incorrect value, expected BTC^USD")
}
p = b.FormatExchangeCurrency(b.GetAvailablePairs(asset.Spot)[0],
asset.Spot).String()
if p != "btc>usd" {
t.Error("incorrect value, expected btc>usd")
}
if b.Config.CurrencyPairs.RequestFormat.Delimiter != ">" ||
b.Config.CurrencyPairs.RequestFormat.Uppercase ||
b.Config.CurrencyPairs.ConfigFormat.Delimiter != "^" ||
!b.Config.CurrencyPairs.ConfigFormat.Uppercase {
t.Error("incorrect delimiter values")
}
// Test !UseGlobalFormat setting of pairs
exchPS := b.CurrencyPairs.Get(asset.Spot)
exchPS.RequestFormat.Delimiter = "~"
exchPS.RequestFormat.Uppercase = false
exchPS.ConfigFormat.Delimiter = "/"
exchPS.ConfigFormat.Uppercase = false
pairs = append(pairs, currency.Pair{Base: currency.XRP, Quote: currency.USD})
b.Config.CurrencyPairs.StorePairs(asset.Spot, pairs, false)
b.Config.CurrencyPairs.StorePairs(asset.Spot, pairs, true)
b.Config.CurrencyPairs.UseGlobalFormat = false
b.CurrencyPairs.UseGlobalFormat = false
b.SetConfigPairs()
// Test four things:
// 1) XRP-USD is set
// 2) pair format is set for RequestFormat
// 3) pair format is set for ConfigFormat
// 4) Config pair store formats are the same as the exchanges
pFmt = b.GetPairFormat(asset.Spot, false)
p = b.GetEnabledPairs(asset.Spot)[2].Format(pFmt.Delimiter,
pFmt.Uppercase).String()
if p != "xrp/usd" {
t.Error("incorrect value, expected xrp/usd")
}
p = b.FormatExchangeCurrency(b.GetAvailablePairs(asset.Spot)[2],
asset.Spot).String()
if p != "xrp~usd" {
t.Error("incorrect value, expected xrp~usd")
}
ps := b.Config.CurrencyPairs.Get(asset.Spot)
if ps.RequestFormat.Delimiter != "~" ||
ps.RequestFormat.Uppercase ||
ps.ConfigFormat.Delimiter != "/" ||
ps.ConfigFormat.Uppercase {
t.Error("incorrect delimiter values")
}
}
// TestGetAuthenticatedAPISupport logic test
func TestGetAuthenticatedAPISupport(t *testing.T) {
t.Parallel()

View File

@@ -86,6 +86,7 @@ const (
UnknownWithdrawalTypeText string = "UNKNOWN"
)
// FeeType is the type for holding a custom fee type (International withdrawal fee)
type FeeType uint8
// InternationalBankTransactionType custom type for calculating fees based on fiat transaction types

View File

@@ -192,9 +192,10 @@ func (h *HitBTC) Run() {
}
forceUpdate := false
if !common.StringDataContains(h.GetEnabledPairs(asset.Spot).Strings(), "-") ||
!common.StringDataContains(h.GetAvailablePairs(asset.Spot).Strings(), "-") {
enabledPairs := []string{"BTC-USD"}
delim := h.GetPairFormat(asset.Spot, false).Delimiter
if !common.StringDataContains(h.GetEnabledPairs(asset.Spot).Strings(), delim) ||
!common.StringDataContains(h.GetAvailablePairs(asset.Spot).Strings(), delim) {
enabledPairs := []string{currency.BTC.String() + delim + currency.USD.String()}
log.Warn(log.ExchangeSys, "Available pairs for HitBTC reset due to config upgrade, please enable the ones you would like again.")
forceUpdate = true

View File

@@ -206,12 +206,12 @@ func (h *HUOBI) Run() {
}
var forceUpdate bool
if common.StringDataContains(h.GetEnabledPairs(asset.Spot).Strings(), "CNY") ||
common.StringDataContains(h.GetAvailablePairs(asset.Spot).Strings(), "CNY") {
if common.StringDataContains(h.GetEnabledPairs(asset.Spot).Strings(), currency.CNY.String()) ||
common.StringDataContains(h.GetAvailablePairs(asset.Spot).Strings(), currency.CNY.String()) {
forceUpdate = true
}
if common.StringDataContains(h.BaseCurrencies.Strings(), "CNY") {
if common.StringDataContains(h.BaseCurrencies.Strings(), currency.CNY.String()) {
cfg := config.GetConfig()
exchCfg, err := cfg.GetExchangeConfig(h.Name)
if err != nil {
@@ -229,7 +229,7 @@ func (h *HUOBI) Run() {
enabledPairs := currency.Pairs{currency.Pair{
Base: currency.BTC.Lower(),
Quote: currency.USDT.Lower(),
Delimiter: "-",
Delimiter: h.GetPairFormat(asset.Spot, false).Delimiter,
},
}
log.Warn(log.ExchangeSys,

View File

@@ -2,7 +2,6 @@ package kraken
import (
"errors"
"fmt"
"strconv"
"strings"
"sync"
@@ -212,9 +211,12 @@ func (k *Kraken) Run() {
}
forceUpdate := false
if !common.StringDataContains(k.GetEnabledPairs(asset.Spot).Strings(), k.GetPairFormat(asset.Spot, false).Delimiter) ||
!common.StringDataContains(k.GetAvailablePairs(asset.Spot).Strings(), k.GetPairFormat(asset.Spot, false).Delimiter) {
enabledPairs := currency.NewPairsFromStrings([]string{fmt.Sprintf("XBT%vUSD", k.GetPairFormat(asset.Spot, false).Delimiter)})
delim := k.GetPairFormat(asset.Spot, false).Delimiter
if !common.StringDataContains(k.GetEnabledPairs(asset.Spot).Strings(), delim) ||
!common.StringDataContains(k.GetAvailablePairs(asset.Spot).Strings(), delim) {
enabledPairs := currency.NewPairsFromStrings(
[]string{currency.XBT.String() + delim + currency.USD.String()},
)
log.Warn(log.ExchangeSys, "Available pairs for Kraken reset due to config upgrade, please enable the ones you would like again")
forceUpdate = true

View File

@@ -1,7 +1,6 @@
package okcoin
import (
"fmt"
"sync"
"time"
@@ -155,9 +154,9 @@ func (o *OKCoin) Run() {
true).Strings(), delim) ||
!common.StringDataContains(o.CurrencyPairs.GetPairs(asset.Spot,
false).Strings(), delim) {
enabledPairs := currency.NewPairsFromStrings([]string{
fmt.Sprintf("BTC%sUSD", delim),
})
enabledPairs := currency.NewPairsFromStrings(
[]string{currency.BTC.String() + delim + currency.USD.String()},
)
log.Warnf(log.ExchangeSys,
"Enabled pairs for %v reset due to config upgrade, please enable the ones you would like again.\n",
o.Name)

View File

@@ -65,7 +65,6 @@ func (o *OKEX) SetDefaults() {
asset.PerpetualSwap,
asset.Index,
},
UseGlobalFormat: false,
}
// Same format used for perpetual swap and futures
fmt1 := currency.PairStore{
@@ -183,54 +182,19 @@ func (o *OKEX) Run() {
o.API.Endpoints.WebsocketURL)
}
if o.Config.CurrencyPairs.Pairs[asset.Spot].ConfigFormat == nil ||
o.Config.CurrencyPairs.Pairs[asset.Spot].RequestFormat == nil ||
o.Config.CurrencyPairs.Pairs[asset.Index].ConfigFormat == nil ||
o.Config.CurrencyPairs.Pairs[asset.Index].RequestFormat == nil {
currFmt := currency.PairStore{
RequestFormat: &currency.PairFormat{
Uppercase: true,
Delimiter: delimiterDash,
},
ConfigFormat: &currency.PairFormat{
Uppercase: true,
Delimiter: delimiterDash,
},
}
o.CurrencyPairs.Store(asset.Spot, currFmt)
o.Config.CurrencyPairs.Store(asset.Spot, currFmt)
o.CurrencyPairs.Store(asset.Index, currFmt)
o.Config.CurrencyPairs.Store(asset.Index, currFmt)
}
if o.Config.CurrencyPairs.Pairs[asset.Futures].ConfigFormat == nil ||
o.Config.CurrencyPairs.Pairs[asset.Futures].RequestFormat == nil ||
o.Config.CurrencyPairs.Pairs[asset.PerpetualSwap].ConfigFormat == nil ||
o.Config.CurrencyPairs.Pairs[asset.PerpetualSwap].RequestFormat == nil {
currFmt := currency.PairStore{
RequestFormat: &currency.PairFormat{
Uppercase: true,
Delimiter: delimiterDash,
},
ConfigFormat: &currency.PairFormat{
Uppercase: true,
Delimiter: delimiterUnderscore,
},
}
o.CurrencyPairs.Store(asset.Futures, currFmt)
o.Config.CurrencyPairs.Store(asset.Futures, currFmt)
o.CurrencyPairs.Store(asset.PerpetualSwap, currFmt)
o.Config.CurrencyPairs.Store(asset.PerpetualSwap, currFmt)
}
if !common.StringDataContains(o.Config.CurrencyPairs.Pairs[asset.Spot].Enabled.Strings(),
o.CurrencyPairs.Pairs[asset.Spot].RequestFormat.Delimiter) {
enabledPairs := currency.NewPairsFromStrings([]string{"EOS-USDT"})
delim := o.GetPairFormat(asset.Spot, false).Delimiter
forceUpdate := false
if !common.StringDataContains(o.GetEnabledPairs(asset.Spot).Strings(), delim) ||
!common.StringDataContains(o.GetAvailablePairs(asset.Spot).Strings(), delim) {
forceUpdate = true
enabledPairs := currency.NewPairsFromStrings(
[]string{currency.BTC.String() + delim + currency.USDT.String()},
)
log.Warnf(log.ExchangeSys,
"Enabled pairs for %v reset due to config upgrade, please enable the ones you would like again.",
o.Name)
err := o.UpdatePairs(enabledPairs, asset.Spot, true, true)
err := o.UpdatePairs(enabledPairs, asset.Spot, true, forceUpdate)
if err != nil {
log.Errorf(log.ExchangeSys,
"%s failed to update currencies.\n",
@@ -239,11 +203,11 @@ func (o *OKEX) Run() {
}
}
if !o.GetEnabledFeatures().AutoPairUpdates {
if !o.GetEnabledFeatures().AutoPairUpdates && !forceUpdate {
return
}
err := o.UpdateTradablePairs(false)
err := o.UpdateTradablePairs(forceUpdate)
if err != nil {
log.Errorf(log.ExchangeSys,
"%s failed to update tradable pairs. Err: %s",

File diff suppressed because one or more lines are too long