Binance,Okx: Add Leverage, MarginType, Positions and CollateralMode support (#1220)

* init

* surprise train commit

* basic distinctions

* the terms of binance are confusing

* renames and introduction of allocatedMargin

* add new margin funcs

* pulling out wires

* implement proper getposition stuff

* bad coding day

* investigate order manager next

* a broken mess, but a progressing one

* finally completes some usdtmargined stuff

* coinMfutures eludes me

* expand to okx

* imports fix

* completes okx wrapper implementations

* cleans and polishes before rpc implementations

* rpc setup, order manager features, exch features

* more rpc, collateral and margin things

* mini test

* looking at rpc response, expansion of features

* reorganising before the storm

* changing how futures requests work

* cleanup and tests of cli usage

* remove silly client side logic

* cleanup

* collateral package, typo fix, margin err, rpc derive

* uses convert.StringToFloat ONLY ON STRUCTS FROM THIS PR

* fix binance order history bug

* niteroos

* adds new funcs to exchange standards testing

* more post merge fixes

* fix binance

* replace simepletimeformat

* fix for merge

* merge fixes

* micro fixes

* order side now required for leverage

* fix up the rest

* global -> portfolio collateral

* Update exchanges/collateral/collateral_test.go

Co-authored-by: Adrian Gallagher <adrian.gallagher@thrasher.io>

* adds fields and todos

* rm field redundancy

* lint fix oopsie daisy

* fixes panic, expands error and cli explanations (sorry shaz)

* ensures casing is appropriate for underlying

* Adds a shiny TODO

---------

Co-authored-by: Adrian Gallagher <adrian.gallagher@thrasher.io>
This commit is contained in:
Scott
2023-09-26 16:16:31 +10:00
committed by GitHub
parent a2ae99ed7f
commit 5f2f6f884b
67 changed files with 11558 additions and 4475 deletions

View File

@@ -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/collateral"
"github.com/thrasher-corp/gocryptotrader/exchanges/currencystate"
"github.com/thrasher-corp/gocryptotrader/exchanges/fundingrate"
"github.com/thrasher-corp/gocryptotrader/exchanges/kline"
@@ -58,7 +59,7 @@ type fExchange struct {
exchange.IBotExchange
}
func (f fExchange) GetPositionSummary(context.Context, *order.PositionSummaryRequest) (*order.PositionSummary, error) {
func (f fExchange) GetFuturesPositionSummary(context.Context, *order.PositionSummaryRequest) (*order.PositionSummary, error) {
leet := decimal.NewFromInt(1337)
return &order.PositionSummary{
MaintenanceMarginRequirement: leet,
@@ -67,27 +68,55 @@ func (f fExchange) GetPositionSummary(context.Context, *order.PositionSummaryReq
CollateralUsed: leet,
MarkPrice: leet,
CurrentSize: leet,
BreakEvenPrice: leet,
AverageOpenPrice: leet,
RecentPNL: leet,
MarginFraction: leet,
PositionPNL: leet,
MaintenanceMarginFraction: leet,
FreeCollateral: leet,
TotalCollateral: leet,
}, nil
}
func (f fExchange) GetFuturesPositions(_ context.Context, req *order.PositionsRequest) ([]order.PositionDetails, error) {
func (f fExchange) ChangePositionMargin(_ context.Context, req *margin.PositionChangeRequest) (*margin.PositionChangeResponse, error) {
return &margin.PositionChangeResponse{
Exchange: f.GetName(),
Pair: req.Pair,
Asset: req.Asset,
AllocatedMargin: req.NewAllocatedMargin,
MarginType: req.MarginType,
}, nil
}
func (f fExchange) SetLeverage(_ context.Context, _ asset.Item, _ currency.Pair, _ margin.Type, _ float64, _ order.Side) error {
return nil
}
func (f fExchange) GetLeverage(_ context.Context, _ asset.Item, _ currency.Pair, _ margin.Type, _ order.Side) (float64, error) {
return 1337, nil
}
func (f fExchange) SetMarginType(_ context.Context, _ asset.Item, _ currency.Pair, _ margin.Type) error {
return nil
}
func (f fExchange) SetCollateralMode(_ context.Context, _ asset.Item, _ collateral.Mode) error {
return nil
}
func (f fExchange) GetCollateralMode(_ context.Context, _ asset.Item) (collateral.Mode, error) {
return collateral.SingleMode, nil
}
func (f fExchange) GetFuturesPositionOrders(_ context.Context, req *order.PositionsRequest) ([]order.PositionResponse, error) {
id, err := uuid.NewV4()
if err != nil {
return nil, err
}
resp := make([]order.PositionDetails, len(req.Pairs))
resp := make([]order.PositionResponse, len(req.Pairs))
tt := time.Now()
for i := range req.Pairs {
resp[i] = order.PositionDetails{
Exchange: f.GetName(),
Asset: req.Asset,
Pair: req.Pairs[i],
resp[i] = order.PositionResponse{
Asset: req.Asset,
Pair: req.Pairs[i],
Orders: []order.Detail{
{
Exchange: f.GetName(),
@@ -288,7 +317,7 @@ func (f fExchange) CalculateTotalCollateral(context.Context, *order.TotalCollate
CollateralCurrency: currency.USD,
AvailableMaintenanceCollateral: decimal.NewFromInt(1338),
AvailableCollateral: decimal.NewFromInt(1337),
UsedBreakdown: &order.UsedCollateralBreakdown{
UsedBreakdown: &collateral.UsedBreakdown{
LockedInStakes: decimal.NewFromInt(3),
LockedInNFTBids: decimal.NewFromInt(3),
LockedInFeeVoucher: decimal.NewFromInt(3),
@@ -296,7 +325,7 @@ func (f fExchange) CalculateTotalCollateral(context.Context, *order.TotalCollate
LockedInSpotOrders: decimal.NewFromInt(3),
LockedAsCollateral: decimal.NewFromInt(3),
},
BreakdownByCurrency: []order.CollateralByCurrency{
BreakdownByCurrency: []collateral.ByCurrency{
{
Currency: currency.USD,
TotalFunds: decimal.NewFromInt(1330),
@@ -307,7 +336,7 @@ func (f fExchange) CalculateTotalCollateral(context.Context, *order.TotalCollate
Currency: currency.DOGE,
TotalFunds: decimal.NewFromInt(1000),
ScaledUsed: decimal.NewFromInt(6),
ScaledUsedBreakdown: &order.UsedCollateralBreakdown{
ScaledUsedBreakdown: &collateral.UsedBreakdown{
LockedInStakes: decimal.NewFromInt(1),
LockedInNFTBids: decimal.NewFromInt(1),
LockedInFeeVoucher: decimal.NewFromInt(1),
@@ -332,7 +361,7 @@ func (f fExchange) CalculateTotalCollateral(context.Context, *order.TotalCollate
// to do the bare minimum required with no API calls or credentials required
func (f fExchange) UpdateAccountInfo(_ context.Context, a asset.Item) (account.Holdings, error) {
if a == asset.Futures {
return account.Holdings{}, errAssetTypeDisabled
return account.Holdings{}, asset.ErrNotSupported
}
return account.Holdings{
Exchange: f.GetName(),
@@ -1249,8 +1278,8 @@ func TestUpdateAccountInfo(t *testing.T) {
}
_, 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)
if !errors.Is(err, currency.ErrAssetNotFound) {
t.Errorf("received '%v', expected '%v'", err, currency.ErrAssetNotFound)
}
_, err = s.UpdateAccountInfo(context.Background(), &gctrpc.GetAccountInfoRequest{
@@ -1286,7 +1315,7 @@ func TestGetOrders(t *testing.T) {
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
}
var wg sync.WaitGroup
om, err := SetupOrderManager(em, engerino.CommunicationsManager, &wg, false, false, 0)
om, err := SetupOrderManager(em, engerino.CommunicationsManager, &wg, &config.OrderManager{})
if !errors.Is(err, nil) {
t.Errorf("received '%v', expected '%v'", err, nil)
}
@@ -1396,7 +1425,7 @@ func TestGetOrder(t *testing.T) {
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
}
var wg sync.WaitGroup
om, err := SetupOrderManager(em, engerino.CommunicationsManager, &wg, false, false, 0)
om, err := SetupOrderManager(em, engerino.CommunicationsManager, &wg, &config.OrderManager{})
if !errors.Is(err, nil) {
t.Errorf("received '%v', expected '%v'", err, nil)
}
@@ -1483,8 +1512,8 @@ func TestCheckVars(t *testing.T) {
e.SetEnabled(true)
err = checkParams("Binance", e, asset.Spot, currency.NewPair(currency.BTC, currency.USDT))
if !errors.Is(err, errAssetTypeDisabled) {
t.Errorf("expected %v, got %v", errAssetTypeDisabled, err)
if !errors.Is(err, currency.ErrPairManagerNotInitialised) {
t.Errorf("expected %v, got %v", currency.ErrPairManagerNotInitialised, err)
}
fmt1 := currency.PairStore{
@@ -1935,7 +1964,7 @@ func TestGetManagedOrders(t *testing.T) {
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
}
var wg sync.WaitGroup
om, err := SetupOrderManager(em, engerino.CommunicationsManager, &wg, false, false, 0)
om, err := SetupOrderManager(em, engerino.CommunicationsManager, &wg, &config.OrderManager{})
if !errors.Is(err, nil) {
t.Errorf("received '%v', expected '%v'", err, nil)
}
@@ -2256,7 +2285,7 @@ func TestCurrencyStateTradingPair(t *testing.T) {
}
}
func TestGetFuturesPositions(t *testing.T) {
func TestGetFuturesPositionsOrders(t *testing.T) {
t.Parallel()
em := NewExchangeManager()
exch, err := em.NewExchangeByName("binance")
@@ -2297,7 +2326,7 @@ func TestGetFuturesPositions(t *testing.T) {
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
}
var wg sync.WaitGroup
om, err := SetupOrderManager(em, &CommunicationManager{}, &wg, false, false, time.Hour)
om, err := SetupOrderManager(em, &CommunicationManager{}, &wg, &config.OrderManager{FuturesTrackingSeekDuration: time.Hour})
if !errors.Is(err, nil) {
t.Errorf("received '%v', expected '%v'", err, nil)
}
@@ -2313,7 +2342,7 @@ func TestGetFuturesPositions(t *testing.T) {
},
}
_, err = s.GetFuturesPositions(context.Background(), &gctrpc.GetFuturesPositionsRequest{
_, err = s.GetFuturesPositionsOrders(context.Background(), &gctrpc.GetFuturesPositionsOrdersRequest{
Exchange: fakeExchangeName,
Asset: asset.Futures.String(),
Pair: &gctrpc.CurrencyPair{
@@ -2322,66 +2351,11 @@ func TestGetFuturesPositions(t *testing.T) {
Quote: cp.Quote.String(),
},
})
if !errors.Is(err, exchange.ErrCredentialsAreEmpty) {
t.Fatalf("received '%v', expected '%v'", err, exchange.ErrCredentialsAreEmpty)
}
ctx := account.DeployCredentialsToContext(context.Background(),
&account.Credentials{
Key: "wow",
Secret: "super wow",
},
)
_, err = s.GetFuturesPositions(ctx, &gctrpc.GetFuturesPositionsRequest{
Exchange: "test",
Asset: asset.Futures.String(),
Pair: &gctrpc.CurrencyPair{
Delimiter: currency.DashDelimiter,
Base: cp.Base.String(),
Quote: cp.Quote.String(),
},
IncludeFullOrderData: true,
IncludeFullFundingRates: true,
IncludePredictedRate: true,
GetPositionStats: true,
GetFundingPayments: true,
})
if !errors.Is(err, ErrExchangeNotFound) {
t.Errorf("received '%v', expected '%v'", err, ErrExchangeNotFound)
}
od := &order.Detail{
Price: 1337,
Amount: 1337,
Fee: 1.337,
Exchange: fakeExchangeName,
OrderID: "test",
Side: order.Long,
Status: order.Open,
AssetType: asset.Futures,
Date: time.Now(),
Pair: cp,
}
err = s.OrderManager.orderStore.futuresPositionController.TrackNewOrder(od)
if !errors.Is(err, nil) {
t.Fatalf("received '%v', expected '%v'", err, nil)
}
_, err = s.GetFuturesPositions(ctx, &gctrpc.GetFuturesPositionsRequest{
Exchange: fakeExchangeName,
Asset: asset.Futures.String(),
Pair: &gctrpc.CurrencyPair{
Delimiter: currency.DashDelimiter,
Base: cp.Base.String(),
Quote: cp.Quote.String(),
},
IncludeFullOrderData: true,
})
if !errors.Is(err, nil) {
t.Fatalf("received '%v', expected '%v'", err, nil)
}
_, err = s.GetFuturesPositions(ctx, &gctrpc.GetFuturesPositionsRequest{
_, err = s.GetFuturesPositionsOrders(context.Background(), &gctrpc.GetFuturesPositionsOrdersRequest{
Exchange: fakeExchangeName,
Asset: asset.Spot.String(),
Pair: &gctrpc.CurrencyPair{
@@ -2424,6 +2398,7 @@ func TestGetCollateral(t *testing.T) {
Available: currency.Pairs{cp},
Enabled: currency.Pairs{cp},
}
b.Features.Supports.FuturesCapabilities.Collateral = true
fakeExchange := fExchange{
IBotExchange: exch,
}
@@ -2965,6 +2940,7 @@ func TestGetFundingRates(t *testing.T) {
Available: currency.Pairs{cp},
Enabled: currency.Pairs{cp},
}
b.Features.Supports.FuturesCapabilities.FundingRates = true
fakeExchange := fExchange{
IBotExchange: exch,
}
@@ -2973,7 +2949,7 @@ func TestGetFundingRates(t *testing.T) {
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
}
var wg sync.WaitGroup
om, err := SetupOrderManager(em, &CommunicationManager{}, &wg, false, false, time.Hour)
om, err := SetupOrderManager(em, &CommunicationManager{}, &wg, &config.OrderManager{FuturesTrackingSeekDuration: time.Hour})
if !errors.Is(err, nil) {
t.Errorf("received '%v', expected '%v'", err, nil)
}
@@ -3073,7 +3049,7 @@ func TestGetLatestFundingRate(t *testing.T) {
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
}
var wg sync.WaitGroup
om, err := SetupOrderManager(em, &CommunicationManager{}, &wg, false, false, time.Hour)
om, err := SetupOrderManager(em, &CommunicationManager{}, &wg, &config.OrderManager{FuturesTrackingSeekDuration: time.Hour})
if !errors.Is(err, nil) {
t.Errorf("received '%v', expected '%v'", err, nil)
}
@@ -3164,6 +3140,7 @@ func TestGetManagedPosition(t *testing.T) {
Available: currency.Pairs{cp, cp2},
Enabled: currency.Pairs{cp, cp2},
}
b.Features.Supports.FuturesCapabilities.OrderManagerPositionTracking = true
fakeExchange := fExchange{
IBotExchange: exch,
}
@@ -3172,7 +3149,7 @@ func TestGetManagedPosition(t *testing.T) {
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
}
var wg sync.WaitGroup
om, err := SetupOrderManager(em, &CommunicationManager{}, &wg, false, false, time.Hour)
om, err := SetupOrderManager(em, &CommunicationManager{}, &wg, &config.OrderManager{FuturesTrackingSeekDuration: time.Hour})
if !errors.Is(err, nil) {
t.Errorf("received '%v', expected '%v'", err, nil)
}
@@ -3221,7 +3198,7 @@ func TestGetManagedPosition(t *testing.T) {
}
request.Asset = asset.Futures.String()
s.OrderManager, err = SetupOrderManager(em, &CommunicationManager{}, &wg, false, false, time.Hour)
s.OrderManager, err = SetupOrderManager(em, &CommunicationManager{}, &wg, &config.OrderManager{FuturesTrackingSeekDuration: time.Hour})
if !errors.Is(err, nil) {
t.Errorf("received '%v', expected '%v'", err, nil)
}
@@ -3314,7 +3291,7 @@ func TestGetAllManagedPositions(t *testing.T) {
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
}
var wg sync.WaitGroup
om, err := SetupOrderManager(em, &CommunicationManager{}, &wg, false, false, time.Hour)
om, err := SetupOrderManager(em, &CommunicationManager{}, &wg, &config.OrderManager{FuturesTrackingSeekDuration: time.Hour})
if !errors.Is(err, nil) {
t.Errorf("received '%v', expected '%v'", err, nil)
}
@@ -3335,7 +3312,7 @@ func TestGetAllManagedPositions(t *testing.T) {
}
request := &gctrpc.GetAllManagedPositionsRequest{}
s.OrderManager, err = SetupOrderManager(em, &CommunicationManager{}, &wg, false, true, time.Hour)
s.OrderManager, err = SetupOrderManager(em, &CommunicationManager{}, &wg, &config.OrderManager{FuturesTrackingSeekDuration: time.Hour, ActivelyTrackFuturesPositions: true})
if !errors.Is(err, nil) {
t.Errorf("received '%v', expected '%v'", err, nil)
}
@@ -3706,3 +3683,383 @@ func TestGetOrderbookAmountByImpact(t *testing.T) {
t.Fatalf("received: '%v' but expected: '%v'", impact.AmountRequired, 1)
}
}
func TestChangePositionMargin(t *testing.T) {
t.Parallel()
em := NewExchangeManager()
exch, err := em.NewExchangeByName("binance")
if err != nil {
t.Fatal(err)
}
exch.SetDefaults()
b := exch.GetBase()
b.Name = fakeExchangeName
b.Enabled = true
cp, err := currency.NewPairFromString("btc-mad")
if err != nil {
t.Fatal(err)
}
b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore)
b.CurrencyPairs.Pairs[asset.USDTMarginedFutures] = &currency.PairStore{
AssetEnabled: convert.BoolPtr(true),
ConfigFormat: &currency.PairFormat{Delimiter: "/"},
RequestFormat: &currency.PairFormat{Delimiter: "/"},
Available: currency.Pairs{cp},
Enabled: currency.Pairs{cp},
}
fakeExchange := fExchange{
IBotExchange: exch,
}
err = em.Add(fakeExchange)
if !errors.Is(err, nil) {
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
}
s := RPCServer{Engine: &Engine{ExchangeManager: em}}
_, err = s.ChangePositionMargin(context.Background(), nil)
if !errors.Is(err, common.ErrNilPointer) {
t.Errorf("received '%v' expected '%v'", err, common.ErrNilPointer)
}
req := &gctrpc.ChangePositionMarginRequest{}
_, err = s.ChangePositionMargin(context.Background(), req)
if !errors.Is(err, currency.ErrCurrencyPairEmpty) {
t.Errorf("received '%v' expected '%v'", err, currency.ErrCurrencyPairEmpty)
}
req.Exchange = fakeExchangeName
req.Pair = &gctrpc.CurrencyPair{
Delimiter: "-",
Base: cp.Base.String(),
Quote: cp.Quote.String(),
}
req.Asset = asset.USDTMarginedFutures.String()
req.MarginSide = "BOTH"
req.OriginalAllocatedMargin = 1337
req.NewAllocatedMargin = 1338
req.MarginType = "isolated"
_, err = s.ChangePositionMargin(context.Background(), req)
if !errors.Is(err, nil) {
t.Errorf("received '%v' expected '%v'", err, nil)
}
}
func TestSetLeverage(t *testing.T) {
t.Parallel()
em := NewExchangeManager()
exch, err := em.NewExchangeByName("binance")
if err != nil {
t.Fatal(err)
}
exch.SetDefaults()
b := exch.GetBase()
b.Name = fakeExchangeName
b.Enabled = true
cp, err := currency.NewPairFromString("btc-mad")
if err != nil {
t.Fatal(err)
}
b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore)
b.CurrencyPairs.Pairs[asset.USDTMarginedFutures] = &currency.PairStore{
AssetEnabled: convert.BoolPtr(true),
ConfigFormat: &currency.PairFormat{Delimiter: "/"},
RequestFormat: &currency.PairFormat{Delimiter: "/"},
Available: currency.Pairs{cp},
Enabled: currency.Pairs{cp},
}
fakeExchange := fExchange{
IBotExchange: exch,
}
err = em.Add(fakeExchange)
if !errors.Is(err, nil) {
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
}
s := RPCServer{Engine: &Engine{ExchangeManager: em}}
_, err = s.SetLeverage(context.Background(), nil)
if !errors.Is(err, common.ErrNilPointer) {
t.Errorf("received '%v' expected '%v'", err, common.ErrNilPointer)
}
req := &gctrpc.SetLeverageRequest{}
_, err = s.SetLeverage(context.Background(), req)
if !errors.Is(err, currency.ErrCurrencyPairEmpty) {
t.Error(err)
}
req.Exchange = fakeExchangeName
req.Pair = &gctrpc.CurrencyPair{
Delimiter: "-",
Base: cp.Base.String(),
Quote: cp.Quote.String(),
}
req.UnderlyingPair = &gctrpc.CurrencyPair{
Delimiter: "-",
Base: cp.Base.String(),
Quote: cp.Quote.String(),
}
req.Asset = asset.USDTMarginedFutures.String()
req.MarginType = "isolated"
req.Leverage = 1337
_, err = s.SetLeverage(context.Background(), req)
if !errors.Is(err, nil) {
t.Error(err)
}
req.OrderSide = "lol"
_, err = s.SetLeverage(context.Background(), req)
if !errors.Is(err, order.ErrSideIsInvalid) {
t.Error(err)
}
req.OrderSide = order.Long.String()
_, err = s.SetLeverage(context.Background(), req)
if !errors.Is(err, nil) {
t.Error(err)
}
}
func TestGetLeverage(t *testing.T) {
t.Parallel()
em := NewExchangeManager()
exch, err := em.NewExchangeByName("binance")
if err != nil {
t.Fatal(err)
}
exch.SetDefaults()
b := exch.GetBase()
b.Name = fakeExchangeName
b.Enabled = true
cp, err := currency.NewPairFromString("btc-mad")
if err != nil {
t.Fatal(err)
}
b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore)
b.CurrencyPairs.Pairs[asset.USDTMarginedFutures] = &currency.PairStore{
AssetEnabled: convert.BoolPtr(true),
ConfigFormat: &currency.PairFormat{Delimiter: "/"},
RequestFormat: &currency.PairFormat{Delimiter: "/"},
Available: currency.Pairs{cp},
Enabled: currency.Pairs{cp},
}
fakeExchange := fExchange{
IBotExchange: exch,
}
err = em.Add(fakeExchange)
if !errors.Is(err, nil) {
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
}
s := RPCServer{Engine: &Engine{ExchangeManager: em}}
_, err = s.GetLeverage(context.Background(), nil)
if !errors.Is(err, common.ErrNilPointer) {
t.Errorf("received '%v' expected '%v'", err, common.ErrNilPointer)
}
req := &gctrpc.GetLeverageRequest{}
_, err = s.GetLeverage(context.Background(), req)
if !errors.Is(err, currency.ErrCurrencyPairEmpty) {
t.Error(err)
}
req.Exchange = fakeExchangeName
req.Pair = &gctrpc.CurrencyPair{
Delimiter: "-",
Base: cp.Base.String(),
Quote: cp.Quote.String(),
}
req.UnderlyingPair = &gctrpc.CurrencyPair{
Delimiter: "-",
Base: cp.Base.String(),
Quote: cp.Quote.String(),
}
req.Asset = asset.USDTMarginedFutures.String()
req.MarginType = "isolated"
lev, err := s.GetLeverage(context.Background(), req)
if !errors.Is(err, nil) {
t.Error(err)
}
if lev.Leverage != 1337 {
t.Errorf("received '%v' expected '%v'", lev, 1337)
}
req.OrderSide = "lol"
_, err = s.GetLeverage(context.Background(), req)
if !errors.Is(err, order.ErrSideIsInvalid) {
t.Error(err)
}
req.OrderSide = order.Long.String()
_, err = s.GetLeverage(context.Background(), req)
if !errors.Is(err, nil) {
t.Error(err)
}
}
func TestSetMarginType(t *testing.T) {
t.Parallel()
em := NewExchangeManager()
exch, err := em.NewExchangeByName("binance")
if err != nil {
t.Fatal(err)
}
exch.SetDefaults()
b := exch.GetBase()
b.Name = fakeExchangeName
b.Enabled = true
cp, err := currency.NewPairFromString("btc-mad")
if err != nil {
t.Fatal(err)
}
b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore)
b.CurrencyPairs.Pairs[asset.USDTMarginedFutures] = &currency.PairStore{
AssetEnabled: convert.BoolPtr(true),
ConfigFormat: &currency.PairFormat{Delimiter: "/"},
RequestFormat: &currency.PairFormat{Delimiter: "/"},
Available: currency.Pairs{cp},
Enabled: currency.Pairs{cp},
}
fakeExchange := fExchange{
IBotExchange: exch,
}
err = em.Add(fakeExchange)
if !errors.Is(err, nil) {
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
}
s := RPCServer{Engine: &Engine{ExchangeManager: em}}
_, err = s.SetMarginType(context.Background(), nil)
if !errors.Is(err, common.ErrNilPointer) {
t.Errorf("received '%v' expected '%v'", err, common.ErrNilPointer)
}
req := &gctrpc.SetMarginTypeRequest{}
_, err = s.SetMarginType(context.Background(), req)
if !errors.Is(err, currency.ErrCurrencyPairEmpty) {
t.Error(err)
}
req.Exchange = fakeExchangeName
req.Pair = &gctrpc.CurrencyPair{
Delimiter: "-",
Base: cp.Base.String(),
Quote: cp.Quote.String(),
}
req.Asset = asset.USDTMarginedFutures.String()
req.MarginType = "isolated"
_, err = s.SetMarginType(context.Background(), req)
if !errors.Is(err, nil) {
t.Error(err)
}
}
func TestSetCollateralMode(t *testing.T) {
t.Parallel()
em := NewExchangeManager()
exch, err := em.NewExchangeByName("binance")
if err != nil {
t.Fatal(err)
}
exch.SetDefaults()
b := exch.GetBase()
b.Name = fakeExchangeName
b.Enabled = true
cp, err := currency.NewPairFromString("btc-mad")
if err != nil {
t.Fatal(err)
}
b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore)
b.CurrencyPairs.Pairs[asset.USDTMarginedFutures] = &currency.PairStore{
AssetEnabled: convert.BoolPtr(true),
ConfigFormat: &currency.PairFormat{Delimiter: "/"},
RequestFormat: &currency.PairFormat{Delimiter: "/"},
Available: currency.Pairs{cp},
Enabled: currency.Pairs{cp},
}
fakeExchange := fExchange{
IBotExchange: exch,
}
err = em.Add(fakeExchange)
if !errors.Is(err, nil) {
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
}
s := RPCServer{Engine: &Engine{ExchangeManager: em}}
_, err = s.SetCollateralMode(context.Background(), nil)
if !errors.Is(err, common.ErrNilPointer) {
t.Errorf("received '%v' expected '%v'", err, common.ErrNilPointer)
}
req := &gctrpc.SetCollateralModeRequest{}
_, err = s.SetCollateralMode(context.Background(), req)
if !errors.Is(err, ErrExchangeNameIsEmpty) {
t.Error(err)
}
req.Exchange = fakeExchangeName
req.Asset = asset.USDTMarginedFutures.String()
req.CollateralMode = "single"
_, err = s.SetCollateralMode(context.Background(), req)
if !errors.Is(err, nil) {
t.Error(err)
}
}
func TestGetCollateralMode(t *testing.T) {
t.Parallel()
em := NewExchangeManager()
exch, err := em.NewExchangeByName("binance")
if err != nil {
t.Fatal(err)
}
exch.SetDefaults()
b := exch.GetBase()
b.Name = fakeExchangeName
b.Enabled = true
b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore)
b.CurrencyPairs.Pairs[asset.USDTMarginedFutures] = &currency.PairStore{
AssetEnabled: convert.BoolPtr(true),
}
fakeExchange := fExchange{
IBotExchange: exch,
}
err = em.Add(fakeExchange)
if !errors.Is(err, nil) {
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
}
s := RPCServer{Engine: &Engine{ExchangeManager: em}}
_, err = s.GetCollateralMode(context.Background(), nil)
if !errors.Is(err, common.ErrNilPointer) {
t.Errorf("received '%v' expected '%v'", err, common.ErrNilPointer)
}
req := &gctrpc.GetCollateralModeRequest{}
_, err = s.GetCollateralMode(context.Background(), req)
if !errors.Is(err, ErrExchangeNameIsEmpty) {
t.Error(err)
}
req.Exchange = fakeExchangeName
req.Asset = asset.USDTMarginedFutures.String()
_, err = s.GetCollateralMode(context.Background(), req)
if !errors.Is(err, nil) {
t.Error(err)
}
}