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

@@ -52,56 +52,56 @@ type EXMO struct {
}
// GetTrades returns the trades for a symbol or symbols
func (e *EXMO) GetTrades(symbol string) (map[string][]Trades, error) {
func (e *EXMO) GetTrades(ctx context.Context, symbol string) (map[string][]Trades, error) {
v := url.Values{}
v.Set("pair", symbol)
result := make(map[string][]Trades)
urlPath := fmt.Sprintf("/v%s/%s", exmoAPIVersion, exmoTrades)
return result, e.SendHTTPRequest(exchange.RestSpot, common.EncodeURLValues(urlPath, v), &result)
return result, e.SendHTTPRequest(ctx, exchange.RestSpot, common.EncodeURLValues(urlPath, v), &result)
}
// GetOrderbook returns the orderbook for a symbol or symbols
func (e *EXMO) GetOrderbook(symbol string) (map[string]Orderbook, error) {
func (e *EXMO) GetOrderbook(ctx context.Context, symbol string) (map[string]Orderbook, error) {
v := url.Values{}
v.Set("pair", symbol)
result := make(map[string]Orderbook)
urlPath := fmt.Sprintf("/v%s/%s", exmoAPIVersion, exmoOrderbook)
return result, e.SendHTTPRequest(exchange.RestSpot, common.EncodeURLValues(urlPath, v), &result)
return result, e.SendHTTPRequest(ctx, exchange.RestSpot, common.EncodeURLValues(urlPath, v), &result)
}
// GetTicker returns the ticker for a symbol or symbols
func (e *EXMO) GetTicker() (map[string]Ticker, error) {
func (e *EXMO) GetTicker(ctx context.Context) (map[string]Ticker, error) {
v := url.Values{}
result := make(map[string]Ticker)
urlPath := fmt.Sprintf("/v%s/%s", exmoAPIVersion, exmoTicker)
return result, e.SendHTTPRequest(exchange.RestSpot, common.EncodeURLValues(urlPath, v), &result)
return result, e.SendHTTPRequest(ctx, exchange.RestSpot, common.EncodeURLValues(urlPath, v), &result)
}
// GetPairSettings returns the pair settings for a symbol or symbols
func (e *EXMO) GetPairSettings() (map[string]PairSettings, error) {
func (e *EXMO) GetPairSettings(ctx context.Context) (map[string]PairSettings, error) {
result := make(map[string]PairSettings)
urlPath := fmt.Sprintf("/v%s/%s", exmoAPIVersion, exmoPairSettings)
return result, e.SendHTTPRequest(exchange.RestSpot, urlPath, &result)
return result, e.SendHTTPRequest(ctx, exchange.RestSpot, urlPath, &result)
}
// GetCurrency returns a list of currencies
func (e *EXMO) GetCurrency() ([]string, error) {
func (e *EXMO) GetCurrency(ctx context.Context) ([]string, error) {
var result []string
urlPath := fmt.Sprintf("/v%s/%s", exmoAPIVersion, exmoCurrency)
return result, e.SendHTTPRequest(exchange.RestSpot, urlPath, &result)
return result, e.SendHTTPRequest(ctx, exchange.RestSpot, urlPath, &result)
}
// GetUserInfo returns the user info
func (e *EXMO) GetUserInfo() (UserInfo, error) {
func (e *EXMO) GetUserInfo(ctx context.Context) (UserInfo, error) {
var result UserInfo
err := e.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost, exmoUserInfo, url.Values{}, &result)
err := e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, exmoUserInfo, url.Values{}, &result)
return result, err
}
// CreateOrder creates an order
// Params: pair, quantity, price and type
// Type can be buy, sell, market_buy, market_sell, market_buy_total and market_sell_total
func (e *EXMO) CreateOrder(pair, orderType string, price, amount float64) (int64, error) {
func (e *EXMO) CreateOrder(ctx context.Context, pair, orderType string, price, amount float64) (int64, error) {
type response struct {
OrderID int64 `json:"order_id"`
Result bool `json:"result"`
@@ -115,7 +115,7 @@ func (e *EXMO) CreateOrder(pair, orderType string, price, amount float64) (int64
v.Set("quantity", strconv.FormatFloat(amount, 'f', -1, 64))
var resp response
err := e.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost, exmoOrderCreate, v, &resp)
err := e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, exmoOrderCreate, v, &resp)
if !resp.Result {
return -1, errors.New(resp.Error)
}
@@ -123,7 +123,7 @@ func (e *EXMO) CreateOrder(pair, orderType string, price, amount float64) (int64
}
// CancelExistingOrder cancels an order by the orderID
func (e *EXMO) CancelExistingOrder(orderID int64) error {
func (e *EXMO) CancelExistingOrder(ctx context.Context, orderID int64) error {
v := url.Values{}
v.Set("order_id", strconv.FormatInt(orderID, 10))
type response struct {
@@ -131,7 +131,7 @@ func (e *EXMO) CancelExistingOrder(orderID int64) error {
Error string `json:"error"`
}
var resp response
err := e.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost, exmoOrderCancel, v, &resp)
err := e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, exmoOrderCancel, v, &resp)
if !resp.Result {
return errors.New(resp.Error)
}
@@ -139,14 +139,14 @@ func (e *EXMO) CancelExistingOrder(orderID int64) error {
}
// GetOpenOrders returns the users open orders
func (e *EXMO) GetOpenOrders() (map[string]OpenOrders, error) {
func (e *EXMO) GetOpenOrders(ctx context.Context) (map[string]OpenOrders, error) {
result := make(map[string]OpenOrders)
err := e.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost, exmoOpenOrders, url.Values{}, &result)
err := e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, exmoOpenOrders, url.Values{}, &result)
return result, err
}
// GetUserTrades returns the user trades
func (e *EXMO) GetUserTrades(pair, offset, limit string) (map[string][]UserTrades, error) {
func (e *EXMO) GetUserTrades(ctx context.Context, pair, offset, limit string) (map[string][]UserTrades, error) {
result := make(map[string][]UserTrades)
v := url.Values{}
v.Set("pair", pair)
@@ -159,12 +159,12 @@ func (e *EXMO) GetUserTrades(pair, offset, limit string) (map[string][]UserTrade
v.Set("limit", limit)
}
err := e.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost, exmoUserTrades, v, &result)
err := e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, exmoUserTrades, v, &result)
return result, err
}
// GetCancelledOrders returns a list of cancelled orders
func (e *EXMO) GetCancelledOrders(offset, limit string) ([]CancelledOrder, error) {
func (e *EXMO) GetCancelledOrders(ctx context.Context, offset, limit string) ([]CancelledOrder, error) {
var result []CancelledOrder
v := url.Values{}
@@ -176,35 +176,35 @@ func (e *EXMO) GetCancelledOrders(offset, limit string) ([]CancelledOrder, error
v.Set("limit", limit)
}
err := e.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost, exmoCancelledOrders, v, &result)
err := e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, exmoCancelledOrders, v, &result)
return result, err
}
// GetOrderTrades returns a history of order trade details for the specific orderID
func (e *EXMO) GetOrderTrades(orderID int64) (OrderTrades, error) {
func (e *EXMO) GetOrderTrades(ctx context.Context, orderID int64) (OrderTrades, error) {
var result OrderTrades
v := url.Values{}
v.Set("order_id", strconv.FormatInt(orderID, 10))
err := e.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost, exmoOrderTrades, v, &result)
err := e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, exmoOrderTrades, v, &result)
return result, err
}
// GetRequiredAmount calculates the sum of buying a certain amount of currency
// for the particular currency pair
func (e *EXMO) GetRequiredAmount(pair string, amount float64) (RequiredAmount, error) {
func (e *EXMO) GetRequiredAmount(ctx context.Context, pair string, amount float64) (RequiredAmount, error) {
v := url.Values{}
v.Set("pair", pair)
v.Set("quantity", strconv.FormatFloat(amount, 'f', -1, 64))
var result RequiredAmount
err := e.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost, exmoRequiredAmount, v, &result)
err := e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, exmoRequiredAmount, v, &result)
return result, err
}
// GetCryptoDepositAddress returns a list of addresses for cryptocurrency deposits
func (e *EXMO) GetCryptoDepositAddress() (map[string]string, error) {
func (e *EXMO) GetCryptoDepositAddress(ctx context.Context) (map[string]string, error) {
var result interface{}
err := e.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost, exmoDepositAddress, url.Values{}, &result)
err := e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, exmoDepositAddress, url.Values{}, &result)
if err != nil {
return nil, err
}
@@ -224,7 +224,7 @@ func (e *EXMO) GetCryptoDepositAddress() (map[string]string, error) {
// WithdrawCryptocurrency withdraws a cryptocurrency from the exchange to the desired address
// NOTE: This API function is available only after request to their tech support team
func (e *EXMO) WithdrawCryptocurrency(currency, address, invoice string, amount float64) (int64, error) {
func (e *EXMO) WithdrawCryptocurrency(ctx context.Context, currency, address, invoice string, amount float64) (int64, error) {
type response struct {
TaskID int64 `json:"task_id,string"`
Result bool `json:"result"`
@@ -242,7 +242,7 @@ func (e *EXMO) WithdrawCryptocurrency(currency, address, invoice string, amount
v.Set("amount", strconv.FormatFloat(amount, 'f', -1, 64))
var resp response
err := e.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost, exmoWithdrawCrypt, v, &resp)
err := e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, exmoWithdrawCrypt, v, &resp)
if err != nil {
return -1, err
}
@@ -253,7 +253,7 @@ func (e *EXMO) WithdrawCryptocurrency(currency, address, invoice string, amount
}
// GetWithdrawTXID gets the result of a withdrawal request
func (e *EXMO) GetWithdrawTXID(taskID int64) (string, error) {
func (e *EXMO) GetWithdrawTXID(ctx context.Context, taskID int64) (string, error) {
type response struct {
Status bool `json:"status"`
TXID string `json:"txid"`
@@ -263,43 +263,43 @@ func (e *EXMO) GetWithdrawTXID(taskID int64) (string, error) {
v.Set("task_id", strconv.FormatInt(taskID, 10))
var result response
err := e.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost, exmoGetWithdrawTXID, v, &result)
err := e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, exmoGetWithdrawTXID, v, &result)
return result.TXID, err
}
// ExcodeCreate creates an EXMO coupon
func (e *EXMO) ExcodeCreate(currency string, amount float64) (ExcodeCreate, error) {
func (e *EXMO) ExcodeCreate(ctx context.Context, currency string, amount float64) (ExcodeCreate, error) {
v := url.Values{}
v.Set("currency", currency)
v.Set("amount", strconv.FormatFloat(amount, 'f', -1, 64))
var result ExcodeCreate
err := e.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost, exmoExcodeCreate, v, &result)
err := e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, exmoExcodeCreate, v, &result)
return result, err
}
// ExcodeLoad loads an EXMO coupon
func (e *EXMO) ExcodeLoad(excode string) (ExcodeLoad, error) {
func (e *EXMO) ExcodeLoad(ctx context.Context, excode string) (ExcodeLoad, error) {
v := url.Values{}
v.Set("code", excode)
var result ExcodeLoad
err := e.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost, exmoExcodeLoad, v, &result)
err := e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, exmoExcodeLoad, v, &result)
return result, err
}
// GetWalletHistory returns the users deposit/withdrawal history
func (e *EXMO) GetWalletHistory(date int64) (WalletHistory, error) {
func (e *EXMO) GetWalletHistory(ctx context.Context, date int64) (WalletHistory, error) {
v := url.Values{}
v.Set("date", strconv.FormatInt(date, 10))
var result WalletHistory
err := e.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost, exmoWalletHistory, v, &result)
err := e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, exmoWalletHistory, v, &result)
return result, err
}
// SendHTTPRequest sends an unauthenticated HTTP request
func (e *EXMO) SendHTTPRequest(endpoint exchange.URL, path string, result interface{}) error {
func (e *EXMO) SendHTTPRequest(ctx context.Context, endpoint exchange.URL, path string, result interface{}) error {
urlPath, err := e.API.Endpoints.GetURL(endpoint)
if err != nil {
return err
@@ -313,13 +313,13 @@ func (e *EXMO) SendHTTPRequest(endpoint exchange.URL, path string, result interf
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
}
return e.SendPayload(context.Background(), request.Unset, func() (*request.Item, error) {
return e.SendPayload(ctx, request.Unset, func() (*request.Item, error) {
return item, nil
})
}
// SendAuthenticatedHTTPRequest sends an authenticated HTTP request
func (e *EXMO) SendAuthenticatedHTTPRequest(epath exchange.URL, method, endpoint string, vals url.Values, result interface{}) error {
func (e *EXMO) SendAuthenticatedHTTPRequest(ctx context.Context, epath exchange.URL, method, endpoint string, vals url.Values, result interface{}) error {
if !e.AllowAuthenticatedRequest() {
return fmt.Errorf("%s %w", e.Name, exchange.ErrAuthenticatedRequestWithoutCredentialsSet)
}
@@ -331,7 +331,7 @@ func (e *EXMO) SendAuthenticatedHTTPRequest(epath exchange.URL, method, endpoint
path := urlPath + fmt.Sprintf("/v%s/%s", exmoAPIVersion, endpoint)
return e.SendPayload(context.Background(), request.Unset, func() (*request.Item, error) {
return e.SendPayload(ctx, request.Unset, func() (*request.Item, error) {
n := e.Requester.GetNonce(true).String()
vals.Set("nonce", n)