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

@@ -40,27 +40,27 @@ type ItBit struct {
// GetTicker returns ticker info for a specified market.
// currencyPair - example "XBTUSD" "XBTSGD" "XBTEUR"
func (i *ItBit) GetTicker(currencyPair string) (Ticker, error) {
func (i *ItBit) GetTicker(ctx context.Context, currencyPair string) (Ticker, error) {
var response Ticker
path := fmt.Sprintf("/%s/%s/%s", itbitMarkets, currencyPair, itbitTicker)
return response, i.SendHTTPRequest(exchange.RestSpot, path, &response)
return response, i.SendHTTPRequest(ctx, exchange.RestSpot, path, &response)
}
// GetOrderbook returns full order book for the specified market.
// currencyPair - example "XBTUSD" "XBTSGD" "XBTEUR"
func (i *ItBit) GetOrderbook(currencyPair string) (OrderbookResponse, error) {
func (i *ItBit) GetOrderbook(ctx context.Context, currencyPair string) (OrderbookResponse, error) {
response := OrderbookResponse{}
path := fmt.Sprintf("/%s/%s/%s", itbitMarkets, currencyPair, itbitOrderbook)
return response, i.SendHTTPRequest(exchange.RestSpot, path, &response)
return response, i.SendHTTPRequest(ctx, exchange.RestSpot, path, &response)
}
// GetTradeHistory returns recent trades for a specified market.
//
// currencyPair - example "XBTUSD" "XBTSGD" "XBTEUR"
// timestamp - matchNumber, only executions after this will be returned
func (i *ItBit) GetTradeHistory(currencyPair, tradeID string) (Trades, error) {
func (i *ItBit) GetTradeHistory(ctx context.Context, currencyPair, tradeID string) (Trades, error) {
response := Trades{}
var req = itbitTrades
@@ -69,7 +69,7 @@ func (i *ItBit) GetTradeHistory(currencyPair, tradeID string) (Trades, error) {
}
path := fmt.Sprintf("/%s/%s/%s", itbitMarkets, currencyPair, req)
return response, i.SendHTTPRequest(exchange.RestSpot, path, &response)
return response, i.SendHTTPRequest(ctx, exchange.RestSpot, path, &response)
}
// GetWallets returns information about all wallets associated with the account.
@@ -77,21 +77,21 @@ func (i *ItBit) GetTradeHistory(currencyPair, tradeID string) (Trades, error) {
// params --
// page - [optional] page to return example 1. default 1
// perPage - [optional] items per page example 50, default 50 max 50
func (i *ItBit) GetWallets(params url.Values) ([]Wallet, error) {
func (i *ItBit) GetWallets(ctx context.Context, params url.Values) ([]Wallet, error) {
var resp []Wallet
params.Set("userId", i.API.Credentials.ClientID)
path := fmt.Sprintf("/%s?%s", itbitWallets, params.Encode())
return resp, i.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodGet, path, nil, &resp)
return resp, i.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, path, nil, &resp)
}
// CreateWallet creates a new wallet with a specified name.
func (i *ItBit) CreateWallet(walletName string) (Wallet, error) {
func (i *ItBit) CreateWallet(ctx context.Context, walletName string) (Wallet, error) {
resp := Wallet{}
params := make(map[string]interface{})
params["userId"] = i.API.Credentials.ClientID
params["name"] = walletName
err := i.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost, "/"+itbitWallets, params, &resp)
err := i.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, "/"+itbitWallets, params, &resp)
if err != nil {
return resp, err
}
@@ -102,11 +102,11 @@ func (i *ItBit) CreateWallet(walletName string) (Wallet, error) {
}
// GetWallet returns wallet information by walletID
func (i *ItBit) GetWallet(walletID string) (Wallet, error) {
func (i *ItBit) GetWallet(ctx context.Context, walletID string) (Wallet, error) {
resp := Wallet{}
path := fmt.Sprintf("/%s/%s", itbitWallets, walletID)
err := i.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodGet, path, nil, &resp)
err := i.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, path, nil, &resp)
if err != nil {
return resp, err
}
@@ -118,11 +118,11 @@ func (i *ItBit) GetWallet(walletID string) (Wallet, error) {
// GetWalletBalance returns balance information for a specific currency in a
// wallet.
func (i *ItBit) GetWalletBalance(walletID, currency string) (Balance, error) {
func (i *ItBit) GetWalletBalance(ctx context.Context, walletID, currency string) (Balance, error) {
resp := Balance{}
path := fmt.Sprintf("/%s/%s/%s/%s", itbitWallets, walletID, itbitBalances, currency)
err := i.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodGet, path, nil, &resp)
err := i.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, path, nil, &resp)
if err != nil {
return resp, err
}
@@ -134,7 +134,7 @@ func (i *ItBit) GetWalletBalance(walletID, currency string) (Balance, error) {
// GetOrders returns active orders for itBit
// perPage defaults to & has a limit of 50
func (i *ItBit) GetOrders(walletID, symbol, status string, page, perPage int64) ([]Order, error) {
func (i *ItBit) GetOrders(ctx context.Context, walletID, symbol, status string, page, perPage int64) ([]Order, error) {
var resp []Order
params := make(map[string]interface{})
params["walletID"] = walletID
@@ -152,16 +152,16 @@ func (i *ItBit) GetOrders(walletID, symbol, status string, page, perPage int64)
params["perPage"] = strconv.FormatInt(perPage, 10)
}
return resp, i.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodGet, itbitOrders, params, &resp)
return resp, i.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, itbitOrders, params, &resp)
}
// GetWalletTrades returns all trades for a specified wallet.
func (i *ItBit) GetWalletTrades(walletID string, params url.Values) (Records, error) {
func (i *ItBit) GetWalletTrades(ctx context.Context, walletID string, params url.Values) (Records, error) {
resp := Records{}
urlPath := fmt.Sprintf("/%s/%s/%s", itbitWallets, walletID, itbitTrades)
path := common.EncodeURLValues(urlPath, params)
err := i.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodGet, path, nil, &resp)
err := i.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, path, nil, &resp)
if err != nil {
return resp, err
}
@@ -172,12 +172,12 @@ func (i *ItBit) GetWalletTrades(walletID string, params url.Values) (Records, er
}
// GetFundingHistoryForWallet returns all funding history for a specified wallet.
func (i *ItBit) GetFundingHistoryForWallet(walletID string, params url.Values) (FundingRecords, error) {
func (i *ItBit) GetFundingHistoryForWallet(ctx context.Context, walletID string, params url.Values) (FundingRecords, error) {
resp := FundingRecords{}
urlPath := fmt.Sprintf("/%s/%s/%s", itbitWallets, walletID, itbitFundingHistory)
path := common.EncodeURLValues(urlPath, params)
err := i.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodGet, path, nil, &resp)
err := i.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, path, nil, &resp)
if err != nil {
return resp, err
}
@@ -188,7 +188,7 @@ func (i *ItBit) GetFundingHistoryForWallet(walletID string, params url.Values) (
}
// PlaceOrder places a new order
func (i *ItBit) PlaceOrder(walletID, side, orderType, currency string, amount, price float64, instrument, clientRef string) (Order, error) {
func (i *ItBit) PlaceOrder(ctx context.Context, walletID, side, orderType, currency string, amount, price float64, instrument, clientRef string) (Order, error) {
resp := Order{}
path := fmt.Sprintf("/%s/%s/%s", itbitWallets, walletID, itbitOrders)
@@ -204,7 +204,7 @@ func (i *ItBit) PlaceOrder(walletID, side, orderType, currency string, amount, p
params["clientOrderIdentifier"] = clientRef
}
err := i.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost, path, params, &resp)
err := i.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, path, params, &resp)
if err != nil {
return resp, err
}
@@ -215,12 +215,12 @@ func (i *ItBit) PlaceOrder(walletID, side, orderType, currency string, amount, p
}
// GetOrder returns an order by id.
func (i *ItBit) GetOrder(walletID string, params url.Values) (Order, error) {
func (i *ItBit) GetOrder(ctx context.Context, walletID string, params url.Values) (Order, error) {
resp := Order{}
urlPath := fmt.Sprintf("/%s/%s/%s", itbitWallets, walletID, itbitOrders)
path := common.EncodeURLValues(urlPath, params)
err := i.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodGet, path, nil, &resp)
err := i.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, path, nil, &resp)
if err != nil {
return resp, err
}
@@ -232,20 +232,20 @@ func (i *ItBit) GetOrder(walletID string, params url.Values) (Order, error) {
// CancelExistingOrder cancels and open order. *This is not a guarantee that the
// order has been cancelled!*
func (i *ItBit) CancelExistingOrder(walletID, orderID string) error {
func (i *ItBit) CancelExistingOrder(ctx context.Context, walletID, orderID string) error {
path := fmt.Sprintf("/%s/%s/%s/%s", itbitWallets, walletID, itbitOrders, orderID)
return i.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodDelete, path, nil, nil)
return i.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodDelete, path, nil, nil)
}
// GetCryptoDepositAddress returns a deposit address to send cryptocurrency to.
func (i *ItBit) GetCryptoDepositAddress(walletID, currency string) (CryptoCurrencyDeposit, error) {
func (i *ItBit) GetCryptoDepositAddress(ctx context.Context, walletID, currency string) (CryptoCurrencyDeposit, error) {
resp := CryptoCurrencyDeposit{}
path := fmt.Sprintf("/%s/%s/%s", itbitWallets, walletID, itbitCryptoDeposits)
params := make(map[string]interface{})
params["currency"] = currency
err := i.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost, path, params, &resp)
err := i.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, path, params, &resp)
if err != nil {
return resp, err
}
@@ -256,7 +256,7 @@ func (i *ItBit) GetCryptoDepositAddress(walletID, currency string) (CryptoCurren
}
// WalletTransfer transfers funds between wallets.
func (i *ItBit) WalletTransfer(walletID, sourceWallet, destWallet string, amount float64, currency string) (WalletTransfer, error) {
func (i *ItBit) WalletTransfer(ctx context.Context, walletID, sourceWallet, destWallet string, amount float64, currency string) (WalletTransfer, error) {
resp := WalletTransfer{}
path := fmt.Sprintf("/%s/%s/%s", itbitWallets, walletID, itbitWalletTransfer)
@@ -266,7 +266,7 @@ func (i *ItBit) WalletTransfer(walletID, sourceWallet, destWallet string, amount
params["amount"] = strconv.FormatFloat(amount, 'f', -1, 64)
params["currencyCode"] = currency
err := i.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost, path, params, &resp)
err := i.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, path, params, &resp)
if err != nil {
return resp, err
}
@@ -277,7 +277,7 @@ func (i *ItBit) WalletTransfer(walletID, sourceWallet, destWallet string, amount
}
// SendHTTPRequest sends an unauthenticated HTTP request
func (i *ItBit) SendHTTPRequest(ep exchange.URL, path string, result interface{}) error {
func (i *ItBit) SendHTTPRequest(ctx context.Context, ep exchange.URL, path string, result interface{}) error {
endpoint, err := i.API.Endpoints.GetURL(ep)
if err != nil {
return err
@@ -292,13 +292,13 @@ func (i *ItBit) SendHTTPRequest(ep exchange.URL, path string, result interface{}
HTTPRecording: i.HTTPRecording,
}
return i.SendPayload(context.Background(), request.Unset, func() (*request.Item, error) {
return i.SendPayload(ctx, request.Unset, func() (*request.Item, error) {
return item, nil
})
}
// SendAuthenticatedHTTPRequest sends an authenticated request to itBit
func (i *ItBit) SendAuthenticatedHTTPRequest(ep exchange.URL, method, path string, params map[string]interface{}, result interface{}) error {
func (i *ItBit) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange.URL, method, path string, params map[string]interface{}, result interface{}) error {
if !i.AllowAuthenticatedRequest() {
return fmt.Errorf("%s %w", i.Name, exchange.ErrAuthenticatedRequestWithoutCredentialsSet)
}
@@ -322,7 +322,7 @@ func (i *ItBit) SendAuthenticatedHTTPRequest(ep exchange.URL, method, path strin
}
var intermediary json.RawMessage
err = i.SendPayload(context.Background(), request.Unset, func() (*request.Item, error) {
err = i.SendPayload(ctx, request.Unset, func() (*request.Item, error) {
n := i.Requester.GetNonce(true).String()
timestamp := strconv.FormatInt(time.Now().UnixNano()/1000000, 10)
@@ -382,7 +382,6 @@ func (i *ItBit) SendAuthenticatedHTTPRequest(ep exchange.URL, method, path strin
errCheck.Description)
}
}
return json.Unmarshal(intermediary, result)
}

View File

@@ -1,6 +1,7 @@
package itbit
import (
"context"
"log"
"net/url"
"os"
@@ -53,7 +54,7 @@ func TestMain(m *testing.M) {
func TestGetTicker(t *testing.T) {
t.Parallel()
_, err := i.GetTicker("XBTUSD")
_, err := i.GetTicker(context.Background(), "XBTUSD")
if err != nil {
t.Error("GetTicker() error", err)
}
@@ -61,7 +62,7 @@ func TestGetTicker(t *testing.T) {
func TestGetOrderbook(t *testing.T) {
t.Parallel()
_, err := i.GetOrderbook("XBTUSD")
_, err := i.GetOrderbook(context.Background(), "XBTUSD")
if err != nil {
t.Error("GetOrderbook() error", err)
}
@@ -69,56 +70,57 @@ func TestGetOrderbook(t *testing.T) {
func TestGetTradeHistory(t *testing.T) {
t.Parallel()
_, err := i.GetTradeHistory("XBTUSD", "0")
_, err := i.GetTradeHistory(context.Background(), "XBTUSD", "0")
if err != nil {
t.Error("GetTradeHistory() error", err)
}
}
func TestGetWallets(t *testing.T) {
_, err := i.GetWallets(url.Values{})
_, err := i.GetWallets(context.Background(), url.Values{})
if err == nil {
t.Error("GetWallets() Expected error")
}
}
func TestCreateWallet(t *testing.T) {
_, err := i.CreateWallet("test")
_, err := i.CreateWallet(context.Background(), "test")
if err == nil {
t.Error("CreateWallet() Expected error")
}
}
func TestGetWallet(t *testing.T) {
_, err := i.GetWallet("1337")
_, err := i.GetWallet(context.Background(), "1337")
if err == nil {
t.Error("GetWallet() Expected error")
}
}
func TestGetWalletBalance(t *testing.T) {
_, err := i.GetWalletBalance("1337", "XRT")
_, err := i.GetWalletBalance(context.Background(), "1337", "XRT")
if err == nil {
t.Error("GetWalletBalance() Expected error")
}
}
func TestGetWalletTrades(t *testing.T) {
_, err := i.GetWalletTrades("1337", url.Values{})
_, err := i.GetWalletTrades(context.Background(), "1337", url.Values{})
if err == nil {
t.Error("GetWalletTrades() Expected error")
}
}
func TestGetFundingHistory(t *testing.T) {
_, err := i.GetFundingHistoryForWallet("1337", url.Values{})
_, err := i.GetFundingHistoryForWallet(context.Background(), "1337", url.Values{})
if err == nil {
t.Error("GetFundingHistory() Expected error")
}
}
func TestPlaceOrder(t *testing.T) {
_, err := i.PlaceOrder("1337", order.Buy.Lower(),
_, err := i.PlaceOrder(context.Background(),
"1337", order.Buy.Lower(),
order.Limit.Lower(), "USD", 1, 0.2, "banjo",
"sauce")
if err == nil {
@@ -127,7 +129,7 @@ func TestPlaceOrder(t *testing.T) {
}
func TestGetOrder(t *testing.T) {
_, err := i.GetOrder("1337", url.Values{})
_, err := i.GetOrder(context.Background(), "1337", url.Values{})
if err == nil {
t.Error("GetOrder() Expected error")
}
@@ -135,21 +137,22 @@ func TestGetOrder(t *testing.T) {
func TestCancelExistingOrder(t *testing.T) {
t.Skip()
err := i.CancelExistingOrder("1337", "1337order")
err := i.CancelExistingOrder(context.Background(), "1337", "1337order")
if err == nil {
t.Error("CancelOrder() Expected error")
}
}
func TestGetCryptoDepositAddress(t *testing.T) {
_, err := i.GetCryptoDepositAddress("1337", "AUD")
_, err := i.GetCryptoDepositAddress(context.Background(), "1337", "AUD")
if err == nil {
t.Error("GetCryptoDepositAddress() Expected error")
}
}
func TestWalletTransfer(t *testing.T) {
_, err := i.WalletTransfer("1337", "mywallet", "anotherwallet", 200, "USD")
_, err := i.WalletTransfer(context.Background(),
"1337", "mywallet", "anotherwallet", 200, "USD")
if err == nil {
t.Error("WalletTransfer() Expected error")
}
@@ -171,7 +174,7 @@ func setFeeBuilder() *exchange.FeeBuilder {
// TestGetFeeByTypeOfflineTradeFee logic test
func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
var feeBuilder = setFeeBuilder()
_, err := i.GetFeeByType(feeBuilder)
_, err := i.GetFeeByType(context.Background(), feeBuilder)
if err != nil {
t.Fatal(err)
}
@@ -267,7 +270,7 @@ func TestGetActiveOrders(t *testing.T) {
AssetType: asset.Spot,
}
_, err := i.GetActiveOrders(&getOrdersRequest)
_, err := i.GetActiveOrders(context.Background(), &getOrdersRequest)
if areTestAPIKeysSet() && err != nil {
t.Errorf("Could not get open orders: %s", err)
} else if !areTestAPIKeysSet() && err == nil {
@@ -281,7 +284,7 @@ func TestGetOrderHistory(t *testing.T) {
AssetType: asset.Spot,
}
_, err := i.GetOrderHistory(&getOrdersRequest)
_, err := i.GetOrderHistory(context.Background(), &getOrdersRequest)
if areTestAPIKeysSet() && err != nil {
t.Errorf("Could not get order history: %s", err)
} else if !areTestAPIKeysSet() && err == nil {
@@ -312,7 +315,7 @@ func TestSubmitOrder(t *testing.T) {
ClientID: "meowOrder",
AssetType: asset.Spot,
}
response, err := i.SubmitOrder(orderSubmission)
response, err := i.SubmitOrder(context.Background(), orderSubmission)
if areTestAPIKeysSet() && (err != nil || !response.IsOrderPlaced) {
t.Errorf("Order failed to be placed: %v", err)
} else if !areTestAPIKeysSet() && err == nil {
@@ -334,7 +337,7 @@ func TestCancelExchangeOrder(t *testing.T) {
AssetType: asset.Spot,
}
err := i.CancelOrder(orderCancellation)
err := i.CancelOrder(context.Background(), orderCancellation)
if !areTestAPIKeysSet() && err == nil {
t.Error("Expecting an error when no keys are set")
@@ -358,7 +361,7 @@ func TestCancelAllExchangeOrders(t *testing.T) {
AssetType: asset.Spot,
}
resp, err := i.CancelAllOrders(orderCancellation)
resp, err := i.CancelAllOrders(context.Background(), orderCancellation)
if !areTestAPIKeysSet() && err == nil {
t.Error("Expecting an error when no keys are set")
@@ -374,7 +377,7 @@ func TestCancelAllExchangeOrders(t *testing.T) {
func TestGetAccountInfo(t *testing.T) {
if areTestAPIKeysSet() {
_, err := i.UpdateAccountInfo(asset.Spot)
_, err := i.UpdateAccountInfo(context.Background(), asset.Spot)
if err == nil {
t.Error("GetAccountInfo() Expected error")
}
@@ -385,7 +388,7 @@ func TestModifyOrder(t *testing.T) {
if areTestAPIKeysSet() && !canManipulateRealOrders {
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
}
_, err := i.ModifyOrder(&order.Modify{AssetType: asset.Spot})
_, err := i.ModifyOrder(context.Background(), &order.Modify{AssetType: asset.Spot})
if err == nil {
t.Error("ModifyOrder() Expected error")
}
@@ -405,7 +408,8 @@ func TestWithdraw(t *testing.T) {
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
}
_, err := i.WithdrawCryptocurrencyFunds(&withdrawCryptoRequest)
_, err := i.WithdrawCryptocurrencyFunds(context.Background(),
&withdrawCryptoRequest)
if err != common.ErrFunctionNotSupported {
t.Errorf("Expected 'Not supported', received %v", err)
}
@@ -417,7 +421,8 @@ func TestWithdrawFiat(t *testing.T) {
}
var withdrawFiatRequest = withdraw.Request{}
_, err := i.WithdrawFiatFunds(&withdrawFiatRequest)
_, err := i.WithdrawFiatFunds(context.Background(),
&withdrawFiatRequest)
if err != common.ErrFunctionNotSupported {
t.Errorf("Expected '%v', received: '%v'", common.ErrFunctionNotSupported, err)
}
@@ -429,14 +434,15 @@ func TestWithdrawInternationalBank(t *testing.T) {
}
var withdrawFiatRequest = withdraw.Request{}
_, err := i.WithdrawFiatFundsToInternationalBank(&withdrawFiatRequest)
_, err := i.WithdrawFiatFundsToInternationalBank(context.Background(),
&withdrawFiatRequest)
if err != common.ErrFunctionNotSupported {
t.Errorf("Expected '%v', received: '%v'", common.ErrFunctionNotSupported, err)
}
}
func TestGetDepositAddress(t *testing.T) {
_, err := i.GetDepositAddress(currency.BTC, "")
_, err := i.GetDepositAddress(context.Background(), currency.BTC, "")
if err == nil {
t.Error("GetDepositAddress() error cannot be nil")
}
@@ -448,7 +454,7 @@ func TestGetRecentTrades(t *testing.T) {
if err != nil {
t.Fatal(err)
}
_, err = i.GetRecentTrades(currencyPair, asset.Spot)
_, err = i.GetRecentTrades(context.Background(), currencyPair, asset.Spot)
if err != nil {
t.Error(err)
}
@@ -460,7 +466,8 @@ func TestGetHistoricTrades(t *testing.T) {
if err != nil {
t.Fatal(err)
}
_, err = i.GetHistoricTrades(currencyPair, asset.Spot, time.Now().Add(-time.Minute*15), time.Now())
_, err = i.GetHistoricTrades(context.Background(),
currencyPair, asset.Spot, time.Now().Add(-time.Minute*15), time.Now())
if err != nil && err != common.ErrFunctionNotSupported {
t.Error(err)
}

View File

@@ -1,6 +1,7 @@
package itbit
import (
"context"
"fmt"
"net/url"
"sort"
@@ -40,7 +41,7 @@ func (i *ItBit) GetDefaultConfig() (*config.ExchangeConfig, error) {
}
if i.Features.Supports.RESTCapabilities.AutoPairUpdates {
err = i.UpdateTradablePairs(true)
err = i.UpdateTradablePairs(context.TODO(), true)
if err != nil {
return nil, err
}
@@ -129,29 +130,29 @@ func (i *ItBit) Run() {
}
// FetchTradablePairs returns a list of the exchanges tradable pairs
func (i *ItBit) FetchTradablePairs(asset asset.Item) ([]string, error) {
func (i *ItBit) FetchTradablePairs(ctx context.Context, asset asset.Item) ([]string, error) {
return nil, common.ErrFunctionNotSupported
}
// UpdateTradablePairs updates the exchanges available pairs and stores
// them in the exchanges config
func (i *ItBit) UpdateTradablePairs(forceUpdate bool) error {
func (i *ItBit) UpdateTradablePairs(ctx context.Context, forceUpdate bool) error {
return common.ErrFunctionNotSupported
}
// UpdateTickers updates the ticker for all currency pairs of a given asset type
func (i *ItBit) UpdateTickers(a asset.Item) error {
func (i *ItBit) UpdateTickers(ctx context.Context, a asset.Item) error {
return common.ErrFunctionNotSupported
}
// UpdateTicker updates and returns the ticker for a currency pair
func (i *ItBit) UpdateTicker(p currency.Pair, a asset.Item) (*ticker.Price, error) {
func (i *ItBit) UpdateTicker(ctx context.Context, p currency.Pair, a asset.Item) (*ticker.Price, error) {
fpair, err := i.FormatExchangeCurrency(p, a)
if err != nil {
return nil, err
}
tick, err := i.GetTicker(fpair.String())
tick, err := i.GetTicker(ctx, fpair.String())
if err != nil {
return nil, err
}
@@ -176,25 +177,25 @@ func (i *ItBit) UpdateTicker(p currency.Pair, a asset.Item) (*ticker.Price, erro
}
// FetchTicker returns the ticker for a currency pair
func (i *ItBit) FetchTicker(p currency.Pair, assetType asset.Item) (*ticker.Price, error) {
func (i *ItBit) FetchTicker(ctx context.Context, p currency.Pair, assetType asset.Item) (*ticker.Price, error) {
tickerNew, err := ticker.GetTicker(i.Name, p, assetType)
if err != nil {
return i.UpdateTicker(p, assetType)
return i.UpdateTicker(ctx, p, assetType)
}
return tickerNew, nil
}
// FetchOrderbook returns orderbook base on the currency pair
func (i *ItBit) FetchOrderbook(p currency.Pair, assetType asset.Item) (*orderbook.Base, error) {
func (i *ItBit) FetchOrderbook(ctx context.Context, p currency.Pair, assetType asset.Item) (*orderbook.Base, error) {
ob, err := orderbook.Get(i.Name, p, assetType)
if err != nil {
return i.UpdateOrderbook(p, assetType)
return i.UpdateOrderbook(ctx, p, assetType)
}
return ob, nil
}
// UpdateOrderbook updates and returns the orderbook for a currency pair
func (i *ItBit) UpdateOrderbook(p currency.Pair, assetType asset.Item) (*orderbook.Base, error) {
func (i *ItBit) UpdateOrderbook(ctx context.Context, p currency.Pair, assetType asset.Item) (*orderbook.Base, error) {
book := &orderbook.Base{
Exchange: i.Name,
Pair: p,
@@ -207,7 +208,7 @@ func (i *ItBit) UpdateOrderbook(p currency.Pair, assetType asset.Item) (*orderbo
return book, err
}
orderbookNew, err := i.GetOrderbook(fpair.String())
orderbookNew, err := i.GetOrderbook(ctx, fpair.String())
if err != nil {
return nil, err
}
@@ -253,11 +254,11 @@ func (i *ItBit) UpdateOrderbook(p currency.Pair, assetType asset.Item) (*orderbo
}
// UpdateAccountInfo retrieves balances for all enabled currencies
func (i *ItBit) UpdateAccountInfo(assetType asset.Item) (account.Holdings, error) {
func (i *ItBit) UpdateAccountInfo(ctx context.Context, assetType asset.Item) (account.Holdings, error) {
var info account.Holdings
info.Exchange = i.Name
wallets, err := i.GetWallets(url.Values{})
wallets, err := i.GetWallets(ctx, url.Values{})
if err != nil {
return info, err
}
@@ -302,10 +303,10 @@ func (i *ItBit) UpdateAccountInfo(assetType asset.Item) (account.Holdings, error
}
// FetchAccountInfo retrieves balances for all enabled currencies
func (i *ItBit) FetchAccountInfo(assetType asset.Item) (account.Holdings, error) {
func (i *ItBit) FetchAccountInfo(ctx context.Context, assetType asset.Item) (account.Holdings, error) {
acc, err := account.GetHoldings(i.Name, assetType)
if err != nil {
return i.UpdateAccountInfo(assetType)
return i.UpdateAccountInfo(ctx, assetType)
}
return acc, nil
@@ -313,24 +314,24 @@ func (i *ItBit) FetchAccountInfo(assetType asset.Item) (account.Holdings, error)
// GetFundingHistory returns funding history, deposits and
// withdrawals
func (i *ItBit) GetFundingHistory() ([]exchange.FundHistory, error) {
func (i *ItBit) GetFundingHistory(ctx context.Context) ([]exchange.FundHistory, error) {
return nil, common.ErrFunctionNotSupported
}
// GetWithdrawalsHistory returns previous withdrawals data
func (i *ItBit) GetWithdrawalsHistory(c currency.Code) (resp []exchange.WithdrawalHistory, err error) {
func (i *ItBit) GetWithdrawalsHistory(ctx context.Context, c currency.Code) (resp []exchange.WithdrawalHistory, err error) {
return nil, common.ErrNotYetImplemented
}
// GetRecentTrades returns the most recent trades for a currency and asset
func (i *ItBit) GetRecentTrades(p currency.Pair, assetType asset.Item) ([]trade.Data, error) {
func (i *ItBit) GetRecentTrades(ctx context.Context, p currency.Pair, assetType asset.Item) ([]trade.Data, error) {
var err error
p, err = i.FormatExchangeCurrency(p, assetType)
if err != nil {
return nil, err
}
var tradeData Trades
tradeData, err = i.GetTradeHistory(p.String(), "")
tradeData, err = i.GetTradeHistory(ctx, p.String(), "")
if err != nil {
return nil, err
}
@@ -357,20 +358,20 @@ func (i *ItBit) GetRecentTrades(p currency.Pair, assetType asset.Item) ([]trade.
}
// GetHistoricTrades returns historic trade data within the timeframe provided
func (i *ItBit) GetHistoricTrades(_ currency.Pair, _ asset.Item, _, _ time.Time) ([]trade.Data, error) {
func (i *ItBit) GetHistoricTrades(_ context.Context, _ currency.Pair, _ asset.Item, _, _ time.Time) ([]trade.Data, error) {
// cannot do time based retrieval of trade data
return nil, common.ErrFunctionNotSupported
}
// SubmitOrder submits a new order
func (i *ItBit) SubmitOrder(s *order.Submit) (order.SubmitResponse, error) {
func (i *ItBit) SubmitOrder(ctx context.Context, s *order.Submit) (order.SubmitResponse, error) {
var submitOrderResponse order.SubmitResponse
if err := s.Validate(); err != nil {
return submitOrderResponse, err
}
var wallet string
wallets, err := i.GetWallets(url.Values{})
wallets, err := i.GetWallets(ctx, url.Values{})
if err != nil {
return submitOrderResponse, err
}
@@ -397,7 +398,8 @@ func (i *ItBit) SubmitOrder(s *order.Submit) (order.SubmitResponse, error) {
return submitOrderResponse, err
}
response, err := i.PlaceOrder(wallet,
response, err := i.PlaceOrder(ctx,
wallet,
s.Side.String(),
s.Type.String(),
fPair.Base.String(),
@@ -421,38 +423,45 @@ func (i *ItBit) SubmitOrder(s *order.Submit) (order.SubmitResponse, error) {
// ModifyOrder will allow of changing orderbook placement and limit to
// market conversion
func (i *ItBit) ModifyOrder(action *order.Modify) (order.Modify, error) {
func (i *ItBit) ModifyOrder(ctx context.Context, action *order.Modify) (order.Modify, error) {
return order.Modify{}, common.ErrFunctionNotSupported
}
// CancelOrder cancels an order by its corresponding ID number
func (i *ItBit) CancelOrder(o *order.Cancel) error {
func (i *ItBit) CancelOrder(ctx context.Context, o *order.Cancel) error {
if err := o.Validate(o.StandardCancel()); err != nil {
return err
}
return i.CancelExistingOrder(o.WalletAddress, o.ID)
return i.CancelExistingOrder(ctx, o.WalletAddress, o.ID)
}
// CancelBatchOrders cancels an orders by their corresponding ID numbers
func (i *ItBit) CancelBatchOrders(o []order.Cancel) (order.CancelBatchResponse, error) {
func (i *ItBit) CancelBatchOrders(ctx context.Context, o []order.Cancel) (order.CancelBatchResponse, error) {
return order.CancelBatchResponse{}, common.ErrNotYetImplemented
}
// CancelAllOrders cancels all orders associated with a currency pair
func (i *ItBit) CancelAllOrders(orderCancellation *order.Cancel) (order.CancelAllResponse, error) {
func (i *ItBit) CancelAllOrders(ctx context.Context, orderCancellation *order.Cancel) (order.CancelAllResponse, error) {
if err := orderCancellation.Validate(); err != nil {
return order.CancelAllResponse{}, err
}
cancelAllOrdersResponse := order.CancelAllResponse{
Status: make(map[string]string),
}
openOrders, err := i.GetOrders(orderCancellation.WalletAddress, "", "open", 0, 0)
openOrders, err := i.GetOrders(ctx,
orderCancellation.WalletAddress,
"",
"open",
0,
0)
if err != nil {
return cancelAllOrdersResponse, err
}
for j := range openOrders {
err = i.CancelExistingOrder(orderCancellation.WalletAddress, openOrders[j].ID)
err = i.CancelExistingOrder(ctx,
orderCancellation.WalletAddress,
openOrders[j].ID)
if err != nil {
cancelAllOrdersResponse.Status[openOrders[j].ID] = err.Error()
}
@@ -462,7 +471,7 @@ func (i *ItBit) CancelAllOrders(orderCancellation *order.Cancel) (order.CancelAl
}
// GetOrderInfo returns order information based on order ID
func (i *ItBit) GetOrderInfo(orderID string, pair currency.Pair, assetType asset.Item) (order.Detail, error) {
func (i *ItBit) GetOrderInfo(ctx context.Context, orderID string, pair currency.Pair, assetType asset.Item) (order.Detail, error) {
var orderDetail order.Detail
return orderDetail, common.ErrNotYetImplemented
}
@@ -471,30 +480,30 @@ func (i *ItBit) GetOrderInfo(orderID string, pair currency.Pair, assetType asset
// NOTE: This has not been implemented due to the fact you need to generate a
// a specific wallet ID and they restrict the amount of deposit address you can
// request limiting them to 2.
func (i *ItBit) GetDepositAddress(_ currency.Code, _ string) (string, error) {
func (i *ItBit) GetDepositAddress(_ context.Context, _ currency.Code, _ string) (string, error) {
return "", common.ErrNotYetImplemented
}
// WithdrawCryptocurrencyFunds returns a withdrawal ID when a withdrawal is
// submitted
func (i *ItBit) WithdrawCryptocurrencyFunds(_ *withdraw.Request) (*withdraw.ExchangeResponse, error) {
func (i *ItBit) WithdrawCryptocurrencyFunds(_ context.Context, _ *withdraw.Request) (*withdraw.ExchangeResponse, error) {
return nil, common.ErrFunctionNotSupported
}
// WithdrawFiatFunds returns a withdrawal ID when a
// withdrawal is submitted
func (i *ItBit) WithdrawFiatFunds(_ *withdraw.Request) (*withdraw.ExchangeResponse, error) {
func (i *ItBit) WithdrawFiatFunds(_ context.Context, _ *withdraw.Request) (*withdraw.ExchangeResponse, error) {
return nil, common.ErrFunctionNotSupported
}
// WithdrawFiatFundsToInternationalBank returns a withdrawal ID when a
// withdrawal is submitted
func (i *ItBit) WithdrawFiatFundsToInternationalBank(_ *withdraw.Request) (*withdraw.ExchangeResponse, error) {
func (i *ItBit) WithdrawFiatFundsToInternationalBank(_ context.Context, _ *withdraw.Request) (*withdraw.ExchangeResponse, error) {
return nil, common.ErrFunctionNotSupported
}
// GetFeeByType returns an estimate of fee based on type of transaction
func (i *ItBit) GetFeeByType(feeBuilder *exchange.FeeBuilder) (float64, error) {
func (i *ItBit) GetFeeByType(ctx context.Context, feeBuilder *exchange.FeeBuilder) (float64, error) {
if !i.AllowAuthenticatedRequest() && // Todo check connection status
feeBuilder.FeeType == exchange.CryptocurrencyTradeFee {
feeBuilder.FeeType = exchange.OfflineTradeFee
@@ -503,11 +512,11 @@ func (i *ItBit) GetFeeByType(feeBuilder *exchange.FeeBuilder) (float64, error) {
}
// GetActiveOrders retrieves any orders that are active/open
func (i *ItBit) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, error) {
func (i *ItBit) GetActiveOrders(ctx context.Context, req *order.GetOrdersRequest) ([]order.Detail, error) {
if err := req.Validate(); err != nil {
return nil, err
}
wallets, err := i.GetWallets(url.Values{})
wallets, err := i.GetWallets(ctx, url.Values{})
if err != nil {
return nil, err
}
@@ -515,7 +524,7 @@ func (i *ItBit) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, er
var allOrders []Order
for x := range wallets {
var resp []Order
resp, err = i.GetOrders(wallets[x].ID, "", "open", 0, 0)
resp, err = i.GetOrders(ctx, wallets[x].ID, "", "open", 0, 0)
if err != nil {
return nil, err
}
@@ -566,12 +575,12 @@ func (i *ItBit) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, er
// GetOrderHistory retrieves account order information
// Can Limit response to specific order status
func (i *ItBit) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail, error) {
func (i *ItBit) GetOrderHistory(ctx context.Context, req *order.GetOrdersRequest) ([]order.Detail, error) {
if err := req.Validate(); err != nil {
return nil, err
}
wallets, err := i.GetWallets(url.Values{})
wallets, err := i.GetWallets(ctx, url.Values{})
if err != nil {
return nil, err
}
@@ -579,7 +588,7 @@ func (i *ItBit) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail, er
var allOrders []Order
for x := range wallets {
var resp []Order
resp, err = i.GetOrders(wallets[x].ID, "", "", 0, 0)
resp, err = i.GetOrders(ctx, wallets[x].ID, "", "", 0, 0)
if err != nil {
return nil, err
}
@@ -634,17 +643,17 @@ func (i *ItBit) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail, er
// ValidateCredentials validates current credentials used for wrapper
// functionality
func (i *ItBit) ValidateCredentials(assetType asset.Item) error {
_, err := i.UpdateAccountInfo(assetType)
func (i *ItBit) ValidateCredentials(ctx context.Context, assetType asset.Item) error {
_, err := i.UpdateAccountInfo(ctx, assetType)
return i.CheckTransientError(err)
}
// GetHistoricCandles returns candles between a time period for a set time interval
func (i *ItBit) GetHistoricCandles(pair currency.Pair, a asset.Item, start, end time.Time, interval kline.Interval) (kline.Item, error) {
func (i *ItBit) GetHistoricCandles(ctx context.Context, pair currency.Pair, a asset.Item, start, end time.Time, interval kline.Interval) (kline.Item, error) {
return kline.Item{}, common.ErrFunctionNotSupported
}
// GetHistoricCandlesExtended returns candles between a time period for a set time interval
func (i *ItBit) GetHistoricCandlesExtended(pair currency.Pair, a asset.Item, start, end time.Time, interval kline.Interval) (kline.Item, error) {
func (i *ItBit) GetHistoricCandlesExtended(ctx context.Context, pair currency.Pair, a asset.Item, start, end time.Time, interval kline.Interval) (kline.Item, error) {
return kline.Item{}, common.ErrFunctionNotSupported
}