exchanges: Initial context propagation (#744)

* gct: phase one context awareness pass

* exchanges: context propagation pass

* common/requester: force context requirement

* gctcli/exchanges: linter fix

* rpcserver: fix test using dummy rpc server

* backtester: fix comments

* grpc: add correct cancel and timeout for commands

* rpcserver_test: add comment on dummy server

* common: deprecated SendHTTPGetRequest

* linter: fix

* linter: turn on no context check

* apichecker: fix context linter issue

* binance: use param context

* common: remove checks as this gets executed before main

* common: change mutex to RW as clients can be used by multiple go routines.

* common: remove init and JIT default client. Unexport global variables and add protection.

* common: Add comments

* bithumb: after dinner mints fix
This commit is contained in:
Ryan O'Hara-Reid
2021-09-11 13:52:07 +10:00
committed by GitHub
parent 72516f7268
commit d636049fb2
168 changed files with 8085 additions and 6996 deletions

View File

@@ -320,7 +320,7 @@ func getAllActiveOrderbooks(m iExchangeManager) []EnabledExchangeOrderbooks {
continue
}
for z := range currencies {
ob, err := exchanges[x].FetchOrderbook(currencies[z], assets[y])
ob, err := exchanges[x].FetchOrderbook(context.TODO(), currencies[z], assets[y])
if err != nil {
log.Errorf(log.APIServerMgr,
"Exchange %s failed to retrieve %s orderbook. Err: %s\n", exchName,
@@ -357,7 +357,7 @@ func getAllActiveTickers(m iExchangeManager) []EnabledExchangeCurrencies {
continue
}
for z := range currencies {
t, err := exchanges[x].FetchTicker(currencies[z], assets[y])
t, err := exchanges[x].FetchTicker(context.TODO(), currencies[z], assets[y])
if err != nil {
log.Errorf(log.APIServerMgr,
"Exchange %s failed to retrieve %s ticker. Err: %s\n", exchName,
@@ -383,7 +383,7 @@ func getAllActiveAccounts(m iExchangeManager) []AllEnabledExchangeAccounts {
exchName := exchanges[x].GetName()
var exchangeAccounts AllEnabledExchangeAccounts
for y := range assets {
a, err := exchanges[x].FetchAccountInfo(assets[y])
a, err := exchanges[x].FetchAccountInfo(context.TODO(), assets[y])
if err != nil {
log.Errorf(log.APIServerMgr,
"Exchange %s failed to retrieve %s ticker. Err: %s\n",
@@ -818,7 +818,7 @@ func wsGetTicker(client *websocketClient, data interface{}) error {
}
return err
}
tick, err := exch.FetchTicker(p, a)
tick, err := exch.FetchTicker(context.TODO(), p, a)
if err != nil {
wsResp.Error = err.Error()
sendErr := client.SendWebsocketMessage(wsResp)
@@ -873,7 +873,7 @@ func wsGetOrderbook(client *websocketClient, data interface{}) error {
}
return err
}
ob, err := exch.FetchOrderbook(p, a)
ob, err := exch.FetchOrderbook(context.TODO(), p, a)
if err != nil {
wsResp.Error = err.Error()
sendErr := client.SendWebsocketMessage(wsResp)

View File

@@ -1,6 +1,7 @@
package engine
import (
"context"
"database/sql"
"errors"
"fmt"
@@ -699,7 +700,12 @@ func (m *DataHistoryManager) processCandleData(job *DataHistoryJob, exch exchang
Status: dataHistoryStatusComplete,
Date: time.Now(),
}
candles, err := exch.GetHistoricCandlesExtended(job.Pair, job.Asset, startRange, endRange, job.Interval)
candles, err := exch.GetHistoricCandlesExtended(context.TODO(),
job.Pair,
job.Asset,
startRange,
endRange,
job.Interval)
if err != nil {
r.Result += "could not get candles: " + err.Error() + ". "
r.Status = dataHistoryStatusFailed
@@ -744,7 +750,11 @@ func (m *DataHistoryManager) processTradeData(job *DataHistoryJob, exch exchange
Status: dataHistoryStatusComplete,
Date: time.Now(),
}
trades, err := exch.GetHistoricTrades(job.Pair, job.Asset, startRange, endRange)
trades, err := exch.GetHistoricTrades(context.TODO(),
job.Pair,
job.Asset,
startRange,
endRange)
if err != nil {
r.Result += "could not get trades: " + err.Error() + ". "
r.Status = dataHistoryStatusFailed
@@ -893,7 +903,12 @@ func (m *DataHistoryManager) validateCandles(job *DataHistoryJob, exch exchange.
Date: time.Now(),
}
apiCandles, err := exch.GetHistoricCandlesExtended(job.Pair, job.Asset, startRange, endRange, job.Interval)
apiCandles, err := exch.GetHistoricCandlesExtended(context.TODO(),
job.Pair,
job.Asset,
startRange,
endRange,
job.Interval)
if err != nil {
r.Result = "could not get API candles: " + err.Error()
r.Status = dataHistoryStatusFailed

View File

@@ -1,6 +1,7 @@
package engine
import (
"context"
"database/sql"
"errors"
"strings"
@@ -1542,7 +1543,7 @@ type dhmExchange struct {
exchange.IBotExchange
}
func (f dhmExchange) GetHistoricCandlesExtended(p currency.Pair, a asset.Item, timeStart, _ time.Time, interval kline.Interval) (kline.Item, error) {
func (f dhmExchange) GetHistoricCandlesExtended(ctx context.Context, p currency.Pair, a asset.Item, timeStart, _ time.Time, interval kline.Interval) (kline.Item, error) {
return kline.Item{
Exchange: testExchange,
Pair: p,
@@ -1577,7 +1578,7 @@ func (f dhmExchange) GetHistoricCandlesExtended(p currency.Pair, a asset.Item, t
}, nil
}
func (f dhmExchange) GetHistoricTrades(p currency.Pair, a asset.Item, startTime, endTime time.Time) ([]trade.Data, error) {
func (f dhmExchange) GetHistoricTrades(ctx context.Context, p currency.Pair, a asset.Item, startTime, endTime time.Time) ([]trade.Data, error) {
return []trade.Data{
{
Exchange: testExchange,

View File

@@ -1,6 +1,7 @@
package engine
import (
"context"
"errors"
"fmt"
"log"
@@ -210,10 +211,22 @@ func validateSettings(b *Engine, s *Settings, flagSet map[string]bool) {
if b.Settings.GlobalHTTPTimeout <= 0 {
b.Settings.GlobalHTTPTimeout = b.Config.GlobalHTTPTimeout
}
common.SetHTTPClientWithTimeout(b.Settings.GlobalHTTPTimeout)
err := common.SetHTTPClientWithTimeout(b.Settings.GlobalHTTPTimeout)
if err != nil {
gctlog.Errorf(gctlog.Global,
"Could not set new HTTP Client with timeout %s error: %v",
b.Settings.GlobalHTTPTimeout,
err)
}
if b.Settings.GlobalHTTPUserAgent != "" {
common.HTTPUserAgent = b.Settings.GlobalHTTPUserAgent
err = common.SetHTTPUserAgent(b.Settings.GlobalHTTPUserAgent)
if err != nil {
gctlog.Errorf(gctlog.Global, "Could not set HTTP User Agent for %s error: %v",
b.Settings.GlobalHTTPUserAgent,
err)
}
}
}
@@ -809,7 +822,7 @@ func (bot *Engine) LoadExchange(name string, wg *sync.WaitGroup) error {
useAsset = assetTypes[a]
break
}
err = exch.ValidateCredentials(useAsset)
err = exch.ValidateCredentials(context.TODO(), useAsset)
if err != nil {
gctlog.Warnf(gctlog.ExchangeSys,
"%s: Cannot validate credentials, authenticated support has been disabled, Error: %s\n",

View File

@@ -1,6 +1,7 @@
package engine
import (
"context"
"errors"
"strings"
"sync/atomic"
@@ -284,7 +285,8 @@ func TestCheckEventCondition(t *testing.T) {
t.Error("expected error")
}
m.m.Unlock()
_, err = exch.FetchTicker(currency.NewPair(currency.BTC, currency.USD), asset.Spot)
_, err = exch.FetchTicker(context.Background(),
currency.NewPair(currency.BTC, currency.USD), asset.Spot)
if !errors.Is(err, nil) {
t.Errorf("error '%v', expected '%v'", err, nil)
}
@@ -308,7 +310,8 @@ func TestCheckEventCondition(t *testing.T) {
}
m.m.Unlock()
_, err = exch.FetchOrderbook(currency.NewPair(currency.BTC, currency.USD), asset.Spot)
_, err = exch.FetchOrderbook(context.Background(),
currency.NewPair(currency.BTC, currency.USD), asset.Spot)
if !errors.Is(err, nil) {
t.Errorf("error '%v', expected '%v'", err, nil)
}

View File

@@ -1,6 +1,7 @@
package engine
import (
"context"
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
@@ -542,22 +543,22 @@ func GetRelatableCurrencies(p currency.Pair, incOrig, incUSDT bool) currency.Pai
// GetSpecificOrderbook returns a specific orderbook given the currency,
// exchangeName and assetType
func (bot *Engine) GetSpecificOrderbook(p currency.Pair, exchangeName string, assetType asset.Item) (*orderbook.Base, error) {
func (bot *Engine) GetSpecificOrderbook(ctx context.Context, p currency.Pair, exchangeName string, assetType asset.Item) (*orderbook.Base, error) {
exch, err := bot.GetExchangeByName(exchangeName)
if err != nil {
return nil, err
}
return exch.FetchOrderbook(p, assetType)
return exch.FetchOrderbook(ctx, p, assetType)
}
// GetSpecificTicker returns a specific ticker given the currency,
// exchangeName and assetType
func (bot *Engine) GetSpecificTicker(p currency.Pair, exchangeName string, assetType asset.Item) (*ticker.Price, error) {
func (bot *Engine) GetSpecificTicker(ctx context.Context, p currency.Pair, exchangeName string, assetType asset.Item) (*ticker.Price, error) {
exch, err := bot.GetExchangeByName(exchangeName)
if err != nil {
return nil, err
}
return exch.FetchTicker(p, assetType)
return exch.FetchTicker(ctx, p, assetType)
}
// GetCollatedExchangeAccountInfoByCoin collates individual exchange account
@@ -668,7 +669,7 @@ func (bot *Engine) GetCryptocurrencyDepositAddressesByExchange(exchName string)
// GetExchangeCryptocurrencyDepositAddress returns the cryptocurrency deposit address for a particular
// exchange
func (bot *Engine) GetExchangeCryptocurrencyDepositAddress(exchName, accountID string, item currency.Code) (string, error) {
func (bot *Engine) GetExchangeCryptocurrencyDepositAddress(ctx context.Context, exchName, accountID string, item currency.Code) (string, error) {
if bot.DepositAddressManager != nil {
return bot.DepositAddressManager.GetDepositAddressByExchangeAndCurrency(exchName, item)
}
@@ -677,7 +678,7 @@ func (bot *Engine) GetExchangeCryptocurrencyDepositAddress(exchName, accountID s
if err != nil {
return "", err
}
return exch.GetDepositAddress(item, accountID)
return exch.GetDepositAddress(ctx, item, accountID)
}
// GetExchangeCryptocurrencyDepositAddresses obtains an exchanges deposit cryptocurrency list
@@ -702,7 +703,9 @@ func (bot *Engine) GetExchangeCryptocurrencyDepositAddresses() map[string]map[st
cryptoAddr := make(map[string]string)
for y := range cryptoCurrencies {
cryptocurrency := cryptoCurrencies[y]
depositAddr, err := exchanges[x].GetDepositAddress(currency.NewCode(cryptocurrency), "")
depositAddr, err := exchanges[x].GetDepositAddress(context.TODO(),
currency.NewCode(cryptocurrency),
"")
if err != nil {
log.Errorf(log.Global, "%s failed to get cryptocurrency deposit addresses. Err: %s\n", exchName, err)
continue
@@ -727,7 +730,7 @@ func (bot *Engine) GetExchangeNames(enabledOnly bool) []string {
}
// GetAllActiveTickers returns all enabled exchange tickers
func (bot *Engine) GetAllActiveTickers() []EnabledExchangeCurrencies {
func (bot *Engine) GetAllActiveTickers(ctx context.Context) []EnabledExchangeCurrencies {
var tickerData []EnabledExchangeCurrencies
exchanges := bot.GetExchanges()
for x := range exchanges {
@@ -746,7 +749,7 @@ func (bot *Engine) GetAllActiveTickers() []EnabledExchangeCurrencies {
continue
}
for z := range currencies {
tp, err := exchanges[x].FetchTicker(currencies[z], assets[y])
tp, err := exchanges[x].FetchTicker(ctx, currencies[z], assets[y])
if err != nil {
log.Errorf(log.ExchangeSys, "Exchange %s failed to retrieve %s ticker. Err: %s\n", exchName,
currencies[z].String(),

View File

@@ -1,6 +1,7 @@
package engine
import (
"context"
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
@@ -773,7 +774,8 @@ func TestGetSpecificOrderbook(t *testing.T) {
t.Fatal(err)
}
ob, err := e.GetSpecificOrderbook(btsusd, testExchange, asset.Spot)
ob, err := e.GetSpecificOrderbook(context.Background(),
btsusd, testExchange, asset.Spot)
if err != nil {
t.Fatal(err)
}
@@ -787,7 +789,8 @@ func TestGetSpecificOrderbook(t *testing.T) {
t.Fatal(err)
}
_, err = e.GetSpecificOrderbook(ethltc, testExchange, asset.Spot)
_, err = e.GetSpecificOrderbook(context.Background(),
ethltc, testExchange, asset.Spot)
if err == nil {
t.Fatal("Unexpected result")
}
@@ -815,7 +818,8 @@ func TestGetSpecificTicker(t *testing.T) {
t.Fatal("ProcessTicker error", err)
}
tick, err := e.GetSpecificTicker(p, testExchange, asset.Spot)
tick, err := e.GetSpecificTicker(context.Background(),
p, testExchange, asset.Spot)
if err != nil {
t.Fatal(err)
}
@@ -829,7 +833,8 @@ func TestGetSpecificTicker(t *testing.T) {
t.Fatal(err)
}
_, err = e.GetSpecificTicker(ethltc, testExchange, asset.Spot)
_, err = e.GetSpecificTicker(context.Background(),
ethltc, testExchange, asset.Spot)
if err == nil {
t.Fatal("Unexpected result")
}

View File

@@ -1,6 +1,7 @@
package engine
import (
"context"
"errors"
"fmt"
"strings"
@@ -86,7 +87,8 @@ func (m *OrderManager) Stop() error {
func (m *OrderManager) gracefulShutdown() {
if m.cfg.CancelOrdersOnShutdown {
log.Debugln(log.OrderMgr, "Order manager: Cancelling any open orders...")
m.CancelAllOrders(m.orderStore.exchangeManager.GetExchanges())
m.CancelAllOrders(context.TODO(),
m.orderStore.exchangeManager.GetExchanges())
}
}
@@ -113,7 +115,7 @@ func (m *OrderManager) run() {
}
// CancelAllOrders iterates and cancels all orders for each exchange provided
func (m *OrderManager) CancelAllOrders(exchangeNames []exchange.IBotExchange) {
func (m *OrderManager) CancelAllOrders(ctx context.Context, exchangeNames []exchange.IBotExchange) {
if m == nil || atomic.LoadInt32(&m.started) == 0 {
return
}
@@ -130,7 +132,7 @@ func (m *OrderManager) CancelAllOrders(exchangeNames []exchange.IBotExchange) {
}
for j := range exchangeOrders {
log.Debugf(log.OrderMgr, "Order manager: Cancelling order(s) for exchange %s.", exchangeNames[i].GetName())
err := m.Cancel(&order.Cancel{
err := m.Cancel(ctx, &order.Cancel{
Exchange: exchangeOrders[j].Exchange,
ID: exchangeOrders[j].ID,
AccountID: exchangeOrders[j].AccountID,
@@ -150,7 +152,7 @@ func (m *OrderManager) CancelAllOrders(exchangeNames []exchange.IBotExchange) {
// Cancel will find the order in the OrderManager, send a cancel request
// to the exchange and if successful, update the status of the order
func (m *OrderManager) Cancel(cancel *order.Cancel) error {
func (m *OrderManager) Cancel(ctx context.Context, cancel *order.Cancel) error {
if m == nil {
return fmt.Errorf("order manager %w", ErrNilSubsystem)
}
@@ -193,7 +195,7 @@ func (m *OrderManager) Cancel(cancel *order.Cancel) error {
log.Debugf(log.OrderMgr, "Order manager: Cancelling order ID %v [%+v]",
cancel.ID, cancel)
err = exch.CancelOrder(cancel)
err = exch.CancelOrder(ctx, cancel)
if err != nil {
err = fmt.Errorf("%v - Failed to cancel order: %w", cancel.Exchange, err)
return err
@@ -219,7 +221,7 @@ func (m *OrderManager) Cancel(cancel *order.Cancel) error {
// GetOrderInfo calls the exchange's wrapper GetOrderInfo function
// and stores the result in the order manager
func (m *OrderManager) GetOrderInfo(exchangeName, orderID string, cp currency.Pair, a asset.Item) (order.Detail, error) {
func (m *OrderManager) GetOrderInfo(ctx context.Context, exchangeName, orderID string, cp currency.Pair, a asset.Item) (order.Detail, error) {
if m == nil {
return order.Detail{}, fmt.Errorf("order manager %w", ErrNilSubsystem)
}
@@ -235,7 +237,7 @@ func (m *OrderManager) GetOrderInfo(exchangeName, orderID string, cp currency.Pa
if err != nil {
return order.Detail{}, err
}
result, err := exch.GetOrderInfo(orderID, cp, a)
result, err := exch.GetOrderInfo(ctx, orderID, cp, a)
if err != nil {
return order.Detail{}, err
}
@@ -285,7 +287,7 @@ func (m *OrderManager) validate(newOrder *order.Submit) error {
// Modify depends on the order.Modify.ID and order.Modify.Exchange fields to uniquely
// identify an order to modify.
func (m *OrderManager) Modify(mod *order.Modify) (*order.ModifyResponse, error) {
func (m *OrderManager) Modify(ctx context.Context, mod *order.Modify) (*order.ModifyResponse, error) {
if m == nil {
return nil, fmt.Errorf("order manager %w", ErrNilSubsystem)
}
@@ -320,7 +322,7 @@ func (m *OrderManager) Modify(mod *order.Modify) (*order.ModifyResponse, error)
if err != nil {
return nil, err
}
res, err := exch.ModifyOrder(mod)
res, err := exch.ModifyOrder(ctx, mod)
if err != nil {
message := fmt.Sprintf(
"Order manager: Exchange %s order ID=%v: failed to modify",
@@ -356,7 +358,7 @@ func (m *OrderManager) Modify(mod *order.Modify) (*order.ModifyResponse, error)
// Submit will take in an order struct, send it to the exchange and
// populate it in the OrderManager if successful
func (m *OrderManager) Submit(newOrder *order.Submit) (*OrderSubmitResponse, error) {
func (m *OrderManager) Submit(ctx context.Context, newOrder *order.Submit) (*OrderSubmitResponse, error) {
if m == nil {
return nil, fmt.Errorf("order manager %w", ErrNilSubsystem)
}
@@ -386,7 +388,7 @@ func (m *OrderManager) Submit(newOrder *order.Submit) (*OrderSubmitResponse, err
err)
}
result, err := exch.SubmitOrder(newOrder)
result, err := exch.SubmitOrder(ctx, newOrder)
if err != nil {
return nil, err
}
@@ -589,7 +591,7 @@ func (m *OrderManager) processOrders() {
Pairs: pairs,
AssetType: supportedAssets[y],
}
result, err := exchanges[i].GetActiveOrders(&req)
result, err := exchanges[i].GetActiveOrders(context.TODO(), &req)
if err != nil {
log.Warnf(log.OrderMgr,
"Order manager: Unable to get active orders for %s and asset type %s: %s",

View File

@@ -1,6 +1,7 @@
package engine
import (
"context"
"errors"
"sync"
"testing"
@@ -20,14 +21,14 @@ type omfExchange struct {
// CancelOrder overrides testExchange's cancel order function
// to do the bare minimum required with no API calls or credentials required
func (f omfExchange) CancelOrder(o *order.Cancel) error {
func (f omfExchange) CancelOrder(ctx context.Context, o *order.Cancel) error {
o.Status = order.Cancelled
return nil
}
// GetOrderInfo overrides testExchange's get order function
// to do the bare minimum required with no API calls or credentials required
func (f omfExchange) GetOrderInfo(orderID string, pair currency.Pair, assetType asset.Item) (order.Detail, error) {
func (f omfExchange) GetOrderInfo(ctx context.Context, orderID string, pair currency.Pair, assetType asset.Item) (order.Detail, error) {
if orderID == "" {
return order.Detail{}, errors.New("")
}
@@ -40,7 +41,7 @@ func (f omfExchange) GetOrderInfo(orderID string, pair currency.Pair, assetType
}, nil
}
func (f omfExchange) ModifyOrder(action *order.Modify) (order.Modify, error) {
func (f omfExchange) ModifyOrder(ctx context.Context, action *order.Modify) (order.Modify, error) {
ans := *action
ans.ID = "modified_order_id"
return ans, nil
@@ -391,35 +392,36 @@ func TestStore_modifyOrder(t *testing.T) {
func TestCancelOrder(t *testing.T) {
m := OrdersSetup(t)
err := m.Cancel(nil)
err := m.Cancel(context.Background(), nil)
if err == nil {
t.Error("Expected error due to empty order")
}
err = m.Cancel(&order.Cancel{})
err = m.Cancel(context.Background(), &order.Cancel{})
if err == nil {
t.Error("Expected error due to empty order")
}
err = m.Cancel(&order.Cancel{
err = m.Cancel(context.Background(), &order.Cancel{
Exchange: testExchange,
})
if err == nil {
t.Error("Expected error due to no order ID")
}
err = m.Cancel(&order.Cancel{
err = m.Cancel(context.Background(), &order.Cancel{
ID: "ID",
})
if err == nil {
t.Error("Expected error due to no Exchange")
}
err = m.Cancel(&order.Cancel{
ID: "ID",
Exchange: testExchange,
AssetType: asset.Binary,
})
err = m.Cancel(context.Background(),
&order.Cancel{
ID: "ID",
Exchange: testExchange,
AssetType: asset.Binary,
})
if err == nil {
t.Error("Expected error due to bad asset type")
}
@@ -434,11 +436,12 @@ func TestCancelOrder(t *testing.T) {
t.Error(err)
}
err = m.Cancel(&order.Cancel{
ID: "Unknown",
Exchange: testExchange,
AssetType: asset.Spot,
})
err = m.Cancel(context.Background(),
&order.Cancel{
ID: "Unknown",
Exchange: testExchange,
AssetType: asset.Spot,
})
if err == nil {
t.Error("Expected error due to no order found")
}
@@ -457,7 +460,7 @@ func TestCancelOrder(t *testing.T) {
Date: time.Now(),
Pair: pair,
}
err = m.Cancel(cancel)
err = m.Cancel(context.Background(), cancel)
if !errors.Is(err, nil) {
t.Errorf("error '%v', expected '%v'", err, nil)
}
@@ -469,13 +472,14 @@ func TestCancelOrder(t *testing.T) {
func TestGetOrderInfo(t *testing.T) {
m := OrdersSetup(t)
_, err := m.GetOrderInfo("", "", currency.Pair{}, "")
_, err := m.GetOrderInfo(context.Background(), "", "", currency.Pair{}, "")
if err == nil {
t.Error("Expected error due to empty order")
}
var result order.Detail
result, err = m.GetOrderInfo(testExchange, "1337", currency.Pair{}, "")
result, err = m.GetOrderInfo(context.Background(),
testExchange, "1337", currency.Pair{}, "")
if err != nil {
t.Error(err)
}
@@ -483,7 +487,8 @@ func TestGetOrderInfo(t *testing.T) {
t.Error("unexpected order returned")
}
result, err = m.GetOrderInfo(testExchange, "1337", currency.Pair{}, "")
result, err = m.GetOrderInfo(context.Background(),
testExchange, "1337", currency.Pair{}, "")
if err != nil {
t.Error(err)
}
@@ -504,7 +509,7 @@ func TestCancelAllOrders(t *testing.T) {
t.Error(err)
}
m.CancelAllOrders([]exchange.IBotExchange{})
m.CancelAllOrders(context.Background(), []exchange.IBotExchange{})
if o.Status == order.Cancelled {
t.Error("Order should not be cancelled")
}
@@ -514,13 +519,13 @@ func TestCancelAllOrders(t *testing.T) {
t.Fatal(err)
}
m.CancelAllOrders([]exchange.IBotExchange{exch})
m.CancelAllOrders(context.Background(), []exchange.IBotExchange{exch})
if o.Status != order.Cancelled {
t.Error("Order should be cancelled")
}
o.Status = order.New
m.CancelAllOrders(nil)
m.CancelAllOrders(context.Background(), nil)
if o.Status != order.New {
t.Error("Order should not be cancelled")
}
@@ -528,7 +533,7 @@ func TestCancelAllOrders(t *testing.T) {
func TestSubmit(t *testing.T) {
m := OrdersSetup(t)
_, err := m.Submit(nil)
_, err := m.Submit(context.Background(), nil)
if err == nil {
t.Error("Expected error from nil order")
}
@@ -539,13 +544,13 @@ func TestSubmit(t *testing.T) {
Status: order.New,
Type: order.Market,
}
_, err = m.Submit(o)
_, err = m.Submit(context.Background(), o)
if err == nil {
t.Error("Expected error from empty exchange")
}
o.Exchange = testExchange
_, err = m.Submit(o)
_, err = m.Submit(context.Background(), o)
if err == nil {
t.Error("Expected error from validation")
}
@@ -562,20 +567,20 @@ func TestSubmit(t *testing.T) {
o.Side = order.Buy
o.Amount = 1
o.Price = 1
_, err = m.Submit(o)
_, err = m.Submit(context.Background(), o)
if err == nil {
t.Error("Expected fail due to order market type is not allowed")
}
m.cfg.AllowMarketOrders = true
m.cfg.LimitAmount = 1
o.Amount = 2
_, err = m.Submit(o)
_, err = m.Submit(context.Background(), o)
if err == nil {
t.Error("Expected fail due to order limit exceeds allowed limit")
}
m.cfg.LimitAmount = 0
m.cfg.AllowedExchanges = []string{"fake"}
_, err = m.Submit(o)
_, err = m.Submit(context.Background(), o)
if err == nil {
t.Error("Expected fail due to order exchange not found in allowed list")
}
@@ -587,13 +592,13 @@ func TestSubmit(t *testing.T) {
m.cfg.AllowedExchanges = nil
m.cfg.AllowedPairs = currency.Pairs{failPair}
_, err = m.Submit(o)
_, err = m.Submit(context.Background(), o)
if err == nil {
t.Error("Expected fail due to order pair not found in allowed list")
}
m.cfg.AllowedPairs = nil
_, err = m.Submit(o)
_, err = m.Submit(context.Background(), o)
if !errors.Is(err, exchange.ErrAuthenticatedRequestWithoutCredentialsSet) {
t.Errorf("error '%v', expected '%v'", err, exchange.ErrAuthenticatedRequestWithoutCredentialsSet)
}
@@ -629,15 +634,14 @@ func TestOrderManager_Modify(t *testing.T) {
AssetType: asset.Spot,
Pair: pair,
ID: "fake_order_id",
//
Price: 8,
Amount: 128,
Price: 8,
Amount: 128,
})
if err != nil {
t.Error(err)
}
resp, err := m.Modify(&mod)
resp, err := m.Modify(context.Background(), &mod)
if expectError {
if err == nil {
t.Fatal("Expected error")

View File

@@ -1,6 +1,7 @@
package engine
import (
"context"
"fmt"
"sync"
"sync/atomic"
@@ -246,7 +247,7 @@ func (m *portfolioManager) getExchangeAccountInfo(exchanges []exchange.IBotExcha
assetTypes := exchanges[x].GetAssetTypes(false) // left as available for now, to sync the full spectrum
var exchangeHoldings account.Holdings
for y := range assetTypes {
accountHoldings, err := exchanges[x].FetchAccountInfo(assetTypes[y])
accountHoldings, err := exchanges[x].FetchAccountInfo(context.TODO(), assetTypes[y])
if err != nil {
log.Errorf(log.PortfolioMgr,
"Error encountered retrieving exchange account info for %s. Error %s\n",

View File

@@ -343,7 +343,7 @@ func (s *RPCServer) GetExchangeInfo(_ context.Context, r *gctrpc.GenericExchange
// GetTicker returns the ticker for a specified exchange, currency pair and
// asset type
func (s *RPCServer) GetTicker(_ context.Context, r *gctrpc.GetTickerRequest) (*gctrpc.TickerResponse, error) {
func (s *RPCServer) GetTicker(ctx context.Context, r *gctrpc.GetTickerRequest) (*gctrpc.TickerResponse, error) {
a, err := asset.New(r.AssetType)
if err != nil {
return nil, err
@@ -363,11 +363,12 @@ func (s *RPCServer) GetTicker(_ context.Context, r *gctrpc.GetTickerRequest) (*g
return nil, err
}
t, err := s.GetSpecificTicker(currency.Pair{
Delimiter: r.Pair.Delimiter,
Base: currency.NewCode(r.Pair.Base),
Quote: currency.NewCode(r.Pair.Quote),
},
t, err := s.GetSpecificTicker(ctx,
currency.Pair{
Delimiter: r.Pair.Delimiter,
Base: currency.NewCode(r.Pair.Base),
Quote: currency.NewCode(r.Pair.Quote),
},
r.Exchange,
a,
)
@@ -392,8 +393,8 @@ func (s *RPCServer) GetTicker(_ context.Context, r *gctrpc.GetTickerRequest) (*g
// GetTickers returns a list of tickers for all enabled exchanges and all
// enabled currency pairs
func (s *RPCServer) GetTickers(_ context.Context, _ *gctrpc.GetTickersRequest) (*gctrpc.GetTickersResponse, error) {
activeTickers := s.GetAllActiveTickers()
func (s *RPCServer) GetTickers(ctx context.Context, _ *gctrpc.GetTickersRequest) (*gctrpc.GetTickersResponse, error) {
activeTickers := s.GetAllActiveTickers(ctx)
var tickers []*gctrpc.Tickers
for x := range activeTickers {
@@ -426,17 +427,18 @@ func (s *RPCServer) GetTickers(_ context.Context, _ *gctrpc.GetTickersRequest) (
// GetOrderbook returns an orderbook for a specific exchange, currency pair
// and asset type
func (s *RPCServer) GetOrderbook(_ context.Context, r *gctrpc.GetOrderbookRequest) (*gctrpc.OrderbookResponse, error) {
func (s *RPCServer) GetOrderbook(ctx context.Context, r *gctrpc.GetOrderbookRequest) (*gctrpc.OrderbookResponse, error) {
a, err := asset.New(r.AssetType)
if err != nil {
return nil, err
}
ob, err := s.GetSpecificOrderbook(currency.Pair{
Delimiter: r.Pair.Delimiter,
Base: currency.NewCode(r.Pair.Base),
Quote: currency.NewCode(r.Pair.Quote),
},
ob, err := s.GetSpecificOrderbook(ctx,
currency.Pair{
Delimiter: r.Pair.Delimiter,
Base: currency.NewCode(r.Pair.Base),
Quote: currency.NewCode(r.Pair.Quote),
},
r.Exchange,
a,
)
@@ -479,7 +481,7 @@ func (s *RPCServer) GetOrderbook(_ context.Context, r *gctrpc.GetOrderbookReques
// GetOrderbooks returns a list of orderbooks for all enabled exchanges and all
// enabled currency pairs
func (s *RPCServer) GetOrderbooks(_ context.Context, _ *gctrpc.GetOrderbooksRequest) (*gctrpc.GetOrderbooksResponse, error) {
func (s *RPCServer) GetOrderbooks(ctx context.Context, _ *gctrpc.GetOrderbooksRequest) (*gctrpc.GetOrderbooksResponse, error) {
exchanges := s.ExchangeManager.GetExchanges()
var obResponse []*gctrpc.Orderbooks
var obs []*gctrpc.OrderbookResponse
@@ -499,7 +501,7 @@ func (s *RPCServer) GetOrderbooks(_ context.Context, _ *gctrpc.GetOrderbooksRequ
continue
}
for z := range currencies {
resp, err := exchanges[x].FetchOrderbook(currencies[z], assets[y])
resp, err := exchanges[x].FetchOrderbook(ctx, currencies[z], assets[y])
if err != nil {
log.Errorf(log.RESTSys,
"Exchange %s failed to retrieve %s orderbook. Err: %s\n", exchName,
@@ -542,7 +544,7 @@ func (s *RPCServer) GetOrderbooks(_ context.Context, _ *gctrpc.GetOrderbooksRequ
}
// GetAccountInfo returns an account balance for a specific exchange
func (s *RPCServer) GetAccountInfo(_ context.Context, r *gctrpc.GetAccountInfoRequest) (*gctrpc.GetAccountInfoResponse, error) {
func (s *RPCServer) GetAccountInfo(ctx context.Context, r *gctrpc.GetAccountInfoRequest) (*gctrpc.GetAccountInfoResponse, error) {
assetType, err := asset.New(r.AssetType)
if err != nil {
return nil, err
@@ -558,7 +560,7 @@ func (s *RPCServer) GetAccountInfo(_ context.Context, r *gctrpc.GetAccountInfoRe
return nil, err
}
resp, err := exch.FetchAccountInfo(assetType)
resp, err := exch.FetchAccountInfo(ctx, assetType)
if err != nil {
return nil, err
}
@@ -567,7 +569,7 @@ func (s *RPCServer) GetAccountInfo(_ context.Context, r *gctrpc.GetAccountInfoRe
}
// UpdateAccountInfo forces an update of the account info
func (s *RPCServer) UpdateAccountInfo(_ context.Context, r *gctrpc.GetAccountInfoRequest) (*gctrpc.GetAccountInfoResponse, error) {
func (s *RPCServer) UpdateAccountInfo(ctx context.Context, r *gctrpc.GetAccountInfoRequest) (*gctrpc.GetAccountInfoResponse, error) {
assetType, err := asset.New(r.AssetType)
if err != nil {
return nil, err
@@ -583,7 +585,7 @@ func (s *RPCServer) UpdateAccountInfo(_ context.Context, r *gctrpc.GetAccountInf
return nil, err
}
resp, err := exch.UpdateAccountInfo(assetType)
resp, err := exch.UpdateAccountInfo(ctx, assetType)
if err != nil {
return nil, err
}
@@ -626,7 +628,7 @@ func (s *RPCServer) GetAccountInfoStream(r *gctrpc.GetAccountInfoRequest, stream
return err
}
initAcc, err := exch.FetchAccountInfo(assetType)
initAcc, err := exch.FetchAccountInfo(stream.Context(), assetType)
if err != nil {
return err
}
@@ -863,7 +865,7 @@ func (s *RPCServer) GetForexRates(_ context.Context, _ *gctrpc.GetForexRatesRequ
// GetOrders returns all open orders, filtered by exchange, currency pair or
// asset type between optional dates
func (s *RPCServer) GetOrders(_ context.Context, r *gctrpc.GetOrdersRequest) (*gctrpc.GetOrdersResponse, error) {
func (s *RPCServer) GetOrders(ctx context.Context, r *gctrpc.GetOrdersRequest) (*gctrpc.GetOrdersResponse, error) {
if r == nil {
return nil, errInvalidArguments
}
@@ -921,7 +923,7 @@ func (s *RPCServer) GetOrders(_ context.Context, r *gctrpc.GetOrdersRequest) (*g
}
var resp []order.Detail
resp, err = exch.GetActiveOrders(request)
resp, err = exch.GetActiveOrders(ctx, request)
if err != nil {
return nil, err
}
@@ -1064,7 +1066,7 @@ func (s *RPCServer) GetManagedOrders(_ context.Context, r *gctrpc.GetOrdersReque
}
// GetOrder returns order information based on exchange and order ID
func (s *RPCServer) GetOrder(_ context.Context, r *gctrpc.GetOrderRequest) (*gctrpc.OrderDetails, error) {
func (s *RPCServer) GetOrder(ctx context.Context, r *gctrpc.GetOrderRequest) (*gctrpc.OrderDetails, error) {
if r == nil {
return nil, errInvalidArguments
}
@@ -1094,7 +1096,11 @@ func (s *RPCServer) GetOrder(_ context.Context, r *gctrpc.GetOrderRequest) (*gct
return nil, err
}
result, err := s.OrderManager.GetOrderInfo(r.Exchange, r.OrderId, pair, a)
result, err := s.OrderManager.GetOrderInfo(ctx,
r.Exchange,
r.OrderId,
pair,
a)
if err != nil {
return nil, fmt.Errorf("error whilst trying to retrieve info for order %s: %w", r.OrderId, err)
}
@@ -1144,7 +1150,7 @@ func (s *RPCServer) GetOrder(_ context.Context, r *gctrpc.GetOrderRequest) (*gct
// SubmitOrder submits an order specified by exchange, currency pair and asset
// type
func (s *RPCServer) SubmitOrder(_ context.Context, r *gctrpc.SubmitOrderRequest) (*gctrpc.SubmitOrderResponse, error) {
func (s *RPCServer) SubmitOrder(ctx context.Context, r *gctrpc.SubmitOrderRequest) (*gctrpc.SubmitOrderResponse, error) {
a, err := asset.New(r.AssetType)
if err != nil {
return nil, err
@@ -1182,7 +1188,7 @@ func (s *RPCServer) SubmitOrder(_ context.Context, r *gctrpc.SubmitOrderRequest)
AssetType: a,
}
resp, err := s.OrderManager.Submit(submission)
resp, err := s.OrderManager.Submit(ctx, submission)
if err != nil {
return &gctrpc.SubmitOrderResponse{}, err
}
@@ -1206,7 +1212,7 @@ func (s *RPCServer) SubmitOrder(_ context.Context, r *gctrpc.SubmitOrderRequest)
// SimulateOrder simulates an order specified by exchange, currency pair and asset
// type
func (s *RPCServer) SimulateOrder(_ context.Context, r *gctrpc.SimulateOrderRequest) (*gctrpc.SimulateOrderResponse, error) {
func (s *RPCServer) SimulateOrder(ctx context.Context, r *gctrpc.SimulateOrderRequest) (*gctrpc.SimulateOrderResponse, error) {
if r.Pair == nil {
return nil, errCurrencyPairUnset
}
@@ -1227,7 +1233,7 @@ func (s *RPCServer) SimulateOrder(_ context.Context, r *gctrpc.SimulateOrderRequ
return nil, err
}
o, err := exch.FetchOrderbook(p, asset.Spot)
o, err := exch.FetchOrderbook(ctx, p, asset.Spot)
if err != nil {
return nil, err
}
@@ -1257,7 +1263,7 @@ func (s *RPCServer) SimulateOrder(_ context.Context, r *gctrpc.SimulateOrderRequ
// WhaleBomb finds the amount required to reach a specific price target for a given exchange, pair
// and asset type
func (s *RPCServer) WhaleBomb(_ context.Context, r *gctrpc.WhaleBombRequest) (*gctrpc.SimulateOrderResponse, error) {
func (s *RPCServer) WhaleBomb(ctx context.Context, r *gctrpc.WhaleBombRequest) (*gctrpc.SimulateOrderResponse, error) {
if r.Pair == nil {
return nil, errCurrencyPairUnset
}
@@ -1278,7 +1284,7 @@ func (s *RPCServer) WhaleBomb(_ context.Context, r *gctrpc.WhaleBombRequest) (*g
return nil, err
}
o, err := exch.FetchOrderbook(p, asset.Spot)
o, err := exch.FetchOrderbook(ctx, p, asset.Spot)
if err != nil {
return nil, err
}
@@ -1311,7 +1317,7 @@ func (s *RPCServer) WhaleBomb(_ context.Context, r *gctrpc.WhaleBombRequest) (*g
// CancelOrder cancels an order specified by exchange, currency pair and asset
// type
func (s *RPCServer) CancelOrder(_ context.Context, r *gctrpc.CancelOrderRequest) (*gctrpc.GenericResponse, error) {
func (s *RPCServer) CancelOrder(ctx context.Context, r *gctrpc.CancelOrderRequest) (*gctrpc.GenericResponse, error) {
if r.Pair == nil {
return nil, errCurrencyPairUnset
}
@@ -1337,15 +1343,16 @@ func (s *RPCServer) CancelOrder(_ context.Context, r *gctrpc.CancelOrderRequest)
return nil, err
}
err = s.OrderManager.Cancel(&order.Cancel{
Exchange: r.Exchange,
AccountID: r.AccountId,
ID: r.OrderId,
Side: order.Side(r.Side),
WalletAddress: r.WalletAddress,
Pair: p,
AssetType: a,
})
err = s.OrderManager.Cancel(ctx,
&order.Cancel{
Exchange: r.Exchange,
AccountID: r.AccountId,
ID: r.OrderId,
Side: order.Side(r.Side),
WalletAddress: r.WalletAddress,
Pair: p,
AssetType: a,
})
if err != nil {
return nil, err
}
@@ -1354,7 +1361,7 @@ func (s *RPCServer) CancelOrder(_ context.Context, r *gctrpc.CancelOrderRequest)
}
// CancelBatchOrders cancels an orders specified by exchange, currency pair and asset type
func (s *RPCServer) CancelBatchOrders(_ context.Context, r *gctrpc.CancelBatchOrdersRequest) (*gctrpc.CancelBatchOrdersResponse, error) {
func (s *RPCServer) CancelBatchOrders(ctx context.Context, r *gctrpc.CancelBatchOrdersRequest) (*gctrpc.CancelBatchOrdersResponse, error) {
pair := currency.Pair{
Delimiter: r.Pair.Delimiter,
Base: currency.NewCode(r.Pair.Base),
@@ -1391,7 +1398,8 @@ func (s *RPCServer) CancelBatchOrders(_ context.Context, r *gctrpc.CancelBatchOr
})
}
_, err = exch.CancelBatchOrders(request)
// TODO: Change to order manager
_, err = exch.CancelBatchOrders(ctx, request)
if err != nil {
return nil, err
}
@@ -1404,13 +1412,14 @@ func (s *RPCServer) CancelBatchOrders(_ context.Context, r *gctrpc.CancelBatchOr
}
// CancelAllOrders cancels all orders, filterable by exchange
func (s *RPCServer) CancelAllOrders(_ context.Context, r *gctrpc.CancelAllOrdersRequest) (*gctrpc.CancelAllOrdersResponse, error) {
func (s *RPCServer) CancelAllOrders(ctx context.Context, r *gctrpc.CancelAllOrdersRequest) (*gctrpc.CancelAllOrdersResponse, error) {
exch, err := s.GetExchangeByName(r.Exchange)
if err != nil {
return nil, err
}
resp, err := exch.CancelAllOrders(nil)
// TODO: Change to order manager
resp, err := exch.CancelAllOrders(ctx, nil)
if err != nil {
return &gctrpc.CancelAllOrdersResponse{}, err
}
@@ -1420,7 +1429,7 @@ func (s *RPCServer) CancelAllOrders(_ context.Context, r *gctrpc.CancelAllOrders
}, nil
}
func (s *RPCServer) ModifyOrder(_ context.Context, r *gctrpc.ModifyOrderRequest) (*gctrpc.ModifyOrderResponse, error) {
func (s *RPCServer) ModifyOrder(ctx context.Context, r *gctrpc.ModifyOrderRequest) (*gctrpc.ModifyOrderResponse, error) {
assetType, err := asset.New(r.Asset)
if err != nil {
return nil, err
@@ -1450,7 +1459,7 @@ func (s *RPCServer) ModifyOrder(_ context.Context, r *gctrpc.ModifyOrderRequest)
Amount: r.Amount,
Price: r.Price,
}
resp, err := s.OrderManager.Modify(&mod)
resp, err := s.OrderManager.Modify(ctx, &mod)
if err != nil {
return nil, err
}
@@ -1501,7 +1510,7 @@ func (s *RPCServer) AddEvent(_ context.Context, r *gctrpc.AddEventRequest) (*gct
}
// RemoveEvent removes an event, specified by an event ID
func (s *RPCServer) RemoveEvent(_ context.Context, r *gctrpc.RemoveEventRequest) (*gctrpc.GenericResponse, error) {
func (s *RPCServer) RemoveEvent(ctx context.Context, r *gctrpc.RemoveEventRequest) (*gctrpc.GenericResponse, error) {
if !s.eventManager.Remove(r.Id) {
return nil, fmt.Errorf("event %d not removed", r.Id)
}
@@ -1511,7 +1520,7 @@ func (s *RPCServer) RemoveEvent(_ context.Context, r *gctrpc.RemoveEventRequest)
// GetCryptocurrencyDepositAddresses returns a list of cryptocurrency deposit
// addresses specified by an exchange
func (s *RPCServer) GetCryptocurrencyDepositAddresses(_ context.Context, r *gctrpc.GetCryptocurrencyDepositAddressesRequest) (*gctrpc.GetCryptocurrencyDepositAddressesResponse, error) {
func (s *RPCServer) GetCryptocurrencyDepositAddresses(ctx context.Context, r *gctrpc.GetCryptocurrencyDepositAddressesRequest) (*gctrpc.GetCryptocurrencyDepositAddressesResponse, error) {
_, err := s.GetExchangeByName(r.Exchange)
if err != nil {
return nil, err
@@ -1523,19 +1532,22 @@ func (s *RPCServer) GetCryptocurrencyDepositAddresses(_ context.Context, r *gctr
// GetCryptocurrencyDepositAddress returns a cryptocurrency deposit address
// specified by exchange and cryptocurrency
func (s *RPCServer) GetCryptocurrencyDepositAddress(_ context.Context, r *gctrpc.GetCryptocurrencyDepositAddressRequest) (*gctrpc.GetCryptocurrencyDepositAddressResponse, error) {
func (s *RPCServer) GetCryptocurrencyDepositAddress(ctx context.Context, r *gctrpc.GetCryptocurrencyDepositAddressRequest) (*gctrpc.GetCryptocurrencyDepositAddressResponse, error) {
_, err := s.GetExchangeByName(r.Exchange)
if err != nil {
return nil, err
}
addr, err := s.GetExchangeCryptocurrencyDepositAddress(r.Exchange, "", currency.NewCode(r.Cryptocurrency))
addr, err := s.GetExchangeCryptocurrencyDepositAddress(ctx,
r.Exchange,
"",
currency.NewCode(r.Cryptocurrency))
return &gctrpc.GetCryptocurrencyDepositAddressResponse{Address: addr}, err
}
// WithdrawCryptocurrencyFunds withdraws cryptocurrency funds specified by
// exchange
func (s *RPCServer) WithdrawCryptocurrencyFunds(_ context.Context, r *gctrpc.WithdrawCryptoRequest) (*gctrpc.WithdrawResponse, error) {
func (s *RPCServer) WithdrawCryptocurrencyFunds(ctx context.Context, r *gctrpc.WithdrawCryptoRequest) (*gctrpc.WithdrawResponse, error) {
_, err := s.GetExchangeByName(r.Exchange)
if err != nil {
return nil, err
@@ -1554,7 +1566,7 @@ func (s *RPCServer) WithdrawCryptocurrencyFunds(_ context.Context, r *gctrpc.Wit
},
}
resp, err := s.Engine.WithdrawManager.SubmitWithdrawal(request)
resp, err := s.Engine.WithdrawManager.SubmitWithdrawal(ctx, request)
if err != nil {
return nil, err
}
@@ -1566,7 +1578,7 @@ func (s *RPCServer) WithdrawCryptocurrencyFunds(_ context.Context, r *gctrpc.Wit
}
// WithdrawFiatFunds withdraws fiat funds specified by exchange
func (s *RPCServer) WithdrawFiatFunds(_ context.Context, r *gctrpc.WithdrawFiatRequest) (*gctrpc.WithdrawResponse, error) {
func (s *RPCServer) WithdrawFiatFunds(ctx context.Context, r *gctrpc.WithdrawFiatRequest) (*gctrpc.WithdrawResponse, error) {
exch, err := s.GetExchangeByName(r.Exchange)
if err != nil {
return nil, err
@@ -1578,7 +1590,8 @@ func (s *RPCServer) WithdrawFiatFunds(_ context.Context, r *gctrpc.WithdrawFiatR
if base == nil {
return nil, errExchangeBaseNotFound
}
bankAccount, err = base.GetExchangeBankAccounts(r.BankAccountId, r.Currency)
bankAccount, err = base.GetExchangeBankAccounts(r.BankAccountId,
r.Currency)
if err != nil {
return nil, err
}
@@ -1595,7 +1608,7 @@ func (s *RPCServer) WithdrawFiatFunds(_ context.Context, r *gctrpc.WithdrawFiatR
},
}
resp, err := s.Engine.WithdrawManager.SubmitWithdrawal(request)
resp, err := s.Engine.WithdrawManager.SubmitWithdrawal(ctx, request)
if err != nil {
return nil, err
}
@@ -1667,7 +1680,7 @@ func (s *RPCServer) WithdrawalEventByID(_ context.Context, r *gctrpc.WithdrawalE
}
// WithdrawalEventsByExchange returns previous withdrawal request details by exchange
func (s *RPCServer) WithdrawalEventsByExchange(_ context.Context, r *gctrpc.WithdrawalEventsByExchangeRequest) (*gctrpc.WithdrawalEventsByExchangeResponse, error) {
func (s *RPCServer) WithdrawalEventsByExchange(ctx context.Context, r *gctrpc.WithdrawalEventsByExchangeRequest) (*gctrpc.WithdrawalEventsByExchangeResponse, error) {
if !s.Config.Database.Enabled {
if r.Id == "" {
exch, err := s.GetExchangeByName(r.Exchange)
@@ -1676,7 +1689,7 @@ func (s *RPCServer) WithdrawalEventsByExchange(_ context.Context, r *gctrpc.With
}
c := currency.NewCode(strings.ToUpper(r.Currency))
ret, err := exch.GetWithdrawalsHistory(c)
ret, err := exch.GetWithdrawalsHistory(ctx, c)
if err != nil {
return nil, err
}
@@ -2154,7 +2167,7 @@ func (s *RPCServer) GetAuditEvent(_ context.Context, r *gctrpc.GetAuditEventRequ
}
// GetHistoricCandles returns historical candles for a given exchange
func (s *RPCServer) GetHistoricCandles(_ context.Context, r *gctrpc.GetHistoricCandlesRequest) (*gctrpc.GetHistoricCandlesResponse, error) {
func (s *RPCServer) GetHistoricCandles(ctx context.Context, r *gctrpc.GetHistoricCandlesRequest) (*gctrpc.GetHistoricCandlesResponse, error) {
start, err := time.Parse(common.SimpleTimeFormat, r.Start)
if err != nil {
return nil, fmt.Errorf("%w cannot parse start time %v", errInvalidTimes, err)
@@ -2214,13 +2227,15 @@ func (s *RPCServer) GetHistoricCandles(_ context.Context, r *gctrpc.GetHistoricC
}
} else {
if r.ExRequest {
klineItem, err = exch.GetHistoricCandlesExtended(pair,
klineItem, err = exch.GetHistoricCandlesExtended(ctx,
pair,
a,
start,
end,
interval)
} else {
klineItem, err = exch.GetHistoricCandles(pair,
klineItem, err = exch.GetHistoricCandles(ctx,
pair,
a,
start,
end,
@@ -2702,7 +2717,7 @@ func (s *RPCServer) SetAllExchangePairs(_ context.Context, r *gctrpc.SetExchange
// UpdateExchangeSupportedPairs forces an update of the supported pairs which
// will update the available pairs list and remove any assets that are disabled
// by the exchange
func (s *RPCServer) UpdateExchangeSupportedPairs(_ context.Context, r *gctrpc.UpdateExchangeSupportedPairsRequest) (*gctrpc.GenericResponse, error) {
func (s *RPCServer) UpdateExchangeSupportedPairs(ctx context.Context, r *gctrpc.UpdateExchangeSupportedPairsRequest) (*gctrpc.GenericResponse, error) {
exch, err := s.GetExchangeByName(r.Exchange)
if err != nil {
return nil, err
@@ -2718,7 +2733,7 @@ func (s *RPCServer) UpdateExchangeSupportedPairs(_ context.Context, r *gctrpc.Up
errors.New("cannot auto pair update for exchange, a manual update is needed")
}
err = exch.UpdateTradablePairs(false)
err = exch.UpdateTradablePairs(ctx, false)
if err != nil {
return nil, err
}
@@ -3280,7 +3295,7 @@ func (s *RPCServer) GetHistoricTrades(r *gctrpc.GetSavedTradesRequest, stream gc
for iterateStartTime := start; iterateStartTime.Before(end); iterateStartTime = iterateStartTime.Add(time.Hour) {
iterateEndTime := iterateStartTime.Add(time.Hour)
trades, err = exch.GetHistoricTrades(cp, a, iterateStartTime, iterateEndTime)
trades, err = exch.GetHistoricTrades(stream.Context(), cp, a, iterateStartTime, iterateEndTime)
if err != nil {
return err
}
@@ -3315,7 +3330,7 @@ func (s *RPCServer) GetHistoricTrades(r *gctrpc.GetSavedTradesRequest, stream gc
}
// GetRecentTrades returns trades
func (s *RPCServer) GetRecentTrades(_ context.Context, r *gctrpc.GetSavedTradesRequest) (*gctrpc.SavedTradesResponse, error) {
func (s *RPCServer) GetRecentTrades(ctx context.Context, r *gctrpc.GetSavedTradesRequest) (*gctrpc.SavedTradesResponse, error) {
if r.Exchange == "" || r.Pair == nil || r.AssetType == "" || r.Pair.String() == "" {
return nil, errInvalidArguments
}
@@ -3340,7 +3355,7 @@ func (s *RPCServer) GetRecentTrades(_ context.Context, r *gctrpc.GetSavedTradesR
return nil, err
}
var trades []trade.Data
trades, err = exch.GetRecentTrades(cp, asset.Item(r.AssetType))
trades, err = exch.GetRecentTrades(ctx, cp, asset.Item(r.AssetType))
if err != nil {
return nil, err
}

View File

@@ -36,6 +36,7 @@ import (
"github.com/thrasher-corp/gocryptotrader/portfolio/banking"
"github.com/thrasher-corp/gocryptotrader/portfolio/withdraw"
"github.com/thrasher-corp/goose"
"google.golang.org/grpc/metadata"
)
const (
@@ -50,7 +51,7 @@ type fExchange struct {
exchange.IBotExchange
}
func (f fExchange) GetHistoricCandles(p currency.Pair, a asset.Item, timeStart, _ time.Time, interval kline.Interval) (kline.Item, error) {
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",
Pair: p,
@@ -69,7 +70,7 @@ func (f fExchange) GetHistoricCandles(p currency.Pair, a asset.Item, timeStart,
}, nil
}
func (f fExchange) GetHistoricCandlesExtended(p currency.Pair, a asset.Item, timeStart, _ time.Time, interval kline.Interval) (kline.Item, error) {
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",
Pair: p,
@@ -90,7 +91,7 @@ func (f fExchange) GetHistoricCandlesExtended(p currency.Pair, a asset.Item, tim
// FetchAccountInfo overrides testExchange's fetch account info function
// to do the bare minimum required with no API calls or credentials required
func (f fExchange) FetchAccountInfo(a asset.Item) (account.Holdings, error) {
func (f fExchange) FetchAccountInfo(ctx context.Context, a asset.Item) (account.Holdings, error) {
return account.Holdings{
Exchange: f.GetName(),
Accounts: []account.SubAccount{
@@ -105,7 +106,7 @@ func (f fExchange) FetchAccountInfo(a asset.Item) (account.Holdings, error) {
// UpdateAccountInfo overrides testExchange's update account info function
// to do the bare minimum required with no API calls or credentials required
func (f fExchange) UpdateAccountInfo(a asset.Item) (account.Holdings, error) {
func (f fExchange) UpdateAccountInfo(ctx context.Context, a asset.Item) (account.Holdings, error) {
if a == asset.Futures {
return account.Holdings{}, errAssetTypeDisabled
}
@@ -875,6 +876,18 @@ func TestGetRecentTrades(t *testing.T) {
}
}
// dummyServer implements a basic RPC server interface for deployment in a test
// when streaming occurs, so we can deliver a context value.
type dummyServer struct{}
func (d *dummyServer) Send(*gctrpc.SavedTradesResponse) error { return nil }
func (d *dummyServer) SetHeader(metadata.MD) error { return nil }
func (d *dummyServer) SendHeader(metadata.MD) error { return nil }
func (d *dummyServer) SetTrailer(metadata.MD) {}
func (d *dummyServer) Context() context.Context { return context.Background() }
func (d *dummyServer) SendMsg(m interface{}) error { return nil }
func (d *dummyServer) RecvMsg(m interface{}) error { return nil }
func TestGetHistoricTrades(t *testing.T) {
engerino := RPCTestSetup(t)
defer CleanRPCTest(t, engerino)
@@ -907,7 +920,7 @@ func TestGetHistoricTrades(t *testing.T) {
AssetType: asset.Spot.String(),
Start: time.Date(2020, 0, 0, 0, 0, 0, 0, time.UTC).Format(common.SimpleTimeFormat),
End: time.Date(2020, 0, 0, 1, 0, 0, 0, time.UTC).Format(common.SimpleTimeFormat),
}, nil)
}, &dummyServer{})
if err != common.ErrFunctionNotSupported {
t.Error(err)
}

View File

@@ -1,6 +1,7 @@
package engine
import (
"context"
"errors"
"github.com/thrasher-corp/gocryptotrader/communications/base"
@@ -54,7 +55,7 @@ type iCommsManager interface {
type iOrderManager interface {
Exists(*order.Detail) bool
Add(*order.Detail) error
Cancel(*order.Cancel) error
Cancel(context.Context, *order.Cancel) error
GetByExchangeAndID(string, string) (*order.Detail, error)
UpdateExistingOrder(*order.Detail) error
}

View File

@@ -1,6 +1,7 @@
package engine
import (
"context"
"errors"
"fmt"
"strconv"
@@ -561,7 +562,9 @@ func (m *syncManager) worker() {
}
m.setProcessing(c.Exchange, c.Pair, c.AssetType, SyncItemOrderbook, true)
result, err := exchanges[x].UpdateOrderbook(c.Pair, c.AssetType)
result, err := exchanges[x].UpdateOrderbook(context.TODO(),
c.Pair,
c.AssetType)
m.PrintOrderbookSummary(result, "REST", err)
if err == nil {
if m.remoteConfig.WebsocketRPC.Enabled {
@@ -621,9 +624,9 @@ func (m *syncManager) worker() {
if m.config.Verbose {
log.Debugf(log.SyncMgr, "Initialising %s REST ticker batching", exchangeName)
}
err = exchanges[x].UpdateTickers(c.AssetType)
err = exchanges[x].UpdateTickers(context.TODO(), c.AssetType)
if err == nil {
result, err = exchanges[x].FetchTicker(c.Pair, c.AssetType)
result, err = exchanges[x].FetchTicker(context.TODO(), c.Pair, c.AssetType)
}
m.tickerBatchLastRequested[exchangeName] = time.Now()
m.mux.Unlock()
@@ -631,10 +634,14 @@ func (m *syncManager) worker() {
if m.config.Verbose {
log.Debugf(log.SyncMgr, "%s Using recent batching cache", exchangeName)
}
result, err = exchanges[x].FetchTicker(c.Pair, c.AssetType)
result, err = exchanges[x].FetchTicker(context.TODO(),
c.Pair,
c.AssetType)
}
} else {
result, err = exchanges[x].UpdateTicker(c.Pair, c.AssetType)
result, err = exchanges[x].UpdateTicker(context.TODO(),
c.Pair,
c.AssetType)
}
m.PrintTickerSummary(result, "REST", err)
if err == nil {

View File

@@ -1,6 +1,7 @@
package engine
import (
"context"
"errors"
"fmt"
"time"
@@ -24,7 +25,7 @@ func SetupWithdrawManager(em iExchangeManager, pm iPortfolioManager, isDryRun bo
// SubmitWithdrawal performs validation and submits a new withdraw request to
// exchange
func (m *WithdrawManager) SubmitWithdrawal(req *withdraw.Request) (*withdraw.Response, error) {
func (m *WithdrawManager) SubmitWithdrawal(ctx context.Context, req *withdraw.Request) (*withdraw.Response, error) {
if m == nil {
return nil, ErrNilSubsystem
}
@@ -60,7 +61,7 @@ func (m *WithdrawManager) SubmitWithdrawal(req *withdraw.Request) (*withdraw.Res
}
}
if req.Type == withdraw.Fiat {
ret, err = exch.WithdrawFiatFunds(req)
ret, err = exch.WithdrawFiatFunds(ctx, req)
if err != nil {
resp.Exchange.Status = err.Error()
} else {
@@ -68,7 +69,7 @@ func (m *WithdrawManager) SubmitWithdrawal(req *withdraw.Request) (*withdraw.Res
resp.Exchange.ID = ret.ID
}
} else if req.Type == withdraw.Crypto {
ret, err = exch.WithdrawCryptocurrencyFunds(req)
ret, err = exch.WithdrawCryptocurrencyFunds(ctx, req)
if err != nil {
resp.Exchange.Status = err.Error()
} else {

View File

@@ -1,6 +1,7 @@
package engine
import (
"context"
"errors"
"sync"
"testing"
@@ -69,7 +70,7 @@ func TestSubmitWithdrawal(t *testing.T) {
Bank: bank,
},
}
_, err = m.SubmitWithdrawal(req)
_, err = m.SubmitWithdrawal(context.Background(), req)
if !errors.Is(err, common.ErrFunctionNotSupported) {
t.Errorf("received %v, expected %v", err, common.ErrFunctionNotSupported)
}
@@ -77,7 +78,7 @@ func TestSubmitWithdrawal(t *testing.T) {
req.Type = withdraw.Crypto
req.Currency = currency.BTC
req.Crypto.Address = "1337"
_, err = m.SubmitWithdrawal(req)
_, err = m.SubmitWithdrawal(context.Background(), req)
if !errors.Is(err, withdraw.ErrStrAddressNotWhiteListed) {
t.Errorf("received %v, expected %v", err, withdraw.ErrStrAddressNotWhiteListed)
}
@@ -95,24 +96,24 @@ func TestSubmitWithdrawal(t *testing.T) {
if !errors.Is(err, nil) {
t.Errorf("received %v, expected %v", err, nil)
}
_, err = m.SubmitWithdrawal(req)
_, err = m.SubmitWithdrawal(context.Background(), req)
if !errors.Is(err, withdraw.ErrStrExchangeNotSupportedByAddress) {
t.Errorf("received %v, expected %v", err, withdraw.ErrStrExchangeNotSupportedByAddress)
}
adds[0].SupportedExchanges = exchangeName
_, err = m.SubmitWithdrawal(req)
_, err = m.SubmitWithdrawal(context.Background(), req)
if !errors.Is(err, exchange.ErrAuthenticatedRequestWithoutCredentialsSet) {
t.Errorf("received %v, expected %v", err, exchange.ErrAuthenticatedRequestWithoutCredentialsSet)
}
_, err = m.SubmitWithdrawal(nil)
_, err = m.SubmitWithdrawal(context.Background(), nil)
if !errors.Is(err, withdraw.ErrRequestCannotBeNil) {
t.Errorf("received %v, expected %v", err, withdraw.ErrRequestCannotBeNil)
}
m.isDryRun = true
_, err = m.SubmitWithdrawal(req)
_, err = m.SubmitWithdrawal(context.Background(), req)
if !errors.Is(err, nil) {
t.Errorf("received %v, expected %v", err, nil)
}