mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-05-18 07:26:50 +00:00
engine/exchanges: Add exchange currency state subsystem (#774)
* state: Add management system (init) * linter: fix * engine: gofmt * gct: after merge fixup * documentation: add * rpc: implement services for testing * gctcli: gofmt state_management.go * documentation: reinstate lost information * state: Add pair check to determine trading operation * exchanges: add interface for specific state scoped subsystem functionality * engine/order_man: reduce code footprint using new method * RPC: implement pair trading request and change exported name to something specific to state * engine: add tests * engine: Add to withdraw manager * documentation: reinstate soxipy in contrib. list * engine: const fake name * Glorious: NITERINOS * merge: fix issues * engine: csm incorporate service name into log output * engine: fix linter issues * gct: fix tests * currencystate: remove management type * rpc: fix tests * backtester: fix tests * Update engine/currency_state_manager.go Co-authored-by: Scott <gloriousCode@users.noreply.github.com> * Update engine/currency_state_manager.go Co-authored-by: Scott <gloriousCode@users.noreply.github.com> * Update exchanges/currencystate/currency_state.go Co-authored-by: Scott <gloriousCode@users.noreply.github.com> * Update exchanges/alert/alert.go Co-authored-by: Scott <gloriousCode@users.noreply.github.com> * Update exchanges/alert/alert.go Co-authored-by: Scott <gloriousCode@users.noreply.github.com> * glorious: nits * config: integrate with config and remove flag delay adjustment * gctcli: fix issues after name changes * engine: gofmt manager file * Update engine/rpcserver.go Co-authored-by: Scott <gloriousCode@users.noreply.github.com> * engine: Add enable/disable manager functions, add default popoulation for potential assets * linter: fix * engine/test: bump subsystem count * Update engine/currency_state_manager.go Co-authored-by: Scott <gloriousCode@users.noreply.github.com> * Update exchanges/bithumb/bithumb.go Co-authored-by: Scott <gloriousCode@users.noreply.github.com> * glorious: nits addressed * alert: fix commenting for its generalized purpose * glorious: nits * engine: use standard string in log output * bitfinex: apply patch, thanks @thrasher- * bitfinex: fix spelling * engine/currencystate: Add logs/fix logs Co-authored-by: Scott <gloriousCode@users.noreply.github.com>
This commit is contained in:
@@ -28,6 +28,7 @@ import (
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/account"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/binance"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/currencystate"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/kline"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
|
||||
@@ -43,6 +44,7 @@ const (
|
||||
unexpectedLackOfError = "unexpected lack of error"
|
||||
migrationsFolder = "migrations"
|
||||
databaseFolder = "database"
|
||||
fakeExchangeName = "fake"
|
||||
)
|
||||
|
||||
// fExchange is a fake exchange with function overrides
|
||||
@@ -53,7 +55,7 @@ type fExchange struct {
|
||||
|
||||
func (f fExchange) GetHistoricCandles(ctx context.Context, p currency.Pair, a asset.Item, timeStart, _ time.Time, interval kline.Interval) (kline.Item, error) {
|
||||
return kline.Item{
|
||||
Exchange: "fake",
|
||||
Exchange: fakeExchangeName,
|
||||
Pair: p,
|
||||
Asset: a,
|
||||
Interval: interval,
|
||||
@@ -72,7 +74,7 @@ func (f fExchange) GetHistoricCandles(ctx context.Context, p currency.Pair, a as
|
||||
|
||||
func (f fExchange) GetHistoricCandlesExtended(ctx context.Context, p currency.Pair, a asset.Item, timeStart, _ time.Time, interval kline.Interval) (kline.Item, error) {
|
||||
return kline.Item{
|
||||
Exchange: "fake",
|
||||
Exchange: fakeExchangeName,
|
||||
Pair: p,
|
||||
Asset: a,
|
||||
Interval: interval,
|
||||
@@ -122,6 +124,36 @@ func (f fExchange) UpdateAccountInfo(ctx context.Context, a asset.Item) (account
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GetCurrencyStateSnapshot overrides interface function
|
||||
func (f fExchange) GetCurrencyStateSnapshot() ([]currencystate.Snapshot, error) {
|
||||
return []currencystate.Snapshot{
|
||||
{
|
||||
Code: currency.BTC,
|
||||
Asset: asset.Spot,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// CanTradePair overrides interface function
|
||||
func (f fExchange) CanTradePair(p currency.Pair, a asset.Item) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// CanTrade overrides interface function
|
||||
func (f fExchange) CanTrade(c currency.Code, a asset.Item) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// CanWithdraw overrides interface function
|
||||
func (f fExchange) CanWithdraw(c currency.Code, a asset.Item) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// CanDeposit overrides interface function
|
||||
func (f fExchange) CanDeposit(c currency.Code, a asset.Item) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Sets up everything required to run any function inside rpcserver
|
||||
// Only use if you require a database, this makes tests slow
|
||||
func RPCTestSetup(t *testing.T) *Engine {
|
||||
@@ -238,7 +270,7 @@ func TestGetSavedTrades(t *testing.T) {
|
||||
t.Error(err)
|
||||
}
|
||||
_, err = s.GetSavedTrades(context.Background(), &gctrpc.GetSavedTradesRequest{
|
||||
Exchange: "fake",
|
||||
Exchange: fakeExchangeName,
|
||||
Pair: &gctrpc.CurrencyPair{
|
||||
Delimiter: currency.DashDelimiter,
|
||||
Base: currency.BTC.String(),
|
||||
@@ -849,7 +881,7 @@ func TestGetRecentTrades(t *testing.T) {
|
||||
t.Error(err)
|
||||
}
|
||||
_, err = s.GetRecentTrades(context.Background(), &gctrpc.GetSavedTradesRequest{
|
||||
Exchange: "fake",
|
||||
Exchange: fakeExchangeName,
|
||||
Pair: &gctrpc.CurrencyPair{
|
||||
Delimiter: currency.DashDelimiter,
|
||||
Base: currency.BTC.String(),
|
||||
@@ -897,7 +929,7 @@ func TestGetHistoricTrades(t *testing.T) {
|
||||
t.Error(err)
|
||||
}
|
||||
err = s.GetHistoricTrades(&gctrpc.GetSavedTradesRequest{
|
||||
Exchange: "fake",
|
||||
Exchange: fakeExchangeName,
|
||||
Pair: &gctrpc.CurrencyPair{
|
||||
Delimiter: currency.DashDelimiter,
|
||||
Base: currency.BTC.String(),
|
||||
@@ -934,7 +966,7 @@ func TestGetAccountInfo(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
b := exch.GetBase()
|
||||
b.Name = "fake"
|
||||
b.Name = fakeExchangeName
|
||||
b.Enabled = true
|
||||
b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore)
|
||||
b.CurrencyPairs.Pairs[asset.Spot] = ¤cy.PairStore{
|
||||
@@ -945,7 +977,7 @@ func TestGetAccountInfo(t *testing.T) {
|
||||
}
|
||||
em.Add(fakeExchange)
|
||||
s := RPCServer{Engine: &Engine{ExchangeManager: em}}
|
||||
_, err = s.GetAccountInfo(context.Background(), &gctrpc.GetAccountInfoRequest{Exchange: "fake", AssetType: asset.Spot.String()})
|
||||
_, err = s.GetAccountInfo(context.Background(), &gctrpc.GetAccountInfoRequest{Exchange: fakeExchangeName, AssetType: asset.Spot.String()})
|
||||
if !errors.Is(err, nil) {
|
||||
t.Errorf("received '%v', expected '%v'", err, nil)
|
||||
}
|
||||
@@ -959,7 +991,7 @@ func TestUpdateAccountInfo(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
b := exch.GetBase()
|
||||
b.Name = "fake"
|
||||
b.Name = fakeExchangeName
|
||||
b.Enabled = true
|
||||
b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore)
|
||||
b.CurrencyPairs.Pairs[asset.Spot] = ¤cy.PairStore{
|
||||
@@ -971,18 +1003,18 @@ func TestUpdateAccountInfo(t *testing.T) {
|
||||
em.Add(fakeExchange)
|
||||
s := RPCServer{Engine: &Engine{ExchangeManager: em}}
|
||||
|
||||
_, err = s.GetAccountInfo(context.Background(), &gctrpc.GetAccountInfoRequest{Exchange: "fake", AssetType: asset.Spot.String()})
|
||||
_, err = s.GetAccountInfo(context.Background(), &gctrpc.GetAccountInfoRequest{Exchange: fakeExchangeName, AssetType: asset.Spot.String()})
|
||||
if !errors.Is(err, nil) {
|
||||
t.Errorf("received '%v', expected '%v'", err, nil)
|
||||
}
|
||||
|
||||
_, err = s.UpdateAccountInfo(context.Background(), &gctrpc.GetAccountInfoRequest{Exchange: "fake", AssetType: asset.Futures.String()})
|
||||
_, err = s.UpdateAccountInfo(context.Background(), &gctrpc.GetAccountInfoRequest{Exchange: fakeExchangeName, AssetType: asset.Futures.String()})
|
||||
if !errors.Is(err, errAssetTypeDisabled) {
|
||||
t.Errorf("received '%v', expected '%v'", err, errAssetTypeDisabled)
|
||||
}
|
||||
|
||||
_, err = s.UpdateAccountInfo(context.Background(), &gctrpc.GetAccountInfoRequest{
|
||||
Exchange: "fake",
|
||||
Exchange: fakeExchangeName,
|
||||
AssetType: asset.Spot.String(),
|
||||
})
|
||||
if !errors.Is(err, nil) {
|
||||
@@ -1862,3 +1894,87 @@ func TestUpdateDataHistoryJobPrerequisite(t *testing.T) {
|
||||
t.Errorf("received %v, expected %v", err, nil)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCurrencyStateGetAll(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := (&RPCServer{Engine: &Engine{}}).CurrencyStateGetAll(context.Background(),
|
||||
&gctrpc.CurrencyStateGetAllRequest{Exchange: fakeExchangeName})
|
||||
if !errors.Is(err, ErrSubSystemNotStarted) {
|
||||
t.Errorf("received %v, expected %v", err, ErrSubSystemNotStarted)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCurrencyStateWithdraw(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := (&RPCServer{
|
||||
Engine: &Engine{},
|
||||
}).CurrencyStateWithdraw(context.Background(),
|
||||
&gctrpc.CurrencyStateWithdrawRequest{
|
||||
Exchange: "wow"})
|
||||
if !errors.Is(err, ErrSubSystemNotStarted) {
|
||||
t.Fatalf("received: %v, but expected: %v", err, ErrSubSystemNotStarted)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCurrencyStateDeposit(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := (&RPCServer{
|
||||
Engine: &Engine{},
|
||||
}).CurrencyStateDeposit(context.Background(),
|
||||
&gctrpc.CurrencyStateDepositRequest{Exchange: "wow"})
|
||||
if !errors.Is(err, ErrSubSystemNotStarted) {
|
||||
t.Fatalf("received: %v, but expected: %v", err, ErrSubSystemNotStarted)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCurrencyStateTrading(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := (&RPCServer{
|
||||
Engine: &Engine{},
|
||||
}).CurrencyStateTrading(context.Background(),
|
||||
&gctrpc.CurrencyStateTradingRequest{Exchange: "wow"})
|
||||
if !errors.Is(err, ErrSubSystemNotStarted) {
|
||||
t.Fatalf("received: %v, but expected: %v", err, ErrSubSystemNotStarted)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCurrencyStateTradingPair(t *testing.T) {
|
||||
t.Parallel()
|
||||
em := SetupExchangeManager()
|
||||
exch, err := em.NewExchangeByName(testExchange)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
b := exch.GetBase()
|
||||
b.Name = fakeExchangeName
|
||||
b.Enabled = true
|
||||
|
||||
cp, err := currency.NewPairFromString("btc-usd")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore)
|
||||
b.CurrencyPairs.Pairs[asset.Spot] = ¤cy.PairStore{
|
||||
AssetEnabled: convert.BoolPtr(true),
|
||||
ConfigFormat: ¤cy.PairFormat{},
|
||||
Available: currency.Pairs{cp},
|
||||
Enabled: currency.Pairs{cp},
|
||||
}
|
||||
fakeExchange := fExchange{
|
||||
IBotExchange: exch,
|
||||
}
|
||||
em.Add(fakeExchange)
|
||||
s := RPCServer{Engine: &Engine{ExchangeManager: em,
|
||||
currencyStateManager: &CurrencyStateManager{started: 1, iExchangeManager: em}}}
|
||||
|
||||
_, err = s.CurrencyStateTradingPair(context.Background(),
|
||||
&gctrpc.CurrencyStateTradingPairRequest{
|
||||
Exchange: fakeExchangeName,
|
||||
Pair: "btc-usd",
|
||||
Asset: "spot",
|
||||
})
|
||||
if !errors.Is(err, nil) {
|
||||
t.Fatalf("received: %v, but expected: %v", err, nil)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user