mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-05-13 15:09:42 +00:00
Config: AssetEnabled upgrade (#1735)
* Config: Move assetEnabled upgrade to Version management * Assets: Do not error on asset not enabled, or disabled This became more messy with Disabling something that's defaulted to disabled. Taking an idealogical stance against erroring that what you want to have done is already done. * CurrencyManager: Set AssetEnabled when StorePairs(enabled) * RPCServer: Fix tests expecting StoreAssetPairFormat to enable the asset Also assertifies * Bitfinex: Fix tests for MarginFunding subs * GCTWrapper: Improve TestMain clarity * BTSE: Add futures to testconfig * Exchanges: Rename StoreAssetPairStore Previously we were calling it "Format", but accepting everything from the PairStore. We were also defaulting to turning the Asset on. Now callers need to get their AssetEnabled set as they want it, so there's no magic This change also moves responsibility for error wrapping outside to the caller. * Config: AssetEnabled upgrade should respect assetTypes Previously we ignored the field and just turned on everything. I think that was because we couldn't get at the old value. In either case, we have the option to do better, and respect the assetEnabled value * Config: Improve exchange config version upgrade error messages
This commit is contained in:
@@ -7,7 +7,6 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/thrasher-corp/gocryptotrader/backtester/common"
|
"github.com/thrasher-corp/gocryptotrader/backtester/common"
|
||||||
"github.com/thrasher-corp/gocryptotrader/common/convert"
|
|
||||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||||
"github.com/thrasher-corp/gocryptotrader/engine"
|
"github.com/thrasher-corp/gocryptotrader/engine"
|
||||||
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
||||||
@@ -30,7 +29,7 @@ func TestLoadCandles(t *testing.T) {
|
|||||||
b.CurrencyPairs.Pairs[asset.Spot] = ¤cy.PairStore{
|
b.CurrencyPairs.Pairs[asset.Spot] = ¤cy.PairStore{
|
||||||
Available: currency.Pairs{cp},
|
Available: currency.Pairs{cp},
|
||||||
Enabled: currency.Pairs{cp},
|
Enabled: currency.Pairs{cp},
|
||||||
AssetEnabled: convert.BoolPtr(true),
|
AssetEnabled: true,
|
||||||
ConfigFormat: ¤cy.PairFormat{Uppercase: true},
|
ConfigFormat: ¤cy.PairFormat{Uppercase: true},
|
||||||
RequestFormat: ¤cy.PairFormat{Uppercase: true}}
|
RequestFormat: ¤cy.PairFormat{Uppercase: true}}
|
||||||
tt1 := time.Now().Add(-time.Minute).Round(gctkline.OneMin.Duration())
|
tt1 := time.Now().Add(-time.Minute).Round(gctkline.OneMin.Duration())
|
||||||
@@ -68,7 +67,7 @@ func TestLoadTrades(t *testing.T) {
|
|||||||
b.CurrencyPairs.Pairs[asset.Spot] = ¤cy.PairStore{
|
b.CurrencyPairs.Pairs[asset.Spot] = ¤cy.PairStore{
|
||||||
Available: currency.Pairs{cp},
|
Available: currency.Pairs{cp},
|
||||||
Enabled: currency.Pairs{cp},
|
Enabled: currency.Pairs{cp},
|
||||||
AssetEnabled: convert.BoolPtr(true),
|
AssetEnabled: true,
|
||||||
ConfigFormat: ¤cy.PairFormat{Uppercase: true},
|
ConfigFormat: ¤cy.PairFormat{Uppercase: true},
|
||||||
RequestFormat: ¤cy.PairFormat{Uppercase: true}}
|
RequestFormat: ¤cy.PairFormat{Uppercase: true}}
|
||||||
interval := gctkline.OneMin
|
interval := gctkline.OneMin
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/thrasher-corp/gocryptotrader/backtester/common"
|
"github.com/thrasher-corp/gocryptotrader/backtester/common"
|
||||||
"github.com/thrasher-corp/gocryptotrader/common/convert"
|
|
||||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||||
"github.com/thrasher-corp/gocryptotrader/engine"
|
"github.com/thrasher-corp/gocryptotrader/engine"
|
||||||
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
||||||
@@ -33,7 +32,7 @@ func TestLoadCandles(t *testing.T) {
|
|||||||
b.CurrencyPairs.Pairs[asset.Spot] = ¤cy.PairStore{
|
b.CurrencyPairs.Pairs[asset.Spot] = ¤cy.PairStore{
|
||||||
Available: currency.Pairs{cp},
|
Available: currency.Pairs{cp},
|
||||||
Enabled: currency.Pairs{cp},
|
Enabled: currency.Pairs{cp},
|
||||||
AssetEnabled: convert.BoolPtr(true),
|
AssetEnabled: true,
|
||||||
RequestFormat: pFormat,
|
RequestFormat: pFormat,
|
||||||
ConfigFormat: pFormat,
|
ConfigFormat: pFormat,
|
||||||
}
|
}
|
||||||
@@ -68,7 +67,7 @@ func TestLoadTrades(t *testing.T) {
|
|||||||
b.CurrencyPairs.Pairs[asset.Spot] = ¤cy.PairStore{
|
b.CurrencyPairs.Pairs[asset.Spot] = ¤cy.PairStore{
|
||||||
Available: currency.Pairs{cp},
|
Available: currency.Pairs{cp},
|
||||||
Enabled: currency.Pairs{cp},
|
Enabled: currency.Pairs{cp},
|
||||||
AssetEnabled: convert.BoolPtr(true),
|
AssetEnabled: true,
|
||||||
RequestFormat: pFormat,
|
RequestFormat: pFormat,
|
||||||
ConfigFormat: pFormat,
|
ConfigFormat: pFormat,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,7 +35,6 @@ import (
|
|||||||
"github.com/thrasher-corp/gocryptotrader/backtester/funding"
|
"github.com/thrasher-corp/gocryptotrader/backtester/funding"
|
||||||
"github.com/thrasher-corp/gocryptotrader/backtester/report"
|
"github.com/thrasher-corp/gocryptotrader/backtester/report"
|
||||||
gctcommon "github.com/thrasher-corp/gocryptotrader/common"
|
gctcommon "github.com/thrasher-corp/gocryptotrader/common"
|
||||||
"github.com/thrasher-corp/gocryptotrader/common/convert"
|
|
||||||
"github.com/thrasher-corp/gocryptotrader/common/key"
|
"github.com/thrasher-corp/gocryptotrader/common/key"
|
||||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||||
"github.com/thrasher-corp/gocryptotrader/database"
|
"github.com/thrasher-corp/gocryptotrader/database"
|
||||||
@@ -182,7 +181,7 @@ func TestLoadDataAPI(t *testing.T) {
|
|||||||
b.CurrencyPairs.Pairs[asset.Spot] = ¤cy.PairStore{
|
b.CurrencyPairs.Pairs[asset.Spot] = ¤cy.PairStore{
|
||||||
Available: currency.Pairs{cp},
|
Available: currency.Pairs{cp},
|
||||||
Enabled: currency.Pairs{cp},
|
Enabled: currency.Pairs{cp},
|
||||||
AssetEnabled: convert.BoolPtr(true),
|
AssetEnabled: true,
|
||||||
ConfigFormat: ¤cy.PairFormat{Uppercase: true},
|
ConfigFormat: ¤cy.PairFormat{Uppercase: true},
|
||||||
RequestFormat: ¤cy.PairFormat{Uppercase: true}}
|
RequestFormat: ¤cy.PairFormat{Uppercase: true}}
|
||||||
|
|
||||||
@@ -236,7 +235,7 @@ func TestLoadDataCSV(t *testing.T) {
|
|||||||
b.CurrencyPairs.Pairs[asset.Spot] = ¤cy.PairStore{
|
b.CurrencyPairs.Pairs[asset.Spot] = ¤cy.PairStore{
|
||||||
Available: currency.Pairs{cp},
|
Available: currency.Pairs{cp},
|
||||||
Enabled: currency.Pairs{cp},
|
Enabled: currency.Pairs{cp},
|
||||||
AssetEnabled: convert.BoolPtr(true),
|
AssetEnabled: true,
|
||||||
ConfigFormat: ¤cy.PairFormat{Uppercase: true},
|
ConfigFormat: ¤cy.PairFormat{Uppercase: true},
|
||||||
RequestFormat: ¤cy.PairFormat{Uppercase: true}}
|
RequestFormat: ¤cy.PairFormat{Uppercase: true}}
|
||||||
_, err = bt.loadData(cfg, exch, cp, asset.Spot, false)
|
_, err = bt.loadData(cfg, exch, cp, asset.Spot, false)
|
||||||
@@ -301,7 +300,7 @@ func TestLoadDataDatabase(t *testing.T) {
|
|||||||
b.CurrencyPairs.Pairs[asset.Spot] = ¤cy.PairStore{
|
b.CurrencyPairs.Pairs[asset.Spot] = ¤cy.PairStore{
|
||||||
Available: currency.Pairs{cp},
|
Available: currency.Pairs{cp},
|
||||||
Enabled: currency.Pairs{cp},
|
Enabled: currency.Pairs{cp},
|
||||||
AssetEnabled: convert.BoolPtr(true),
|
AssetEnabled: true,
|
||||||
ConfigFormat: ¤cy.PairFormat{Uppercase: true},
|
ConfigFormat: ¤cy.PairFormat{Uppercase: true},
|
||||||
RequestFormat: ¤cy.PairFormat{Uppercase: true}}
|
RequestFormat: ¤cy.PairFormat{Uppercase: true}}
|
||||||
bt.databaseManager, err = engine.SetupDatabaseConnectionManager(&cfg.DataSettings.DatabaseData.Config)
|
bt.databaseManager, err = engine.SetupDatabaseConnectionManager(&cfg.DataSettings.DatabaseData.Config)
|
||||||
@@ -384,7 +383,7 @@ func TestLoadDataLive(t *testing.T) {
|
|||||||
b.CurrencyPairs.Pairs[asset.Spot] = ¤cy.PairStore{
|
b.CurrencyPairs.Pairs[asset.Spot] = ¤cy.PairStore{
|
||||||
Available: currency.Pairs{cp},
|
Available: currency.Pairs{cp},
|
||||||
Enabled: currency.Pairs{cp},
|
Enabled: currency.Pairs{cp},
|
||||||
AssetEnabled: convert.BoolPtr(true),
|
AssetEnabled: true,
|
||||||
ConfigFormat: ¤cy.PairFormat{Uppercase: true},
|
ConfigFormat: ¤cy.PairFormat{Uppercase: true},
|
||||||
RequestFormat: ¤cy.PairFormat{Uppercase: true}}
|
RequestFormat: ¤cy.PairFormat{Uppercase: true}}
|
||||||
_, err = bt.loadData(cfg, exch, cp, asset.Spot, false)
|
_, err = bt.loadData(cfg, exch, cp, asset.Spot, false)
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
"github.com/thrasher-corp/gocryptotrader/backtester/common"
|
"github.com/thrasher-corp/gocryptotrader/backtester/common"
|
||||||
"github.com/thrasher-corp/gocryptotrader/backtester/data"
|
"github.com/thrasher-corp/gocryptotrader/backtester/data"
|
||||||
datakline "github.com/thrasher-corp/gocryptotrader/backtester/data/kline"
|
datakline "github.com/thrasher-corp/gocryptotrader/backtester/data/kline"
|
||||||
@@ -15,7 +16,6 @@ import (
|
|||||||
"github.com/thrasher-corp/gocryptotrader/backtester/funding"
|
"github.com/thrasher-corp/gocryptotrader/backtester/funding"
|
||||||
"github.com/thrasher-corp/gocryptotrader/backtester/report"
|
"github.com/thrasher-corp/gocryptotrader/backtester/report"
|
||||||
gctcommon "github.com/thrasher-corp/gocryptotrader/common"
|
gctcommon "github.com/thrasher-corp/gocryptotrader/common"
|
||||||
"github.com/thrasher-corp/gocryptotrader/common/convert"
|
|
||||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||||
"github.com/thrasher-corp/gocryptotrader/engine"
|
"github.com/thrasher-corp/gocryptotrader/engine"
|
||||||
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
||||||
@@ -316,25 +316,18 @@ func TestFetchLatestData(t *testing.T) {
|
|||||||
funding: &fakeFunding{},
|
funding: &fakeFunding{},
|
||||||
}
|
}
|
||||||
_, err := dataHandler.FetchLatestData()
|
_, err := dataHandler.FetchLatestData()
|
||||||
if !errors.Is(err, engine.ErrSubSystemNotStarted) {
|
require.ErrorIs(t, err, engine.ErrSubSystemNotStarted)
|
||||||
t.Errorf("received '%v' expected '%v'", err, engine.ErrSubSystemNotStarted)
|
|
||||||
}
|
|
||||||
|
|
||||||
dataHandler.started = 1
|
dataHandler.started = 1
|
||||||
_, err = dataHandler.FetchLatestData()
|
_, err = dataHandler.FetchLatestData()
|
||||||
if !errors.Is(err, nil) {
|
require.NoError(t, err)
|
||||||
t.Errorf("received '%v' expected '%v'", err, nil)
|
cp := currency.NewBTCUSDT()
|
||||||
}
|
|
||||||
cp := currency.NewPair(currency.BTC, currency.USDT).Format(
|
|
||||||
currency.PairFormat{
|
|
||||||
Uppercase: true,
|
|
||||||
})
|
|
||||||
f := &binanceus.Binanceus{}
|
f := &binanceus.Binanceus{}
|
||||||
f.SetDefaults()
|
f.SetDefaults()
|
||||||
fb := f.GetBase()
|
fb := f.GetBase()
|
||||||
fbA := fb.CurrencyPairs.Pairs[asset.Spot]
|
require.NoError(t, fb.CurrencyPairs.SetAssetEnabled(asset.Spot, true), "SetAssetEnabled must not error")
|
||||||
fbA.Enabled = fbA.Enabled.Add(cp)
|
require.NoError(t, fb.CurrencyPairs.StorePairs(asset.Spot, currency.Pairs{cp}, false), "StorePairs must not error")
|
||||||
fbA.Available = fbA.Available.Add(cp)
|
require.NoError(t, fb.CurrencyPairs.StorePairs(asset.Spot, currency.Pairs{cp}, true), "StorePairs must not error")
|
||||||
dataHandler.sourcesToCheck = []*liveDataSourceDataHandler{
|
dataHandler.sourcesToCheck = []*liveDataSourceDataHandler{
|
||||||
{
|
{
|
||||||
exchange: f,
|
exchange: f,
|
||||||
@@ -370,15 +363,11 @@ func TestFetchLatestData(t *testing.T) {
|
|||||||
}
|
}
|
||||||
dataHandler.dataHolder = &fakeDataHolder{}
|
dataHandler.dataHolder = &fakeDataHolder{}
|
||||||
_, err = dataHandler.FetchLatestData()
|
_, err = dataHandler.FetchLatestData()
|
||||||
if !errors.Is(err, nil) {
|
require.NoError(t, err)
|
||||||
t.Errorf("received '%v' expected '%v'", err, nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
var dh *dataChecker
|
var dh *dataChecker
|
||||||
_, err = dh.FetchLatestData()
|
_, err = dh.FetchLatestData()
|
||||||
if !errors.Is(err, gctcommon.ErrNilPointer) {
|
require.ErrorIs(t, err, gctcommon.ErrNilPointer)
|
||||||
t.Errorf("received '%v' expected '%v'", err, gctcommon.ErrNilPointer)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLoadCandleData(t *testing.T) {
|
func TestLoadCandleData(t *testing.T) {
|
||||||
@@ -402,7 +391,7 @@ func TestLoadCandleData(t *testing.T) {
|
|||||||
eba := exch.CurrencyPairs.Pairs[asset.Spot]
|
eba := exch.CurrencyPairs.Pairs[asset.Spot]
|
||||||
eba.Available = eba.Available.Add(cp)
|
eba.Available = eba.Available.Add(cp)
|
||||||
eba.Enabled = eba.Enabled.Add(cp)
|
eba.Enabled = eba.Enabled.Add(cp)
|
||||||
eba.AssetEnabled = convert.BoolPtr(true)
|
eba.AssetEnabled = true
|
||||||
l.exchange = exch
|
l.exchange = exch
|
||||||
l.dataType = common.DataCandle
|
l.dataType = common.DataCandle
|
||||||
l.asset = asset.Spot
|
l.asset = asset.Spot
|
||||||
@@ -440,16 +429,12 @@ func TestSetDataForClosingAllPositions(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dataHandler.started = 1
|
dataHandler.started = 1
|
||||||
cp := currency.NewPair(currency.BTC, currency.USDT).Format(
|
cp := currency.NewBTCUSDT()
|
||||||
currency.PairFormat{
|
|
||||||
Uppercase: true,
|
|
||||||
})
|
|
||||||
f := &binanceus.Binanceus{}
|
f := &binanceus.Binanceus{}
|
||||||
f.SetDefaults()
|
f.SetDefaults()
|
||||||
fb := f.GetBase()
|
fb := f.GetBase()
|
||||||
fbA := fb.CurrencyPairs.Pairs[asset.Spot]
|
err := fb.CurrencyPairs.StorePairs(asset.Spot, currency.Pairs{cp}, true)
|
||||||
fbA.Enabled = fbA.Enabled.Add(cp)
|
require.NoError(t, err, "StorePairs must not error")
|
||||||
fbA.Available = fbA.Available.Add(cp)
|
|
||||||
dataHandler.sourcesToCheck = []*liveDataSourceDataHandler{
|
dataHandler.sourcesToCheck = []*liveDataSourceDataHandler{
|
||||||
{
|
{
|
||||||
exchange: f,
|
exchange: f,
|
||||||
@@ -484,7 +469,7 @@ func TestSetDataForClosingAllPositions(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
dataHandler.dataHolder = &fakeDataHolder{}
|
dataHandler.dataHolder = &fakeDataHolder{}
|
||||||
_, err := dataHandler.FetchLatestData()
|
_, err = dataHandler.FetchLatestData()
|
||||||
if !errors.Is(err, nil) {
|
if !errors.Is(err, nil) {
|
||||||
t.Errorf("received '%v' expected '%v'", err, nil)
|
t.Errorf("received '%v' expected '%v'", err, nil)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -186,7 +186,7 @@ func (bt *BackTest) SetupFromConfig(cfg *config.Config, templatePath, output str
|
|||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("%v %v %w", cfg.CurrencySettings[i].ExchangeName, cfg.CurrencySettings[i].Asset, asset.ErrNotSupported)
|
return fmt.Errorf("%v %v %w", cfg.CurrencySettings[i].ExchangeName, cfg.CurrencySettings[i].Asset, asset.ErrNotSupported)
|
||||||
}
|
}
|
||||||
exchangeAsset.AssetEnabled = convert.BoolPtr(true)
|
exchangeAsset.AssetEnabled = true
|
||||||
cp := currency.NewPair(cfg.CurrencySettings[i].Base, cfg.CurrencySettings[i].Quote).Format(*exchangeAsset.RequestFormat)
|
cp := currency.NewPair(cfg.CurrencySettings[i].Base, cfg.CurrencySettings[i].Quote).Format(*exchangeAsset.RequestFormat)
|
||||||
exchangeAsset.Available = exchangeAsset.Available.Add(cp)
|
exchangeAsset.Available = exchangeAsset.Available.Add(cp)
|
||||||
exchangeAsset.Enabled = exchangeAsset.Enabled.Add(cp)
|
exchangeAsset.Enabled = exchangeAsset.Enabled.Add(cp)
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/shopspring/decimal"
|
"github.com/shopspring/decimal"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
"github.com/thrasher-corp/gocryptotrader/backtester/common"
|
"github.com/thrasher-corp/gocryptotrader/backtester/common"
|
||||||
"github.com/thrasher-corp/gocryptotrader/backtester/data"
|
"github.com/thrasher-corp/gocryptotrader/backtester/data"
|
||||||
"github.com/thrasher-corp/gocryptotrader/backtester/data/kline"
|
"github.com/thrasher-corp/gocryptotrader/backtester/data/kline"
|
||||||
@@ -16,7 +17,6 @@ import (
|
|||||||
"github.com/thrasher-corp/gocryptotrader/backtester/eventtypes/order"
|
"github.com/thrasher-corp/gocryptotrader/backtester/eventtypes/order"
|
||||||
"github.com/thrasher-corp/gocryptotrader/backtester/funding"
|
"github.com/thrasher-corp/gocryptotrader/backtester/funding"
|
||||||
gctcommon "github.com/thrasher-corp/gocryptotrader/common"
|
gctcommon "github.com/thrasher-corp/gocryptotrader/common"
|
||||||
"github.com/thrasher-corp/gocryptotrader/common/convert"
|
|
||||||
gctconfig "github.com/thrasher-corp/gocryptotrader/config"
|
gctconfig "github.com/thrasher-corp/gocryptotrader/config"
|
||||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||||
"github.com/thrasher-corp/gocryptotrader/engine"
|
"github.com/thrasher-corp/gocryptotrader/engine"
|
||||||
@@ -245,31 +245,22 @@ func TestExecuteOrder(t *testing.T) {
|
|||||||
em := engine.NewExchangeManager()
|
em := engine.NewExchangeManager()
|
||||||
const testExchange = "binanceus"
|
const testExchange = "binanceus"
|
||||||
exch, err := em.NewExchangeByName(testExchange)
|
exch, err := em.NewExchangeByName(testExchange)
|
||||||
if err != nil {
|
require.NoError(t, err, "NewExchangeByName must not error")
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
exch.SetDefaults()
|
exch.SetDefaults()
|
||||||
exchB := exch.GetBase()
|
exchB := exch.GetBase()
|
||||||
exchB.States = currencystate.NewCurrencyStates()
|
exchB.States = currencystate.NewCurrencyStates()
|
||||||
err = em.Add(exch)
|
err = em.Add(exch)
|
||||||
if !errors.Is(err, nil) {
|
require.NoError(t, err, "ExchangeManager.Add exchange must not error")
|
||||||
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
|
|
||||||
}
|
|
||||||
bot.OrderManager, err = engine.SetupOrderManager(em, &engine.CommunicationManager{}, &bot.ServicesWG, &gctconfig.OrderManager{})
|
bot.OrderManager, err = engine.SetupOrderManager(em, &engine.CommunicationManager{}, &bot.ServicesWG, &gctconfig.OrderManager{})
|
||||||
if !errors.Is(err, nil) {
|
require.NoError(t, err, "engine.SetupOrderManager must not error")
|
||||||
t.Errorf("received: %v, expected: %v", err, nil)
|
|
||||||
}
|
|
||||||
err = bot.OrderManager.Start()
|
err = bot.OrderManager.Start()
|
||||||
if !errors.Is(err, nil) {
|
require.NoError(t, err, "OrderManager.Start must not error")
|
||||||
t.Errorf("received: %v, expected: %v", err, nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
p := currency.NewPair(currency.BTC, currency.USDT)
|
p := currency.NewPair(currency.BTC, currency.USDT)
|
||||||
a := asset.Spot
|
a := asset.Spot
|
||||||
|
require.NoError(t, exchB.CurrencyPairs.SetAssetEnabled(a, true), "SetAssetEnabled must not error")
|
||||||
_, err = exch.UpdateOrderbook(context.Background(), p, a)
|
_, err = exch.UpdateOrderbook(context.Background(), p, a)
|
||||||
if err != nil {
|
require.NoError(t, err, "UpdateOrderbook must not error")
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
f := &binanceus.Binanceus{}
|
f := &binanceus.Binanceus{}
|
||||||
f.Name = testExchange
|
f.Name = testExchange
|
||||||
cs := Settings{
|
cs := Settings{
|
||||||
@@ -381,7 +372,7 @@ func TestExecuteOrderBuySellSizeLimit(t *testing.T) {
|
|||||||
},
|
},
|
||||||
Pairs: map[asset.Item]*currency.PairStore{
|
Pairs: map[asset.Item]*currency.PairStore{
|
||||||
asset.Spot: {
|
asset.Spot: {
|
||||||
AssetEnabled: convert.BoolPtr(true),
|
AssetEnabled: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/thrasher-corp/gocryptotrader/common/convert"
|
|
||||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||||
"github.com/thrasher-corp/gocryptotrader/engine"
|
"github.com/thrasher-corp/gocryptotrader/engine"
|
||||||
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
||||||
@@ -55,7 +54,7 @@ func TestCreateUSDTrackingPairs(t *testing.T) {
|
|||||||
eba := exchB.CurrencyPairs.Pairs[a]
|
eba := exchB.CurrencyPairs.Pairs[a]
|
||||||
eba.Available = eba.Available.Add(cp, cp2, cp3)
|
eba.Available = eba.Available.Add(cp, cp2, cp3)
|
||||||
eba.Enabled = eba.Enabled.Add(cp, cp2, cp3)
|
eba.Enabled = eba.Enabled.Add(cp, cp2, cp3)
|
||||||
eba.AssetEnabled = convert.BoolPtr(true)
|
eba.AssetEnabled = true
|
||||||
|
|
||||||
err = em.Add(exch)
|
err = em.Add(exch)
|
||||||
if !errors.Is(err, nil) {
|
if !errors.Is(err, nil) {
|
||||||
|
|||||||
@@ -55,22 +55,24 @@ func ({{.Variable}} *{{.CapitalName}}) SetDefaults() {
|
|||||||
// can use this example below:
|
// can use this example below:
|
||||||
|
|
||||||
fmt1 := currency.PairStore{
|
fmt1 := currency.PairStore{
|
||||||
|
AssetEnabled: true,
|
||||||
RequestFormat: ¤cy.PairFormat{Uppercase: true},
|
RequestFormat: ¤cy.PairFormat{Uppercase: true},
|
||||||
ConfigFormat: ¤cy.PairFormat{Uppercase: true},
|
ConfigFormat: ¤cy.PairFormat{Uppercase: true},
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt2 := currency.PairStore{
|
fmt2 := currency.PairStore{
|
||||||
|
AssetEnabled: true,
|
||||||
RequestFormat: ¤cy.PairFormat{Uppercase: true},
|
RequestFormat: ¤cy.PairFormat{Uppercase: true},
|
||||||
ConfigFormat: ¤cy.PairFormat{Uppercase: true, Delimiter: ":"},
|
ConfigFormat: ¤cy.PairFormat{Uppercase: true, Delimiter: ":"},
|
||||||
}
|
}
|
||||||
|
|
||||||
err = {{.Variable}}.StoreAssetPairFormat(asset.Spot, fmt1)
|
err = {{.Variable}}.SetAssetPairStore(asset.Spot, fmt1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorln(log.ExchangeSys, err)
|
log.Errorf(log.ExchangeSys, "%s error storing `%s` default asset formats: %s", {{.Variable}}.Name, asset.Spot, err)
|
||||||
}
|
}
|
||||||
err = {{.Variable}}.StoreAssetPairFormat(asset.Margin, fmt2)
|
err = {{.Variable}}.SetAssetPairStore(asset.Margin, fmt2)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorln(log.ExchangeSys, err)
|
log.Errorf(log.ExchangeSys, "%s error storing `%s` default asset formats: %s", {{.Variable}}.Name, asset.Margin, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fill out the capabilities/features that the exchange supports
|
// Fill out the capabilities/features that the exchange supports
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
"github.com/thrasher-corp/gocryptotrader/common"
|
"github.com/thrasher-corp/gocryptotrader/common"
|
||||||
"github.com/thrasher-corp/gocryptotrader/common/key"
|
"github.com/thrasher-corp/gocryptotrader/common/key"
|
||||||
"github.com/thrasher-corp/gocryptotrader/config"
|
"github.com/thrasher-corp/gocryptotrader/config"
|
||||||
@@ -102,14 +103,9 @@ func setupExchange(ctx context.Context, t *testing.T, name string, cfg *config.C
|
|||||||
b := exch.GetBase()
|
b := exch.GetBase()
|
||||||
|
|
||||||
assets := b.CurrencyPairs.GetAssetTypes(false)
|
assets := b.CurrencyPairs.GetAssetTypes(false)
|
||||||
if len(assets) == 0 {
|
require.NotEmpty(t, assets, "exchange %s must have assets", name)
|
||||||
t.Fatalf("Cannot setup %v, exchange has no assets", name)
|
for _, a := range assets {
|
||||||
}
|
require.NoErrorf(t, b.CurrencyPairs.SetAssetEnabled(a, true), "exchange %s SetAssetEnabled must not error for %s", name, a)
|
||||||
for j := range assets {
|
|
||||||
err = b.CurrencyPairs.SetAssetEnabled(assets[j], true)
|
|
||||||
if err != nil && !errors.Is(err, currency.ErrAssetAlreadyEnabled) {
|
|
||||||
t.Fatalf("Cannot setup %v SetAssetEnabled %v", name, err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add +1 to len to verify that exchanges can handle requests with unset pairs and assets
|
// Add +1 to len to verify that exchanges can handle requests with unset pairs and assets
|
||||||
|
|||||||
@@ -904,16 +904,6 @@ func (c *Config) CheckExchangeConfigValues() error {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, a := range assets {
|
|
||||||
if err := e.CurrencyPairs.IsAssetEnabled(a); errors.Is(err, currency.ErrAssetIsNil) {
|
|
||||||
// Checks if we have an old config without the ability to enable disable the entire asset
|
|
||||||
log.Warnf(log.ConfigMgr, "Exchange %s: upgrading config for asset type %s and setting enabled.\n", e.Name, a)
|
|
||||||
if err := e.CurrencyPairs.SetAssetEnabled(a, true); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if enabled := e.CurrencyPairs.GetAssetTypes(true); len(enabled) == 0 {
|
if enabled := e.CurrencyPairs.GetAssetTypes(true); len(enabled) == 0 {
|
||||||
// turn on an asset if all disabled
|
// turn on an asset if all disabled
|
||||||
log.Warnf(log.ConfigMgr, "%s assets disabled, turning on asset %s", e.Name, assets[0])
|
log.Warnf(log.ConfigMgr, "%s assets disabled, turning on asset %s", e.Name, assets[0])
|
||||||
|
|||||||
@@ -720,10 +720,10 @@ func TestCheckPairConsistency(t *testing.T) {
|
|||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
var c Config
|
var c Config
|
||||||
err := c.CheckPairConsistency("asdf")
|
p1 := currency.NewPairWithDelimiter("LTC", "USD", "_")
|
||||||
if !errors.Is(err, ErrExchangeNotFound) {
|
p2 := currency.NewPairWithDelimiter("BTC", "USD", "_")
|
||||||
t.Fatalf("received: '%v' buy expected: '%v'", err, ErrExchangeNotFound)
|
|
||||||
}
|
assert.ErrorIs(t, c.CheckPairConsistency("asdf"), ErrExchangeNotFound)
|
||||||
|
|
||||||
c.Exchanges = append(c.Exchanges,
|
c.Exchanges = append(c.Exchanges,
|
||||||
Exchange{
|
Exchange{
|
||||||
@@ -731,18 +731,9 @@ func TestCheckPairConsistency(t *testing.T) {
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
// Test nil pair store
|
assert.ErrorIs(t, c.CheckPairConsistency(testFakeExchangeName), errPairsManagerIsNil)
|
||||||
err = c.CheckPairConsistency(testFakeExchangeName)
|
|
||||||
if !errors.Is(err, errPairsManagerIsNil) {
|
|
||||||
t.Fatalf("received: '%v' buy expected: '%v'", err, errPairsManagerIsNil)
|
|
||||||
}
|
|
||||||
|
|
||||||
enabled, err := currency.NewPairDelimiter("BTC_USD", "_")
|
pm := ¤cy.PairsManager{
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
c.Exchanges[0].CurrencyPairs = ¤cy.PairsManager{
|
|
||||||
Pairs: map[asset.Item]*currency.PairStore{
|
Pairs: map[asset.Item]*currency.PairStore{
|
||||||
asset.Spot: {
|
asset.Spot: {
|
||||||
RequestFormat: ¤cy.PairFormat{
|
RequestFormat: ¤cy.PairFormat{
|
||||||
@@ -754,123 +745,51 @@ func TestCheckPairConsistency(t *testing.T) {
|
|||||||
Delimiter: "_",
|
Delimiter: "_",
|
||||||
},
|
},
|
||||||
Enabled: currency.Pairs{
|
Enabled: currency.Pairs{
|
||||||
enabled,
|
p2,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
c.Exchanges[0].CurrencyPairs = pm
|
||||||
|
|
||||||
// Test for nil avail pairs
|
assert.NoError(t, c.CheckPairConsistency(testFakeExchangeName), "Should not error on empty available pairs")
|
||||||
err = c.CheckPairConsistency(testFakeExchangeName)
|
assert.Empty(t, pm.Pairs[asset.Spot].Enabled, "Unavailable pairs should be removed from enabled")
|
||||||
if !errors.Is(err, nil) {
|
|
||||||
t.Fatalf("received: '%v' buy expected: '%v'", err, nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
p1, err := currency.NewPairDelimiter("LTC_USD", "_")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test that enabled pair is not found in the available pairs
|
// Test that enabled pair is not found in the available pairs
|
||||||
c.Exchanges[0].CurrencyPairs.Pairs[asset.Spot].Available = currency.Pairs{
|
pm.Pairs[asset.Spot].Available = currency.Pairs{p1}
|
||||||
p1,
|
|
||||||
}
|
|
||||||
|
|
||||||
// LTC_USD is only found in the available pairs list and should therefore
|
// LTC_USD is only found in the available pairs list and should therefore
|
||||||
// be added to the enabled pairs list due to the atLestOneEnabled code
|
// be added to the enabled pairs list due to the atLeastOneEnabled code
|
||||||
err = c.CheckPairConsistency(testFakeExchangeName)
|
assert.NoError(t, c.CheckPairConsistency(testFakeExchangeName), "Should not error when adding a pair from available to enabled")
|
||||||
if err != nil {
|
require.Equal(t, 1, len(pm.Pairs[asset.Spot].Enabled), "One pair must be enabled")
|
||||||
t.Fatal(err)
|
assert.True(t, slices.Contains(pm.Pairs[asset.Spot].Enabled, p1), "Newly enabled pair should be in Enabled")
|
||||||
}
|
|
||||||
|
|
||||||
if len(c.Exchanges[0].CurrencyPairs.Pairs[asset.Spot].Enabled) != 1 {
|
pm.Pairs[asset.Spot].Available = currency.Pairs{p1, p2}
|
||||||
t.Fatal("there should be at least one pair located in this list")
|
assert.NoError(t, c.CheckPairConsistency(testFakeExchangeName), "Should not error with no changes to be made")
|
||||||
}
|
|
||||||
|
|
||||||
if !c.Exchanges[0].CurrencyPairs.Pairs[asset.Spot].Enabled[0].Equal(p1) {
|
pm.Pairs[asset.Spot].Enabled = nil
|
||||||
t.Fatal("LTC_USD should be contained in the enabled pairs list")
|
assert.NoError(t, c.CheckPairConsistency(testFakeExchangeName), "Should not error when adding a pair from available to enabled to fulfil atLeastOne")
|
||||||
}
|
assert.NotEmpty(t, pm.Pairs[asset.Spot].Enabled, "One pair should be enabled")
|
||||||
|
|
||||||
p2, err := currency.NewPairDelimiter("BTC_USD", "_")
|
pm.Pairs[asset.Spot].Enabled = currency.Pairs{p1, p2}
|
||||||
if err != nil {
|
assert.NoError(t, c.CheckPairConsistency(testFakeExchangeName), "CheckPairConsistency should not error with when removing an invalid pair")
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add the BTC_USD pair and see result
|
assert.NoError(t, c.CheckPairConsistency(testFakeExchangeName), "CheckPairConsistency should not error with consistent pairs")
|
||||||
c.Exchanges[0].CurrencyPairs.Pairs[asset.Spot].Available = currency.Pairs{
|
|
||||||
p1, p2,
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := c.CheckPairConsistency(testFakeExchangeName); err != nil {
|
pm.Pairs[asset.Spot].AssetEnabled = true
|
||||||
t.Fatal(err)
|
pm.Pairs[asset.Spot].Enabled = currency.Pairs{}
|
||||||
}
|
assert.NoError(t, c.CheckPairConsistency(testFakeExchangeName), "CheckPairConsistency should not error with spot asset enabled but no pairs")
|
||||||
|
|
||||||
// Test that an empty enabled pair is populated with an available pair
|
pm.Pairs[asset.Spot].AssetEnabled = true
|
||||||
c.Exchanges[0].CurrencyPairs.Pairs[asset.Spot].Enabled = nil
|
pm.Pairs[asset.Spot].Enabled = currency.Pairs{currency.NewPair(currency.DASH, currency.USD)}
|
||||||
if err := c.CheckPairConsistency(testFakeExchangeName); err != nil {
|
assert.NoError(t, c.CheckPairConsistency(testFakeExchangeName), "CheckPairConsistency should not error with spot asset enabled and enabled pairs")
|
||||||
t.Error("unexpected result", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(c.Exchanges[0].CurrencyPairs.Pairs[asset.Spot].Enabled) != 1 {
|
pm.Pairs[asset.Spot].AssetEnabled = false
|
||||||
t.Fatal("should be populated with at least one currency pair")
|
pm.Pairs[asset.Spot].Enabled = currency.Pairs{}
|
||||||
}
|
assert.NoError(t, c.CheckPairConsistency(testFakeExchangeName), "CheckPairConsistency should not error with spot asset disabled and no enabled pairs")
|
||||||
|
|
||||||
// Test that an invalid enabled pair is removed from the list
|
pm.Pairs[asset.Spot].Enabled = currency.Pairs{currency.NewPair(currency.DASH, currency.USD), p1, p2}
|
||||||
c.Exchanges[0].CurrencyPairs.Pairs[asset.Spot].Enabled = currency.Pairs{
|
assert.NoError(t, c.CheckPairConsistency(testFakeExchangeName), "CheckPairConsistency should not error with spot asset disabled but enabled pairs")
|
||||||
p1,
|
|
||||||
p2,
|
|
||||||
}
|
|
||||||
if err := c.CheckPairConsistency(testFakeExchangeName); err != nil {
|
|
||||||
t.Error("unexpected result")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test when no update is required as the available pairs and enabled pairs
|
|
||||||
// are consistent
|
|
||||||
if err := c.CheckPairConsistency(testFakeExchangeName); err != nil {
|
|
||||||
t.Error("unexpected result")
|
|
||||||
}
|
|
||||||
|
|
||||||
c.Exchanges[0].CurrencyPairs.Pairs[asset.Spot].AssetEnabled = convert.BoolPtr(true)
|
|
||||||
c.Exchanges[0].CurrencyPairs.Pairs[asset.Spot].Enabled = currency.Pairs{}
|
|
||||||
|
|
||||||
// Test no conflict and at least one on enabled asset type
|
|
||||||
if err := c.CheckPairConsistency(testFakeExchangeName); err != nil {
|
|
||||||
t.Error("unexpected result")
|
|
||||||
}
|
|
||||||
|
|
||||||
c.Exchanges[0].CurrencyPairs.Pairs[asset.Spot].AssetEnabled = convert.BoolPtr(true)
|
|
||||||
c.Exchanges[0].CurrencyPairs.Pairs[asset.Spot].Enabled = currency.Pairs{currency.NewPair(currency.DASH, currency.USD)}
|
|
||||||
|
|
||||||
// Test with conflict and at least one on enabled asset type
|
|
||||||
if err := c.CheckPairConsistency(testFakeExchangeName); err != nil {
|
|
||||||
t.Error("unexpected result")
|
|
||||||
}
|
|
||||||
|
|
||||||
c.Exchanges[0].CurrencyPairs.Pairs[asset.Spot].AssetEnabled = convert.BoolPtr(false)
|
|
||||||
c.Exchanges[0].CurrencyPairs.Pairs[asset.Spot].Enabled = currency.Pairs{}
|
|
||||||
|
|
||||||
// Test no conflict and at least one on disabled asset type
|
|
||||||
if err := c.CheckPairConsistency(testFakeExchangeName); err != nil {
|
|
||||||
t.Error("unexpected result")
|
|
||||||
}
|
|
||||||
|
|
||||||
c.Exchanges[0].CurrencyPairs.Pairs[asset.Spot].Enabled = currency.Pairs{
|
|
||||||
currency.NewPair(currency.DASH, currency.USD),
|
|
||||||
p1,
|
|
||||||
p2,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test with conflict and at least one on disabled asset type
|
|
||||||
if err := c.CheckPairConsistency(testFakeExchangeName); err != nil {
|
|
||||||
t.Error("unexpected result")
|
|
||||||
}
|
|
||||||
|
|
||||||
c.Exchanges[0].CurrencyPairs.Pairs[asset.Spot].AssetEnabled = nil
|
|
||||||
|
|
||||||
// assetType enabled failure check
|
|
||||||
if err := c.CheckPairConsistency(testFakeExchangeName); err != nil {
|
|
||||||
t.Error("unexpected result")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSupportsPair(t *testing.T) {
|
func TestSupportsPair(t *testing.T) {
|
||||||
@@ -884,7 +803,7 @@ func TestSupportsPair(t *testing.T) {
|
|||||||
CurrencyPairs: ¤cy.PairsManager{
|
CurrencyPairs: ¤cy.PairsManager{
|
||||||
Pairs: map[asset.Item]*currency.PairStore{
|
Pairs: map[asset.Item]*currency.PairStore{
|
||||||
asset.Spot: {
|
asset.Spot: {
|
||||||
AssetEnabled: convert.BoolPtr(true),
|
AssetEnabled: true,
|
||||||
Available: []currency.Pair{currency.NewPair(currency.BTC, currency.USD)},
|
Available: []currency.Pair{currency.NewPair(currency.BTC, currency.USD)},
|
||||||
ConfigFormat: fmt,
|
ConfigFormat: fmt,
|
||||||
RequestFormat: fmt,
|
RequestFormat: fmt,
|
||||||
@@ -1538,7 +1457,7 @@ func TestCheckExchangeConfigValues(t *testing.T) {
|
|||||||
cfg.Exchanges = append(cfg.Exchanges, cpy[0])
|
cfg.Exchanges = append(cfg.Exchanges, cpy[0])
|
||||||
|
|
||||||
cfg.Exchanges[0].CurrencyPairs.Pairs[asset.Spot].Enabled = nil
|
cfg.Exchanges[0].CurrencyPairs.Pairs[asset.Spot].Enabled = nil
|
||||||
cfg.Exchanges[0].CurrencyPairs.Pairs[asset.Spot].AssetEnabled = convert.BoolPtr(false)
|
cfg.Exchanges[0].CurrencyPairs.Pairs[asset.Spot].AssetEnabled = false
|
||||||
err = cfg.CheckExchangeConfigValues()
|
err = cfg.CheckExchangeConfigValues()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
@@ -1711,7 +1630,7 @@ func TestCheckConfig(t *testing.T) {
|
|||||||
LastUpdated: 0,
|
LastUpdated: 0,
|
||||||
Pairs: map[asset.Item]*currency.PairStore{
|
Pairs: map[asset.Item]*currency.PairStore{
|
||||||
asset.Spot: {
|
asset.Spot: {
|
||||||
AssetEnabled: convert.BoolPtr(true),
|
AssetEnabled: true,
|
||||||
Available: currency.Pairs{cp1, cp2},
|
Available: currency.Pairs{cp1, cp2},
|
||||||
Enabled: currency.Pairs{cp1},
|
Enabled: currency.Pairs{cp1},
|
||||||
ConfigFormat: ¤cy.EMPTYFORMAT,
|
ConfigFormat: ¤cy.EMPTYFORMAT,
|
||||||
|
|||||||
86
config/versions/v4.go
Normal file
86
config/versions/v4.go
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
package versions
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/buger/jsonparser"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
errUpgradingAssetTypes = errors.New("error upgrading assetTypes")
|
||||||
|
errUpgradingCurrencyPairs = errors.New("error upgrading currencyPairs.pairs")
|
||||||
|
)
|
||||||
|
|
||||||
|
// Version4 is an Exchange upgrade to move currencyPairs.assetTypes to currencyPairs.pairs.*.assetEnabled
|
||||||
|
type Version4 struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
Manager.registerVersion(4, &Version4{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Exchanges returns all exchanges: "*"
|
||||||
|
func (v *Version4) Exchanges() []string { return []string{"*"} }
|
||||||
|
|
||||||
|
// UpgradeExchange sets AssetEnabled: true for all assets listed in assetTypes, and false for any with no field
|
||||||
|
func (v *Version4) UpgradeExchange(_ context.Context, e []byte) ([]byte, error) {
|
||||||
|
toEnable := map[string]bool{}
|
||||||
|
|
||||||
|
assetTypesFn := func(asset []byte, valueType jsonparser.ValueType, _ int, _ error) {
|
||||||
|
if valueType == jsonparser.String {
|
||||||
|
toEnable[string(asset)] = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_, err := jsonparser.ArrayEach(e, assetTypesFn, "currencyPairs", "assetTypes")
|
||||||
|
if err != nil && !errors.Is(err, jsonparser.KeyPathNotFoundError) {
|
||||||
|
return e, fmt.Errorf("%w: %w", errUpgradingAssetTypes, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
assetEnabledFn := func(assetBytes []byte, v []byte, _ jsonparser.ValueType, _ int) (err error) {
|
||||||
|
asset := string(assetBytes)
|
||||||
|
if toEnable[asset] {
|
||||||
|
e, err = jsonparser.Set(e, []byte(`true`), "currencyPairs", "pairs", asset, "assetEnabled")
|
||||||
|
} else {
|
||||||
|
var vT jsonparser.ValueType
|
||||||
|
_, vT, _, err = jsonparser.Get(v, "assetEnabled")
|
||||||
|
switch {
|
||||||
|
case vT == jsonparser.Null, errors.Is(err, jsonparser.KeyPathNotFoundError):
|
||||||
|
e, err = jsonparser.Set(e, []byte(`false`), "currencyPairs", "pairs", asset, "assetEnabled")
|
||||||
|
case err == nil && vT != jsonparser.Boolean:
|
||||||
|
err = fmt.Errorf("assetEnabled: %w (`%s`)", jsonparser.UnknownValueTypeError, vT)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
err = fmt.Errorf("%w for asset `%s`", err, asset)
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err = jsonparser.ObjectEach(bytes.Clone(e), assetEnabledFn, "currencyPairs", "pairs"); err != nil {
|
||||||
|
return e, fmt.Errorf("%w: %w", errUpgradingCurrencyPairs, err)
|
||||||
|
}
|
||||||
|
e = jsonparser.Delete(e, "currencyPairs", "assetTypes")
|
||||||
|
return e, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DowngradeExchange moves AssetEnabled assets into AssetType field
|
||||||
|
func (v *Version4) DowngradeExchange(_ context.Context, e []byte) ([]byte, error) {
|
||||||
|
assetTypes := []string{}
|
||||||
|
|
||||||
|
assetEnabledFn := func(asset []byte, v []byte, _ jsonparser.ValueType, _ int) error {
|
||||||
|
if b, err := jsonparser.GetBoolean(v, "assetEnabled"); err == nil {
|
||||||
|
if b {
|
||||||
|
assetTypes = append(assetTypes, fmt.Sprintf("%q", asset))
|
||||||
|
}
|
||||||
|
e = jsonparser.Delete(e, "currencyPairs", "pairs", string(asset), "assetEnabled")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if err := jsonparser.ObjectEach(bytes.Clone(e), assetEnabledFn, "currencyPairs", "pairs"); err != nil {
|
||||||
|
return e, err
|
||||||
|
}
|
||||||
|
return jsonparser.Set(e, []byte(`[`+strings.Join(assetTypes, ",")+`]`), "currencyPairs", "assetTypes")
|
||||||
|
}
|
||||||
91
config/versions/v4_test.go
Normal file
91
config/versions/v4_test.go
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
package versions
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"context"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/buger/jsonparser"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestVersion4ExchangeType(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
assert.Implements(t, (*ExchangeVersion)(nil), new(Version4))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVersion4Exchanges(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
assert.Equal(t, []string{"*"}, new(Version4).Exchanges())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVersion4Upgrade(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
_, err := new(Version4).UpgradeExchange(context.Background(), []byte{})
|
||||||
|
require.ErrorIs(t, err, errUpgradingAssetTypes)
|
||||||
|
|
||||||
|
_, err = new(Version4).UpgradeExchange(context.Background(), []byte(`{}`))
|
||||||
|
require.ErrorIs(t, err, errUpgradingCurrencyPairs)
|
||||||
|
|
||||||
|
in := []byte(`{"name":"Cracken","currencyPairs":{"assetTypes":["spot"],"pairs":{"spot":{"enabled":"BTC-AUD","available":"BTC-AUD"},"futures":{"assetEnabled":true},"options":{},"margin":{"assetEnabled":null}}}}`)
|
||||||
|
out, err := new(Version4).UpgradeExchange(context.Background(), in)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotEmpty(t, out)
|
||||||
|
|
||||||
|
_, _, _, err = jsonparser.Get(out, "currencyPairs", "assetTypes") //nolint:dogsled // Ignored return values really not needed
|
||||||
|
assert.ErrorIs(t, err, jsonparser.KeyPathNotFoundError, "assetTypes should be removed")
|
||||||
|
|
||||||
|
e, err := jsonparser.GetBoolean(out, "currencyPairs", "pairs", "spot", "assetEnabled")
|
||||||
|
require.NoError(t, err, "Must find assetEnabled for spot")
|
||||||
|
assert.True(t, e, "assetEnabled should be set to true")
|
||||||
|
|
||||||
|
e, err = jsonparser.GetBoolean(out, "currencyPairs", "pairs", "futures", "assetEnabled")
|
||||||
|
require.NoError(t, err, "Must find assetEnabled for futures")
|
||||||
|
assert.True(t, e, "assetEnabled should be set to true")
|
||||||
|
|
||||||
|
e, err = jsonparser.GetBoolean(out, "currencyPairs", "pairs", "options", "assetEnabled")
|
||||||
|
require.NoError(t, err, "Must find assetEnabled for options")
|
||||||
|
assert.False(t, e, "assetEnabled should be set to false")
|
||||||
|
|
||||||
|
e, err = jsonparser.GetBoolean(out, "currencyPairs", "pairs", "margin", "assetEnabled")
|
||||||
|
require.NoError(t, err, "Must find assetEnabled for margin")
|
||||||
|
assert.False(t, e, "assetEnabled should be set to false")
|
||||||
|
|
||||||
|
out2, err := new(Version4).UpgradeExchange(context.Background(), out)
|
||||||
|
require.NoError(t, err, "Must not error on re-upgrading")
|
||||||
|
assert.Equal(t, out, out2, "Should not affect an already upgraded config")
|
||||||
|
|
||||||
|
in = []byte(`{"name":"Cracken","currencyPairs":{"assetTypes":["spot"],"pairs":{"spot":{"assetEnabled":{}}}}}`)
|
||||||
|
_, err = new(Version4).UpgradeExchange(context.Background(), in)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
in = []byte(`{"name":"Cracken","currencyPairs":{"assetTypes":["spot"],"pairs":{"margin":{"assetEnabled":{}}}}}`)
|
||||||
|
_, err = new(Version4).UpgradeExchange(context.Background(), in)
|
||||||
|
require.ErrorIs(t, err, jsonparser.UnknownValueTypeError)
|
||||||
|
require.ErrorContains(t, err, "`margin`")
|
||||||
|
require.ErrorContains(t, err, "`object`")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVersion4Downgrade(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
in := []byte(`{"name":"Cracken","currencyPairs":{"pairs":{"spot":{"enabled":"BTC-AUD","available":"BTC-AUD","assetEnabled":true},"futures":{"assetEnabled":false},"options":{},"options_combo":{"assetEnabled":true}}}}`)
|
||||||
|
out, err := new(Version4).DowngradeExchange(context.Background(), in)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotEmpty(t, out)
|
||||||
|
|
||||||
|
v, vT, _, err := jsonparser.Get(out, "currencyPairs", "assetTypes")
|
||||||
|
require.NoError(t, err, "assetTypes must be found")
|
||||||
|
require.Equal(t, jsonparser.Array, vT, "assetTypes must be an array")
|
||||||
|
require.Equal(t, `["spot","options_combo"]`, string(v), "assetTypes must be correct")
|
||||||
|
|
||||||
|
assetEnabledFn := func(k []byte, v []byte, _ jsonparser.ValueType, _ int) error {
|
||||||
|
_, err = jsonparser.GetBoolean(v, "assetEnabled")
|
||||||
|
require.ErrorIsf(t, err, jsonparser.KeyPathNotFoundError, "assetEnabled must be removed from %s", k)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
err = jsonparser.ObjectEach(bytes.Clone(out), assetEnabledFn, "currencyPairs", "pairs")
|
||||||
|
require.NoError(t, err, "Must not error visiting currencyPairs")
|
||||||
|
}
|
||||||
@@ -168,7 +168,7 @@ func exchangeDeploy(ctx context.Context, patch ExchangeVersion, method func(Exch
|
|||||||
defer func() { i++ }()
|
defer func() { i++ }()
|
||||||
name, err := jsonparser.GetString(exchOrig, "name")
|
name, err := jsonparser.GetString(exchOrig, "name")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errs = common.AppendError(errs, fmt.Errorf("%w: %w `name`: %w", errModifyingExchange, common.ErrGettingField, err))
|
errs = common.AppendError(errs, fmt.Errorf("%w [%d]: %w `name`: %w", errModifyingExchange, i, common.ErrGettingField, err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
for _, want := range wanted {
|
for _, want := range wanted {
|
||||||
@@ -177,12 +177,12 @@ func exchangeDeploy(ctx context.Context, patch ExchangeVersion, method func(Exch
|
|||||||
}
|
}
|
||||||
exchNew, err := method(patch, ctx, exchOrig)
|
exchNew, err := method(patch, ctx, exchOrig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errs = common.AppendError(errs, fmt.Errorf("%w: %w", errModifyingExchange, err))
|
errs = common.AppendError(errs, fmt.Errorf("%w for `%s`: %w", errModifyingExchange, name, err))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if !bytes.Equal(exchNew, exchOrig) {
|
if !bytes.Equal(exchNew, exchOrig) {
|
||||||
if j, err = jsonparser.Set(j, exchNew, "exchanges", "["+strconv.Itoa(i)+"]"); err != nil {
|
if j, err = jsonparser.Set(j, exchNew, "exchanges", "["+strconv.Itoa(i)+"]"); err != nil {
|
||||||
errs = common.AppendError(errs, fmt.Errorf("%w: %w `exchanges.[%d]`: %w", errModifyingExchange, common.ErrSettingField, i, err))
|
errs = common.AppendError(errs, fmt.Errorf("%w `%s`/exchanges[%d]: %w: %w", errModifyingExchange, name, i, common.ErrSettingField, err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ func TestDeploy(t *testing.T) {
|
|||||||
_, err = m.Deploy(context.Background(), in, UseLatestVersion)
|
_, err = m.Deploy(context.Background(), in, UseLatestVersion)
|
||||||
require.Implements(t, (*ExchangeVersion)(nil), m.versions[1])
|
require.Implements(t, (*ExchangeVersion)(nil), m.versions[1])
|
||||||
require.ErrorIs(t, err, errUpgrade)
|
require.ErrorIs(t, err, errUpgrade)
|
||||||
|
require.ErrorContains(t, err, "for `Juan`")
|
||||||
|
|
||||||
j2, err = m.Deploy(context.Background(), j, 0)
|
j2, err = m.Deploy(context.Background(), j, 0)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@@ -83,6 +84,7 @@ func TestExchangeDeploy(t *testing.T) {
|
|||||||
require.ErrorIs(t, err, common.ErrGettingField)
|
require.ErrorIs(t, err, common.ErrGettingField)
|
||||||
require.ErrorIs(t, err, jsonparser.KeyPathNotFoundError)
|
require.ErrorIs(t, err, jsonparser.KeyPathNotFoundError)
|
||||||
require.ErrorContains(t, err, "`name`")
|
require.ErrorContains(t, err, "`name`")
|
||||||
|
require.ErrorContains(t, err, "[0]")
|
||||||
|
|
||||||
in = []byte(`{"version":0,"exchanges":[{"name":"Juan"},{"name":"Megashaft"}]}`)
|
in = []byte(`{"version":0,"exchanges":[{"name":"Juan"},{"name":"Megashaft"}]}`)
|
||||||
_, err = exchangeDeploy(context.Background(), v, ExchangeVersion.UpgradeExchange, in)
|
_, err = exchangeDeploy(context.Background(), v, ExchangeVersion.UpgradeExchange, in)
|
||||||
|
|||||||
@@ -7,15 +7,12 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/thrasher-corp/gocryptotrader/common"
|
"github.com/thrasher-corp/gocryptotrader/common"
|
||||||
"github.com/thrasher-corp/gocryptotrader/common/convert"
|
|
||||||
"github.com/thrasher-corp/gocryptotrader/encoding/json"
|
"github.com/thrasher-corp/gocryptotrader/encoding/json"
|
||||||
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Public errors
|
// Public errors
|
||||||
var (
|
var (
|
||||||
ErrAssetAlreadyEnabled = errors.New("asset already enabled")
|
|
||||||
ErrAssetIsNil = errors.New("asset is nil")
|
|
||||||
ErrAssetNotFound = errors.New("asset type not found in pair store")
|
ErrAssetNotFound = errors.New("asset type not found in pair store")
|
||||||
ErrPairAlreadyEnabled = errors.New("pair already enabled")
|
ErrPairAlreadyEnabled = errors.New("pair already enabled")
|
||||||
ErrPairFormatIsNil = errors.New("pair format is nil")
|
ErrPairFormatIsNil = errors.New("pair format is nil")
|
||||||
@@ -38,7 +35,7 @@ func (p *PairsManager) GetAssetTypes(enabled bool) asset.Items {
|
|||||||
defer p.mutex.RUnlock()
|
defer p.mutex.RUnlock()
|
||||||
assetTypes := make(asset.Items, 0, len(p.Pairs))
|
assetTypes := make(asset.Items, 0, len(p.Pairs))
|
||||||
for k, ps := range p.Pairs {
|
for k, ps := range p.Pairs {
|
||||||
if enabled && (ps.AssetEnabled == nil || !*ps.AssetEnabled) {
|
if enabled && !ps.AssetEnabled {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
assetTypes = append(assetTypes, k)
|
assetTypes = append(assetTypes, k)
|
||||||
@@ -205,8 +202,11 @@ func (p *PairsManager) GetFormat(a asset.Item, request bool) (PairFormat, error)
|
|||||||
return *pFmt, nil
|
return *pFmt, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// StorePairs stores a list of pairs based on the asset type and whether
|
// StorePairs stores a list of pairs for an asset type
|
||||||
// they're enabled or not
|
// If enabled is true:
|
||||||
|
// * AssetEnabled is set true if the pair list is not empty
|
||||||
|
// * pairs replace the Enabled pairs
|
||||||
|
// * pairs are added to Available pairs
|
||||||
func (p *PairsManager) StorePairs(a asset.Item, pairs Pairs, enabled bool) error {
|
func (p *PairsManager) StorePairs(a asset.Item, pairs Pairs, enabled bool) error {
|
||||||
if !a.IsValid() {
|
if !a.IsValid() {
|
||||||
return fmt.Errorf("%s %w", a, asset.ErrNotSupported)
|
return fmt.Errorf("%s %w", a, asset.ErrNotSupported)
|
||||||
@@ -226,6 +226,10 @@ func (p *PairsManager) StorePairs(a asset.Item, pairs Pairs, enabled bool) error
|
|||||||
}
|
}
|
||||||
|
|
||||||
if enabled {
|
if enabled {
|
||||||
|
if len(pairs) != 0 {
|
||||||
|
pairStore.AssetEnabled = true
|
||||||
|
pairStore.Available.Add(pairs...)
|
||||||
|
}
|
||||||
pairStore.Enabled = slices.Clone(pairs)
|
pairStore.Enabled = slices.Clone(pairs)
|
||||||
} else {
|
} else {
|
||||||
pairStore.Available = slices.Clone(pairs)
|
pairStore.Available = slices.Clone(pairs)
|
||||||
@@ -246,9 +250,7 @@ func (p *PairsManager) EnsureOnePairEnabled() (Pair, asset.Item, error) {
|
|||||||
p.mutex.Lock()
|
p.mutex.Lock()
|
||||||
defer p.mutex.Unlock()
|
defer p.mutex.Unlock()
|
||||||
for _, v := range p.Pairs {
|
for _, v := range p.Pairs {
|
||||||
if v.AssetEnabled == nil ||
|
if !v.AssetEnabled || len(v.Available) == 0 {
|
||||||
!*v.AssetEnabled ||
|
|
||||||
len(v.Available) == 0 {
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if len(v.Enabled) > 0 {
|
if len(v.Enabled) > 0 {
|
||||||
@@ -256,9 +258,7 @@ func (p *PairsManager) EnsureOnePairEnabled() (Pair, asset.Item, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
for k, v := range p.Pairs {
|
for k, v := range p.Pairs {
|
||||||
if v.AssetEnabled == nil ||
|
if !v.AssetEnabled || len(v.Available) == 0 {
|
||||||
!*v.AssetEnabled ||
|
|
||||||
len(v.Available) == 0 {
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
rp, err := v.Available.GetRandomPair()
|
rp, err := v.Available.GetRandomPair()
|
||||||
@@ -324,8 +324,7 @@ func (p *PairsManager) EnablePair(a asset.Item, pair Pair) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !pairStore.Available.Contains(pair, true) {
|
if !pairStore.Available.Contains(pair, true) {
|
||||||
return fmt.Errorf("%s %w in the list of available pairs",
|
return fmt.Errorf("%s %w in the list of available pairs", pair, ErrPairNotFound)
|
||||||
pair, ErrPairNotFound)
|
|
||||||
}
|
}
|
||||||
pairStore.Enabled = pairStore.Enabled.Add(pair)
|
pairStore.Enabled = pairStore.Enabled.Add(pair)
|
||||||
return nil
|
return nil
|
||||||
@@ -348,10 +347,7 @@ func (p *PairsManager) IsPairAvailable(pair Pair, a asset.Item) (bool, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
if pairStore.AssetEnabled == nil {
|
return pairStore.AssetEnabled && pairStore.Available.Contains(pair, true), nil
|
||||||
return false, fmt.Errorf("%s %w", a, ErrAssetIsNil)
|
|
||||||
}
|
|
||||||
return *pairStore.AssetEnabled && pairStore.Available.Contains(pair, true), nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsPairEnabled checks if a pair is enabled for an enabled asset type
|
// IsPairEnabled checks if a pair is enabled for an enabled asset type
|
||||||
@@ -371,10 +367,7 @@ func (p *PairsManager) IsPairEnabled(pair Pair, a asset.Item) (bool, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
if pairStore.AssetEnabled == nil {
|
return pairStore.AssetEnabled && pairStore.Enabled.Contains(pair, true), nil
|
||||||
return false, fmt.Errorf("%s %w", a, ErrAssetIsNil)
|
|
||||||
}
|
|
||||||
return *pairStore.AssetEnabled && pairStore.Enabled.Contains(pair, true), nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsAssetEnabled checks to see if an asset is enabled
|
// IsAssetEnabled checks to see if an asset is enabled
|
||||||
@@ -391,11 +384,7 @@ func (p *PairsManager) IsAssetEnabled(a asset.Item) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if pairStore.AssetEnabled == nil {
|
if !pairStore.AssetEnabled {
|
||||||
return fmt.Errorf("%s %w", a, ErrAssetIsNil)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !*pairStore.AssetEnabled {
|
|
||||||
return fmt.Errorf("%s %w", a, asset.ErrNotEnabled)
|
return fmt.Errorf("%s %w", a, asset.ErrNotEnabled)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@@ -424,18 +413,8 @@ func (p *PairsManager) SetAssetEnabled(a asset.Item, enabled bool) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if pairStore.AssetEnabled == nil {
|
pairStore.AssetEnabled = enabled
|
||||||
pairStore.AssetEnabled = convert.BoolPtr(enabled)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if !*pairStore.AssetEnabled && !enabled {
|
|
||||||
return errors.New("asset already disabled")
|
|
||||||
} else if *pairStore.AssetEnabled && enabled {
|
|
||||||
return ErrAssetAlreadyEnabled
|
|
||||||
}
|
|
||||||
|
|
||||||
*pairStore.AssetEnabled = enabled
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -547,13 +526,8 @@ func (ps *PairStore) clone() *PairStore {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var assetEnabled *bool
|
|
||||||
if ps.AssetEnabled != nil {
|
|
||||||
assetEnabled = convert.BoolPtr(*ps.AssetEnabled)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &PairStore{
|
return &PairStore{
|
||||||
AssetEnabled: assetEnabled,
|
AssetEnabled: ps.AssetEnabled,
|
||||||
Enabled: slices.Clone(ps.Enabled),
|
Enabled: slices.Clone(ps.Enabled),
|
||||||
Available: slices.Clone(ps.Available),
|
Available: slices.Clone(ps.Available),
|
||||||
RequestFormat: ps.RequestFormat.clone(),
|
RequestFormat: ps.RequestFormat.clone(),
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import (
|
|||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"github.com/thrasher-corp/gocryptotrader/common/convert"
|
|
||||||
"github.com/thrasher-corp/gocryptotrader/encoding/json"
|
"github.com/thrasher-corp/gocryptotrader/encoding/json"
|
||||||
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
||||||
)
|
)
|
||||||
@@ -24,7 +23,7 @@ func initTest(t *testing.T) *PairsManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
spot := &PairStore{
|
spot := &PairStore{
|
||||||
AssetEnabled: convert.BoolPtr(true),
|
AssetEnabled: true,
|
||||||
Available: spotAvailable,
|
Available: spotAvailable,
|
||||||
Enabled: spotEnabled,
|
Enabled: spotEnabled,
|
||||||
RequestFormat: &PairFormat{Uppercase: true},
|
RequestFormat: &PairFormat{Uppercase: true},
|
||||||
@@ -32,7 +31,7 @@ func initTest(t *testing.T) *PairsManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
futures := &PairStore{
|
futures := &PairStore{
|
||||||
AssetEnabled: convert.BoolPtr(false),
|
AssetEnabled: false,
|
||||||
Available: spotAvailable,
|
Available: spotAvailable,
|
||||||
Enabled: spotEnabled,
|
Enabled: spotEnabled,
|
||||||
RequestFormat: &PairFormat{Uppercase: true},
|
RequestFormat: &PairFormat{Uppercase: true},
|
||||||
@@ -463,72 +462,54 @@ func TestEnablePair(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestIsAssetEnabled_SetAssetEnabled(t *testing.T) {
|
func TestAssetEnabled(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
p := initTest(t)
|
p := initTest(t)
|
||||||
|
|
||||||
err := p.IsAssetEnabled(asset.Empty)
|
err := p.IsAssetEnabled(asset.Empty)
|
||||||
if !errors.Is(err, asset.ErrNotSupported) {
|
assert.ErrorIs(t, err, asset.ErrNotSupported)
|
||||||
t.Fatalf("received: '%v' but expected: '%v'", err, asset.ErrNotSupported)
|
|
||||||
}
|
|
||||||
p.Pairs = nil
|
p.Pairs = nil
|
||||||
|
|
||||||
// Test enabling a pair when the pair manager is not initialised
|
// Test enabling a pair when the pair manager is not initialised
|
||||||
err = p.IsAssetEnabled(asset.Spot)
|
err = p.IsAssetEnabled(asset.Spot)
|
||||||
if err == nil {
|
assert.ErrorIs(t, err, ErrPairManagerNotInitialised)
|
||||||
t.Error("unexpected result")
|
|
||||||
}
|
|
||||||
|
|
||||||
err = p.SetAssetEnabled(asset.Spot, true)
|
err = p.SetAssetEnabled(asset.Spot, true)
|
||||||
if err == nil {
|
assert.ErrorIs(t, err, ErrPairManagerNotInitialised)
|
||||||
t.Fatal("unexpected result")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test asset type which doesn't exist
|
// Test asset type which doesn't exist
|
||||||
p = initTest(t)
|
p = initTest(t)
|
||||||
|
|
||||||
p.Pairs[asset.Spot].AssetEnabled = nil
|
p.Pairs[asset.Spot].AssetEnabled = false
|
||||||
|
|
||||||
err = p.IsAssetEnabled(asset.Spot)
|
err = p.IsAssetEnabled(asset.Spot)
|
||||||
if err == nil {
|
assert.ErrorIs(t, err, asset.ErrNotEnabled)
|
||||||
t.Error("unexpected result")
|
|
||||||
}
|
|
||||||
|
|
||||||
err = p.SetAssetEnabled(asset.Spot, false)
|
err = p.SetAssetEnabled(asset.Spot, false)
|
||||||
if err != nil {
|
assert.NoError(t, err)
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = p.SetAssetEnabled(asset.Spot, false)
|
err = p.SetAssetEnabled(asset.Spot, false)
|
||||||
if err == nil {
|
assert.NoError(t, err, "Setting to disabled twice should not error")
|
||||||
t.Fatal("unexpected result")
|
|
||||||
}
|
|
||||||
|
|
||||||
err = p.IsAssetEnabled(asset.Spot)
|
err = p.IsAssetEnabled(asset.Spot)
|
||||||
if err == nil {
|
assert.ErrorIs(t, err, asset.ErrNotEnabled)
|
||||||
t.Error("unexpected result")
|
|
||||||
}
|
|
||||||
|
|
||||||
err = p.SetAssetEnabled(asset.Spot, true)
|
err = p.SetAssetEnabled(asset.Spot, true)
|
||||||
if err != nil {
|
assert.NoError(t, err)
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = p.SetAssetEnabled(asset.Spot, true)
|
err = p.SetAssetEnabled(asset.Spot, true)
|
||||||
if err == nil {
|
assert.NoError(t, err, "Setting to enabled twice should not error")
|
||||||
t.Fatal("unexpected result")
|
|
||||||
}
|
|
||||||
|
|
||||||
err = p.IsAssetEnabled(asset.Spot)
|
err = p.IsAssetEnabled(asset.Spot)
|
||||||
if err != nil {
|
assert.NoError(t, err, "IsAssetEnabled should not error")
|
||||||
t.Error("unexpected result")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestFullStoreUnmarshalMarshal tests json Mashal and Unmarshal
|
// TestFullStoreUnmarshalMarshal tests json Mashal and Unmarshal
|
||||||
func TestFullStoreUnmarshalMarshal(t *testing.T) {
|
func TestFullStoreUnmarshalMarshal(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
var um = make(FullStore)
|
var um = make(FullStore)
|
||||||
um[asset.Spot] = &PairStore{AssetEnabled: convert.BoolPtr(true)}
|
um[asset.Spot] = &PairStore{AssetEnabled: true}
|
||||||
|
|
||||||
data, err := json.Marshal(um)
|
data, err := json.Marshal(um)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -591,7 +572,7 @@ func TestIsPairAvailable(t *testing.T) {
|
|||||||
|
|
||||||
pm.Pairs[asset.PerpetualSwap] = &PairStore{}
|
pm.Pairs[asset.PerpetualSwap] = &PairStore{}
|
||||||
_, err = pm.IsPairAvailable(cp, asset.PerpetualSwap)
|
_, err = pm.IsPairAvailable(cp, asset.PerpetualSwap)
|
||||||
assert.ErrorIs(t, err, ErrAssetIsNil, "Should error when store AssetEnabled is nil")
|
require.NoError(t, err, "Must not error when store is empty")
|
||||||
|
|
||||||
_, err = pm.IsPairAvailable(EMPTYPAIR, asset.PerpetualSwap)
|
_, err = pm.IsPairAvailable(EMPTYPAIR, asset.PerpetualSwap)
|
||||||
assert.ErrorIs(t, err, ErrCurrencyPairEmpty, "Should error when currency pair is empty")
|
assert.ErrorIs(t, err, ErrCurrencyPairEmpty, "Should error when currency pair is empty")
|
||||||
@@ -602,62 +583,35 @@ func TestIsPairEnabled(t *testing.T) {
|
|||||||
pm := initTest(t)
|
pm := initTest(t)
|
||||||
cp := NewPairWithDelimiter("BTC", "USD", "-")
|
cp := NewPairWithDelimiter("BTC", "USD", "-")
|
||||||
enabled, err := pm.IsPairEnabled(cp, asset.Spot)
|
enabled, err := pm.IsPairEnabled(cp, asset.Spot)
|
||||||
if !errors.Is(err, nil) {
|
require.NoError(t, err)
|
||||||
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
|
assert.True(t, enabled, "IsPairEnabled should return true when pair is enabled")
|
||||||
}
|
|
||||||
|
|
||||||
if !enabled {
|
|
||||||
t.Fatal("expected pair to be enabled")
|
|
||||||
}
|
|
||||||
|
|
||||||
enabled, err = pm.IsPairEnabled(NewPair(SAFE, MOONRISE), asset.Spot)
|
enabled, err = pm.IsPairEnabled(NewPair(SAFE, MOONRISE), asset.Spot)
|
||||||
if !errors.Is(err, nil) {
|
require.NoError(t, err)
|
||||||
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
|
assert.False(t, enabled, "IsPairEnabled should return false when pair does not exist")
|
||||||
}
|
|
||||||
|
|
||||||
if enabled {
|
|
||||||
t.Fatal("expected pair to be disabled")
|
|
||||||
}
|
|
||||||
|
|
||||||
enabled, err = pm.IsPairEnabled(cp, asset.Futures)
|
enabled, err = pm.IsPairEnabled(cp, asset.Futures)
|
||||||
if !errors.Is(err, nil) {
|
require.NoError(t, err)
|
||||||
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
|
assert.False(t, enabled, "IsPairEnabled should return false when asset not enabled")
|
||||||
}
|
|
||||||
|
|
||||||
if enabled {
|
|
||||||
t.Fatal("expected pair to be disabled because asset type is not enabled")
|
|
||||||
}
|
|
||||||
|
|
||||||
cp = NewPairWithDelimiter("XRP", "DOGE", "-")
|
cp = NewPairWithDelimiter("XRP", "DOGE", "-")
|
||||||
enabled, err = pm.IsPairEnabled(cp, asset.Spot)
|
enabled, err = pm.IsPairEnabled(cp, asset.Spot)
|
||||||
if !errors.Is(err, nil) {
|
require.NoError(t, err)
|
||||||
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
|
assert.False(t, enabled, "IsPairEnabled should return false when pair not in enabled list")
|
||||||
}
|
|
||||||
|
|
||||||
if enabled {
|
|
||||||
t.Fatal("expected pair to be disabled because pair not found in enabled list")
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = pm.IsPairEnabled(cp, asset.PerpetualSwap)
|
_, err = pm.IsPairEnabled(cp, asset.PerpetualSwap)
|
||||||
if !errors.Is(err, ErrAssetNotFound) {
|
assert.ErrorIs(t, err, ErrAssetNotFound)
|
||||||
t.Fatalf("received: '%v' but expected: '%v'", err, ErrAssetNotFound)
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = pm.IsPairEnabled(cp, asset.Item(1337))
|
_, err = pm.IsPairEnabled(cp, asset.Item(1337))
|
||||||
if !errors.Is(err, asset.ErrNotSupported) {
|
assert.ErrorIs(t, err, asset.ErrNotSupported)
|
||||||
t.Fatalf("received: '%v' but expected: '%v'", err, asset.ErrNotSupported)
|
|
||||||
}
|
|
||||||
|
|
||||||
pm.Pairs[asset.PerpetualSwap] = &PairStore{}
|
pm.Pairs[asset.PerpetualSwap] = &PairStore{}
|
||||||
_, err = pm.IsPairEnabled(cp, asset.PerpetualSwap)
|
enabled, err = pm.IsPairEnabled(cp, asset.PerpetualSwap)
|
||||||
if !errors.Is(err, ErrAssetIsNil) {
|
require.NoError(t, err, "Must not error when store is empty")
|
||||||
t.Fatalf("received: '%v' but expected: '%v'", err, ErrAssetIsNil)
|
assert.False(t, enabled, "Should return false when store is empty")
|
||||||
}
|
|
||||||
|
|
||||||
_, err = pm.IsPairEnabled(EMPTYPAIR, asset.PerpetualSwap)
|
_, err = pm.IsPairEnabled(EMPTYPAIR, asset.PerpetualSwap)
|
||||||
if !errors.Is(err, ErrCurrencyPairEmpty) {
|
assert.ErrorIs(t, err, ErrCurrencyPairEmpty)
|
||||||
t.Fatalf("received: '%v' but expected: '%v'", err, ErrCurrencyPairEmpty)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestEnsureOnePairEnabled(t *testing.T) {
|
func TestEnsureOnePairEnabled(t *testing.T) {
|
||||||
@@ -667,7 +621,7 @@ func TestEnsureOnePairEnabled(t *testing.T) {
|
|||||||
Pairs: map[asset.Item]*PairStore{
|
Pairs: map[asset.Item]*PairStore{
|
||||||
asset.Futures: {},
|
asset.Futures: {},
|
||||||
asset.Spot: {
|
asset.Spot: {
|
||||||
AssetEnabled: convert.BoolPtr(true),
|
AssetEnabled: true,
|
||||||
Available: []Pair{
|
Available: []Pair{
|
||||||
p,
|
p,
|
||||||
},
|
},
|
||||||
@@ -700,13 +654,13 @@ func TestEnsureOnePairEnabled(t *testing.T) {
|
|||||||
pm = PairsManager{
|
pm = PairsManager{
|
||||||
Pairs: map[asset.Item]*PairStore{
|
Pairs: map[asset.Item]*PairStore{
|
||||||
asset.Futures: {
|
asset.Futures: {
|
||||||
AssetEnabled: convert.BoolPtr(true),
|
AssetEnabled: true,
|
||||||
Available: []Pair{
|
Available: []Pair{
|
||||||
NewPair(BTC, USDC),
|
NewPair(BTC, USDC),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
asset.Spot: {
|
asset.Spot: {
|
||||||
AssetEnabled: convert.BoolPtr(true),
|
AssetEnabled: true,
|
||||||
Enabled: []Pair{
|
Enabled: []Pair{
|
||||||
p,
|
p,
|
||||||
},
|
},
|
||||||
@@ -733,11 +687,11 @@ func TestEnsureOnePairEnabled(t *testing.T) {
|
|||||||
pm = PairsManager{
|
pm = PairsManager{
|
||||||
Pairs: map[asset.Item]*PairStore{
|
Pairs: map[asset.Item]*PairStore{
|
||||||
asset.Futures: {
|
asset.Futures: {
|
||||||
AssetEnabled: convert.BoolPtr(true),
|
AssetEnabled: true,
|
||||||
Available: []Pair{p},
|
Available: []Pair{p},
|
||||||
},
|
},
|
||||||
asset.Options: {
|
asset.Options: {
|
||||||
AssetEnabled: convert.BoolPtr(true),
|
AssetEnabled: true,
|
||||||
Available: []Pair{},
|
Available: []Pair{},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -776,20 +730,20 @@ func TestLoad(t *testing.T) {
|
|||||||
RequestFormat: fmt2,
|
RequestFormat: fmt2,
|
||||||
Pairs: map[asset.Item]*PairStore{
|
Pairs: map[asset.Item]*PairStore{
|
||||||
asset.Futures: {
|
asset.Futures: {
|
||||||
AssetEnabled: convert.BoolPtr(true),
|
AssetEnabled: true,
|
||||||
Available: []Pair{p},
|
Available: []Pair{p},
|
||||||
},
|
},
|
||||||
asset.Options: {
|
asset.Options: {
|
||||||
AssetEnabled: convert.BoolPtr(false),
|
AssetEnabled: false,
|
||||||
Available: []Pair{},
|
Available: []Pair{},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
base.Load(&seed)
|
base.Load(&seed)
|
||||||
assert.True(t, *base.Pairs[asset.Futures].AssetEnabled, "Futures AssetEnabled should be true")
|
assert.True(t, base.Pairs[asset.Futures].AssetEnabled, "Futures AssetEnabled should be true")
|
||||||
assert.True(t, base.Pairs[asset.Futures].Available.Contains(p, true), "Futures Available Pairs should contain BTCUSDT")
|
assert.True(t, base.Pairs[asset.Futures].Available.Contains(p, true), "Futures Available Pairs should contain BTCUSDT")
|
||||||
assert.False(t, *base.Pairs[asset.Options].AssetEnabled, "Options AssetEnabled should be false")
|
assert.False(t, base.Pairs[asset.Options].AssetEnabled, "Options AssetEnabled should be false")
|
||||||
assert.Equal(t, tt, base.LastUpdated, "Last Updated should be correct")
|
assert.Equal(t, tt, base.LastUpdated, "Last Updated should be correct")
|
||||||
assert.Equal(t, fmt1.Uppercase, base.ConfigFormat.Uppercase, "ConfigFormat Uppercase should be correct")
|
assert.Equal(t, fmt1.Uppercase, base.ConfigFormat.Uppercase, "ConfigFormat Uppercase should be correct")
|
||||||
assert.Equal(t, fmt2.Delimiter, base.RequestFormat.Delimiter, "RequestFormat Delimiter should be correct")
|
assert.Equal(t, fmt2.Delimiter, base.RequestFormat.Delimiter, "RequestFormat Delimiter should be correct")
|
||||||
@@ -909,7 +863,7 @@ func TestIsAssetSupported(t *testing.T) {
|
|||||||
p := PairsManager{
|
p := PairsManager{
|
||||||
Pairs: FullStore{
|
Pairs: FullStore{
|
||||||
asset.Spot: {
|
asset.Spot: {
|
||||||
AssetEnabled: convert.BoolPtr(false),
|
AssetEnabled: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ type FullStore map[asset.Item]*PairStore
|
|||||||
|
|
||||||
// PairStore stores a currency pair store
|
// PairStore stores a currency pair store
|
||||||
type PairStore struct {
|
type PairStore struct {
|
||||||
AssetEnabled *bool `json:"assetEnabled"`
|
AssetEnabled bool `json:"assetEnabled"`
|
||||||
Enabled Pairs `json:"enabled"`
|
Enabled Pairs `json:"enabled"`
|
||||||
Available Pairs `json:"available"`
|
Available Pairs `json:"available"`
|
||||||
RequestFormat *PairFormat `json:"requestFormat,omitempty"`
|
RequestFormat *PairFormat `json:"requestFormat,omitempty"`
|
||||||
|
|||||||
@@ -156,6 +156,7 @@ Similar to the configs, spot support is inbuilt but other asset types will need
|
|||||||
|
|
||||||
```go
|
```go
|
||||||
spot := currency.PairStore{
|
spot := currency.PairStore{
|
||||||
|
AssetEnabled: true,
|
||||||
RequestFormat: ¤cy.PairFormat{
|
RequestFormat: ¤cy.PairFormat{
|
||||||
Uppercase: true,
|
Uppercase: true,
|
||||||
Delimiter: "/",
|
Delimiter: "/",
|
||||||
@@ -166,6 +167,7 @@ Similar to the configs, spot support is inbuilt but other asset types will need
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
futures := currency.PairStore{
|
futures := currency.PairStore{
|
||||||
|
AssetEnabled: true,
|
||||||
RequestFormat: ¤cy.PairFormat{
|
RequestFormat: ¤cy.PairFormat{
|
||||||
Uppercase: true,
|
Uppercase: true,
|
||||||
Delimiter: "-",
|
Delimiter: "-",
|
||||||
@@ -176,14 +178,14 @@ Similar to the configs, spot support is inbuilt but other asset types will need
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
err := f.StoreAssetPairFormat(asset.Spot, spot)
|
err := f.SetAssetPairStore(asset.Spot, spot)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorln(log.ExchangeSys, err)
|
log.Errorf(log.ExchangeSys, "%s error storing `spot` default asset formats: %s", bi.Name, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = f.StoreAssetPairFormat(asset.Futures, futures)
|
err = f.SetAssetPairStore(asset.Futures, futures)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorln(log.ExchangeSys, err)
|
log.Errorf(log.ExchangeSys, "%s error storing `futures` default asset formats: %s", bi.Name, err)
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ import (
|
|||||||
|
|
||||||
"github.com/gofrs/uuid"
|
"github.com/gofrs/uuid"
|
||||||
"github.com/thrasher-corp/gocryptotrader/common"
|
"github.com/thrasher-corp/gocryptotrader/common"
|
||||||
"github.com/thrasher-corp/gocryptotrader/common/convert"
|
|
||||||
"github.com/thrasher-corp/gocryptotrader/config"
|
"github.com/thrasher-corp/gocryptotrader/config"
|
||||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||||
"github.com/thrasher-corp/gocryptotrader/database"
|
"github.com/thrasher-corp/gocryptotrader/database"
|
||||||
@@ -924,7 +923,7 @@ func createDHM(t *testing.T) (*DataHistoryManager, *datahistoryjob.DataHistoryJo
|
|||||||
b.CurrencyPairs.Pairs[asset.Spot] = ¤cy.PairStore{
|
b.CurrencyPairs.Pairs[asset.Spot] = ¤cy.PairStore{
|
||||||
Available: currency.Pairs{cp, cp2},
|
Available: currency.Pairs{cp, cp2},
|
||||||
Enabled: currency.Pairs{cp, cp2},
|
Enabled: currency.Pairs{cp, cp2},
|
||||||
AssetEnabled: convert.BoolPtr(true)}
|
AssetEnabled: true}
|
||||||
err = em.Add(exch)
|
err = em.Add(exch)
|
||||||
if !errors.Is(err, nil) {
|
if !errors.Is(err, nil) {
|
||||||
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
|
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
|
||||||
@@ -940,7 +939,7 @@ func createDHM(t *testing.T) (*DataHistoryManager, *datahistoryjob.DataHistoryJo
|
|||||||
b.CurrencyPairs.Pairs[asset.Spot] = ¤cy.PairStore{
|
b.CurrencyPairs.Pairs[asset.Spot] = ¤cy.PairStore{
|
||||||
Available: currency.Pairs{cp, cp2},
|
Available: currency.Pairs{cp, cp2},
|
||||||
Enabled: currency.Pairs{cp, cp2},
|
Enabled: currency.Pairs{cp, cp2},
|
||||||
AssetEnabled: convert.BoolPtr(true),
|
AssetEnabled: true,
|
||||||
ConfigFormat: ¤cy.PairFormat{Uppercase: true},
|
ConfigFormat: ¤cy.PairFormat{Uppercase: true},
|
||||||
RequestFormat: ¤cy.PairFormat{Uppercase: true},
|
RequestFormat: ¤cy.PairFormat{Uppercase: true},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,14 +46,14 @@ func CreateTestBot(tb testing.TB) *Engine {
|
|||||||
|
|
||||||
pairs1 := map[asset.Item]*currency.PairStore{
|
pairs1 := map[asset.Item]*currency.PairStore{
|
||||||
asset.Spot: {
|
asset.Spot: {
|
||||||
AssetEnabled: convert.BoolPtr(true),
|
AssetEnabled: true,
|
||||||
Available: currency.Pairs{cp1},
|
Available: currency.Pairs{cp1},
|
||||||
Enabled: currency.Pairs{cp1},
|
Enabled: currency.Pairs{cp1},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
pairs2 := map[asset.Item]*currency.PairStore{
|
pairs2 := map[asset.Item]*currency.PairStore{
|
||||||
asset.Spot: {
|
asset.Spot: {
|
||||||
AssetEnabled: convert.BoolPtr(true),
|
AssetEnabled: true,
|
||||||
Available: currency.Pairs{cp2},
|
Available: currency.Pairs{cp2},
|
||||||
Enabled: currency.Pairs{cp2},
|
Enabled: currency.Pairs{cp2},
|
||||||
},
|
},
|
||||||
@@ -372,7 +372,7 @@ func TestGetSpecificAvailablePairs(t *testing.T) {
|
|||||||
Name: testExchange,
|
Name: testExchange,
|
||||||
CurrencyPairs: ¤cy.PairsManager{Pairs: map[asset.Item]*currency.PairStore{
|
CurrencyPairs: ¤cy.PairsManager{Pairs: map[asset.Item]*currency.PairStore{
|
||||||
asset.Spot: {
|
asset.Spot: {
|
||||||
AssetEnabled: convert.BoolPtr(true),
|
AssetEnabled: true,
|
||||||
Enabled: currency.Pairs{currency.NewPair(currency.BTC, currency.USD), currency.NewPair(currency.BTC, c)},
|
Enabled: currency.Pairs{currency.NewPair(currency.BTC, currency.USD), currency.NewPair(currency.BTC, c)},
|
||||||
Available: currency.Pairs{currency.NewPair(currency.BTC, currency.USD), currency.NewPair(currency.BTC, c)},
|
Available: currency.Pairs{currency.NewPair(currency.BTC, currency.USD), currency.NewPair(currency.BTC, c)},
|
||||||
ConfigFormat: ¤cy.PairFormat{
|
ConfigFormat: ¤cy.PairFormat{
|
||||||
@@ -717,7 +717,7 @@ func TestGetExchangeNamesByCurrency(t *testing.T) {
|
|||||||
Name: bf,
|
Name: bf,
|
||||||
CurrencyPairs: ¤cy.PairsManager{Pairs: map[asset.Item]*currency.PairStore{
|
CurrencyPairs: ¤cy.PairsManager{Pairs: map[asset.Item]*currency.PairStore{
|
||||||
asset.Spot: {
|
asset.Spot: {
|
||||||
AssetEnabled: convert.BoolPtr(true),
|
AssetEnabled: true,
|
||||||
Enabled: currency.Pairs{btcjpy},
|
Enabled: currency.Pairs{btcjpy},
|
||||||
Available: currency.Pairs{btcjpy},
|
Available: currency.Pairs{btcjpy},
|
||||||
ConfigFormat: ¤cy.PairFormat{
|
ConfigFormat: ¤cy.PairFormat{
|
||||||
@@ -950,7 +950,7 @@ func (f fakeDepositExchange) GetDepositAddress(_ context.Context, _ currency.Cod
|
|||||||
|
|
||||||
func createDepositEngine(opts *fakeDepositExchangeOpts) *Engine {
|
func createDepositEngine(opts *fakeDepositExchangeOpts) *Engine {
|
||||||
ps := currency.PairStore{
|
ps := currency.PairStore{
|
||||||
AssetEnabled: convert.BoolPtr(true),
|
AssetEnabled: true,
|
||||||
Enabled: currency.Pairs{
|
Enabled: currency.Pairs{
|
||||||
currency.NewPair(currency.BTC, currency.USDT),
|
currency.NewPair(currency.BTC, currency.USDT),
|
||||||
currency.NewPair(currency.XRP, currency.USDT),
|
currency.NewPair(currency.XRP, currency.USDT),
|
||||||
|
|||||||
@@ -807,12 +807,12 @@ func TestProcessOrders(t *testing.T) {
|
|||||||
},
|
},
|
||||||
Pairs: map[asset.Item]*currency.PairStore{
|
Pairs: map[asset.Item]*currency.PairStore{
|
||||||
asset.Spot: {
|
asset.Spot: {
|
||||||
AssetEnabled: convert.BoolPtr(true),
|
AssetEnabled: true,
|
||||||
Enabled: pairs,
|
Enabled: pairs,
|
||||||
Available: pairs,
|
Available: pairs,
|
||||||
},
|
},
|
||||||
asset.Futures: {
|
asset.Futures: {
|
||||||
AssetEnabled: convert.BoolPtr(true),
|
AssetEnabled: true,
|
||||||
Enabled: pairs,
|
Enabled: pairs,
|
||||||
Available: pairs,
|
Available: pairs,
|
||||||
},
|
},
|
||||||
@@ -831,12 +831,12 @@ func TestProcessOrders(t *testing.T) {
|
|||||||
},
|
},
|
||||||
Pairs: map[asset.Item]*currency.PairStore{
|
Pairs: map[asset.Item]*currency.PairStore{
|
||||||
asset.Spot: {
|
asset.Spot: {
|
||||||
AssetEnabled: convert.BoolPtr(true),
|
AssetEnabled: true,
|
||||||
Enabled: pairs,
|
Enabled: pairs,
|
||||||
Available: pairs,
|
Available: pairs,
|
||||||
},
|
},
|
||||||
asset.Futures: {
|
asset.Futures: {
|
||||||
AssetEnabled: convert.BoolPtr(true),
|
AssetEnabled: true,
|
||||||
Enabled: pairs,
|
Enabled: pairs,
|
||||||
Available: pairs,
|
Available: pairs,
|
||||||
},
|
},
|
||||||
@@ -1522,14 +1522,14 @@ func TestGetOpenFuturesPosition(t *testing.T) {
|
|||||||
b.Enabled = true
|
b.Enabled = true
|
||||||
b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore)
|
b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore)
|
||||||
b.CurrencyPairs.Pairs[asset.Futures] = ¤cy.PairStore{
|
b.CurrencyPairs.Pairs[asset.Futures] = ¤cy.PairStore{
|
||||||
AssetEnabled: convert.BoolPtr(true),
|
AssetEnabled: true,
|
||||||
RequestFormat: ¤cy.PairFormat{Delimiter: "-"},
|
RequestFormat: ¤cy.PairFormat{Delimiter: "-"},
|
||||||
ConfigFormat: ¤cy.PairFormat{Delimiter: "-"},
|
ConfigFormat: ¤cy.PairFormat{Delimiter: "-"},
|
||||||
Available: currency.Pairs{cp},
|
Available: currency.Pairs{cp},
|
||||||
Enabled: currency.Pairs{cp},
|
Enabled: currency.Pairs{cp},
|
||||||
}
|
}
|
||||||
b.CurrencyPairs.Pairs[asset.Spot] = ¤cy.PairStore{
|
b.CurrencyPairs.Pairs[asset.Spot] = ¤cy.PairStore{
|
||||||
AssetEnabled: convert.BoolPtr(true),
|
AssetEnabled: true,
|
||||||
ConfigFormat: ¤cy.PairFormat{Delimiter: "/"},
|
ConfigFormat: ¤cy.PairFormat{Delimiter: "/"},
|
||||||
RequestFormat: ¤cy.PairFormat{Delimiter: "/"},
|
RequestFormat: ¤cy.PairFormat{Delimiter: "/"},
|
||||||
Available: currency.Pairs{cp},
|
Available: currency.Pairs{cp},
|
||||||
@@ -1616,14 +1616,14 @@ func TestProcessFuturesPositions(t *testing.T) {
|
|||||||
|
|
||||||
b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore)
|
b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore)
|
||||||
b.CurrencyPairs.Pairs[asset.Futures] = ¤cy.PairStore{
|
b.CurrencyPairs.Pairs[asset.Futures] = ¤cy.PairStore{
|
||||||
AssetEnabled: convert.BoolPtr(true),
|
AssetEnabled: true,
|
||||||
RequestFormat: ¤cy.PairFormat{Delimiter: "-"},
|
RequestFormat: ¤cy.PairFormat{Delimiter: "-"},
|
||||||
ConfigFormat: ¤cy.PairFormat{Delimiter: "-"},
|
ConfigFormat: ¤cy.PairFormat{Delimiter: "-"},
|
||||||
Available: currency.Pairs{cp, cp2},
|
Available: currency.Pairs{cp, cp2},
|
||||||
Enabled: currency.Pairs{cp, cp2},
|
Enabled: currency.Pairs{cp, cp2},
|
||||||
}
|
}
|
||||||
b.CurrencyPairs.Pairs[asset.Spot] = ¤cy.PairStore{
|
b.CurrencyPairs.Pairs[asset.Spot] = ¤cy.PairStore{
|
||||||
AssetEnabled: convert.BoolPtr(true),
|
AssetEnabled: true,
|
||||||
ConfigFormat: ¤cy.PairFormat{Delimiter: "/"},
|
ConfigFormat: ¤cy.PairFormat{Delimiter: "/"},
|
||||||
RequestFormat: ¤cy.PairFormat{Delimiter: "/"},
|
RequestFormat: ¤cy.PairFormat{Delimiter: "/"},
|
||||||
Available: currency.Pairs{cp, cp2},
|
Available: currency.Pairs{cp, cp2},
|
||||||
|
|||||||
@@ -25,7 +25,6 @@ import (
|
|||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"github.com/thrasher-corp/gocryptotrader/common"
|
"github.com/thrasher-corp/gocryptotrader/common"
|
||||||
"github.com/thrasher-corp/gocryptotrader/common/convert"
|
|
||||||
"github.com/thrasher-corp/gocryptotrader/common/key"
|
"github.com/thrasher-corp/gocryptotrader/common/key"
|
||||||
"github.com/thrasher-corp/gocryptotrader/config"
|
"github.com/thrasher-corp/gocryptotrader/config"
|
||||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||||
@@ -485,7 +484,7 @@ func RPCTestSetup(t *testing.T) *Engine {
|
|||||||
b.CurrencyPairs.Pairs[asset.Spot] = ¤cy.PairStore{
|
b.CurrencyPairs.Pairs[asset.Spot] = ¤cy.PairStore{
|
||||||
Available: currency.Pairs{cp},
|
Available: currency.Pairs{cp},
|
||||||
Enabled: currency.Pairs{cp},
|
Enabled: currency.Pairs{cp},
|
||||||
AssetEnabled: convert.BoolPtr(true),
|
AssetEnabled: true,
|
||||||
ConfigFormat: ¤cy.PairFormat{Uppercase: true},
|
ConfigFormat: ¤cy.PairFormat{Uppercase: true},
|
||||||
RequestFormat: ¤cy.PairFormat{Uppercase: true}}
|
RequestFormat: ¤cy.PairFormat{Uppercase: true}}
|
||||||
err = em.Add(exch)
|
err = em.Add(exch)
|
||||||
@@ -504,7 +503,7 @@ func RPCTestSetup(t *testing.T) *Engine {
|
|||||||
b.CurrencyPairs.Pairs[asset.Spot] = ¤cy.PairStore{
|
b.CurrencyPairs.Pairs[asset.Spot] = ¤cy.PairStore{
|
||||||
Available: currency.Pairs{cp},
|
Available: currency.Pairs{cp},
|
||||||
Enabled: currency.Pairs{cp},
|
Enabled: currency.Pairs{cp},
|
||||||
AssetEnabled: convert.BoolPtr(true),
|
AssetEnabled: true,
|
||||||
ConfigFormat: ¤cy.PairFormat{Uppercase: true},
|
ConfigFormat: ¤cy.PairFormat{Uppercase: true},
|
||||||
RequestFormat: ¤cy.PairFormat{Uppercase: true}}
|
RequestFormat: ¤cy.PairFormat{Uppercase: true}}
|
||||||
err = em.Add(exch)
|
err = em.Add(exch)
|
||||||
@@ -1268,7 +1267,7 @@ func TestGetAccountInfo(t *testing.T) {
|
|||||||
b.Enabled = true
|
b.Enabled = true
|
||||||
b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore)
|
b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore)
|
||||||
b.CurrencyPairs.Pairs[asset.Spot] = ¤cy.PairStore{
|
b.CurrencyPairs.Pairs[asset.Spot] = ¤cy.PairStore{
|
||||||
AssetEnabled: convert.BoolPtr(true),
|
AssetEnabled: true,
|
||||||
}
|
}
|
||||||
fakeExchange := fExchange{
|
fakeExchange := fExchange{
|
||||||
IBotExchange: exch,
|
IBotExchange: exch,
|
||||||
@@ -1296,7 +1295,7 @@ func TestUpdateAccountInfo(t *testing.T) {
|
|||||||
b.Enabled = true
|
b.Enabled = true
|
||||||
b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore)
|
b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore)
|
||||||
b.CurrencyPairs.Pairs[asset.Spot] = ¤cy.PairStore{
|
b.CurrencyPairs.Pairs[asset.Spot] = ¤cy.PairStore{
|
||||||
AssetEnabled: convert.BoolPtr(true),
|
AssetEnabled: true,
|
||||||
}
|
}
|
||||||
fakeExchange := fExchange{
|
fakeExchange := fExchange{
|
||||||
IBotExchange: exch,
|
IBotExchange: exch,
|
||||||
@@ -1342,7 +1341,7 @@ func TestGetOrders(t *testing.T) {
|
|||||||
b.CurrencyPairs.Pairs[asset.Spot] = ¤cy.PairStore{
|
b.CurrencyPairs.Pairs[asset.Spot] = ¤cy.PairStore{
|
||||||
Available: currency.Pairs{cp},
|
Available: currency.Pairs{cp},
|
||||||
Enabled: currency.Pairs{cp},
|
Enabled: currency.Pairs{cp},
|
||||||
AssetEnabled: convert.BoolPtr(true),
|
AssetEnabled: true,
|
||||||
ConfigFormat: ¤cy.PairFormat{Uppercase: true},
|
ConfigFormat: ¤cy.PairFormat{Uppercase: true},
|
||||||
RequestFormat: ¤cy.PairFormat{Uppercase: true}}
|
RequestFormat: ¤cy.PairFormat{Uppercase: true}}
|
||||||
err = em.Add(exch)
|
err = em.Add(exch)
|
||||||
@@ -1452,7 +1451,7 @@ func TestGetOrder(t *testing.T) {
|
|||||||
b.CurrencyPairs.Pairs[asset.Spot] = ¤cy.PairStore{
|
b.CurrencyPairs.Pairs[asset.Spot] = ¤cy.PairStore{
|
||||||
Available: currency.Pairs{cp},
|
Available: currency.Pairs{cp},
|
||||||
Enabled: currency.Pairs{cp},
|
Enabled: currency.Pairs{cp},
|
||||||
AssetEnabled: convert.BoolPtr(true),
|
AssetEnabled: true,
|
||||||
ConfigFormat: ¤cy.PairFormat{Uppercase: true},
|
ConfigFormat: ¤cy.PairFormat{Uppercase: true},
|
||||||
RequestFormat: ¤cy.PairFormat{Uppercase: true}}
|
RequestFormat: ¤cy.PairFormat{Uppercase: true}}
|
||||||
err = em.Add(exch)
|
err = em.Add(exch)
|
||||||
@@ -1534,97 +1533,53 @@ func TestCheckVars(t *testing.T) {
|
|||||||
t.Parallel()
|
t.Parallel()
|
||||||
var e exchange.IBotExchange
|
var e exchange.IBotExchange
|
||||||
err := checkParams("Binance", e, asset.Spot, currency.NewPair(currency.BTC, currency.USDT))
|
err := checkParams("Binance", e, asset.Spot, currency.NewPair(currency.BTC, currency.USDT))
|
||||||
if !errors.Is(err, errExchangeNotLoaded) {
|
assert.ErrorIs(t, err, errExchangeNotLoaded, "checkParams should error correctly")
|
||||||
t.Errorf("expected %v, got %v", errExchangeNotLoaded, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
e = &binance.Binance{}
|
e = &binance.Binance{}
|
||||||
err = checkParams("Binance", e, asset.Spot, currency.NewPair(currency.BTC, currency.USDT))
|
err = checkParams("Binance", e, asset.Spot, currency.NewPair(currency.BTC, currency.USDT))
|
||||||
if !errors.Is(err, errExchangeNotEnabled) {
|
assert.ErrorIs(t, err, errExchangeNotEnabled, "checkParams should error correctly")
|
||||||
t.Errorf("expected %v, got %v", errExchangeNotEnabled, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
e.SetEnabled(true)
|
e.SetEnabled(true)
|
||||||
|
|
||||||
err = checkParams("Binance", e, asset.Spot, currency.NewPair(currency.BTC, currency.USDT))
|
err = checkParams("Binance", e, asset.Spot, currency.NewPair(currency.BTC, currency.USDT))
|
||||||
if !errors.Is(err, currency.ErrPairManagerNotInitialised) {
|
assert.ErrorIs(t, err, currency.ErrPairManagerNotInitialised, "checkParams should error correctly")
|
||||||
t.Errorf("expected %v, got %v", currency.ErrPairManagerNotInitialised, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt1 := currency.PairStore{
|
b := e.GetBase()
|
||||||
RequestFormat: ¤cy.PairFormat{Uppercase: true},
|
|
||||||
ConfigFormat: ¤cy.PairFormat{
|
for _, a := range []asset.Item{asset.Spot, asset.Margin, asset.CoinMarginedFutures, asset.USDTMarginedFutures} {
|
||||||
Delimiter: currency.DashDelimiter,
|
ps := currency.PairStore{
|
||||||
Uppercase: true,
|
AssetEnabled: true,
|
||||||
},
|
RequestFormat: ¤cy.PairFormat{Uppercase: true},
|
||||||
}
|
ConfigFormat: ¤cy.PairFormat{Delimiter: currency.DashDelimiter, Uppercase: true},
|
||||||
coinFutures := currency.PairStore{
|
}
|
||||||
RequestFormat: ¤cy.PairFormat{
|
switch a {
|
||||||
Uppercase: true,
|
case asset.CoinMarginedFutures:
|
||||||
Delimiter: currency.UnderscoreDelimiter,
|
ps.RequestFormat = ¤cy.PairFormat{Uppercase: true, Delimiter: currency.UnderscoreDelimiter}
|
||||||
},
|
ps.ConfigFormat = ¤cy.PairFormat{Uppercase: true, Delimiter: currency.UnderscoreDelimiter}
|
||||||
ConfigFormat: ¤cy.PairFormat{
|
case asset.USDTMarginedFutures:
|
||||||
Uppercase: true,
|
ps.ConfigFormat = ¤cy.PairFormat{Uppercase: true, Delimiter: currency.DashDelimiter}
|
||||||
Delimiter: currency.UnderscoreDelimiter,
|
}
|
||||||
},
|
require.NoError(t, b.SetAssetPairStore(a, ps), "SetAssetPairStore must not error")
|
||||||
}
|
|
||||||
usdtFutures := currency.PairStore{
|
|
||||||
RequestFormat: ¤cy.PairFormat{
|
|
||||||
Uppercase: true,
|
|
||||||
},
|
|
||||||
ConfigFormat: ¤cy.PairFormat{
|
|
||||||
Uppercase: true,
|
|
||||||
Delimiter: currency.DashDelimiter,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
err = e.GetBase().StoreAssetPairFormat(asset.Spot, fmt1)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
}
|
|
||||||
err = e.GetBase().StoreAssetPairFormat(asset.Margin, fmt1)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
}
|
|
||||||
err = e.GetBase().StoreAssetPairFormat(asset.CoinMarginedFutures, coinFutures)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
}
|
|
||||||
err = e.GetBase().StoreAssetPairFormat(asset.USDTMarginedFutures, usdtFutures)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
err = checkParams("Binance", e, asset.Spot, currency.NewPair(currency.BTC, currency.USDT))
|
err = checkParams("Binance", e, asset.Spot, currency.NewPair(currency.BTC, currency.USDT))
|
||||||
if !errors.Is(err, errCurrencyPairInvalid) {
|
assert.ErrorIs(t, err, errCurrencyPairInvalid, "checkParams should error correctly")
|
||||||
t.Errorf("expected %v, got %v", errCurrencyPairInvalid, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
var data = []currency.Pair{
|
var data = []currency.Pair{
|
||||||
{Delimiter: currency.DashDelimiter, Base: currency.BTC, Quote: currency.USDT},
|
{Delimiter: currency.DashDelimiter, Base: currency.BTC, Quote: currency.USDT},
|
||||||
}
|
}
|
||||||
|
|
||||||
err = e.GetBase().CurrencyPairs.StorePairs(asset.Spot, data, false)
|
err = b.CurrencyPairs.StorePairs(asset.Spot, data, false)
|
||||||
if err != nil {
|
require.NoError(t, err, "StorePairs must not error")
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = checkParams("Binance", e, asset.Spot, currency.NewPair(currency.BTC, currency.USDT))
|
err = checkParams("Binance", e, asset.Spot, currency.NewPair(currency.BTC, currency.USDT))
|
||||||
if !errors.Is(err, errCurrencyNotEnabled) {
|
require.ErrorIs(t, err, errCurrencyNotEnabled, "checkParams must error correctly")
|
||||||
t.Errorf("expected %v, got %v", errCurrencyNotEnabled, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = e.GetBase().CurrencyPairs.EnablePair(
|
err = b.CurrencyPairs.EnablePair(asset.Spot, currency.Pair{Delimiter: currency.DashDelimiter, Base: currency.BTC, Quote: currency.USDT})
|
||||||
asset.Spot,
|
require.NoError(t, err, "EnablePair must not error")
|
||||||
currency.Pair{Delimiter: currency.DashDelimiter, Base: currency.BTC, Quote: currency.USDT},
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = checkParams("Binance", e, asset.Spot, currency.NewPair(currency.BTC, currency.USDT))
|
err = checkParams("Binance", e, asset.Spot, currency.NewPair(currency.BTC, currency.USDT))
|
||||||
if err != nil {
|
require.NoError(t, err, "checkParams must not error")
|
||||||
t.Error(err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestParseEvents(t *testing.T) {
|
func TestParseEvents(t *testing.T) {
|
||||||
@@ -1704,7 +1659,7 @@ func TestRPCServerUpsertDataHistoryJob(t *testing.T) {
|
|||||||
b.CurrencyPairs.Pairs[asset.Spot] = ¤cy.PairStore{
|
b.CurrencyPairs.Pairs[asset.Spot] = ¤cy.PairStore{
|
||||||
Available: currency.Pairs{cp},
|
Available: currency.Pairs{cp},
|
||||||
Enabled: currency.Pairs{cp},
|
Enabled: currency.Pairs{cp},
|
||||||
AssetEnabled: convert.BoolPtr(true)}
|
AssetEnabled: true}
|
||||||
err = em.Add(exch)
|
err = em.Add(exch)
|
||||||
if !errors.Is(err, nil) {
|
if !errors.Is(err, nil) {
|
||||||
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
|
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
|
||||||
@@ -1974,7 +1929,7 @@ func TestGetManagedOrders(t *testing.T) {
|
|||||||
b.CurrencyPairs.Pairs[asset.Spot] = ¤cy.PairStore{
|
b.CurrencyPairs.Pairs[asset.Spot] = ¤cy.PairStore{
|
||||||
Available: currency.Pairs{cp},
|
Available: currency.Pairs{cp},
|
||||||
Enabled: currency.Pairs{cp},
|
Enabled: currency.Pairs{cp},
|
||||||
AssetEnabled: convert.BoolPtr(true),
|
AssetEnabled: true,
|
||||||
ConfigFormat: ¤cy.PairFormat{Uppercase: true},
|
ConfigFormat: ¤cy.PairFormat{Uppercase: true},
|
||||||
RequestFormat: ¤cy.PairFormat{Uppercase: true}}
|
RequestFormat: ¤cy.PairFormat{Uppercase: true}}
|
||||||
err = em.Add(exch)
|
err = em.Add(exch)
|
||||||
@@ -2277,7 +2232,7 @@ func TestCurrencyStateTradingPair(t *testing.T) {
|
|||||||
|
|
||||||
b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore)
|
b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore)
|
||||||
b.CurrencyPairs.Pairs[asset.Spot] = ¤cy.PairStore{
|
b.CurrencyPairs.Pairs[asset.Spot] = ¤cy.PairStore{
|
||||||
AssetEnabled: convert.BoolPtr(true),
|
AssetEnabled: true,
|
||||||
ConfigFormat: ¤cy.EMPTYFORMAT,
|
ConfigFormat: ¤cy.EMPTYFORMAT,
|
||||||
Available: currency.Pairs{cp},
|
Available: currency.Pairs{cp},
|
||||||
Enabled: currency.Pairs{cp},
|
Enabled: currency.Pairs{cp},
|
||||||
@@ -2323,14 +2278,14 @@ func TestGetFuturesPositionsOrders(t *testing.T) {
|
|||||||
|
|
||||||
b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore)
|
b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore)
|
||||||
b.CurrencyPairs.Pairs[asset.Futures] = ¤cy.PairStore{
|
b.CurrencyPairs.Pairs[asset.Futures] = ¤cy.PairStore{
|
||||||
AssetEnabled: convert.BoolPtr(true),
|
AssetEnabled: true,
|
||||||
RequestFormat: ¤cy.PairFormat{Delimiter: "-"},
|
RequestFormat: ¤cy.PairFormat{Delimiter: "-"},
|
||||||
ConfigFormat: ¤cy.PairFormat{Delimiter: "-"},
|
ConfigFormat: ¤cy.PairFormat{Delimiter: "-"},
|
||||||
Available: currency.Pairs{cp},
|
Available: currency.Pairs{cp},
|
||||||
Enabled: currency.Pairs{cp},
|
Enabled: currency.Pairs{cp},
|
||||||
}
|
}
|
||||||
b.CurrencyPairs.Pairs[asset.Spot] = ¤cy.PairStore{
|
b.CurrencyPairs.Pairs[asset.Spot] = ¤cy.PairStore{
|
||||||
AssetEnabled: convert.BoolPtr(true),
|
AssetEnabled: true,
|
||||||
ConfigFormat: ¤cy.PairFormat{Delimiter: "/"},
|
ConfigFormat: ¤cy.PairFormat{Delimiter: "/"},
|
||||||
RequestFormat: ¤cy.PairFormat{Delimiter: "/"},
|
RequestFormat: ¤cy.PairFormat{Delimiter: "/"},
|
||||||
Available: currency.Pairs{cp},
|
Available: currency.Pairs{cp},
|
||||||
@@ -2405,13 +2360,13 @@ func TestGetCollateral(t *testing.T) {
|
|||||||
|
|
||||||
b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore)
|
b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore)
|
||||||
b.CurrencyPairs.Pairs[asset.Futures] = ¤cy.PairStore{
|
b.CurrencyPairs.Pairs[asset.Futures] = ¤cy.PairStore{
|
||||||
AssetEnabled: convert.BoolPtr(true),
|
AssetEnabled: true,
|
||||||
ConfigFormat: ¤cy.EMPTYFORMAT,
|
ConfigFormat: ¤cy.EMPTYFORMAT,
|
||||||
Available: currency.Pairs{cp},
|
Available: currency.Pairs{cp},
|
||||||
Enabled: currency.Pairs{cp},
|
Enabled: currency.Pairs{cp},
|
||||||
}
|
}
|
||||||
b.CurrencyPairs.Pairs[asset.Spot] = ¤cy.PairStore{
|
b.CurrencyPairs.Pairs[asset.Spot] = ¤cy.PairStore{
|
||||||
AssetEnabled: convert.BoolPtr(true),
|
AssetEnabled: true,
|
||||||
ConfigFormat: ¤cy.EMPTYFORMAT,
|
ConfigFormat: ¤cy.EMPTYFORMAT,
|
||||||
Available: currency.Pairs{cp},
|
Available: currency.Pairs{cp},
|
||||||
Enabled: currency.Pairs{cp},
|
Enabled: currency.Pairs{cp},
|
||||||
@@ -2530,13 +2485,13 @@ func TestGetTechnicalAnalysis(t *testing.T) {
|
|||||||
|
|
||||||
b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore)
|
b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore)
|
||||||
b.CurrencyPairs.Pairs[asset.Futures] = ¤cy.PairStore{
|
b.CurrencyPairs.Pairs[asset.Futures] = ¤cy.PairStore{
|
||||||
AssetEnabled: convert.BoolPtr(true),
|
AssetEnabled: true,
|
||||||
ConfigFormat: ¤cy.PairFormat{},
|
ConfigFormat: ¤cy.PairFormat{},
|
||||||
Available: currency.Pairs{cp},
|
Available: currency.Pairs{cp},
|
||||||
Enabled: currency.Pairs{cp},
|
Enabled: currency.Pairs{cp},
|
||||||
}
|
}
|
||||||
b.CurrencyPairs.Pairs[asset.Spot] = ¤cy.PairStore{
|
b.CurrencyPairs.Pairs[asset.Spot] = ¤cy.PairStore{
|
||||||
AssetEnabled: convert.BoolPtr(true),
|
AssetEnabled: true,
|
||||||
ConfigFormat: ¤cy.PairFormat{},
|
ConfigFormat: ¤cy.PairFormat{},
|
||||||
Available: currency.Pairs{cp},
|
Available: currency.Pairs{cp},
|
||||||
Enabled: currency.Pairs{cp},
|
Enabled: currency.Pairs{cp},
|
||||||
@@ -2802,7 +2757,7 @@ func TestGetMarginRatesHistory(t *testing.T) {
|
|||||||
|
|
||||||
b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore)
|
b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore)
|
||||||
b.CurrencyPairs.Pairs[asset.Spot] = ¤cy.PairStore{
|
b.CurrencyPairs.Pairs[asset.Spot] = ¤cy.PairStore{
|
||||||
AssetEnabled: convert.BoolPtr(true),
|
AssetEnabled: true,
|
||||||
ConfigFormat: ¤cy.PairFormat{},
|
ConfigFormat: ¤cy.PairFormat{},
|
||||||
Available: currency.Pairs{cp},
|
Available: currency.Pairs{cp},
|
||||||
Enabled: currency.Pairs{cp},
|
Enabled: currency.Pairs{cp},
|
||||||
@@ -2945,7 +2900,7 @@ func TestGetFundingRates(t *testing.T) {
|
|||||||
|
|
||||||
b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore)
|
b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore)
|
||||||
err = b.CurrencyPairs.Store(asset.Futures, ¤cy.PairStore{
|
err = b.CurrencyPairs.Store(asset.Futures, ¤cy.PairStore{
|
||||||
AssetEnabled: convert.BoolPtr(true),
|
AssetEnabled: true,
|
||||||
RequestFormat: ¤cy.PairFormat{Delimiter: "-"},
|
RequestFormat: ¤cy.PairFormat{Delimiter: "-"},
|
||||||
ConfigFormat: ¤cy.PairFormat{Delimiter: "-"},
|
ConfigFormat: ¤cy.PairFormat{Delimiter: "-"},
|
||||||
Available: currency.Pairs{cp},
|
Available: currency.Pairs{cp},
|
||||||
@@ -2956,7 +2911,7 @@ func TestGetFundingRates(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
err = b.CurrencyPairs.Store(asset.Spot, ¤cy.PairStore{
|
err = b.CurrencyPairs.Store(asset.Spot, ¤cy.PairStore{
|
||||||
AssetEnabled: convert.BoolPtr(true),
|
AssetEnabled: true,
|
||||||
ConfigFormat: ¤cy.PairFormat{Delimiter: "/"},
|
ConfigFormat: ¤cy.PairFormat{Delimiter: "/"},
|
||||||
RequestFormat: ¤cy.PairFormat{Delimiter: "/"},
|
RequestFormat: ¤cy.PairFormat{Delimiter: "/"},
|
||||||
Available: currency.Pairs{cp},
|
Available: currency.Pairs{cp},
|
||||||
@@ -3053,7 +3008,7 @@ func TestGetLatestFundingRate(t *testing.T) {
|
|||||||
|
|
||||||
b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore)
|
b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore)
|
||||||
err = b.CurrencyPairs.Store(asset.Futures, ¤cy.PairStore{
|
err = b.CurrencyPairs.Store(asset.Futures, ¤cy.PairStore{
|
||||||
AssetEnabled: convert.BoolPtr(true),
|
AssetEnabled: true,
|
||||||
RequestFormat: ¤cy.PairFormat{Delimiter: "-"},
|
RequestFormat: ¤cy.PairFormat{Delimiter: "-"},
|
||||||
ConfigFormat: ¤cy.PairFormat{Delimiter: "-"},
|
ConfigFormat: ¤cy.PairFormat{Delimiter: "-"},
|
||||||
Available: currency.Pairs{cp},
|
Available: currency.Pairs{cp},
|
||||||
@@ -3063,7 +3018,7 @@ func TestGetLatestFundingRate(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
err = b.CurrencyPairs.Store(asset.Spot, ¤cy.PairStore{
|
err = b.CurrencyPairs.Store(asset.Spot, ¤cy.PairStore{
|
||||||
AssetEnabled: convert.BoolPtr(true),
|
AssetEnabled: true,
|
||||||
ConfigFormat: ¤cy.PairFormat{Delimiter: "/"},
|
ConfigFormat: ¤cy.PairFormat{Delimiter: "/"},
|
||||||
RequestFormat: ¤cy.PairFormat{Delimiter: "/"},
|
RequestFormat: ¤cy.PairFormat{Delimiter: "/"},
|
||||||
Available: currency.Pairs{cp},
|
Available: currency.Pairs{cp},
|
||||||
@@ -3158,14 +3113,14 @@ func TestGetManagedPosition(t *testing.T) {
|
|||||||
|
|
||||||
b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore)
|
b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore)
|
||||||
b.CurrencyPairs.Pairs[asset.Futures] = ¤cy.PairStore{
|
b.CurrencyPairs.Pairs[asset.Futures] = ¤cy.PairStore{
|
||||||
AssetEnabled: convert.BoolPtr(true),
|
AssetEnabled: true,
|
||||||
RequestFormat: ¤cy.PairFormat{Delimiter: "-"},
|
RequestFormat: ¤cy.PairFormat{Delimiter: "-"},
|
||||||
ConfigFormat: ¤cy.PairFormat{Delimiter: "-"},
|
ConfigFormat: ¤cy.PairFormat{Delimiter: "-"},
|
||||||
Available: currency.Pairs{cp, cp2},
|
Available: currency.Pairs{cp, cp2},
|
||||||
Enabled: currency.Pairs{cp, cp2},
|
Enabled: currency.Pairs{cp, cp2},
|
||||||
}
|
}
|
||||||
b.CurrencyPairs.Pairs[asset.Spot] = ¤cy.PairStore{
|
b.CurrencyPairs.Pairs[asset.Spot] = ¤cy.PairStore{
|
||||||
AssetEnabled: convert.BoolPtr(true),
|
AssetEnabled: true,
|
||||||
ConfigFormat: ¤cy.PairFormat{Delimiter: "/"},
|
ConfigFormat: ¤cy.PairFormat{Delimiter: "/"},
|
||||||
RequestFormat: ¤cy.PairFormat{Delimiter: "/"},
|
RequestFormat: ¤cy.PairFormat{Delimiter: "/"},
|
||||||
Available: currency.Pairs{cp, cp2},
|
Available: currency.Pairs{cp, cp2},
|
||||||
@@ -3301,14 +3256,14 @@ func TestGetAllManagedPositions(t *testing.T) {
|
|||||||
|
|
||||||
b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore)
|
b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore)
|
||||||
b.CurrencyPairs.Pairs[asset.Futures] = ¤cy.PairStore{
|
b.CurrencyPairs.Pairs[asset.Futures] = ¤cy.PairStore{
|
||||||
AssetEnabled: convert.BoolPtr(true),
|
AssetEnabled: true,
|
||||||
RequestFormat: ¤cy.PairFormat{Delimiter: "-"},
|
RequestFormat: ¤cy.PairFormat{Delimiter: "-"},
|
||||||
ConfigFormat: ¤cy.PairFormat{Delimiter: "-"},
|
ConfigFormat: ¤cy.PairFormat{Delimiter: "-"},
|
||||||
Available: currency.Pairs{cp, cp2},
|
Available: currency.Pairs{cp, cp2},
|
||||||
Enabled: currency.Pairs{cp, cp2},
|
Enabled: currency.Pairs{cp, cp2},
|
||||||
}
|
}
|
||||||
b.CurrencyPairs.Pairs[asset.Spot] = ¤cy.PairStore{
|
b.CurrencyPairs.Pairs[asset.Spot] = ¤cy.PairStore{
|
||||||
AssetEnabled: convert.BoolPtr(true),
|
AssetEnabled: true,
|
||||||
ConfigFormat: ¤cy.PairFormat{Delimiter: "/"},
|
ConfigFormat: ¤cy.PairFormat{Delimiter: "/"},
|
||||||
RequestFormat: ¤cy.PairFormat{Delimiter: "/"},
|
RequestFormat: ¤cy.PairFormat{Delimiter: "/"},
|
||||||
Available: currency.Pairs{cp, cp2},
|
Available: currency.Pairs{cp, cp2},
|
||||||
@@ -3407,7 +3362,7 @@ func TestGetOrderbookMovement(t *testing.T) {
|
|||||||
|
|
||||||
b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore)
|
b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore)
|
||||||
b.CurrencyPairs.Pairs[asset.Spot] = ¤cy.PairStore{
|
b.CurrencyPairs.Pairs[asset.Spot] = ¤cy.PairStore{
|
||||||
AssetEnabled: convert.BoolPtr(true),
|
AssetEnabled: true,
|
||||||
ConfigFormat: ¤cy.PairFormat{Delimiter: "/"},
|
ConfigFormat: ¤cy.PairFormat{Delimiter: "/"},
|
||||||
RequestFormat: ¤cy.PairFormat{Delimiter: "/"},
|
RequestFormat: ¤cy.PairFormat{Delimiter: "/"},
|
||||||
Available: currency.Pairs{cp},
|
Available: currency.Pairs{cp},
|
||||||
@@ -3520,7 +3475,7 @@ func TestGetOrderbookAmountByNominal(t *testing.T) {
|
|||||||
|
|
||||||
b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore)
|
b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore)
|
||||||
b.CurrencyPairs.Pairs[asset.Spot] = ¤cy.PairStore{
|
b.CurrencyPairs.Pairs[asset.Spot] = ¤cy.PairStore{
|
||||||
AssetEnabled: convert.BoolPtr(true),
|
AssetEnabled: true,
|
||||||
ConfigFormat: ¤cy.PairFormat{Delimiter: "/"},
|
ConfigFormat: ¤cy.PairFormat{Delimiter: "/"},
|
||||||
RequestFormat: ¤cy.PairFormat{Delimiter: "/"},
|
RequestFormat: ¤cy.PairFormat{Delimiter: "/"},
|
||||||
Available: currency.Pairs{cp},
|
Available: currency.Pairs{cp},
|
||||||
@@ -3626,7 +3581,7 @@ func TestGetOrderbookAmountByImpact(t *testing.T) {
|
|||||||
|
|
||||||
b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore)
|
b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore)
|
||||||
b.CurrencyPairs.Pairs[asset.Spot] = ¤cy.PairStore{
|
b.CurrencyPairs.Pairs[asset.Spot] = ¤cy.PairStore{
|
||||||
AssetEnabled: convert.BoolPtr(true),
|
AssetEnabled: true,
|
||||||
ConfigFormat: ¤cy.PairFormat{Delimiter: "/"},
|
ConfigFormat: ¤cy.PairFormat{Delimiter: "/"},
|
||||||
RequestFormat: ¤cy.PairFormat{Delimiter: "/"},
|
RequestFormat: ¤cy.PairFormat{Delimiter: "/"},
|
||||||
Available: currency.Pairs{cp},
|
Available: currency.Pairs{cp},
|
||||||
@@ -3734,7 +3689,7 @@ func TestChangePositionMargin(t *testing.T) {
|
|||||||
|
|
||||||
b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore)
|
b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore)
|
||||||
b.CurrencyPairs.Pairs[asset.USDTMarginedFutures] = ¤cy.PairStore{
|
b.CurrencyPairs.Pairs[asset.USDTMarginedFutures] = ¤cy.PairStore{
|
||||||
AssetEnabled: convert.BoolPtr(true),
|
AssetEnabled: true,
|
||||||
ConfigFormat: ¤cy.PairFormat{Delimiter: "/"},
|
ConfigFormat: ¤cy.PairFormat{Delimiter: "/"},
|
||||||
RequestFormat: ¤cy.PairFormat{Delimiter: "/"},
|
RequestFormat: ¤cy.PairFormat{Delimiter: "/"},
|
||||||
Available: currency.Pairs{cp},
|
Available: currency.Pairs{cp},
|
||||||
@@ -3797,7 +3752,7 @@ func TestSetLeverage(t *testing.T) {
|
|||||||
|
|
||||||
b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore)
|
b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore)
|
||||||
b.CurrencyPairs.Pairs[asset.USDTMarginedFutures] = ¤cy.PairStore{
|
b.CurrencyPairs.Pairs[asset.USDTMarginedFutures] = ¤cy.PairStore{
|
||||||
AssetEnabled: convert.BoolPtr(true),
|
AssetEnabled: true,
|
||||||
ConfigFormat: ¤cy.PairFormat{Delimiter: "/"},
|
ConfigFormat: ¤cy.PairFormat{Delimiter: "/"},
|
||||||
RequestFormat: ¤cy.PairFormat{Delimiter: "/"},
|
RequestFormat: ¤cy.PairFormat{Delimiter: "/"},
|
||||||
Available: currency.Pairs{cp},
|
Available: currency.Pairs{cp},
|
||||||
@@ -3875,7 +3830,7 @@ func TestGetLeverage(t *testing.T) {
|
|||||||
|
|
||||||
b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore)
|
b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore)
|
||||||
b.CurrencyPairs.Pairs[asset.USDTMarginedFutures] = ¤cy.PairStore{
|
b.CurrencyPairs.Pairs[asset.USDTMarginedFutures] = ¤cy.PairStore{
|
||||||
AssetEnabled: convert.BoolPtr(true),
|
AssetEnabled: true,
|
||||||
ConfigFormat: ¤cy.PairFormat{Delimiter: "/"},
|
ConfigFormat: ¤cy.PairFormat{Delimiter: "/"},
|
||||||
RequestFormat: ¤cy.PairFormat{Delimiter: "/"},
|
RequestFormat: ¤cy.PairFormat{Delimiter: "/"},
|
||||||
Available: currency.Pairs{cp},
|
Available: currency.Pairs{cp},
|
||||||
@@ -3955,7 +3910,7 @@ func TestSetMarginType(t *testing.T) {
|
|||||||
|
|
||||||
b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore)
|
b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore)
|
||||||
b.CurrencyPairs.Pairs[asset.USDTMarginedFutures] = ¤cy.PairStore{
|
b.CurrencyPairs.Pairs[asset.USDTMarginedFutures] = ¤cy.PairStore{
|
||||||
AssetEnabled: convert.BoolPtr(true),
|
AssetEnabled: true,
|
||||||
ConfigFormat: ¤cy.PairFormat{Delimiter: "/"},
|
ConfigFormat: ¤cy.PairFormat{Delimiter: "/"},
|
||||||
RequestFormat: ¤cy.PairFormat{Delimiter: "/"},
|
RequestFormat: ¤cy.PairFormat{Delimiter: "/"},
|
||||||
Available: currency.Pairs{cp},
|
Available: currency.Pairs{cp},
|
||||||
@@ -4015,7 +3970,7 @@ func TestSetCollateralMode(t *testing.T) {
|
|||||||
|
|
||||||
b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore)
|
b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore)
|
||||||
b.CurrencyPairs.Pairs[asset.USDTMarginedFutures] = ¤cy.PairStore{
|
b.CurrencyPairs.Pairs[asset.USDTMarginedFutures] = ¤cy.PairStore{
|
||||||
AssetEnabled: convert.BoolPtr(true),
|
AssetEnabled: true,
|
||||||
ConfigFormat: ¤cy.PairFormat{Delimiter: "/"},
|
ConfigFormat: ¤cy.PairFormat{Delimiter: "/"},
|
||||||
RequestFormat: ¤cy.PairFormat{Delimiter: "/"},
|
RequestFormat: ¤cy.PairFormat{Delimiter: "/"},
|
||||||
Available: currency.Pairs{cp},
|
Available: currency.Pairs{cp},
|
||||||
@@ -4064,7 +4019,7 @@ func TestGetCollateralMode(t *testing.T) {
|
|||||||
b.Enabled = true
|
b.Enabled = true
|
||||||
b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore)
|
b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore)
|
||||||
b.CurrencyPairs.Pairs[asset.USDTMarginedFutures] = ¤cy.PairStore{
|
b.CurrencyPairs.Pairs[asset.USDTMarginedFutures] = ¤cy.PairStore{
|
||||||
AssetEnabled: convert.BoolPtr(true),
|
AssetEnabled: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
fakeExchange := fExchange{
|
fakeExchange := fExchange{
|
||||||
@@ -4107,7 +4062,7 @@ func TestGetOpenInterest(t *testing.T) {
|
|||||||
b.Enabled = true
|
b.Enabled = true
|
||||||
b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore)
|
b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore)
|
||||||
b.CurrencyPairs.Pairs[asset.USDTMarginedFutures] = ¤cy.PairStore{
|
b.CurrencyPairs.Pairs[asset.USDTMarginedFutures] = ¤cy.PairStore{
|
||||||
AssetEnabled: convert.BoolPtr(true),
|
AssetEnabled: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
fakeExchange := fExchange{
|
fakeExchange := fExchange{
|
||||||
@@ -4288,7 +4243,7 @@ func TestGetCurrencyTradeURL(t *testing.T) {
|
|||||||
b.Enabled = true
|
b.Enabled = true
|
||||||
b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore)
|
b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore)
|
||||||
err = b.CurrencyPairs.Store(asset.Spot, ¤cy.PairStore{
|
err = b.CurrencyPairs.Store(asset.Spot, ¤cy.PairStore{
|
||||||
AssetEnabled: convert.BoolPtr(true),
|
AssetEnabled: true,
|
||||||
Enabled: []currency.Pair{currency.NewPair(currency.BTC, currency.USDT)},
|
Enabled: []currency.Pair{currency.NewPair(currency.BTC, currency.USDT)},
|
||||||
Available: []currency.Pair{currency.NewPair(currency.BTC, currency.USDT)},
|
Available: []currency.Pair{currency.NewPair(currency.BTC, currency.USDT)},
|
||||||
RequestFormat: ¤cy.PairFormat{Uppercase: true},
|
RequestFormat: ¤cy.PairFormat{Uppercase: true},
|
||||||
|
|||||||
@@ -36,6 +36,29 @@ import (
|
|||||||
"github.com/thrasher-corp/gocryptotrader/portfolio/withdraw"
|
"github.com/thrasher-corp/gocryptotrader/portfolio/withdraw"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var defaultAssetPairStores = map[asset.Item]currency.PairStore{
|
||||||
|
asset.Spot: {
|
||||||
|
AssetEnabled: true,
|
||||||
|
RequestFormat: ¤cy.PairFormat{Uppercase: true},
|
||||||
|
ConfigFormat: ¤cy.PairFormat{Delimiter: currency.DashDelimiter, Uppercase: true},
|
||||||
|
},
|
||||||
|
asset.Margin: {
|
||||||
|
AssetEnabled: true,
|
||||||
|
RequestFormat: ¤cy.PairFormat{Uppercase: true},
|
||||||
|
ConfigFormat: ¤cy.PairFormat{Delimiter: currency.DashDelimiter, Uppercase: true},
|
||||||
|
},
|
||||||
|
asset.CoinMarginedFutures: {
|
||||||
|
AssetEnabled: true,
|
||||||
|
RequestFormat: ¤cy.PairFormat{Uppercase: true, Delimiter: currency.UnderscoreDelimiter},
|
||||||
|
ConfigFormat: ¤cy.PairFormat{Uppercase: true, Delimiter: currency.UnderscoreDelimiter},
|
||||||
|
},
|
||||||
|
asset.USDTMarginedFutures: {
|
||||||
|
AssetEnabled: true,
|
||||||
|
RequestFormat: ¤cy.PairFormat{Uppercase: true},
|
||||||
|
ConfigFormat: ¤cy.PairFormat{Uppercase: true, Delimiter: currency.UnderscoreDelimiter},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
// SetDefaults sets the basic defaults for Binance
|
// SetDefaults sets the basic defaults for Binance
|
||||||
func (b *Binance) SetDefaults() {
|
func (b *Binance) SetDefaults() {
|
||||||
b.Name = "Binance"
|
b.Name = "Binance"
|
||||||
@@ -45,60 +68,18 @@ func (b *Binance) SetDefaults() {
|
|||||||
b.API.CredentialsValidator.RequiresSecret = true
|
b.API.CredentialsValidator.RequiresSecret = true
|
||||||
b.SetValues()
|
b.SetValues()
|
||||||
|
|
||||||
fmt1 := currency.PairStore{
|
for a, ps := range defaultAssetPairStores {
|
||||||
RequestFormat: ¤cy.PairFormat{Uppercase: true},
|
if err := b.SetAssetPairStore(a, ps); err != nil {
|
||||||
ConfigFormat: ¤cy.PairFormat{
|
log.Errorf(log.ExchangeSys, "%s error storing `%s` default asset formats: %s", b.Name, a, err)
|
||||||
Delimiter: currency.DashDelimiter,
|
}
|
||||||
Uppercase: true,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
coinFutures := currency.PairStore{
|
|
||||||
RequestFormat: ¤cy.PairFormat{
|
for _, a := range []asset.Item{asset.Margin, asset.CoinMarginedFutures, asset.USDTMarginedFutures} {
|
||||||
Uppercase: true,
|
if err := b.DisableAssetWebsocketSupport(a); err != nil {
|
||||||
Delimiter: currency.UnderscoreDelimiter,
|
log.Errorf(log.ExchangeSys, "%s error disabling `%s` asset type websocket support: %s", b.Name, a, err)
|
||||||
},
|
}
|
||||||
ConfigFormat: ¤cy.PairFormat{
|
|
||||||
Uppercase: true,
|
|
||||||
Delimiter: currency.UnderscoreDelimiter,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
usdtFutures := currency.PairStore{
|
|
||||||
RequestFormat: ¤cy.PairFormat{
|
|
||||||
Uppercase: true,
|
|
||||||
},
|
|
||||||
ConfigFormat: ¤cy.PairFormat{
|
|
||||||
Uppercase: true,
|
|
||||||
Delimiter: currency.UnderscoreDelimiter,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
err := b.StoreAssetPairFormat(asset.Spot, fmt1)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorln(log.ExchangeSys, err)
|
|
||||||
}
|
|
||||||
err = b.StoreAssetPairFormat(asset.Margin, fmt1)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorln(log.ExchangeSys, err)
|
|
||||||
}
|
|
||||||
err = b.DisableAssetWebsocketSupport(asset.Margin)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorln(log.ExchangeSys, err)
|
|
||||||
}
|
|
||||||
err = b.StoreAssetPairFormat(asset.CoinMarginedFutures, coinFutures)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorln(log.ExchangeSys, err)
|
|
||||||
}
|
|
||||||
err = b.DisableAssetWebsocketSupport(asset.CoinMarginedFutures)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorln(log.ExchangeSys, err)
|
|
||||||
}
|
|
||||||
err = b.StoreAssetPairFormat(asset.USDTMarginedFutures, usdtFutures)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorln(log.ExchangeSys, err)
|
|
||||||
}
|
|
||||||
err = b.DisableAssetWebsocketSupport(asset.USDTMarginedFutures)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorln(log.ExchangeSys, err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
b.Features = exchange.Features{
|
b.Features = exchange.Features{
|
||||||
Supports: exchange.FeaturesSupported{
|
Supports: exchange.FeaturesSupported{
|
||||||
REST: true,
|
REST: true,
|
||||||
@@ -196,6 +177,7 @@ func (b *Binance) SetDefaults() {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var err error
|
||||||
b.Requester, err = request.New(b.Name,
|
b.Requester, err = request.New(b.Name,
|
||||||
common.NewHTTPClientWithTimeout(exchange.DefaultHTTPTimeout),
|
common.NewHTTPClientWithTimeout(exchange.DefaultHTTPTimeout),
|
||||||
request.WithLimiter(GetRateLimits()))
|
request.WithLimiter(GetRateLimits()))
|
||||||
|
|||||||
@@ -40,15 +40,15 @@ func (bi *Binanceus) SetDefaults() {
|
|||||||
bi.SetValues()
|
bi.SetValues()
|
||||||
|
|
||||||
fmt1 := currency.PairStore{
|
fmt1 := currency.PairStore{
|
||||||
|
AssetEnabled: true,
|
||||||
RequestFormat: ¤cy.PairFormat{Uppercase: true},
|
RequestFormat: ¤cy.PairFormat{Uppercase: true},
|
||||||
ConfigFormat: ¤cy.PairFormat{
|
ConfigFormat: ¤cy.PairFormat{
|
||||||
Delimiter: currency.DashDelimiter,
|
Delimiter: currency.DashDelimiter,
|
||||||
Uppercase: true,
|
Uppercase: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
err := bi.StoreAssetPairFormat(asset.Spot, fmt1)
|
if err := bi.SetAssetPairStore(asset.Spot, fmt1); err != nil {
|
||||||
if err != nil {
|
log.Errorf(log.ExchangeSys, "%s error storing `spot` default asset formats: %s", bi.Name, err)
|
||||||
log.Errorln(log.ExchangeSys, err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bi.Features = exchange.Features{
|
bi.Features = exchange.Features{
|
||||||
@@ -122,6 +122,8 @@ func (bi *Binanceus) SetDefaults() {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var err error
|
||||||
bi.Requester, err = request.New(bi.Name,
|
bi.Requester, err = request.New(bi.Name,
|
||||||
common.NewHTTPClientWithTimeout(exchange.DefaultHTTPTimeout),
|
common.NewHTTPClientWithTimeout(exchange.DefaultHTTPTimeout),
|
||||||
request.WithLimiter(GetRateLimit()))
|
request.WithLimiter(GetRateLimit()))
|
||||||
|
|||||||
@@ -1148,15 +1148,23 @@ func TestGenerateSubscriptions(t *testing.T) {
|
|||||||
s := baseSub.Clone()
|
s := baseSub.Clone()
|
||||||
s.Asset = a
|
s.Asset = a
|
||||||
s.Pairs = currency.Pairs{p}
|
s.Pairs = currency.Pairs{p}
|
||||||
|
prefix := "t"
|
||||||
|
if a == asset.MarginFunding {
|
||||||
|
prefix = "f"
|
||||||
|
}
|
||||||
switch s.Channel {
|
switch s.Channel {
|
||||||
case subscription.TickerChannel:
|
case subscription.TickerChannel:
|
||||||
s.QualifiedChannel = `{"channel":"ticker","symbol":"t` + p.String() + `"}`
|
s.QualifiedChannel = `{"channel":"ticker","symbol":"` + prefix + p.String() + `"}`
|
||||||
case subscription.CandlesChannel:
|
case subscription.CandlesChannel:
|
||||||
s.QualifiedChannel = `{"channel":"candles","key":"trade:1m:t` + p.String() + `"}`
|
if a == asset.MarginFunding {
|
||||||
|
s.QualifiedChannel = `{"channel":"candles","key":"trade:1m:` + prefix + p.String() + `:p30"}`
|
||||||
|
} else {
|
||||||
|
s.QualifiedChannel = `{"channel":"candles","key":"trade:1m:` + prefix + p.String() + `"}`
|
||||||
|
}
|
||||||
case subscription.OrderbookChannel:
|
case subscription.OrderbookChannel:
|
||||||
s.QualifiedChannel = `{"channel":"book","len":100,"prec":"R0","symbol":"t` + p.String() + `"}`
|
s.QualifiedChannel = `{"channel":"book","len":100,"prec":"R0","symbol":"` + prefix + p.String() + `"}`
|
||||||
case subscription.AllTradesChannel:
|
case subscription.AllTradesChannel:
|
||||||
s.QualifiedChannel = `{"channel":"trades","symbol":"t` + p.String() + `"}`
|
s.QualifiedChannel = `{"channel":"trades","symbol":"` + prefix + p.String() + `"}`
|
||||||
}
|
}
|
||||||
exp = append(exp, s)
|
exp = append(exp, s)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,33 +41,23 @@ func (b *Bitfinex) SetDefaults() {
|
|||||||
b.API.CredentialsValidator.RequiresKey = true
|
b.API.CredentialsValidator.RequiresKey = true
|
||||||
b.API.CredentialsValidator.RequiresSecret = true
|
b.API.CredentialsValidator.RequiresSecret = true
|
||||||
|
|
||||||
fmt1 := currency.PairStore{
|
for _, a := range []asset.Item{asset.Spot, asset.Margin, asset.MarginFunding} {
|
||||||
RequestFormat: ¤cy.PairFormat{Uppercase: true},
|
ps := currency.PairStore{
|
||||||
ConfigFormat: ¤cy.PairFormat{Uppercase: true, Delimiter: currency.DashDelimiter},
|
AssetEnabled: true,
|
||||||
}
|
RequestFormat: ¤cy.PairFormat{Uppercase: true},
|
||||||
|
ConfigFormat: ¤cy.PairFormat{Uppercase: true, Delimiter: currency.DashDelimiter},
|
||||||
fmt2 := currency.PairStore{
|
}
|
||||||
RequestFormat: ¤cy.PairFormat{Uppercase: true},
|
if a == asset.Margin {
|
||||||
ConfigFormat: ¤cy.PairFormat{Uppercase: true, Delimiter: ":"},
|
ps.ConfigFormat.Delimiter = ":"
|
||||||
}
|
}
|
||||||
|
if err := b.SetAssetPairStore(a, ps); err != nil {
|
||||||
err := b.StoreAssetPairFormat(asset.Spot, fmt1)
|
log.Errorf(log.ExchangeSys, "%s error storing `%s` default asset formats: %s", b.Name, a, err)
|
||||||
if err != nil {
|
}
|
||||||
log.Errorln(log.ExchangeSys, err)
|
|
||||||
}
|
|
||||||
err = b.StoreAssetPairFormat(asset.Margin, fmt2)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorln(log.ExchangeSys, err)
|
|
||||||
}
|
|
||||||
err = b.StoreAssetPairFormat(asset.MarginFunding, fmt1)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorln(log.ExchangeSys, err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Margin WS Currently not fully implemented and causes subscription collisions with spot
|
// Margin WS Currently not fully implemented and causes subscription collisions with spot
|
||||||
err = b.DisableAssetWebsocketSupport(asset.Margin)
|
if err := b.DisableAssetWebsocketSupport(asset.Margin); err != nil {
|
||||||
if err != nil {
|
log.Errorf(log.ExchangeSys, "%s error disabling `%s` asset type websocket support: %s", b.Name, asset.Margin, err)
|
||||||
log.Errorln(log.ExchangeSys, err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Implement Futures and Securities asset types.
|
// TODO: Implement Futures and Securities asset types.
|
||||||
@@ -162,6 +152,7 @@ func (b *Bitfinex) SetDefaults() {
|
|||||||
Subscriptions: defaultSubscriptions.Clone(),
|
Subscriptions: defaultSubscriptions.Clone(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var err error
|
||||||
b.Requester, err = request.New(b.Name,
|
b.Requester, err = request.New(b.Name,
|
||||||
common.NewHTTPClientWithTimeout(exchange.DefaultHTTPTimeout),
|
common.NewHTTPClientWithTimeout(exchange.DefaultHTTPTimeout),
|
||||||
request.WithLimiter(GetRateLimit()))
|
request.WithLimiter(GetRateLimit()))
|
||||||
|
|||||||
@@ -42,37 +42,22 @@ func (b *Bitmex) SetDefaults() {
|
|||||||
b.API.CredentialsValidator.RequiresKey = true
|
b.API.CredentialsValidator.RequiresKey = true
|
||||||
b.API.CredentialsValidator.RequiresSecret = true
|
b.API.CredentialsValidator.RequiresSecret = true
|
||||||
|
|
||||||
configFmt := ¤cy.PairFormat{Uppercase: true, Delimiter: currency.DashDelimiter}
|
for _, a := range []asset.Item{asset.Spot, asset.PerpetualContract, asset.Futures, asset.Index} {
|
||||||
standardRequestFmt := ¤cy.PairFormat{Uppercase: true}
|
ps := currency.PairStore{
|
||||||
spotRequestFormat := ¤cy.PairFormat{Uppercase: true, Delimiter: currency.UnderscoreDelimiter}
|
AssetEnabled: true,
|
||||||
|
RequestFormat: ¤cy.PairFormat{Uppercase: true},
|
||||||
spot := currency.PairStore{RequestFormat: spotRequestFormat, ConfigFormat: configFmt}
|
ConfigFormat: ¤cy.PairFormat{Uppercase: true, Delimiter: currency.DashDelimiter},
|
||||||
err := b.StoreAssetPairFormat(asset.Spot, spot)
|
}
|
||||||
if err != nil {
|
if a == asset.Spot {
|
||||||
log.Errorln(log.ExchangeSys, err)
|
ps.RequestFormat.Delimiter = currency.UnderscoreDelimiter
|
||||||
|
}
|
||||||
|
if err := b.SetAssetPairStore(a, ps); err != nil {
|
||||||
|
log.Errorf(log.ExchangeSys, "%s error storing `%s` default asset formats: %s", b.Name, a, err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
perp := currency.PairStore{RequestFormat: standardRequestFmt, ConfigFormat: configFmt}
|
if err := b.DisableAssetWebsocketSupport(asset.Index); err != nil {
|
||||||
err = b.StoreAssetPairFormat(asset.PerpetualContract, perp)
|
log.Errorf(log.ExchangeSys, "%s error disabling `%s` asset type websocket support: %s", b.Name, asset.Index, err)
|
||||||
if err != nil {
|
|
||||||
log.Errorln(log.ExchangeSys, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
futures := currency.PairStore{RequestFormat: standardRequestFmt, ConfigFormat: configFmt}
|
|
||||||
err = b.StoreAssetPairFormat(asset.Futures, futures)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorln(log.ExchangeSys, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
index := currency.PairStore{RequestFormat: standardRequestFmt, ConfigFormat: configFmt}
|
|
||||||
err = b.StoreAssetPairFormat(asset.Index, index)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorln(log.ExchangeSys, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = b.DisableAssetWebsocketSupport(asset.Index)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorln(log.ExchangeSys, err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
b.Features = exchange.Features{
|
b.Features = exchange.Features{
|
||||||
@@ -139,6 +124,7 @@ func (b *Bitmex) SetDefaults() {
|
|||||||
Subscriptions: defaultSubscriptions.Clone(),
|
Subscriptions: defaultSubscriptions.Clone(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var err error
|
||||||
b.Requester, err = request.New(b.Name,
|
b.Requester, err = request.New(b.Name,
|
||||||
common.NewHTTPClientWithTimeout(exchange.DefaultHTTPTimeout),
|
common.NewHTTPClientWithTimeout(exchange.DefaultHTTPTimeout),
|
||||||
request.WithLimiter(GetRateLimit()))
|
request.WithLimiter(GetRateLimit()))
|
||||||
|
|||||||
@@ -45,33 +45,18 @@ func (b *BTSE) SetDefaults() {
|
|||||||
b.API.CredentialsValidator.RequiresKey = true
|
b.API.CredentialsValidator.RequiresKey = true
|
||||||
b.API.CredentialsValidator.RequiresSecret = true
|
b.API.CredentialsValidator.RequiresSecret = true
|
||||||
|
|
||||||
fmt1 := currency.PairStore{
|
for _, a := range []asset.Item{asset.Spot, asset.Futures} {
|
||||||
RequestFormat: ¤cy.PairFormat{
|
ps := currency.PairStore{
|
||||||
Uppercase: true,
|
AssetEnabled: true,
|
||||||
Delimiter: currency.DashDelimiter,
|
RequestFormat: ¤cy.PairFormat{Uppercase: true},
|
||||||
},
|
ConfigFormat: ¤cy.PairFormat{Uppercase: true, Delimiter: currency.DashDelimiter},
|
||||||
ConfigFormat: ¤cy.PairFormat{
|
}
|
||||||
Uppercase: true,
|
if a == asset.Spot {
|
||||||
Delimiter: currency.DashDelimiter,
|
ps.RequestFormat.Delimiter = currency.DashDelimiter
|
||||||
},
|
}
|
||||||
}
|
if err := b.SetAssetPairStore(a, ps); err != nil {
|
||||||
err := b.StoreAssetPairFormat(asset.Spot, fmt1)
|
log.Errorf(log.ExchangeSys, "%s error storing `%s` default asset formats: %s", b.Name, a, err)
|
||||||
if err != nil {
|
}
|
||||||
log.Errorln(log.ExchangeSys, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt2 := currency.PairStore{
|
|
||||||
RequestFormat: ¤cy.PairFormat{
|
|
||||||
Uppercase: true,
|
|
||||||
},
|
|
||||||
ConfigFormat: ¤cy.PairFormat{
|
|
||||||
Uppercase: true,
|
|
||||||
Delimiter: currency.DashDelimiter,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
err = b.StoreAssetPairFormat(asset.Futures, fmt2)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorln(log.ExchangeSys, err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
b.Features = exchange.Features{
|
b.Features = exchange.Features{
|
||||||
@@ -143,6 +128,7 @@ func (b *BTSE) SetDefaults() {
|
|||||||
Subscriptions: defaultSubscriptions.Clone(),
|
Subscriptions: defaultSubscriptions.Clone(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var err error
|
||||||
b.Requester, err = request.New(b.Name,
|
b.Requester, err = request.New(b.Name,
|
||||||
common.NewHTTPClientWithTimeout(exchange.DefaultHTTPTimeout),
|
common.NewHTTPClientWithTimeout(exchange.DefaultHTTPTimeout),
|
||||||
request.WithLimiter(GetRateLimit()))
|
request.WithLimiter(GetRateLimit()))
|
||||||
|
|||||||
@@ -61,15 +61,15 @@ func (by *Bybit) SetDefaults() {
|
|||||||
by.API.CredentialsValidator.RequiresSecret = true
|
by.API.CredentialsValidator.RequiresSecret = true
|
||||||
|
|
||||||
for _, n := range assetPairFmts {
|
for _, n := range assetPairFmts {
|
||||||
ps := currency.PairStore{RequestFormat: n.reqFmt, ConfigFormat: n.cfgFmt}
|
ps := currency.PairStore{AssetEnabled: true, RequestFormat: n.reqFmt, ConfigFormat: n.cfgFmt}
|
||||||
if err := by.StoreAssetPairFormat(n.asset, ps); err != nil {
|
if err := by.SetAssetPairStore(n.asset, ps); err != nil {
|
||||||
log.Errorf(log.ExchangeSys, "%v %v", n.asset, err)
|
log.Errorf(log.ExchangeSys, "%s error storing `%s` default asset formats: %s", by.Name, n.asset, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, a := range []asset.Item{asset.CoinMarginedFutures, asset.USDTMarginedFutures, asset.USDCMarginedFutures, asset.Options} {
|
for _, a := range []asset.Item{asset.CoinMarginedFutures, asset.USDTMarginedFutures, asset.USDCMarginedFutures, asset.Options} {
|
||||||
if err := by.DisableAssetWebsocketSupport(a); err != nil {
|
if err := by.DisableAssetWebsocketSupport(a); err != nil {
|
||||||
log.Errorln(log.ExchangeSys, err)
|
log.Errorf(log.ExchangeSys, "%s error disabling `%s` asset type websocket support: %s", by.Name, a, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -43,13 +43,12 @@ func (d *Deribit) SetDefaults() {
|
|||||||
|
|
||||||
dashFormat := ¤cy.PairFormat{Uppercase: true, Delimiter: currency.DashDelimiter}
|
dashFormat := ¤cy.PairFormat{Uppercase: true, Delimiter: currency.DashDelimiter}
|
||||||
underscoreFormat := ¤cy.PairFormat{Uppercase: true, Delimiter: currency.UnderscoreDelimiter}
|
underscoreFormat := ¤cy.PairFormat{Uppercase: true, Delimiter: currency.UnderscoreDelimiter}
|
||||||
err := d.StoreAssetPairFormat(asset.Spot, currency.PairStore{RequestFormat: underscoreFormat, ConfigFormat: underscoreFormat})
|
if err := d.SetAssetPairStore(asset.Spot, currency.PairStore{AssetEnabled: true, RequestFormat: underscoreFormat, ConfigFormat: underscoreFormat}); err != nil {
|
||||||
if err != nil {
|
log.Errorf(log.ExchangeSys, "%s error storing `%s` default asset formats: %s", d.Name, asset.Spot, err)
|
||||||
log.Errorln(log.ExchangeSys, err)
|
|
||||||
}
|
}
|
||||||
for _, assetType := range []asset.Item{asset.Futures, asset.Options, asset.OptionCombo, asset.FutureCombo} {
|
for _, a := range []asset.Item{asset.Futures, asset.Options, asset.OptionCombo, asset.FutureCombo} {
|
||||||
if err = d.StoreAssetPairFormat(assetType, currency.PairStore{RequestFormat: dashFormat, ConfigFormat: dashFormat}); err != nil {
|
if err := d.SetAssetPairStore(a, currency.PairStore{AssetEnabled: true, RequestFormat: dashFormat, ConfigFormat: dashFormat}); err != nil {
|
||||||
log.Errorln(log.ExchangeSys, err)
|
log.Errorf(log.ExchangeSys, "%s error storing `%s` default asset formats: %s", d.Name, a, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -128,6 +127,8 @@ func (d *Deribit) SetDefaults() {
|
|||||||
},
|
},
|
||||||
Subscriptions: defaultSubscriptions.Clone(),
|
Subscriptions: defaultSubscriptions.Clone(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var err error
|
||||||
d.Requester, err = request.New(d.Name,
|
d.Requester, err = request.New(d.Name,
|
||||||
common.NewHTTPClientWithTimeout(exchange.DefaultHTTPTimeout),
|
common.NewHTTPClientWithTimeout(exchange.DefaultHTTPTimeout),
|
||||||
request.WithLimiter(GetRateLimits()),
|
request.WithLimiter(GetRateLimits()),
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ import (
|
|||||||
"unicode"
|
"unicode"
|
||||||
|
|
||||||
"github.com/thrasher-corp/gocryptotrader/common"
|
"github.com/thrasher-corp/gocryptotrader/common"
|
||||||
"github.com/thrasher-corp/gocryptotrader/common/convert"
|
|
||||||
"github.com/thrasher-corp/gocryptotrader/common/key"
|
"github.com/thrasher-corp/gocryptotrader/common/key"
|
||||||
"github.com/thrasher-corp/gocryptotrader/config"
|
"github.com/thrasher-corp/gocryptotrader/config"
|
||||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||||
@@ -58,6 +57,7 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
errSetAssetPairStore = errors.New("error storing asset pair store")
|
||||||
errEndpointStringNotFound = errors.New("endpoint string not found")
|
errEndpointStringNotFound = errors.New("endpoint string not found")
|
||||||
errConfigPairFormatRequiresDelimiter = errors.New("config pair format requires delimiter")
|
errConfigPairFormatRequiresDelimiter = errors.New("config pair format requires delimiter")
|
||||||
errSetDefaultsNotCalled = errors.New("set defaults not called")
|
errSetDefaultsNotCalled = errors.New("set defaults not called")
|
||||||
@@ -309,68 +309,56 @@ func (b *Base) SetCurrencyPairFormat() error {
|
|||||||
func (b *Base) SetConfigPairs() error {
|
func (b *Base) SetConfigPairs() error {
|
||||||
assetTypes := b.Config.CurrencyPairs.GetAssetTypes(false)
|
assetTypes := b.Config.CurrencyPairs.GetAssetTypes(false)
|
||||||
exchangeAssets := b.CurrencyPairs.GetAssetTypes(false)
|
exchangeAssets := b.CurrencyPairs.GetAssetTypes(false)
|
||||||
for x := range assetTypes {
|
for _, a := range assetTypes {
|
||||||
if !exchangeAssets.Contains(assetTypes[x]) {
|
if !exchangeAssets.Contains(a) {
|
||||||
log.Warnf(log.ExchangeSys,
|
log.Warnf(log.ExchangeSys, "%s exchange asset type %s unsupported, please manually remove from configuration", b.Name, a)
|
||||||
"%s exchange asset type %s unsupported, please manually remove from configuration",
|
continue
|
||||||
b.Name,
|
}
|
||||||
assetTypes[x])
|
if !b.Config.CurrencyPairs.UseGlobalFormat {
|
||||||
continue // If there are unsupported assets contained in config, skip.
|
// TODO: Should be in SetCurrencyPairFormat. See #1748
|
||||||
|
if err := b.setConfigPairFormatFromExchange(a); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cfgPS, err := b.Config.CurrencyPairs.Get(a)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := b.CurrencyPairs.StorePairs(a, cfgPS.Available, false); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := b.CurrencyPairs.StorePairs(a, cfgPS.Enabled, true); err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
var enabledAsset bool
|
var enabledAsset bool
|
||||||
if b.Config.CurrencyPairs.IsAssetEnabled(assetTypes[x]) == nil {
|
if b.Config.CurrencyPairs.IsAssetEnabled(a) == nil {
|
||||||
enabledAsset = true
|
enabledAsset = true
|
||||||
}
|
}
|
||||||
|
|
||||||
err := b.CurrencyPairs.SetAssetEnabled(assetTypes[x], enabledAsset)
|
// Must happen after StorePairs, which would have enabled the asset automatically
|
||||||
// Suppress error when assets are enabled by default and they are being
|
if err := b.CurrencyPairs.SetAssetEnabled(a, enabledAsset); err != nil {
|
||||||
// enabled by config. A check for the inverse
|
|
||||||
// e.g. currency.ErrAssetAlreadyDisabled is not needed.
|
|
||||||
if err != nil && !errors.Is(err, currency.ErrAssetAlreadyEnabled) {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
cfgPS, err := b.Config.CurrencyPairs.Get(assetTypes[x])
|
// setConfigPairFormatFromExchange sets the config formats from the exchange's format
|
||||||
if err != nil {
|
// This deprecated behaviour will be removed, because config should not be backloaded from runtime
|
||||||
|
func (b *Base) setConfigPairFormatFromExchange(a asset.Item) error {
|
||||||
|
ps, err := b.CurrencyPairs.Get(a)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if ps.ConfigFormat != nil {
|
||||||
|
if err := b.Config.CurrencyPairs.StoreFormat(a, ps.ConfigFormat, true); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if b.Config.CurrencyPairs.UseGlobalFormat {
|
if ps.RequestFormat != nil {
|
||||||
err = b.CurrencyPairs.StorePairs(assetTypes[x], cfgPS.Available, false)
|
if err := b.Config.CurrencyPairs.StoreFormat(a, ps.RequestFormat, false); err != nil {
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
err = b.CurrencyPairs.StorePairs(assetTypes[x], cfgPS.Enabled, true)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
exchPS, err := b.CurrencyPairs.Get(assetTypes[x])
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if exchPS.ConfigFormat != nil {
|
|
||||||
err = b.Config.CurrencyPairs.StoreFormat(assetTypes[x], exchPS.ConfigFormat, true)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if exchPS.RequestFormat != nil {
|
|
||||||
err = b.Config.CurrencyPairs.StoreFormat(assetTypes[x], exchPS.RequestFormat, false)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
err = b.CurrencyPairs.StorePairs(assetTypes[x], cfgPS.Available, false)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
err = b.CurrencyPairs.StorePairs(assetTypes[x], cfgPS.Enabled, true)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -533,8 +521,7 @@ func (b *Base) IsEnabled() bool {
|
|||||||
|
|
||||||
// SetupDefaults sets the exchange settings based on the supplied config
|
// SetupDefaults sets the exchange settings based on the supplied config
|
||||||
func (b *Base) SetupDefaults(exch *config.Exchange) error {
|
func (b *Base) SetupDefaults(exch *config.Exchange) error {
|
||||||
err := exch.Validate()
|
if err := exch.Validate(); err != nil {
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -560,8 +547,7 @@ func (b *Base) SetupDefaults(exch *config.Exchange) error {
|
|||||||
exch.HTTPTimeout = DefaultHTTPTimeout
|
exch.HTTPTimeout = DefaultHTTPTimeout
|
||||||
}
|
}
|
||||||
|
|
||||||
err = b.SetHTTPClientTimeout(exch.HTTPTimeout)
|
if err := b.SetHTTPClientTimeout(exch.HTTPTimeout); err != nil {
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -569,8 +555,7 @@ func (b *Base) SetupDefaults(exch *config.Exchange) error {
|
|||||||
exch.CurrencyPairs = &b.CurrencyPairs
|
exch.CurrencyPairs = &b.CurrencyPairs
|
||||||
a := exch.CurrencyPairs.GetAssetTypes(false)
|
a := exch.CurrencyPairs.GetAssetTypes(false)
|
||||||
for i := range a {
|
for i := range a {
|
||||||
err = exch.CurrencyPairs.SetAssetEnabled(a[i], true)
|
if err := exch.CurrencyPairs.SetAssetEnabled(a[i], true); err != nil {
|
||||||
if err != nil && !errors.Is(err, currency.ErrAssetAlreadyEnabled) {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -578,18 +563,15 @@ func (b *Base) SetupDefaults(exch *config.Exchange) error {
|
|||||||
|
|
||||||
b.HTTPDebugging = exch.HTTPDebugging
|
b.HTTPDebugging = exch.HTTPDebugging
|
||||||
b.BypassConfigFormatUpgrades = exch.CurrencyPairs.BypassConfigFormatUpgrades
|
b.BypassConfigFormatUpgrades = exch.CurrencyPairs.BypassConfigFormatUpgrades
|
||||||
err = b.SetHTTPClientUserAgent(exch.HTTPUserAgent)
|
if err := b.SetHTTPClientUserAgent(exch.HTTPUserAgent); err != nil {
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = b.SetCurrencyPairFormat()
|
if err := b.SetCurrencyPairFormat(); err != nil {
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = b.SetConfigPairs()
|
if err := b.SetConfigPairs(); err != nil {
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -599,27 +581,26 @@ func (b *Base) SetupDefaults(exch *config.Exchange) error {
|
|||||||
b.API.Endpoints = b.NewEndpoints()
|
b.API.Endpoints = b.NewEndpoints()
|
||||||
}
|
}
|
||||||
|
|
||||||
err = b.SetAPIURL()
|
if err := b.SetAPIURL(); err != nil {
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
b.SetAPICredentialDefaults()
|
b.SetAPICredentialDefaults()
|
||||||
|
|
||||||
err = b.SetClientProxyAddress(exch.ProxyAddress)
|
if err := b.SetClientProxyAddress(exch.ProxyAddress); err != nil {
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
b.BaseCurrencies = exch.BaseCurrencies
|
b.BaseCurrencies = exch.BaseCurrencies
|
||||||
|
|
||||||
if exch.Orderbook.VerificationBypass {
|
if exch.Orderbook.VerificationBypass {
|
||||||
log.Warnf(log.ExchangeSys,
|
log.Warnf(log.ExchangeSys, "%s orderbook verification has been bypassed via config.", b.Name)
|
||||||
"%s orderbook verification has been bypassed via config.",
|
|
||||||
b.Name)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
b.CanVerifyOrderbook = !exch.Orderbook.VerificationBypass
|
b.CanVerifyOrderbook = !exch.Orderbook.VerificationBypass
|
||||||
b.States = currencystate.NewCurrencyStates()
|
b.States = currencystate.NewCurrencyStates()
|
||||||
return err
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetPairs sets the exchange currency pairs for either enabledPairs or
|
// SetPairs sets the exchange currency pairs for either enabledPairs or
|
||||||
@@ -1004,30 +985,18 @@ func (b *Base) EnableRateLimiter() error {
|
|||||||
return b.Requester.EnableRateLimiter()
|
return b.Requester.EnableRateLimiter()
|
||||||
}
|
}
|
||||||
|
|
||||||
// StoreAssetPairFormat initialises and stores a defined asset format
|
// SetAssetPairStore initialises and stores a defined asset format
|
||||||
func (b *Base) StoreAssetPairFormat(a asset.Item, f currency.PairStore) error {
|
func (b *Base) SetAssetPairStore(a asset.Item, f currency.PairStore) error {
|
||||||
if a.String() == "" {
|
if a.String() == "" {
|
||||||
return fmt.Errorf("%s cannot add to pairs manager, no asset provided",
|
return asset.ErrInvalidAsset
|
||||||
b.Name)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if f.AssetEnabled == nil {
|
if f.RequestFormat == nil || f.ConfigFormat == nil {
|
||||||
f.AssetEnabled = convert.BoolPtr(true)
|
return currency.ErrPairFormatIsNil
|
||||||
}
|
|
||||||
|
|
||||||
if f.RequestFormat == nil {
|
|
||||||
return fmt.Errorf("%s cannot add to pairs manager, request pair format not provided",
|
|
||||||
b.Name)
|
|
||||||
}
|
|
||||||
|
|
||||||
if f.ConfigFormat == nil {
|
|
||||||
return fmt.Errorf("%s cannot add to pairs manager, config pair format not provided",
|
|
||||||
b.Name)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if f.ConfigFormat.Delimiter == "" {
|
if f.ConfigFormat.Delimiter == "" {
|
||||||
return fmt.Errorf("exchange %s cannot set asset %s pair format %w",
|
return errConfigPairFormatRequiresDelimiter
|
||||||
b.Name, a, errConfigPairFormatRequiresDelimiter)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if b.CurrencyPairs.Pairs == nil {
|
if b.CurrencyPairs.Pairs == nil {
|
||||||
@@ -1035,6 +1004,7 @@ func (b *Base) StoreAssetPairFormat(a asset.Item, f currency.PairStore) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
b.CurrencyPairs.Pairs[a] = &f
|
b.CurrencyPairs.Pairs[a] = &f
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1076,7 +1046,7 @@ func (b *Base) SetGlobalPairsManager(request, config *currency.PairFormat, asset
|
|||||||
return fmt.Errorf("%s cannot set pairs manager, asset is empty string", b.Name)
|
return fmt.Errorf("%s cannot set pairs manager, asset is empty string", b.Name)
|
||||||
}
|
}
|
||||||
b.CurrencyPairs.Pairs[assets[i]] = new(currency.PairStore)
|
b.CurrencyPairs.Pairs[assets[i]] = new(currency.PairStore)
|
||||||
b.CurrencyPairs.Pairs[assets[i]].AssetEnabled = convert.BoolPtr(true)
|
b.CurrencyPairs.Pairs[assets[i]].AssetEnabled = true
|
||||||
b.CurrencyPairs.Pairs[assets[i]].ConfigFormat = config
|
b.CurrencyPairs.Pairs[assets[i]].ConfigFormat = config
|
||||||
b.CurrencyPairs.Pairs[assets[i]].RequestFormat = request
|
b.CurrencyPairs.Pairs[assets[i]].RequestFormat = request
|
||||||
}
|
}
|
||||||
@@ -1471,9 +1441,7 @@ func getURLTypeFromString(ep string) (URL, error) {
|
|||||||
// check availability of asset type.
|
// check availability of asset type.
|
||||||
func (b *Base) DisableAssetWebsocketSupport(aType asset.Item) error {
|
func (b *Base) DisableAssetWebsocketSupport(aType asset.Item) error {
|
||||||
if !b.SupportsAsset(aType) {
|
if !b.SupportsAsset(aType) {
|
||||||
return fmt.Errorf("%s %w",
|
return fmt.Errorf("%s %w", aType, asset.ErrNotSupported)
|
||||||
aType,
|
|
||||||
asset.ErrNotSupported)
|
|
||||||
}
|
}
|
||||||
b.AssetWebsocketSupport.m.Lock()
|
b.AssetWebsocketSupport.m.Lock()
|
||||||
if b.AssetWebsocketSupport.unsupported == nil {
|
if b.AssetWebsocketSupport.unsupported == nil {
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import (
|
|||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"github.com/thrasher-corp/gocryptotrader/common"
|
"github.com/thrasher-corp/gocryptotrader/common"
|
||||||
"github.com/thrasher-corp/gocryptotrader/common/convert"
|
|
||||||
"github.com/thrasher-corp/gocryptotrader/common/key"
|
"github.com/thrasher-corp/gocryptotrader/common/key"
|
||||||
"github.com/thrasher-corp/gocryptotrader/config"
|
"github.com/thrasher-corp/gocryptotrader/config"
|
||||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||||
@@ -536,7 +535,7 @@ func TestLoadConfigPairs(t *testing.T) {
|
|||||||
},
|
},
|
||||||
Pairs: map[asset.Item]*currency.PairStore{
|
Pairs: map[asset.Item]*currency.PairStore{
|
||||||
asset.Spot: {
|
asset.Spot: {
|
||||||
AssetEnabled: convert.BoolPtr(true),
|
AssetEnabled: true,
|
||||||
Enabled: pairs,
|
Enabled: pairs,
|
||||||
Available: pairs,
|
Available: pairs,
|
||||||
},
|
},
|
||||||
@@ -913,7 +912,7 @@ func TestSetPairs(t *testing.T) {
|
|||||||
},
|
},
|
||||||
Pairs: map[asset.Item]*currency.PairStore{
|
Pairs: map[asset.Item]*currency.PairStore{
|
||||||
asset.Spot: {
|
asset.Spot: {
|
||||||
AssetEnabled: convert.BoolPtr(true),
|
AssetEnabled: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -973,7 +972,7 @@ func TestUpdatePairs(t *testing.T) {
|
|||||||
CurrencyPairs: currency.PairsManager{
|
CurrencyPairs: currency.PairsManager{
|
||||||
Pairs: map[asset.Item]*currency.PairStore{
|
Pairs: map[asset.Item]*currency.PairStore{
|
||||||
asset.Spot: {
|
asset.Spot: {
|
||||||
AssetEnabled: convert.BoolPtr(true),
|
AssetEnabled: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ConfigFormat: ¤cy.PairFormat{Uppercase: true, Delimiter: currency.DashDelimiter},
|
ConfigFormat: ¤cy.PairFormat{Uppercase: true, Delimiter: currency.DashDelimiter},
|
||||||
@@ -1292,7 +1291,7 @@ func TestSupportsAsset(t *testing.T) {
|
|||||||
var b Base
|
var b Base
|
||||||
b.CurrencyPairs.Pairs = map[asset.Item]*currency.PairStore{
|
b.CurrencyPairs.Pairs = map[asset.Item]*currency.PairStore{
|
||||||
asset.Spot: {
|
asset.Spot: {
|
||||||
AssetEnabled: convert.BoolPtr(true),
|
AssetEnabled: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
assert.True(t, b.SupportsAsset(asset.Spot), "Spot should be supported")
|
assert.True(t, b.SupportsAsset(asset.Spot), "Spot should be supported")
|
||||||
@@ -1335,7 +1334,7 @@ func TestGetAssetType(t *testing.T) {
|
|||||||
}
|
}
|
||||||
b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore)
|
b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore)
|
||||||
b.CurrencyPairs.Pairs[asset.Spot] = ¤cy.PairStore{
|
b.CurrencyPairs.Pairs[asset.Spot] = ¤cy.PairStore{
|
||||||
AssetEnabled: convert.BoolPtr(true),
|
AssetEnabled: true,
|
||||||
Enabled: currency.Pairs{
|
Enabled: currency.Pairs{
|
||||||
currency.NewPair(currency.BTC, currency.USD),
|
currency.NewPair(currency.BTC, currency.USD),
|
||||||
},
|
},
|
||||||
@@ -1373,7 +1372,7 @@ func TestGetFormattedPairAndAssetType(t *testing.T) {
|
|||||||
b.CurrencyPairs.ConfigFormat = pFmt
|
b.CurrencyPairs.ConfigFormat = pFmt
|
||||||
b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore)
|
b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore)
|
||||||
b.CurrencyPairs.Pairs[asset.Spot] = ¤cy.PairStore{
|
b.CurrencyPairs.Pairs[asset.Spot] = ¤cy.PairStore{
|
||||||
AssetEnabled: convert.BoolPtr(true),
|
AssetEnabled: true,
|
||||||
Enabled: currency.Pairs{
|
Enabled: currency.Pairs{
|
||||||
currency.NewPair(currency.BTC, currency.USD),
|
currency.NewPair(currency.BTC, currency.USD),
|
||||||
},
|
},
|
||||||
@@ -1397,47 +1396,37 @@ func TestGetFormattedPairAndAssetType(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestStoreAssetPairFormat(t *testing.T) {
|
func TestSetAssetPairStore(t *testing.T) {
|
||||||
b := Base{
|
b := Base{
|
||||||
Config: &config.Exchange{Name: "kitties"},
|
Config: &config.Exchange{Name: "kitties"},
|
||||||
}
|
}
|
||||||
|
|
||||||
err := b.StoreAssetPairFormat(asset.Empty, currency.PairStore{})
|
err := b.SetAssetPairStore(asset.Empty, currency.PairStore{})
|
||||||
if err == nil {
|
assert.ErrorIs(t, err, asset.ErrInvalidAsset)
|
||||||
t.Error("error cannot be nil")
|
|
||||||
}
|
|
||||||
|
|
||||||
err = b.StoreAssetPairFormat(asset.Spot, currency.PairStore{})
|
err = b.SetAssetPairStore(asset.Spot, currency.PairStore{})
|
||||||
if err == nil {
|
assert.ErrorIs(t, err, currency.ErrPairFormatIsNil)
|
||||||
t.Error("error cannot be nil")
|
|
||||||
}
|
|
||||||
|
|
||||||
err = b.StoreAssetPairFormat(asset.Spot, currency.PairStore{
|
err = b.SetAssetPairStore(asset.Spot, currency.PairStore{RequestFormat: ¤cy.PairFormat{Uppercase: true}})
|
||||||
RequestFormat: ¤cy.PairFormat{Uppercase: true}})
|
assert.ErrorIs(t, err, currency.ErrPairFormatIsNil)
|
||||||
if err == nil {
|
|
||||||
t.Error("error cannot be nil")
|
|
||||||
}
|
|
||||||
|
|
||||||
err = b.StoreAssetPairFormat(asset.Spot, currency.PairStore{
|
err = b.SetAssetPairStore(asset.Spot, currency.PairStore{
|
||||||
RequestFormat: ¤cy.PairFormat{Uppercase: true},
|
RequestFormat: ¤cy.PairFormat{Uppercase: true},
|
||||||
ConfigFormat: ¤cy.PairFormat{Uppercase: true}})
|
ConfigFormat: ¤cy.PairFormat{Uppercase: true}})
|
||||||
if !errors.Is(err, errConfigPairFormatRequiresDelimiter) {
|
assert.ErrorIs(t, err, errConfigPairFormatRequiresDelimiter)
|
||||||
t.Fatalf("received: '%v' but expected: '%v'", err, errConfigPairFormatRequiresDelimiter)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = b.StoreAssetPairFormat(asset.Futures, currency.PairStore{
|
err = b.SetAssetPairStore(asset.Futures, currency.PairStore{
|
||||||
RequestFormat: ¤cy.PairFormat{Uppercase: true},
|
RequestFormat: ¤cy.PairFormat{Uppercase: true},
|
||||||
ConfigFormat: ¤cy.PairFormat{Uppercase: true, Delimiter: currency.DashDelimiter}})
|
ConfigFormat: ¤cy.PairFormat{Uppercase: true, Delimiter: currency.DashDelimiter}})
|
||||||
if err != nil {
|
assert.NoError(t, err)
|
||||||
t.Error(err)
|
assert.False(t, b.CurrencyPairs.Pairs[asset.Futures].AssetEnabled, "SetAssetPairStore should not magically enable AssetTypes")
|
||||||
}
|
|
||||||
|
|
||||||
err = b.StoreAssetPairFormat(asset.Futures, currency.PairStore{
|
err = b.SetAssetPairStore(asset.Futures, currency.PairStore{
|
||||||
|
AssetEnabled: true,
|
||||||
RequestFormat: ¤cy.PairFormat{Uppercase: true},
|
RequestFormat: ¤cy.PairFormat{Uppercase: true},
|
||||||
ConfigFormat: ¤cy.PairFormat{Uppercase: true, Delimiter: currency.DashDelimiter}})
|
ConfigFormat: ¤cy.PairFormat{Uppercase: true, Delimiter: currency.DashDelimiter}})
|
||||||
if err != nil {
|
assert.NoError(t, err)
|
||||||
t.Error(err)
|
assert.True(t, b.CurrencyPairs.Pairs[asset.Futures].AssetEnabled, "AssetEnabled should be respected")
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSetGlobalPairsManager(t *testing.T) {
|
func TestSetGlobalPairsManager(t *testing.T) {
|
||||||
@@ -1518,7 +1507,7 @@ func TestBase_ValidateKline(t *testing.T) {
|
|||||||
CurrencyPairs: currency.PairsManager{
|
CurrencyPairs: currency.PairsManager{
|
||||||
Pairs: map[asset.Item]*currency.PairStore{
|
Pairs: map[asset.Item]*currency.PairStore{
|
||||||
asset.Spot: {
|
asset.Spot: {
|
||||||
AssetEnabled: convert.BoolPtr(true),
|
AssetEnabled: true,
|
||||||
Enabled: pairs,
|
Enabled: pairs,
|
||||||
Available: availablePairs,
|
Available: availablePairs,
|
||||||
},
|
},
|
||||||
@@ -1797,7 +1786,7 @@ func TestFormatSymbol(t *testing.T) {
|
|||||||
Uppercase: true,
|
Uppercase: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
err := b.StoreAssetPairFormat(asset.Spot, spotStore)
|
err := b.SetAssetPairStore(asset.Spot, spotStore)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
@@ -1909,7 +1898,7 @@ func TestAssetWebsocketFunctionality(t *testing.T) {
|
|||||||
t.Fatalf("expected error: %v but received: %v", asset.ErrNotSupported, err)
|
t.Fatalf("expected error: %v but received: %v", asset.ErrNotSupported, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = b.StoreAssetPairFormat(asset.Spot, currency.PairStore{
|
err = b.SetAssetPairStore(asset.Spot, currency.PairStore{
|
||||||
RequestFormat: ¤cy.PairFormat{
|
RequestFormat: ¤cy.PairFormat{
|
||||||
Uppercase: true,
|
Uppercase: true,
|
||||||
},
|
},
|
||||||
@@ -2122,14 +2111,14 @@ func TestGetPairAndAssetTypeRequestFormatted(t *testing.T) {
|
|||||||
CurrencyPairs: currency.PairsManager{
|
CurrencyPairs: currency.PairsManager{
|
||||||
Pairs: map[asset.Item]*currency.PairStore{
|
Pairs: map[asset.Item]*currency.PairStore{
|
||||||
asset.Spot: {
|
asset.Spot: {
|
||||||
AssetEnabled: convert.BoolPtr(true),
|
AssetEnabled: true,
|
||||||
Enabled: enabledPairs,
|
Enabled: enabledPairs,
|
||||||
Available: availablePairs,
|
Available: availablePairs,
|
||||||
RequestFormat: ¤cy.PairFormat{Delimiter: "-", Uppercase: true},
|
RequestFormat: ¤cy.PairFormat{Delimiter: "-", Uppercase: true},
|
||||||
ConfigFormat: ¤cy.EMPTYFORMAT,
|
ConfigFormat: ¤cy.EMPTYFORMAT,
|
||||||
},
|
},
|
||||||
asset.PerpetualContract: {
|
asset.PerpetualContract: {
|
||||||
AssetEnabled: convert.BoolPtr(true),
|
AssetEnabled: true,
|
||||||
Enabled: enabledPairs,
|
Enabled: enabledPairs,
|
||||||
Available: availablePairs,
|
Available: availablePairs,
|
||||||
RequestFormat: ¤cy.PairFormat{Delimiter: "_", Uppercase: true},
|
RequestFormat: ¤cy.PairFormat{Delimiter: "_", Uppercase: true},
|
||||||
@@ -2265,7 +2254,7 @@ func TestGetKlineRequest(t *testing.T) {
|
|||||||
|
|
||||||
b.Features.Enabled.Kline.Intervals = kline.DeployExchangeIntervals(kline.IntervalCapacity{Interval: kline.OneDay, Capacity: 1439})
|
b.Features.Enabled.Kline.Intervals = kline.DeployExchangeIntervals(kline.IntervalCapacity{Interval: kline.OneDay, Capacity: 1439})
|
||||||
err = b.CurrencyPairs.Store(asset.Spot, ¤cy.PairStore{
|
err = b.CurrencyPairs.Store(asset.Spot, ¤cy.PairStore{
|
||||||
AssetEnabled: convert.BoolPtr(true),
|
AssetEnabled: true,
|
||||||
Enabled: []currency.Pair{pair},
|
Enabled: []currency.Pair{pair},
|
||||||
Available: []currency.Pair{pair},
|
Available: []currency.Pair{pair},
|
||||||
})
|
})
|
||||||
@@ -2289,7 +2278,7 @@ func TestGetKlineRequest(t *testing.T) {
|
|||||||
assert.ErrorIs(t, err, currency.ErrPairFormatIsNil, "GetKlineRequest should return Format is Nil")
|
assert.ErrorIs(t, err, currency.ErrPairFormatIsNil, "GetKlineRequest should return Format is Nil")
|
||||||
|
|
||||||
err = b.CurrencyPairs.Store(asset.Spot, ¤cy.PairStore{
|
err = b.CurrencyPairs.Store(asset.Spot, ¤cy.PairStore{
|
||||||
AssetEnabled: convert.BoolPtr(true),
|
AssetEnabled: true,
|
||||||
Enabled: []currency.Pair{pair},
|
Enabled: []currency.Pair{pair},
|
||||||
Available: []currency.Pair{pair},
|
Available: []currency.Pair{pair},
|
||||||
RequestFormat: ¤cy.PairFormat{Uppercase: true},
|
RequestFormat: ¤cy.PairFormat{Uppercase: true},
|
||||||
@@ -2316,7 +2305,7 @@ func TestGetKlineRequest(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
err = b.CurrencyPairs.Store(asset.Futures, ¤cy.PairStore{
|
err = b.CurrencyPairs.Store(asset.Futures, ¤cy.PairStore{
|
||||||
AssetEnabled: convert.BoolPtr(true),
|
AssetEnabled: true,
|
||||||
Enabled: []currency.Pair{pair},
|
Enabled: []currency.Pair{pair},
|
||||||
Available: []currency.Pair{pair},
|
Available: []currency.Pair{pair},
|
||||||
RequestFormat: ¤cy.PairFormat{Uppercase: true},
|
RequestFormat: ¤cy.PairFormat{Uppercase: true},
|
||||||
@@ -2442,7 +2431,7 @@ func TestGetKlineExtendedRequest(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
err = b.CurrencyPairs.Store(asset.Spot, ¤cy.PairStore{
|
err = b.CurrencyPairs.Store(asset.Spot, ¤cy.PairStore{
|
||||||
AssetEnabled: convert.BoolPtr(true),
|
AssetEnabled: true,
|
||||||
Enabled: []currency.Pair{pair},
|
Enabled: []currency.Pair{pair},
|
||||||
Available: []currency.Pair{pair},
|
Available: []currency.Pair{pair},
|
||||||
})
|
})
|
||||||
@@ -2454,7 +2443,7 @@ func TestGetKlineExtendedRequest(t *testing.T) {
|
|||||||
assert.ErrorIs(t, err, currency.ErrPairFormatIsNil, "GetKlineExtendedRequest should error correctly")
|
assert.ErrorIs(t, err, currency.ErrPairFormatIsNil, "GetKlineExtendedRequest should error correctly")
|
||||||
|
|
||||||
err = b.CurrencyPairs.Store(asset.Spot, ¤cy.PairStore{
|
err = b.CurrencyPairs.Store(asset.Spot, ¤cy.PairStore{
|
||||||
AssetEnabled: convert.BoolPtr(true),
|
AssetEnabled: true,
|
||||||
Enabled: []currency.Pair{pair},
|
Enabled: []currency.Pair{pair},
|
||||||
Available: []currency.Pair{pair},
|
Available: []currency.Pair{pair},
|
||||||
RequestFormat: ¤cy.PairFormat{Uppercase: true},
|
RequestFormat: ¤cy.PairFormat{Uppercase: true},
|
||||||
@@ -2573,7 +2562,7 @@ func TestEnsureOnePairEnabled(t *testing.T) {
|
|||||||
Pairs: map[asset.Item]*currency.PairStore{
|
Pairs: map[asset.Item]*currency.PairStore{
|
||||||
asset.Futures: {},
|
asset.Futures: {},
|
||||||
asset.Spot: {
|
asset.Spot: {
|
||||||
AssetEnabled: convert.BoolPtr(true),
|
AssetEnabled: true,
|
||||||
Available: []currency.Pair{
|
Available: []currency.Pair{
|
||||||
currency.NewPair(currency.BTC, currency.USDT),
|
currency.NewPair(currency.BTC, currency.USDT),
|
||||||
},
|
},
|
||||||
@@ -2646,7 +2635,7 @@ func TestMatchSymbolWithAvailablePairs(t *testing.T) {
|
|||||||
b := Base{Name: "test"}
|
b := Base{Name: "test"}
|
||||||
whatIWant := currency.NewPair(currency.BTC, currency.USDT)
|
whatIWant := currency.NewPair(currency.BTC, currency.USDT)
|
||||||
err := b.CurrencyPairs.Store(asset.Spot, ¤cy.PairStore{
|
err := b.CurrencyPairs.Store(asset.Spot, ¤cy.PairStore{
|
||||||
AssetEnabled: convert.BoolPtr(true),
|
AssetEnabled: true,
|
||||||
Available: []currency.Pair{whatIWant}})
|
Available: []currency.Pair{whatIWant}})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@@ -2682,7 +2671,7 @@ func TestMatchSymbolCheckEnabled(t *testing.T) {
|
|||||||
whatIWant := currency.NewPair(currency.BTC, currency.USDT)
|
whatIWant := currency.NewPair(currency.BTC, currency.USDT)
|
||||||
availButNoEnabled := currency.NewPair(currency.BTC, currency.AUD)
|
availButNoEnabled := currency.NewPair(currency.BTC, currency.AUD)
|
||||||
err := b.CurrencyPairs.Store(asset.Spot, ¤cy.PairStore{
|
err := b.CurrencyPairs.Store(asset.Spot, ¤cy.PairStore{
|
||||||
AssetEnabled: convert.BoolPtr(true),
|
AssetEnabled: true,
|
||||||
Available: []currency.Pair{whatIWant, availButNoEnabled},
|
Available: []currency.Pair{whatIWant, availButNoEnabled},
|
||||||
Enabled: []currency.Pair{whatIWant},
|
Enabled: []currency.Pair{whatIWant},
|
||||||
})
|
})
|
||||||
@@ -2741,7 +2730,7 @@ func TestIsPairEnabled(t *testing.T) {
|
|||||||
whatIWant := currency.NewPair(currency.BTC, currency.USDT)
|
whatIWant := currency.NewPair(currency.BTC, currency.USDT)
|
||||||
availButNoEnabled := currency.NewPair(currency.BTC, currency.AUD)
|
availButNoEnabled := currency.NewPair(currency.BTC, currency.AUD)
|
||||||
err := b.CurrencyPairs.Store(asset.Spot, ¤cy.PairStore{
|
err := b.CurrencyPairs.Store(asset.Spot, ¤cy.PairStore{
|
||||||
AssetEnabled: convert.BoolPtr(true),
|
AssetEnabled: true,
|
||||||
Available: []currency.Pair{whatIWant, availButNoEnabled},
|
Available: []currency.Pair{whatIWant, availButNoEnabled},
|
||||||
Enabled: []currency.Pair{whatIWant},
|
Enabled: []currency.Pair{whatIWant},
|
||||||
})
|
})
|
||||||
@@ -3130,3 +3119,20 @@ func TestGetTradingRequirements(t *testing.T) {
|
|||||||
requirements = (&Base{Features: Features{TradingRequirements: protocol.TradingRequirements{ClientOrderID: true}}}).GetTradingRequirements()
|
requirements = (&Base{Features: Features{TradingRequirements: protocol.TradingRequirements{ClientOrderID: true}}}).GetTradingRequirements()
|
||||||
require.NotEmpty(t, requirements)
|
require.NotEmpty(t, requirements)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSetConfigPairFormatFromExchange(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
b := Base{Config: &config.Exchange{CurrencyPairs: ¤cy.PairsManager{}}}
|
||||||
|
err := b.setConfigPairFormatFromExchange(asset.Spot)
|
||||||
|
assert.ErrorIs(t, err, asset.ErrNotSupported, "setConfigPairFormatFromExchange should error correctly without pairs")
|
||||||
|
err = b.CurrencyPairs.Store(asset.Spot, ¤cy.PairStore{
|
||||||
|
Enabled: currency.Pairs{btcusdPair},
|
||||||
|
ConfigFormat: ¤cy.PairFormat{Delimiter: "🐋"},
|
||||||
|
RequestFormat: ¤cy.PairFormat{Delimiter: "🦥"},
|
||||||
|
})
|
||||||
|
require.NoError(t, err, "CurrencyPairs.Store must not error")
|
||||||
|
err = b.setConfigPairFormatFromExchange(asset.Spot)
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Equal(t, "🐋", b.Config.CurrencyPairs.Pairs[asset.Spot].ConfigFormat.Delimiter, "ConfigFormat should be correct and have a blow hole")
|
||||||
|
assert.Equal(t, "🦥", b.Config.CurrencyPairs.Pairs[asset.Spot].RequestFormat.Delimiter, "RequestFormat should be correct and kinda lazy")
|
||||||
|
}
|
||||||
|
|||||||
@@ -41,47 +41,25 @@ func (h *HUOBI) SetDefaults() {
|
|||||||
h.API.CredentialsValidator.RequiresKey = true
|
h.API.CredentialsValidator.RequiresKey = true
|
||||||
h.API.CredentialsValidator.RequiresSecret = true
|
h.API.CredentialsValidator.RequiresSecret = true
|
||||||
|
|
||||||
fmt1 := currency.PairStore{
|
for _, a := range []asset.Item{asset.Spot, asset.CoinMarginedFutures, asset.Futures} {
|
||||||
RequestFormat: ¤cy.PairFormat{Uppercase: false},
|
ps := currency.PairStore{
|
||||||
ConfigFormat: ¤cy.PairFormat{
|
AssetEnabled: true,
|
||||||
Delimiter: currency.DashDelimiter,
|
RequestFormat: ¤cy.PairFormat{Uppercase: true},
|
||||||
Uppercase: true,
|
ConfigFormat: ¤cy.PairFormat{Uppercase: true, Delimiter: currency.DashDelimiter},
|
||||||
},
|
}
|
||||||
}
|
switch a {
|
||||||
coinFutures := currency.PairStore{
|
case asset.Spot:
|
||||||
RequestFormat: ¤cy.PairFormat{
|
ps.RequestFormat.Uppercase = false
|
||||||
Uppercase: true,
|
case asset.CoinMarginedFutures:
|
||||||
Delimiter: currency.DashDelimiter,
|
ps.RequestFormat.Delimiter = currency.DashDelimiter
|
||||||
},
|
}
|
||||||
ConfigFormat: ¤cy.PairFormat{
|
if err := h.SetAssetPairStore(a, ps); err != nil {
|
||||||
Uppercase: true,
|
log.Errorf(log.ExchangeSys, "%s error storing `%s` default asset formats: %s", h.Name, a, err)
|
||||||
Delimiter: currency.DashDelimiter,
|
}
|
||||||
},
|
|
||||||
}
|
|
||||||
futuresFormatting := currency.PairStore{
|
|
||||||
RequestFormat: ¤cy.PairFormat{
|
|
||||||
Uppercase: true,
|
|
||||||
},
|
|
||||||
ConfigFormat: ¤cy.PairFormat{
|
|
||||||
Uppercase: true,
|
|
||||||
Delimiter: currency.DashDelimiter,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
err := h.StoreAssetPairFormat(asset.Spot, fmt1)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorln(log.ExchangeSys, err)
|
|
||||||
}
|
|
||||||
err = h.StoreAssetPairFormat(asset.CoinMarginedFutures, coinFutures)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorln(log.ExchangeSys, err)
|
|
||||||
}
|
|
||||||
err = h.StoreAssetPairFormat(asset.Futures, futuresFormatting)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorln(log.ExchangeSys, err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, a := range []asset.Item{asset.Futures, asset.CoinMarginedFutures} {
|
for _, a := range []asset.Item{asset.Futures, asset.CoinMarginedFutures} {
|
||||||
if err = h.DisableAssetWebsocketSupport(a); err != nil {
|
if err := h.DisableAssetWebsocketSupport(a); err != nil {
|
||||||
log.Errorf(log.ExchangeSys, "%s error disabling `%s` asset type websocket support: %s", h.Name, a, err)
|
log.Errorf(log.ExchangeSys, "%s error disabling `%s` asset type websocket support: %s", h.Name, a, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -171,6 +149,7 @@ func (h *HUOBI) SetDefaults() {
|
|||||||
Subscriptions: defaultSubscriptions.Clone(),
|
Subscriptions: defaultSubscriptions.Clone(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var err error
|
||||||
h.Requester, err = request.New(h.Name,
|
h.Requester, err = request.New(h.Name,
|
||||||
common.NewHTTPClientWithTimeout(exchange.DefaultHTTPTimeout),
|
common.NewHTTPClientWithTimeout(exchange.DefaultHTTPTimeout),
|
||||||
request.WithLimiter(GetRateLimit()))
|
request.WithLimiter(GetRateLimit()))
|
||||||
|
|||||||
@@ -43,42 +43,22 @@ func (k *Kraken) SetDefaults() {
|
|||||||
k.API.CredentialsValidator.RequiresSecret = true
|
k.API.CredentialsValidator.RequiresSecret = true
|
||||||
k.API.CredentialsValidator.RequiresBase64DecodeSecret = true
|
k.API.CredentialsValidator.RequiresBase64DecodeSecret = true
|
||||||
|
|
||||||
pairStore := currency.PairStore{
|
for _, a := range []asset.Item{asset.Spot, asset.Futures} {
|
||||||
RequestFormat: ¤cy.PairFormat{
|
ps := currency.PairStore{
|
||||||
Uppercase: true,
|
AssetEnabled: true,
|
||||||
Separator: ",",
|
RequestFormat: ¤cy.PairFormat{Uppercase: true},
|
||||||
},
|
ConfigFormat: ¤cy.PairFormat{Uppercase: true, Delimiter: currency.UnderscoreDelimiter},
|
||||||
ConfigFormat: ¤cy.PairFormat{
|
}
|
||||||
Uppercase: true,
|
if a == asset.Futures {
|
||||||
Delimiter: currency.UnderscoreDelimiter,
|
ps.RequestFormat.Delimiter = currency.UnderscoreDelimiter
|
||||||
Separator: ",",
|
}
|
||||||
},
|
if err := k.SetAssetPairStore(a, ps); err != nil {
|
||||||
|
log.Errorf(log.ExchangeSys, "%s error storing `%s` default asset formats: %s", k.Name, a, err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
futures := currency.PairStore{
|
if err := k.DisableAssetWebsocketSupport(asset.Futures); err != nil {
|
||||||
RequestFormat: ¤cy.PairFormat{
|
log.Errorf(log.ExchangeSys, "%s error disabling `%s` asset type websocket support: %s", k.Name, asset.Futures, err)
|
||||||
Delimiter: currency.UnderscoreDelimiter,
|
|
||||||
Uppercase: true,
|
|
||||||
},
|
|
||||||
ConfigFormat: ¤cy.PairFormat{
|
|
||||||
Uppercase: true,
|
|
||||||
Delimiter: currency.UnderscoreDelimiter,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
err := k.StoreAssetPairFormat(asset.Spot, pairStore)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorln(log.ExchangeSys, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = k.StoreAssetPairFormat(asset.Futures, futures)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorln(log.ExchangeSys, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = k.DisableAssetWebsocketSupport(asset.Futures)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorln(log.ExchangeSys, err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
k.Features = exchange.Features{
|
k.Features = exchange.Features{
|
||||||
@@ -171,6 +151,7 @@ func (k *Kraken) SetDefaults() {
|
|||||||
Subscriptions: defaultSubscriptions.Clone(),
|
Subscriptions: defaultSubscriptions.Clone(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var err error
|
||||||
k.Requester, err = request.New(k.Name,
|
k.Requester, err = request.New(k.Name,
|
||||||
common.NewHTTPClientWithTimeout(exchange.DefaultHTTPTimeout),
|
common.NewHTTPClientWithTimeout(exchange.DefaultHTTPTimeout),
|
||||||
request.WithLimiter(request.NewBasicRateLimit(krakenRateInterval, krakenRequestRate, 1)))
|
request.WithLimiter(request.NewBasicRateLimit(krakenRateInterval, krakenRequestRate, 1)))
|
||||||
|
|||||||
@@ -44,26 +44,21 @@ func (ku *Kucoin) SetDefaults() {
|
|||||||
ku.API.CredentialsValidator.RequiresSecret = true
|
ku.API.CredentialsValidator.RequiresSecret = true
|
||||||
ku.API.CredentialsValidator.RequiresClientID = true
|
ku.API.CredentialsValidator.RequiresClientID = true
|
||||||
|
|
||||||
spot := currency.PairStore{
|
for _, a := range []asset.Item{asset.Spot, asset.Margin, asset.Futures} {
|
||||||
RequestFormat: ¤cy.PairFormat{Uppercase: true, Delimiter: currency.DashDelimiter},
|
ps := currency.PairStore{
|
||||||
ConfigFormat: ¤cy.PairFormat{Uppercase: true, Delimiter: currency.DashDelimiter},
|
AssetEnabled: true,
|
||||||
}
|
RequestFormat: ¤cy.PairFormat{Uppercase: true, Delimiter: currency.DashDelimiter},
|
||||||
futures := currency.PairStore{
|
ConfigFormat: ¤cy.PairFormat{Uppercase: true, Delimiter: currency.DashDelimiter},
|
||||||
RequestFormat: ¤cy.PairFormat{Uppercase: true},
|
}
|
||||||
ConfigFormat: ¤cy.PairFormat{Uppercase: true, Delimiter: currency.UnderscoreDelimiter},
|
if a == asset.Futures {
|
||||||
}
|
ps.RequestFormat.Delimiter = ""
|
||||||
err := ku.StoreAssetPairFormat(asset.Spot, spot)
|
ps.ConfigFormat.Delimiter = currency.UnderscoreDelimiter
|
||||||
if err != nil {
|
}
|
||||||
log.Errorln(log.ExchangeSys, err)
|
if err := ku.SetAssetPairStore(a, ps); err != nil {
|
||||||
}
|
log.Errorf(log.ExchangeSys, "%s error storing `%s` default asset formats: %s", ku.Name, a, err)
|
||||||
err = ku.StoreAssetPairFormat(asset.Margin, spot)
|
}
|
||||||
if err != nil {
|
|
||||||
log.Errorln(log.ExchangeSys, err)
|
|
||||||
}
|
|
||||||
err = ku.StoreAssetPairFormat(asset.Futures, futures)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorln(log.ExchangeSys, err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ku.Features = exchange.Features{
|
ku.Features = exchange.Features{
|
||||||
CurrencyTranslations: currency.NewTranslations(map[currency.Code]currency.Code{
|
CurrencyTranslations: currency.NewTranslations(map[currency.Code]currency.Code{
|
||||||
currency.XBT: currency.BTC,
|
currency.XBT: currency.BTC,
|
||||||
@@ -151,6 +146,8 @@ func (ku *Kucoin) SetDefaults() {
|
|||||||
},
|
},
|
||||||
Subscriptions: defaultSubscriptions.Clone(),
|
Subscriptions: defaultSubscriptions.Clone(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var err error
|
||||||
ku.Requester, err = request.New(ku.Name,
|
ku.Requester, err = request.New(ku.Name,
|
||||||
common.NewHTTPClientWithTimeout(exchange.DefaultHTTPTimeout),
|
common.NewHTTPClientWithTimeout(exchange.DefaultHTTPTimeout),
|
||||||
request.WithLimiter(GetRateLimit()))
|
request.WithLimiter(GetRateLimit()))
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ import (
|
|||||||
|
|
||||||
var errValidationCheckFailed = errors.New("validation check failed")
|
var errValidationCheckFailed = errors.New("validation check failed")
|
||||||
|
|
||||||
func TestSubmit_Validate(t *testing.T) {
|
func TestSubmitValidate(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
testPair := currency.NewPair(currency.BTC, currency.LTC)
|
testPair := currency.NewPair(currency.BTC, currency.LTC)
|
||||||
tester := []struct {
|
tester := []struct {
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/thrasher-corp/gocryptotrader/common/convert"
|
|
||||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||||
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
||||||
"github.com/thrasher-corp/gocryptotrader/exchanges/bitstamp"
|
"github.com/thrasher-corp/gocryptotrader/exchanges/bitstamp"
|
||||||
@@ -21,7 +20,7 @@ func TestSimulate(t *testing.T) {
|
|||||||
},
|
},
|
||||||
Pairs: map[asset.Item]*currency.PairStore{
|
Pairs: map[asset.Item]*currency.PairStore{
|
||||||
asset.Spot: {
|
asset.Spot: {
|
||||||
AssetEnabled: convert.BoolPtr(true),
|
AssetEnabled: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package sharedtestvalues
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@@ -11,6 +10,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||||
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||||
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
||||||
@@ -154,32 +154,26 @@ func SetupCurrencyPairsForExchangeAsset(t *testing.T, exch exchange.IBotExchange
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
b := exch.GetBase()
|
b := exch.GetBase()
|
||||||
|
|
||||||
err := b.CurrencyPairs.SetAssetEnabled(a, true)
|
err := b.CurrencyPairs.SetAssetEnabled(a, true)
|
||||||
if err != nil && !errors.Is(err, currency.ErrAssetAlreadyEnabled) {
|
require.NoError(t, err, "SetAssetEnabled must not error")
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
availPairs, err := b.CurrencyPairs.GetPairs(a, false)
|
availPairs, err := b.CurrencyPairs.GetPairs(a, false)
|
||||||
if err != nil {
|
require.NoError(t, err, "GetPairs must not error")
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
apLen := len(availPairs)
|
apLen := len(availPairs)
|
||||||
enabledPairs, err := b.CurrencyPairs.GetPairs(a, true)
|
enabledPairs, err := b.CurrencyPairs.GetPairs(a, true)
|
||||||
if err != nil {
|
require.NoError(t, err, "GetPairs must not error")
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
epLen := len(enabledPairs)
|
epLen := len(enabledPairs)
|
||||||
availPairs = availPairs.Add(cp...)
|
availPairs = availPairs.Add(cp...)
|
||||||
enabledPairs = enabledPairs.Add(cp...)
|
enabledPairs = enabledPairs.Add(cp...)
|
||||||
if len(availPairs) != apLen {
|
if len(availPairs) != apLen {
|
||||||
err = b.CurrencyPairs.StorePairs(a, availPairs, false)
|
err = b.CurrencyPairs.StorePairs(a, availPairs, false)
|
||||||
if err != nil {
|
require.NoError(t, err, "StorePairs must not error")
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if len(enabledPairs) != epLen {
|
if len(enabledPairs) != epLen {
|
||||||
err = b.CurrencyPairs.StorePairs(a, enabledPairs, true)
|
err = b.CurrencyPairs.StorePairs(a, enabledPairs, true)
|
||||||
if err != nil {
|
require.NoError(t, err, "StorePairs must not error")
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,50 +31,41 @@ func TestMain(m *testing.M) {
|
|||||||
var err error
|
var err error
|
||||||
engine.Bot, err = engine.NewFromSettings(&settings, nil)
|
engine.Bot, err = engine.NewFromSettings(&settings, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Print(err)
|
log.Fatalf("Error from engine.NewFromSettings: %s", err)
|
||||||
os.Exit(1)
|
|
||||||
}
|
}
|
||||||
em := engine.NewExchangeManager()
|
em := engine.NewExchangeManager()
|
||||||
exch, err := em.NewExchangeByName(exch.Value)
|
exch, err := em.NewExchangeByName(exch.Value)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Print(err)
|
log.Fatalf("Error from NewExchangeByName: %s", err)
|
||||||
os.Exit(1)
|
|
||||||
}
|
}
|
||||||
cfg, err := exchange.GetDefaultConfig(context.Background(), exch)
|
cfg, err := exchange.GetDefaultConfig(context.Background(), exch)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatalf("Error during GetDefaultConfig: %s", err)
|
||||||
}
|
}
|
||||||
err = exch.Setup(cfg)
|
if err = exch.Setup(cfg); err != nil {
|
||||||
if err != nil {
|
log.Fatalf("Error during exch.Setup: %s", err)
|
||||||
log.Fatal(err)
|
|
||||||
}
|
}
|
||||||
err = em.Add(exch)
|
if err = em.Add(exch); err != nil {
|
||||||
if !errors.Is(err, nil) {
|
log.Fatalf("Error during ExchangeManager.Add: %s", err)
|
||||||
log.Fatalf("received: '%v' but expected: '%v'", err, nil)
|
|
||||||
}
|
}
|
||||||
engine.Bot.ExchangeManager = em
|
engine.Bot.ExchangeManager = em
|
||||||
engine.Bot.WithdrawManager, err = engine.SetupWithdrawManager(em, nil, true)
|
engine.Bot.WithdrawManager, err = engine.SetupWithdrawManager(em, nil, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Print(err)
|
log.Fatalf("Error during engine.SetupWithdrawManage: %s", err)
|
||||||
os.Exit(1)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
engine.Bot.DepositAddressManager = engine.SetupDepositAddressManager()
|
engine.Bot.DepositAddressManager = engine.SetupDepositAddressManager()
|
||||||
err = engine.Bot.DepositAddressManager.Sync(engine.Bot.GetAllExchangeCryptocurrencyDepositAddresses())
|
err = engine.Bot.DepositAddressManager.Sync(engine.Bot.GetAllExchangeCryptocurrencyDepositAddresses())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Print(err)
|
log.Fatalf("Error syncing DepositAddressManager: %s", err)
|
||||||
os.Exit(1)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
engine.Bot.OrderManager, err = engine.SetupOrderManager(em, &engine.CommunicationManager{}, &engine.Bot.ServicesWG, &config.OrderManager{})
|
engine.Bot.OrderManager, err = engine.SetupOrderManager(em, &engine.CommunicationManager{}, &engine.Bot.ServicesWG, &config.OrderManager{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Print(err)
|
log.Fatalf("Error during SetupOrderManager: %s", err)
|
||||||
os.Exit(1)
|
|
||||||
}
|
}
|
||||||
err = engine.Bot.OrderManager.Start()
|
if err = engine.Bot.OrderManager.Start(); err != nil {
|
||||||
if err != nil {
|
log.Fatalf("Error starting OrderManager: %s", err)
|
||||||
log.Print(err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
}
|
||||||
modules.SetModuleWrapper(Setup())
|
modules.SetModuleWrapper(Setup())
|
||||||
os.Exit(m.Run())
|
os.Exit(m.Run())
|
||||||
|
|||||||
22
testdata/configtest.json
vendored
22
testdata/configtest.json
vendored
@@ -345,7 +345,27 @@
|
|||||||
"spot": {
|
"spot": {
|
||||||
"assetEnabled": true,
|
"assetEnabled": true,
|
||||||
"enabled": "BTC-USD",
|
"enabled": "BTC-USD",
|
||||||
"available": "BTC-CNY,BTC-EUR,BTC-GBP,BTC-HKD,BTC-JPY,BTC-SGD,BTC-USD,ETH-CNY,ETH-EUR,ETH-GBP,ETH-HKD,ETH-JPY,ETH-SGD,ETH-USD,LTC-CNY,LTC-EUR,LTC-GBP,LTC-HKD,LTC-JPY,LTC-SGD,LTC-USD,USDT-CNY,USDT-EUR,USDT-GBP,USDT-HKD,USDT-JPY,USDT-SGD,USDT-USD,XMR-CNY,XMR-EUR,XMR-GBP,XMR-HKD,XMR-JPY,XMR-SGD,XMR-USD"
|
"available": "BTC-CNY,BTC-EUR,BTC-GBP,BTC-HKD,BTC-JPY,BTC-SGD,BTC-USD,ETH-CNY,ETH-EUR,ETH-GBP,ETH-HKD,ETH-JPY,ETH-SGD,ETH-USD,LTC-CNY,LTC-EUR,LTC-GBP,LTC-HKD,LTC-JPY,LTC-SGD,LTC-USD,USDT-CNY,USDT-EUR,USDT-GBP,USDT-HKD,USDT-JPY,USDT-SGD,USDT-USD,XMR-CNY,XMR-EUR,XMR-GBP,XMR-HKD,XMR-JPY,XMR-SGD,XMR-USD",
|
||||||
|
"requestFormat": {
|
||||||
|
"uppercase": true
|
||||||
|
},
|
||||||
|
"configFormat": {
|
||||||
|
"uppercase": true,
|
||||||
|
"delimiter": "-"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"futures": {
|
||||||
|
"assetEnabled": true,
|
||||||
|
"enabled": "BTC-PFC",
|
||||||
|
"available": "PENDLE-PFC,RUNE-PFC,1KSHIB-PFC,ALGO-PFC,BAND-PFC,BNB-PFC,CRV-PFC,C98-PFC,DOGE-PFC,ENS-PFC,JUP-PFC,LINK-PFC,SUI-PFC,1KPEPE-PFC,ARB-PFC,BAL-PFC,CHR-PFC,DYDX-PFC,W-PFC,YFI-PFC,ZIL-PFC,ONDO-PFC,BTC-U24,1INCH-PFC,CELR-PFC,CHZ-PFC,CTSI-PFC,ENA-PFC,FET-PFC,FTM-PFC,WLD-PFC,BTC-PFC,BOME-PFC,MAVIA-PFC,TIA-PFC,ETH-U24,BAT-PFC,ENJ-PFC,ORDI-PFC,WIF-PFC,TAO-PFC,EGLD-PFC,FIL-PFC,KSM-PFC,NEO-PFC,PEOPLE-PFC,SEI-PFC,APE-PFC,APT-PFC,GRT-PFC,INJ-PFC,MANA-PFC,NEAR-PFC,SKL-PFC,TOKEN-PFC,UNI-PFC,ZK-PFC,ETH-Z24,NOT-PFC,STX-PFC,TON-PFC,ETC-PFC,1KFLOKI-PFC,BCH-PFC,DOT-PFC,EOS-PFC,ETHFI-PFC,GALA-PFC,LDO-PFC,OMG-PFC,PYTH-PFC,BTC-Z24,KAS-PFC,MASK-PFC,STORJ-PFC,SUSHI-PFC,XTZ-PFC,ETH-PFC,LTC-PFC,ALICE-PFC,COMP-PFC,GMT-PFC,IOTX-PFC,KLAY-PFC,KNC-PFC,OP-PFC,SNX-PFC,TRX-PFC,XMR-PFC,XRP-PFC,AAVE-PFC,ATOM-PFC,IMX-PFC,MATIC-PFC,MKR-PFC,ONE-PFC,SAND-PFC,SOL-PFC,TRB-PFC,THETA-PFC,ADA-PFC,AVAX-PFC,AXS-PFC,IO-PFC",
|
||||||
|
"requestFormat": {
|
||||||
|
"uppercase": true,
|
||||||
|
"delimiter": "-"
|
||||||
|
},
|
||||||
|
"configFormat": {
|
||||||
|
"uppercase": true,
|
||||||
|
"delimiter": "-"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user