mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-06-07 23:16:53 +00:00
cmd/exchange_template, exchanges: Update templates and propogate to exchanges (#1777)
* Added TimeInForce type and updated related files * Linter issue fix and minor coinbasepro type update * Bitrex consts update * added unit test and minor changes in bittrex * Unit tests update * Fix minor linter issues * Update TestStringToTimeInForce unit test * Exchange test template change * A different approach * fix conflict with gateio timeInForce * minor exchange template update * Minor fix to test_files template * Update order tests * Complete updating the order unit tests * Updating exchange wrapper and test template files * update kucoin and deribit wrapper to match the time in force change * minor comment update * fix time-in-force related test errors * linter issue fix * ADD_NEW_EXCHANGE documentation update * time in force constants, functions and unit tests update * shift tif policies to TimeInForce * Update time-in-force, related functions, and unit tests * fix linter issue and time-in-force processing * added a good till crossing tif value * order type fix and fix related tim-in-force entries * update time-in-force unmarshaling and unit test * consistency guideline added * fix time-in-force error in gateio * linter issue fix * update based on review comments * add unit test and fix missing issues * minor fix and added benchmark unit test * change GTT to GTC for limit * fix linter issue * added time-in-force value to place order param * fix minor issues based on review comment and move tif code to separate files * update on exchanges linked to time-in-force * resolve missing review comments * minor linter issues fix * added time-in-force handler and update timeInForce parametered endpoint * minor fixes based on review * nits fix * update based on review * linter fix * rm getTimeInForce func and minor change to time-in-force * minor change * update based on review comments * wrappers and time-in-force calling approach * minor change * update gateio string to timeInForce conversion and unit test * update exchange template * update wrapper template file * policy comments, and template files update * rename all exchange types name to Exchange * update on template files and template generation * templates and generation code and other updates * linter issue fix * added subscriptions and websocket templates * update ADD_NEW_EXCHANGE.md with recent binance functions and implementations * rename template files and update unit tests * minor template and unit test fix * rename templates and fix on unit tests * update on template files and documentation * removed unnecessary tag fix and update templates * fix Add_NEW_EXCHANGE.md doc file * formatting, comments, and error checks update on template files * rename exchange receivers to e and ex for consistency * rename unit test exchange receiver and minor updates * linter issues fix * fix deribit issue and minor style update * fix test issues caused by receiver change * raname local variables exchange declaration variables * update templates comments * update templates and related comments * renamed ex to e * update template comments * toggle WS to false to improve coverage * template comments update * added test coverage to Ws enabled and minor changes --------- Co-authored-by: Samuel Reid <43227667+cranktakular@users.noreply.github.com>
This commit is contained in:
@@ -60,18 +60,18 @@ const (
|
||||
bitstampRequestRate = 8000
|
||||
)
|
||||
|
||||
// Bitstamp is the overarching type across the bitstamp package
|
||||
type Bitstamp struct {
|
||||
// Exchange implements exchange.IBotExchange and contains additional specific api methods for interacting with Bitstamp
|
||||
type Exchange struct {
|
||||
exchange.Base
|
||||
}
|
||||
|
||||
// GetFee returns an estimate of fee based on type of transaction
|
||||
func (b *Bitstamp) GetFee(ctx context.Context, feeBuilder *exchange.FeeBuilder) (float64, error) {
|
||||
func (e *Exchange) GetFee(ctx context.Context, feeBuilder *exchange.FeeBuilder) (float64, error) {
|
||||
var fee float64
|
||||
|
||||
switch feeBuilder.FeeType {
|
||||
case exchange.CryptocurrencyTradeFee:
|
||||
tradingFee, err := b.getTradingFee(ctx, feeBuilder)
|
||||
tradingFee, err := e.getTradingFee(ctx, feeBuilder)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("error getting trading fee: %w", err)
|
||||
}
|
||||
@@ -92,8 +92,8 @@ func (b *Bitstamp) GetFee(ctx context.Context, feeBuilder *exchange.FeeBuilder)
|
||||
}
|
||||
|
||||
// GetTradingFee returns a trading fee based on a currency
|
||||
func (b *Bitstamp) getTradingFee(ctx context.Context, feeBuilder *exchange.FeeBuilder) (float64, error) {
|
||||
tradingFees, err := b.GetAccountTradingFee(ctx, feeBuilder.Pair)
|
||||
func (e *Exchange) getTradingFee(ctx context.Context, feeBuilder *exchange.FeeBuilder) (float64, error) {
|
||||
tradingFees, err := e.GetAccountTradingFee(ctx, feeBuilder.Pair)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@@ -106,23 +106,23 @@ func (b *Bitstamp) getTradingFee(ctx context.Context, feeBuilder *exchange.FeeBu
|
||||
}
|
||||
|
||||
// GetAccountTradingFee returns a TradingFee for a pair
|
||||
func (b *Bitstamp) GetAccountTradingFee(ctx context.Context, pair currency.Pair) (TradingFees, error) {
|
||||
func (e *Exchange) GetAccountTradingFee(ctx context.Context, pair currency.Pair) (TradingFees, error) {
|
||||
path := bitstampAPITradingFees + "/" + strings.ToLower(pair.String())
|
||||
|
||||
var resp TradingFees
|
||||
if pair.IsEmpty() {
|
||||
return resp, currency.ErrCurrencyPairEmpty
|
||||
}
|
||||
err := b.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, path, true, nil, &resp)
|
||||
err := e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, path, true, nil, &resp)
|
||||
|
||||
return resp, err
|
||||
}
|
||||
|
||||
// GetAccountTradingFees returns a slice of TradingFee
|
||||
func (b *Bitstamp) GetAccountTradingFees(ctx context.Context) ([]TradingFees, error) {
|
||||
func (e *Exchange) GetAccountTradingFees(ctx context.Context) ([]TradingFees, error) {
|
||||
path := bitstampAPITradingFees
|
||||
var resp []TradingFees
|
||||
err := b.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, path, true, nil, &resp)
|
||||
err := e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, path, true, nil, &resp)
|
||||
return resp, err
|
||||
}
|
||||
|
||||
@@ -155,7 +155,7 @@ func getInternationalBankDepositFee(amount float64) float64 {
|
||||
}
|
||||
|
||||
// GetTicker returns ticker information
|
||||
func (b *Bitstamp) GetTicker(ctx context.Context, currency string, hourly bool) (*Ticker, error) {
|
||||
func (e *Exchange) GetTicker(ctx context.Context, currency string, hourly bool) (*Ticker, error) {
|
||||
response := Ticker{}
|
||||
tickerEndpoint := bitstampAPITicker
|
||||
|
||||
@@ -163,13 +163,13 @@ func (b *Bitstamp) GetTicker(ctx context.Context, currency string, hourly bool)
|
||||
tickerEndpoint = bitstampAPITickerHourly
|
||||
}
|
||||
path := "/v" + bitstampAPIVersion + "/" + tickerEndpoint + "/" + strings.ToLower(currency) + "/"
|
||||
return &response, b.SendHTTPRequest(ctx, exchange.RestSpot, path, &response)
|
||||
return &response, e.SendHTTPRequest(ctx, exchange.RestSpot, path, &response)
|
||||
}
|
||||
|
||||
// GetOrderbook Returns a JSON dictionary with "bids" and "asks". Each is a list
|
||||
// of open orders and each order is represented as a list holding the price and
|
||||
// the amount.
|
||||
func (b *Bitstamp) GetOrderbook(ctx context.Context, currency string) (*Orderbook, error) {
|
||||
func (e *Exchange) GetOrderbook(ctx context.Context, currency string) (*Orderbook, error) {
|
||||
type response struct {
|
||||
Timestamp types.Time `json:"timestamp"`
|
||||
Bids [][2]types.Number `json:"bids"`
|
||||
@@ -178,7 +178,7 @@ func (b *Bitstamp) GetOrderbook(ctx context.Context, currency string) (*Orderboo
|
||||
|
||||
path := "/v" + bitstampAPIVersion + "/" + bitstampAPIOrderbook + "/" + strings.ToLower(currency) + "/"
|
||||
var resp response
|
||||
err := b.SendHTTPRequest(ctx, exchange.RestSpot, path, &resp)
|
||||
err := e.SendHTTPRequest(ctx, exchange.RestSpot, path, &resp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -204,35 +204,35 @@ func (b *Bitstamp) GetOrderbook(ctx context.Context, currency string) (*Orderboo
|
||||
|
||||
// GetTradingPairs returns a list of trading pairs which Bitstamp
|
||||
// currently supports
|
||||
func (b *Bitstamp) GetTradingPairs(ctx context.Context) ([]TradingPair, error) {
|
||||
func (e *Exchange) GetTradingPairs(ctx context.Context) ([]TradingPair, error) {
|
||||
var result []TradingPair
|
||||
path := "/v" + bitstampAPIVersion + "/" + bitstampAPITradingPairsInfo
|
||||
return result, b.SendHTTPRequest(ctx, exchange.RestSpot, path, &result)
|
||||
return result, e.SendHTTPRequest(ctx, exchange.RestSpot, path, &result)
|
||||
}
|
||||
|
||||
// GetTransactions returns transaction information
|
||||
// value parameter ["time"] = "minute", "hour", "day" will collate your
|
||||
// response into time intervals.
|
||||
func (b *Bitstamp) GetTransactions(ctx context.Context, currencyPair, timePeriod string) ([]Transactions, error) {
|
||||
func (e *Exchange) GetTransactions(ctx context.Context, currencyPair, timePeriod string) ([]Transactions, error) {
|
||||
var transactions []Transactions
|
||||
requestURL := "/v" + bitstampAPIVersion + "/" + bitstampAPITransactions + "/" + strings.ToLower(currencyPair) + "/"
|
||||
if timePeriod != "" {
|
||||
requestURL += "?time=" + url.QueryEscape(timePeriod)
|
||||
}
|
||||
return transactions, b.SendHTTPRequest(ctx, exchange.RestSpot, requestURL, &transactions)
|
||||
return transactions, e.SendHTTPRequest(ctx, exchange.RestSpot, requestURL, &transactions)
|
||||
}
|
||||
|
||||
// GetEURUSDConversionRate returns the conversion rate between Euro and USD
|
||||
func (b *Bitstamp) GetEURUSDConversionRate(ctx context.Context) (EURUSDConversionRate, error) {
|
||||
func (e *Exchange) GetEURUSDConversionRate(ctx context.Context) (EURUSDConversionRate, error) {
|
||||
rate := EURUSDConversionRate{}
|
||||
path := "/" + bitstampAPIEURUSD
|
||||
return rate, b.SendHTTPRequest(ctx, exchange.RestSpot, path, &rate)
|
||||
return rate, e.SendHTTPRequest(ctx, exchange.RestSpot, path, &rate)
|
||||
}
|
||||
|
||||
// GetBalance returns full balance of currency held on the exchange
|
||||
func (b *Bitstamp) GetBalance(ctx context.Context) (Balances, error) {
|
||||
func (e *Exchange) GetBalance(ctx context.Context) (Balances, error) {
|
||||
var balance map[string]types.Number
|
||||
err := b.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, bitstampAPIBalance, true, nil, &balance)
|
||||
err := e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, bitstampAPIBalance, true, nil, &balance)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -258,41 +258,41 @@ func (b *Bitstamp) GetBalance(ctx context.Context) (Balances, error) {
|
||||
}
|
||||
|
||||
// GetUserTransactions returns an array of transactions
|
||||
func (b *Bitstamp) GetUserTransactions(ctx context.Context, currencyPair string) ([]UserTransactions, error) {
|
||||
func (e *Exchange) GetUserTransactions(ctx context.Context, currencyPair string) ([]UserTransactions, error) {
|
||||
var resp []UserTransactions
|
||||
var err error
|
||||
if currencyPair == "" {
|
||||
err = b.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, bitstampAPIUserTransactions, true, url.Values{}, &resp)
|
||||
err = e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, bitstampAPIUserTransactions, true, url.Values{}, &resp)
|
||||
} else {
|
||||
err = b.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, bitstampAPIUserTransactions+"/"+currencyPair, true, url.Values{}, &resp)
|
||||
err = e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, bitstampAPIUserTransactions+"/"+currencyPair, true, url.Values{}, &resp)
|
||||
}
|
||||
return resp, err
|
||||
}
|
||||
|
||||
// GetOpenOrders returns all open orders on the exchange
|
||||
func (b *Bitstamp) GetOpenOrders(ctx context.Context, currencyPair string) ([]Order, error) {
|
||||
func (e *Exchange) GetOpenOrders(ctx context.Context, currencyPair string) ([]Order, error) {
|
||||
var resp []Order
|
||||
path := bitstampAPIOpenOrders + "/" + strings.ToLower(currencyPair)
|
||||
return resp, b.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, path, true, nil, &resp)
|
||||
return resp, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, path, true, nil, &resp)
|
||||
}
|
||||
|
||||
// GetOrderStatus returns an the status of an order by its ID
|
||||
func (b *Bitstamp) GetOrderStatus(ctx context.Context, orderID int64) (OrderStatus, error) {
|
||||
func (e *Exchange) GetOrderStatus(ctx context.Context, orderID int64) (OrderStatus, error) {
|
||||
resp := OrderStatus{}
|
||||
req := url.Values{}
|
||||
req.Add("id", strconv.FormatInt(orderID, 10))
|
||||
|
||||
return resp,
|
||||
b.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, bitstampAPIOrderStatus, false, req, &resp)
|
||||
e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, bitstampAPIOrderStatus, false, req, &resp)
|
||||
}
|
||||
|
||||
// CancelExistingOrder cancels order by ID
|
||||
func (b *Bitstamp) CancelExistingOrder(ctx context.Context, orderID int64) (CancelOrder, error) {
|
||||
func (e *Exchange) CancelExistingOrder(ctx context.Context, orderID int64) (CancelOrder, error) {
|
||||
req := url.Values{}
|
||||
req.Add("id", strconv.FormatInt(orderID, 10))
|
||||
|
||||
var result CancelOrder
|
||||
err := b.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, bitstampAPICancelOrder, true, req, &result)
|
||||
err := e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, bitstampAPICancelOrder, true, req, &result)
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
@@ -301,15 +301,15 @@ func (b *Bitstamp) CancelExistingOrder(ctx context.Context, orderID int64) (Canc
|
||||
}
|
||||
|
||||
// CancelAllExistingOrders cancels all open orders on the exchange
|
||||
func (b *Bitstamp) CancelAllExistingOrders(ctx context.Context) (bool, error) {
|
||||
func (e *Exchange) CancelAllExistingOrders(ctx context.Context) (bool, error) {
|
||||
result := false
|
||||
|
||||
return result,
|
||||
b.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, bitstampAPICancelAllOrders, false, nil, &result)
|
||||
e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, bitstampAPICancelAllOrders, false, nil, &result)
|
||||
}
|
||||
|
||||
// PlaceOrder places an order on the exchange.
|
||||
func (b *Bitstamp) PlaceOrder(ctx context.Context, currencyPair string, price, amount float64, buy, market bool) (Order, error) {
|
||||
func (e *Exchange) PlaceOrder(ctx context.Context, currencyPair string, price, amount float64, buy, market bool) (Order, error) {
|
||||
req := url.Values{}
|
||||
req.Add("amount", strconv.FormatFloat(amount, 'f', -1, 64))
|
||||
req.Add("price", strconv.FormatFloat(price, 'f', -1, 64))
|
||||
@@ -328,13 +328,13 @@ func (b *Bitstamp) PlaceOrder(ctx context.Context, currencyPair string, price, a
|
||||
}
|
||||
|
||||
return response,
|
||||
b.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, path, true, req, &response)
|
||||
e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, path, true, req, &response)
|
||||
}
|
||||
|
||||
// GetWithdrawalRequests returns withdrawal requests for the account
|
||||
// timedelta - positive integer with max value 50000000 which returns requests
|
||||
// from number of seconds ago to now.
|
||||
func (b *Bitstamp) GetWithdrawalRequests(ctx context.Context, timedelta int64) ([]WithdrawalRequests, error) {
|
||||
func (e *Exchange) GetWithdrawalRequests(ctx context.Context, timedelta int64) ([]WithdrawalRequests, error) {
|
||||
var resp []WithdrawalRequests
|
||||
if timedelta > 50000000 || timedelta < 0 {
|
||||
return resp, errors.New("time delta exceeded, max: 50000000 min: 0")
|
||||
@@ -348,7 +348,7 @@ func (b *Bitstamp) GetWithdrawalRequests(ctx context.Context, timedelta int64) (
|
||||
}
|
||||
|
||||
return resp,
|
||||
b.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, bitstampAPIWithdrawalRequests, false, value, &resp)
|
||||
e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, bitstampAPIWithdrawalRequests, false, value, &resp)
|
||||
}
|
||||
|
||||
// CryptoWithdrawal withdraws a cryptocurrency into a supplied wallet, returns ID
|
||||
@@ -356,7 +356,7 @@ func (b *Bitstamp) GetWithdrawalRequests(ctx context.Context, timedelta int64) (
|
||||
// address - The wallet address of the cryptocurrency
|
||||
// symbol - the type of crypto ie "ltc", "btc", "eth"
|
||||
// destTag - only for XRP default to ""
|
||||
func (b *Bitstamp) CryptoWithdrawal(ctx context.Context, amount float64, address, symbol, destTag string) (*CryptoWithdrawalResponse, error) {
|
||||
func (e *Exchange) CryptoWithdrawal(ctx context.Context, amount float64, address, symbol, destTag string) (*CryptoWithdrawalResponse, error) {
|
||||
req := url.Values{}
|
||||
req.Add("amount", strconv.FormatFloat(amount, 'f', -1, 64))
|
||||
req.Add("address", address)
|
||||
@@ -375,11 +375,11 @@ func (b *Bitstamp) CryptoWithdrawal(ctx context.Context, amount float64, address
|
||||
|
||||
var resp CryptoWithdrawalResponse
|
||||
endpoint = strings.ToLower(symbol) + "_withdrawal"
|
||||
return &resp, b.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, endpoint, true, req, &resp)
|
||||
return &resp, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, endpoint, true, req, &resp)
|
||||
}
|
||||
|
||||
// OpenBankWithdrawal Opens a bank withdrawal request (SEPA or international)
|
||||
func (b *Bitstamp) OpenBankWithdrawal(ctx context.Context, amount float64, currency,
|
||||
func (e *Exchange) OpenBankWithdrawal(ctx context.Context, amount float64, currency,
|
||||
name, iban, bic, address, postalCode, city, country,
|
||||
comment, withdrawalType string,
|
||||
) (FIATWithdrawalResponse, error) {
|
||||
@@ -397,11 +397,11 @@ func (b *Bitstamp) OpenBankWithdrawal(ctx context.Context, amount float64, curre
|
||||
req.Add("comment", comment)
|
||||
|
||||
resp := FIATWithdrawalResponse{}
|
||||
return resp, b.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, bitstampAPIOpenWithdrawal, true, req, &resp)
|
||||
return resp, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, bitstampAPIOpenWithdrawal, true, req, &resp)
|
||||
}
|
||||
|
||||
// OpenInternationalBankWithdrawal Opens a bank withdrawal request (international)
|
||||
func (b *Bitstamp) OpenInternationalBankWithdrawal(ctx context.Context, amount float64, currency,
|
||||
func (e *Exchange) OpenInternationalBankWithdrawal(ctx context.Context, amount float64, currency,
|
||||
name, iban, bic, address, postalCode, city, country,
|
||||
bankName, bankAddress, bankPostCode, bankCity, bankCountry, internationalCurrency,
|
||||
comment, withdrawalType string,
|
||||
@@ -426,27 +426,27 @@ func (b *Bitstamp) OpenInternationalBankWithdrawal(ctx context.Context, amount f
|
||||
req.Add("bank_country", bankCountry)
|
||||
|
||||
resp := FIATWithdrawalResponse{}
|
||||
return resp, b.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, bitstampAPIOpenWithdrawal, true, req, &resp)
|
||||
return resp, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, bitstampAPIOpenWithdrawal, true, req, &resp)
|
||||
}
|
||||
|
||||
// GetCryptoDepositAddress returns a depositing address by crypto.
|
||||
// crypto - example "btc", "ltc", "eth", "xrp" or "bch"
|
||||
func (b *Bitstamp) GetCryptoDepositAddress(ctx context.Context, crypto currency.Code) (*DepositAddress, error) {
|
||||
func (e *Exchange) GetCryptoDepositAddress(ctx context.Context, crypto currency.Code) (*DepositAddress, error) {
|
||||
path := crypto.Lower().String() + "_address"
|
||||
var resp DepositAddress
|
||||
return &resp, b.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, path, true, nil, &resp)
|
||||
return &resp, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, path, true, nil, &resp)
|
||||
}
|
||||
|
||||
// GetUnconfirmedBitcoinDeposits returns unconfirmed transactions
|
||||
func (b *Bitstamp) GetUnconfirmedBitcoinDeposits(ctx context.Context) ([]UnconfirmedBTCTransactions, error) {
|
||||
func (e *Exchange) GetUnconfirmedBitcoinDeposits(ctx context.Context) ([]UnconfirmedBTCTransactions, error) {
|
||||
var response []UnconfirmedBTCTransactions
|
||||
|
||||
return response,
|
||||
b.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, bitstampAPIUnconfirmedBitcoin, false, nil, &response)
|
||||
e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, bitstampAPIUnconfirmedBitcoin, false, nil, &response)
|
||||
}
|
||||
|
||||
// OHLC returns OHLCV data for step (interval)
|
||||
func (b *Bitstamp) OHLC(ctx context.Context, currency string, start, end time.Time, step, limit string) (resp OHLCResponse, err error) {
|
||||
func (e *Exchange) OHLC(ctx context.Context, currency string, start, end time.Time, step, limit string) (resp OHLCResponse, err error) {
|
||||
v := url.Values{}
|
||||
v.Add("limit", limit)
|
||||
v.Add("step", step)
|
||||
@@ -460,7 +460,7 @@ func (b *Bitstamp) OHLC(ctx context.Context, currency string, start, end time.Ti
|
||||
if !end.IsZero() {
|
||||
v.Add("end", strconv.FormatInt(end.Unix(), 10))
|
||||
}
|
||||
return resp, b.SendHTTPRequest(ctx, exchange.RestSpot, common.EncodeURLValues("/v"+bitstampAPIVersion+"/"+bitstampAPIOHLC+"/"+currency, v), &resp)
|
||||
return resp, e.SendHTTPRequest(ctx, exchange.RestSpot, common.EncodeURLValues("/v"+bitstampAPIVersion+"/"+bitstampAPIOHLC+"/"+currency, v), &resp)
|
||||
}
|
||||
|
||||
// TransferAccountBalance transfers funds from either a main or sub account
|
||||
@@ -468,7 +468,7 @@ func (b *Bitstamp) OHLC(ctx context.Context, currency string, start, end time.Ti
|
||||
// currency - which currency to transfer
|
||||
// subaccount - name of account
|
||||
// toMain - bool either to or from account
|
||||
func (b *Bitstamp) TransferAccountBalance(ctx context.Context, amount float64, currency, subAccount string, toMain bool) error {
|
||||
func (e *Exchange) TransferAccountBalance(ctx context.Context, amount float64, currency, subAccount string, toMain bool) error {
|
||||
req := url.Values{}
|
||||
req.Add("amount", strconv.FormatFloat(amount, 'f', -1, 64))
|
||||
req.Add("currency", currency)
|
||||
@@ -488,12 +488,12 @@ func (b *Bitstamp) TransferAccountBalance(ctx context.Context, amount float64, c
|
||||
|
||||
var resp any
|
||||
|
||||
return b.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, path, true, req, &resp)
|
||||
return e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, path, true, req, &resp)
|
||||
}
|
||||
|
||||
// SendHTTPRequest sends an unauthenticated HTTP request
|
||||
func (b *Bitstamp) SendHTTPRequest(ctx context.Context, ep exchange.URL, path string, result any) error {
|
||||
endpoint, err := b.API.Endpoints.GetURL(ep)
|
||||
func (e *Exchange) SendHTTPRequest(ctx context.Context, ep exchange.URL, path string, result any) error {
|
||||
endpoint, err := e.API.Endpoints.GetURL(ep)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -501,22 +501,22 @@ func (b *Bitstamp) SendHTTPRequest(ctx context.Context, ep exchange.URL, path st
|
||||
Method: http.MethodGet,
|
||||
Path: endpoint + path,
|
||||
Result: result,
|
||||
Verbose: b.Verbose,
|
||||
HTTPDebugging: b.HTTPDebugging,
|
||||
HTTPRecording: b.HTTPRecording,
|
||||
Verbose: e.Verbose,
|
||||
HTTPDebugging: e.HTTPDebugging,
|
||||
HTTPRecording: e.HTTPRecording,
|
||||
}
|
||||
return b.SendPayload(ctx, request.Unset, func() (*request.Item, error) {
|
||||
return e.SendPayload(ctx, request.Unset, func() (*request.Item, error) {
|
||||
return item, nil
|
||||
}, request.UnauthenticatedRequest)
|
||||
}
|
||||
|
||||
// SendAuthenticatedHTTPRequest sends an authenticated request
|
||||
func (b *Bitstamp) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange.URL, path string, v2 bool, values url.Values, result any) error {
|
||||
creds, err := b.GetCredentials(ctx)
|
||||
func (e *Exchange) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange.URL, path string, v2 bool, values url.Values, result any) error {
|
||||
creds, err := e.GetCredentials(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
endpoint, err := b.API.Endpoints.GetURL(ep)
|
||||
endpoint, err := e.API.Endpoints.GetURL(ep)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -526,8 +526,8 @@ func (b *Bitstamp) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange
|
||||
}
|
||||
|
||||
interim := json.RawMessage{}
|
||||
err = b.SendPayload(ctx, request.Unset, func() (*request.Item, error) {
|
||||
n := b.Requester.GetNonce(nonce.UnixNano).String()
|
||||
err = e.SendPayload(ctx, request.Unset, func() (*request.Item, error) {
|
||||
n := e.Requester.GetNonce(nonce.UnixNano).String()
|
||||
|
||||
values.Set("key", creds.Key)
|
||||
values.Set("nonce", n)
|
||||
@@ -559,9 +559,9 @@ func (b *Bitstamp) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange
|
||||
Body: readerValues,
|
||||
Result: &interim,
|
||||
NonceEnabled: true,
|
||||
Verbose: b.Verbose,
|
||||
HTTPDebugging: b.HTTPDebugging,
|
||||
HTTPRecording: b.HTTPRecording,
|
||||
Verbose: e.Verbose,
|
||||
HTTPDebugging: e.HTTPDebugging,
|
||||
HTTPRecording: e.HTTPRecording,
|
||||
}, nil
|
||||
}, request.AuthenticatedRequest)
|
||||
if err != nil {
|
||||
|
||||
@@ -16,13 +16,13 @@ import (
|
||||
var mockTests = false
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
b = new(Bitstamp)
|
||||
if err := testexch.Setup(b); err != nil {
|
||||
e = new(Exchange)
|
||||
if err := testexch.Setup(e); err != nil {
|
||||
log.Fatalf("Bitstamp Setup error: %s", err)
|
||||
}
|
||||
if apiKey != "" && apiSecret != "" {
|
||||
b.API.AuthenticatedSupport = true
|
||||
b.SetCredentials(apiKey, apiSecret, customerID, "", "", "")
|
||||
e.API.AuthenticatedSupport = true
|
||||
e.SetCredentials(apiKey, apiSecret, customerID, "", "", "")
|
||||
}
|
||||
log.Printf(sharedtestvalues.LiveTesting, b.Name)
|
||||
os.Exit(m.Run())
|
||||
|
||||
@@ -15,12 +15,12 @@ import (
|
||||
var mockTests = true
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
b = new(Bitstamp)
|
||||
if err := testexch.Setup(b); err != nil {
|
||||
e = new(Exchange)
|
||||
if err := testexch.Setup(e); err != nil {
|
||||
log.Fatalf("Bitstamp Setup error: %s", err)
|
||||
}
|
||||
|
||||
if err := testexch.MockHTTPInstance(b, "api"); err != nil {
|
||||
if err := testexch.MockHTTPInstance(e, "api"); err != nil {
|
||||
log.Fatalf("Bitstamp MockHTTPInstance error: %s", err)
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -55,51 +55,51 @@ var subscriptionNames = map[string]string{
|
||||
}
|
||||
|
||||
// WsConnect connects to a websocket feed
|
||||
func (b *Bitstamp) WsConnect() error {
|
||||
if !b.Websocket.IsEnabled() || !b.IsEnabled() {
|
||||
func (e *Exchange) WsConnect() error {
|
||||
if !e.Websocket.IsEnabled() || !e.IsEnabled() {
|
||||
return websocket.ErrWebsocketNotEnabled
|
||||
}
|
||||
ctx := context.TODO()
|
||||
var dialer gws.Dialer
|
||||
err := b.Websocket.Conn.Dial(ctx, &dialer, http.Header{})
|
||||
err := e.Websocket.Conn.Dial(ctx, &dialer, http.Header{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if b.Verbose {
|
||||
log.Debugf(log.ExchangeSys, "%s Connected to Websocket.\n", b.Name)
|
||||
if e.Verbose {
|
||||
log.Debugf(log.ExchangeSys, "%s Connected to Websocket.\n", e.Name)
|
||||
}
|
||||
b.Websocket.Conn.SetupPingHandler(request.Unset, websocket.PingHandler{
|
||||
e.Websocket.Conn.SetupPingHandler(request.Unset, websocket.PingHandler{
|
||||
MessageType: gws.TextMessage,
|
||||
Message: hbMsg,
|
||||
Delay: hbInterval,
|
||||
})
|
||||
err = b.seedOrderBook(ctx)
|
||||
err = e.seedOrderBook(ctx)
|
||||
if err != nil {
|
||||
b.Websocket.DataHandler <- err
|
||||
e.Websocket.DataHandler <- err
|
||||
}
|
||||
|
||||
b.Websocket.Wg.Add(1)
|
||||
go b.wsReadData(ctx)
|
||||
e.Websocket.Wg.Add(1)
|
||||
go e.wsReadData(ctx)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// wsReadData receives and passes on websocket messages for processing
|
||||
func (b *Bitstamp) wsReadData(ctx context.Context) {
|
||||
defer b.Websocket.Wg.Done()
|
||||
func (e *Exchange) wsReadData(ctx context.Context) {
|
||||
defer e.Websocket.Wg.Done()
|
||||
|
||||
for {
|
||||
resp := b.Websocket.Conn.ReadMessage()
|
||||
resp := e.Websocket.Conn.ReadMessage()
|
||||
if resp.Raw == nil {
|
||||
return
|
||||
}
|
||||
if err := b.wsHandleData(ctx, resp.Raw); err != nil {
|
||||
b.Websocket.DataHandler <- err
|
||||
if err := e.wsHandleData(ctx, resp.Raw); err != nil {
|
||||
e.Websocket.DataHandler <- err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (b *Bitstamp) wsHandleData(_ context.Context, respRaw []byte) error {
|
||||
func (e *Exchange) wsHandleData(_ context.Context, respRaw []byte) error {
|
||||
event, err := jsonparser.GetUnsafeString(respRaw, "event")
|
||||
if err != nil {
|
||||
return fmt.Errorf("%w `event`: %w", common.ErrParsingWSField, err)
|
||||
@@ -110,40 +110,40 @@ func (b *Bitstamp) wsHandleData(_ context.Context, respRaw []byte) error {
|
||||
case "heartbeat":
|
||||
return nil
|
||||
case "subscription_succeeded", "unsubscription_succeeded":
|
||||
return b.handleWSSubscription(event, respRaw)
|
||||
return e.handleWSSubscription(event, respRaw)
|
||||
case "data":
|
||||
return b.handleWSOrderbook(respRaw)
|
||||
return e.handleWSOrderbook(respRaw)
|
||||
case "trade":
|
||||
return b.handleWSTrade(respRaw)
|
||||
return e.handleWSTrade(respRaw)
|
||||
case "order_created", "order_deleted", "order_changed":
|
||||
return b.handleWSOrder(event, respRaw)
|
||||
return e.handleWSOrder(event, respRaw)
|
||||
case "request_reconnect":
|
||||
go func() {
|
||||
if err := b.Websocket.Shutdown(); err != nil { // Connection monitor will reconnect
|
||||
log.Errorf(log.WebsocketMgr, "%s failed to shutdown websocket: %v", b.Name, err)
|
||||
if err := e.Websocket.Shutdown(); err != nil { // Connection monitor will reconnect
|
||||
log.Errorf(log.WebsocketMgr, "%s failed to shutdown websocket: %v", e.Name, err)
|
||||
}
|
||||
}()
|
||||
default:
|
||||
b.Websocket.DataHandler <- websocket.UnhandledMessageWarning{Message: b.Name + websocket.UnhandledMessage + string(respRaw)}
|
||||
e.Websocket.DataHandler <- websocket.UnhandledMessageWarning{Message: e.Name + websocket.UnhandledMessage + string(respRaw)}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *Bitstamp) handleWSSubscription(event string, respRaw []byte) error {
|
||||
func (e *Exchange) handleWSSubscription(event string, respRaw []byte) error {
|
||||
channel, err := jsonparser.GetUnsafeString(respRaw, "channel")
|
||||
if err != nil {
|
||||
return fmt.Errorf("%w `channel`: %w", common.ErrParsingWSField, err)
|
||||
}
|
||||
event = strings.TrimSuffix(event, "scription_succeeded")
|
||||
return b.Websocket.Match.RequireMatchWithData(event+":"+channel, respRaw)
|
||||
return e.Websocket.Match.RequireMatchWithData(event+":"+channel, respRaw)
|
||||
}
|
||||
|
||||
func (b *Bitstamp) handleWSTrade(msg []byte) error {
|
||||
if !b.IsSaveTradeDataEnabled() {
|
||||
func (e *Exchange) handleWSTrade(msg []byte) error {
|
||||
if !e.IsSaveTradeDataEnabled() {
|
||||
return nil
|
||||
}
|
||||
|
||||
_, p, err := b.parseChannelName(msg)
|
||||
_, p, err := e.parseChannelName(msg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -161,7 +161,7 @@ func (b *Bitstamp) handleWSTrade(msg []byte) error {
|
||||
Timestamp: wsTradeTemp.Data.Timestamp.Time(),
|
||||
CurrencyPair: p,
|
||||
AssetType: asset.Spot,
|
||||
Exchange: b.Name,
|
||||
Exchange: e.Name,
|
||||
Price: wsTradeTemp.Data.Price,
|
||||
Amount: wsTradeTemp.Data.Amount,
|
||||
Side: side,
|
||||
@@ -169,8 +169,8 @@ func (b *Bitstamp) handleWSTrade(msg []byte) error {
|
||||
})
|
||||
}
|
||||
|
||||
func (b *Bitstamp) handleWSOrder(event string, msg []byte) error {
|
||||
channel, p, err := b.parseChannelName(msg)
|
||||
func (e *Exchange) handleWSOrder(event string, msg []byte) error {
|
||||
channel, p, err := e.parseChannelName(msg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -211,7 +211,7 @@ func (b *Bitstamp) handleWSOrder(event string, msg []byte) error {
|
||||
Amount: r.Order.Amount,
|
||||
RemainingAmount: r.Order.RemainingAmount,
|
||||
ExecutedAmount: executedAmount,
|
||||
Exchange: b.Name,
|
||||
Exchange: e.Name,
|
||||
OrderID: r.Order.IDStr,
|
||||
ClientOrderID: r.Order.ClientOrderID,
|
||||
Side: r.Order.Side.Side(),
|
||||
@@ -221,43 +221,43 @@ func (b *Bitstamp) handleWSOrder(event string, msg []byte) error {
|
||||
Pair: p,
|
||||
}
|
||||
|
||||
b.Websocket.DataHandler <- d
|
||||
e.Websocket.DataHandler <- d
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *Bitstamp) generateSubscriptions() (subscription.List, error) {
|
||||
return b.Features.Subscriptions.ExpandTemplates(b)
|
||||
func (e *Exchange) generateSubscriptions() (subscription.List, error) {
|
||||
return e.Features.Subscriptions.ExpandTemplates(e)
|
||||
}
|
||||
|
||||
// GetSubscriptionTemplate returns a subscription channel template
|
||||
func (b *Bitstamp) GetSubscriptionTemplate(_ *subscription.Subscription) (*template.Template, error) {
|
||||
func (e *Exchange) GetSubscriptionTemplate(_ *subscription.Subscription) (*template.Template, error) {
|
||||
return template.New("master.tmpl").Funcs(template.FuncMap{"channelName": channelName}).Parse(subTplText)
|
||||
}
|
||||
|
||||
// Subscribe sends a websocket message to receive data from a list of channels
|
||||
func (b *Bitstamp) Subscribe(subs subscription.List) error {
|
||||
func (e *Exchange) Subscribe(subs subscription.List) error {
|
||||
ctx := context.TODO()
|
||||
return b.manageSubsWithCreds(ctx, subs, "sub")
|
||||
return e.manageSubsWithCreds(ctx, subs, "sub")
|
||||
}
|
||||
|
||||
// Unsubscribe sends a websocket message to stop receiving data from a list of channels
|
||||
func (b *Bitstamp) Unsubscribe(subs subscription.List) error {
|
||||
func (e *Exchange) Unsubscribe(subs subscription.List) error {
|
||||
ctx := context.TODO()
|
||||
return b.manageSubsWithCreds(ctx, subs, "unsub")
|
||||
return e.manageSubsWithCreds(ctx, subs, "unsub")
|
||||
}
|
||||
|
||||
func (b *Bitstamp) manageSubsWithCreds(ctx context.Context, subs subscription.List, op string) error {
|
||||
func (e *Exchange) manageSubsWithCreds(ctx context.Context, subs subscription.List, op string) error {
|
||||
var errs error
|
||||
var creds *WebsocketAuthResponse
|
||||
if authed := subs.Private(); len(authed) > 0 {
|
||||
creds, errs = b.FetchWSAuth(ctx)
|
||||
creds, errs = e.FetchWSAuth(ctx)
|
||||
}
|
||||
return common.AppendError(errs, b.ParallelChanOp(ctx, subs, func(ctx context.Context, s subscription.List) error { return b.manageSubs(ctx, s, op, creds) }, 1))
|
||||
return common.AppendError(errs, e.ParallelChanOp(ctx, subs, func(ctx context.Context, s subscription.List) error { return e.manageSubs(ctx, s, op, creds) }, 1))
|
||||
}
|
||||
|
||||
func (b *Bitstamp) manageSubs(ctx context.Context, subs subscription.List, op string, creds *WebsocketAuthResponse) error {
|
||||
subs, errs := subs.ExpandTemplates(b)
|
||||
func (e *Exchange) manageSubs(ctx context.Context, subs subscription.List, op string, creds *WebsocketAuthResponse) error {
|
||||
subs, errs := subs.ExpandTemplates(e)
|
||||
for _, s := range subs {
|
||||
req := websocketEventRequest{
|
||||
Event: "bts:" + op + "scribe",
|
||||
@@ -272,12 +272,12 @@ func (b *Bitstamp) manageSubs(ctx context.Context, subs subscription.List, op st
|
||||
req.Data.Channel = "private-" + req.Data.Channel + "-" + strconv.Itoa(int(creds.UserID))
|
||||
req.Data.Auth = creds.Token
|
||||
}
|
||||
_, err := b.Websocket.Conn.SendMessageReturnResponse(ctx, request.Unset, op+":"+req.Data.Channel, req)
|
||||
_, err := e.Websocket.Conn.SendMessageReturnResponse(ctx, request.Unset, op+":"+req.Data.Channel, req)
|
||||
if err == nil {
|
||||
if op == "sub" {
|
||||
err = b.Websocket.AddSuccessfulSubscriptions(b.Websocket.Conn, s)
|
||||
err = e.Websocket.AddSuccessfulSubscriptions(e.Websocket.Conn, s)
|
||||
} else {
|
||||
err = b.Websocket.RemoveSubscriptions(b.Websocket.Conn, s)
|
||||
err = e.Websocket.RemoveSubscriptions(e.Websocket.Conn, s)
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
@@ -288,8 +288,8 @@ func (b *Bitstamp) manageSubs(ctx context.Context, subs subscription.List, op st
|
||||
return errs
|
||||
}
|
||||
|
||||
func (b *Bitstamp) handleWSOrderbook(msg []byte) error {
|
||||
_, p, err := b.parseChannelName(msg)
|
||||
func (e *Exchange) handleWSOrderbook(msg []byte) error {
|
||||
_, p, err := e.parseChannelName(msg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -305,8 +305,8 @@ func (b *Bitstamp) handleWSOrderbook(msg []byte) error {
|
||||
Pair: p,
|
||||
LastUpdated: wsOrderBookResp.Data.Microtimestamp.Time(),
|
||||
Asset: asset.Spot,
|
||||
Exchange: b.Name,
|
||||
ValidateOrderbook: b.ValidateOrderbook,
|
||||
Exchange: e.Name,
|
||||
ValidateOrderbook: e.ValidateOrderbook,
|
||||
}
|
||||
|
||||
for i := range wsOrderBookResp.Data.Asks {
|
||||
@@ -318,21 +318,21 @@ func (b *Bitstamp) handleWSOrderbook(msg []byte) error {
|
||||
obUpdate.Bids[i].Amount = wsOrderBookResp.Data.Bids[i][1].Float64()
|
||||
}
|
||||
filterOrderbookZeroBidPrice(obUpdate)
|
||||
return b.Websocket.Orderbook.LoadSnapshot(obUpdate)
|
||||
return e.Websocket.Orderbook.LoadSnapshot(obUpdate)
|
||||
}
|
||||
|
||||
func (b *Bitstamp) seedOrderBook(ctx context.Context) error {
|
||||
p, err := b.GetEnabledPairs(asset.Spot)
|
||||
func (e *Exchange) seedOrderBook(ctx context.Context) error {
|
||||
p, err := e.GetEnabledPairs(asset.Spot)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for x := range p {
|
||||
pairFmt, err := b.FormatExchangeCurrency(p[x], asset.Spot)
|
||||
pairFmt, err := e.FormatExchangeCurrency(p[x], asset.Spot)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
orderbookSeed, err := b.GetOrderbook(ctx, pairFmt.String())
|
||||
orderbookSeed, err := e.GetOrderbook(ctx, pairFmt.String())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -340,8 +340,8 @@ func (b *Bitstamp) seedOrderBook(ctx context.Context) error {
|
||||
newOrderBook := &orderbook.Book{
|
||||
Pair: p[x],
|
||||
Asset: asset.Spot,
|
||||
Exchange: b.Name,
|
||||
ValidateOrderbook: b.ValidateOrderbook,
|
||||
Exchange: e.Name,
|
||||
ValidateOrderbook: e.ValidateOrderbook,
|
||||
Bids: make(orderbook.Levels, len(orderbookSeed.Bids)),
|
||||
Asks: make(orderbook.Levels, len(orderbookSeed.Asks)),
|
||||
LastUpdated: orderbookSeed.Timestamp,
|
||||
@@ -362,7 +362,7 @@ func (b *Bitstamp) seedOrderBook(ctx context.Context) error {
|
||||
|
||||
filterOrderbookZeroBidPrice(newOrderBook)
|
||||
|
||||
err = b.Websocket.Orderbook.LoadSnapshot(newOrderBook)
|
||||
err = e.Websocket.Orderbook.LoadSnapshot(newOrderBook)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -372,9 +372,9 @@ func (b *Bitstamp) seedOrderBook(ctx context.Context) error {
|
||||
|
||||
// FetchWSAuth Retrieves a userID and auth-token from REST for subscribing to a websocket channel
|
||||
// The token life-expectancy is only about 60s; use it immediately and do not store it
|
||||
func (b *Bitstamp) FetchWSAuth(ctx context.Context) (*WebsocketAuthResponse, error) {
|
||||
func (e *Exchange) FetchWSAuth(ctx context.Context) (*WebsocketAuthResponse, error) {
|
||||
resp := &WebsocketAuthResponse{}
|
||||
err := b.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, bitstampAPIWSAuthToken, true, nil, resp)
|
||||
err := e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, bitstampAPIWSAuthToken, true, nil, resp)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error fetching auth token: %w", err)
|
||||
}
|
||||
@@ -382,7 +382,7 @@ func (b *Bitstamp) FetchWSAuth(ctx context.Context) (*WebsocketAuthResponse, err
|
||||
}
|
||||
|
||||
// parseChannelName splits the ws message channel and returns the channel name and pair
|
||||
func (b *Bitstamp) parseChannelName(respRaw []byte) (string, currency.Pair, error) {
|
||||
func (e *Exchange) parseChannelName(respRaw []byte) (string, currency.Pair, error) {
|
||||
channel, err := jsonparser.GetUnsafeString(respRaw, "channel")
|
||||
if err != nil {
|
||||
return "", currency.EMPTYPAIR, fmt.Errorf("%w `channel`: %w", common.ErrParsingWSField, err)
|
||||
@@ -403,7 +403,7 @@ func (b *Bitstamp) parseChannelName(respRaw []byte) (string, currency.Pair, erro
|
||||
return "", currency.EMPTYPAIR, fmt.Errorf("%w: %s", errChannelUnderscores, channel)
|
||||
}
|
||||
|
||||
enabledPairs, err := b.GetEnabledPairs(asset.Spot)
|
||||
enabledPairs, err := e.GetEnabledPairs(asset.Spot)
|
||||
if err != nil {
|
||||
return "", currency.EMPTYPAIR, err
|
||||
}
|
||||
|
||||
@@ -31,24 +31,24 @@ import (
|
||||
)
|
||||
|
||||
// SetDefaults sets default for Bitstamp
|
||||
func (b *Bitstamp) SetDefaults() {
|
||||
b.Name = "Bitstamp"
|
||||
b.Enabled = true
|
||||
b.Verbose = true
|
||||
b.API.CredentialsValidator.RequiresKey = true
|
||||
b.API.CredentialsValidator.RequiresSecret = true
|
||||
b.API.CredentialsValidator.RequiresClientID = true
|
||||
func (e *Exchange) SetDefaults() {
|
||||
e.Name = "Bitstamp"
|
||||
e.Enabled = true
|
||||
e.Verbose = true
|
||||
e.API.CredentialsValidator.RequiresKey = true
|
||||
e.API.CredentialsValidator.RequiresSecret = true
|
||||
e.API.CredentialsValidator.RequiresClientID = true
|
||||
requestFmt := ¤cy.EMPTYFORMAT
|
||||
configFmt := ¤cy.PairFormat{
|
||||
Uppercase: true,
|
||||
Delimiter: currency.ForwardSlashDelimiter,
|
||||
}
|
||||
err := b.SetGlobalPairsManager(requestFmt, configFmt, asset.Spot)
|
||||
err := e.SetGlobalPairsManager(requestFmt, configFmt, asset.Spot)
|
||||
if err != nil {
|
||||
log.Errorln(log.ExchangeSys, err)
|
||||
}
|
||||
|
||||
b.Features = exchange.Features{
|
||||
e.Features = exchange.Features{
|
||||
Supports: exchange.FeaturesSupported{
|
||||
REST: true,
|
||||
Websocket: true,
|
||||
@@ -110,70 +110,70 @@ func (b *Bitstamp) SetDefaults() {
|
||||
Subscriptions: defaultSubscriptions.Clone(),
|
||||
}
|
||||
|
||||
b.Requester, err = request.New(b.Name,
|
||||
e.Requester, err = request.New(e.Name,
|
||||
common.NewHTTPClientWithTimeout(exchange.DefaultHTTPTimeout),
|
||||
request.WithLimiter(request.NewBasicRateLimit(bitstampRateInterval, bitstampRequestRate, 1)))
|
||||
if err != nil {
|
||||
log.Errorln(log.ExchangeSys, err)
|
||||
}
|
||||
b.API.Endpoints = b.NewEndpoints()
|
||||
err = b.API.Endpoints.SetDefaultEndpoints(map[exchange.URL]string{
|
||||
e.API.Endpoints = e.NewEndpoints()
|
||||
err = e.API.Endpoints.SetDefaultEndpoints(map[exchange.URL]string{
|
||||
exchange.RestSpot: bitstampAPIURL,
|
||||
exchange.WebsocketSpot: bitstampWSURL,
|
||||
})
|
||||
if err != nil {
|
||||
log.Errorln(log.ExchangeSys, err)
|
||||
}
|
||||
b.Websocket = websocket.NewManager()
|
||||
b.WebsocketResponseMaxLimit = exchange.DefaultWebsocketResponseMaxLimit
|
||||
b.WebsocketResponseCheckTimeout = exchange.DefaultWebsocketResponseCheckTimeout
|
||||
b.WebsocketOrderbookBufferLimit = exchange.DefaultWebsocketOrderbookBufferLimit
|
||||
e.Websocket = websocket.NewManager()
|
||||
e.WebsocketResponseMaxLimit = exchange.DefaultWebsocketResponseMaxLimit
|
||||
e.WebsocketResponseCheckTimeout = exchange.DefaultWebsocketResponseCheckTimeout
|
||||
e.WebsocketOrderbookBufferLimit = exchange.DefaultWebsocketOrderbookBufferLimit
|
||||
}
|
||||
|
||||
// Setup sets configuration values to bitstamp
|
||||
func (b *Bitstamp) Setup(exch *config.Exchange) error {
|
||||
func (e *Exchange) Setup(exch *config.Exchange) error {
|
||||
err := exch.Validate()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !exch.Enabled {
|
||||
b.SetEnabled(false)
|
||||
e.SetEnabled(false)
|
||||
return nil
|
||||
}
|
||||
err = b.SetupDefaults(exch)
|
||||
err = e.SetupDefaults(exch)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
wsURL, err := b.API.Endpoints.GetURL(exchange.WebsocketSpot)
|
||||
wsURL, err := e.API.Endpoints.GetURL(exchange.WebsocketSpot)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = b.Websocket.Setup(&websocket.ManagerSetup{
|
||||
err = e.Websocket.Setup(&websocket.ManagerSetup{
|
||||
ExchangeConfig: exch,
|
||||
DefaultURL: bitstampWSURL,
|
||||
RunningURL: wsURL,
|
||||
Connector: b.WsConnect,
|
||||
Subscriber: b.Subscribe,
|
||||
Unsubscriber: b.Unsubscribe,
|
||||
GenerateSubscriptions: b.generateSubscriptions,
|
||||
Features: &b.Features.Supports.WebsocketCapabilities,
|
||||
Connector: e.WsConnect,
|
||||
Subscriber: e.Subscribe,
|
||||
Unsubscriber: e.Unsubscribe,
|
||||
GenerateSubscriptions: e.generateSubscriptions,
|
||||
Features: &e.Features.Supports.WebsocketCapabilities,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return b.Websocket.SetupNewConnection(&websocket.ConnectionSetup{
|
||||
URL: b.Websocket.GetWebsocketURL(),
|
||||
return e.Websocket.SetupNewConnection(&websocket.ConnectionSetup{
|
||||
URL: e.Websocket.GetWebsocketURL(),
|
||||
ResponseCheckTimeout: exch.WebsocketResponseCheckTimeout,
|
||||
ResponseMaxLimit: exch.WebsocketResponseMaxLimit,
|
||||
})
|
||||
}
|
||||
|
||||
// FetchTradablePairs returns a list of the exchanges tradable pairs
|
||||
func (b *Bitstamp) FetchTradablePairs(ctx context.Context, _ asset.Item) (currency.Pairs, error) {
|
||||
symbols, err := b.GetTradingPairs(ctx)
|
||||
func (e *Exchange) FetchTradablePairs(ctx context.Context, _ asset.Item) (currency.Pairs, error) {
|
||||
symbols, err := e.GetTradingPairs(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -194,24 +194,24 @@ func (b *Bitstamp) FetchTradablePairs(ctx context.Context, _ asset.Item) (curren
|
||||
|
||||
// UpdateTradablePairs updates the exchanges available pairs and stores
|
||||
// them in the exchanges config
|
||||
func (b *Bitstamp) UpdateTradablePairs(ctx context.Context, forceUpdate bool) error {
|
||||
pairs, err := b.FetchTradablePairs(ctx, asset.Spot)
|
||||
func (e *Exchange) UpdateTradablePairs(ctx context.Context, forceUpdate bool) error {
|
||||
pairs, err := e.FetchTradablePairs(ctx, asset.Spot)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = b.UpdatePairs(pairs, asset.Spot, false, forceUpdate)
|
||||
err = e.UpdatePairs(pairs, asset.Spot, false, forceUpdate)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return b.EnsureOnePairEnabled()
|
||||
return e.EnsureOnePairEnabled()
|
||||
}
|
||||
|
||||
// UpdateOrderExecutionLimits sets exchange execution order limits for an asset type
|
||||
func (b *Bitstamp) UpdateOrderExecutionLimits(ctx context.Context, a asset.Item) error {
|
||||
func (e *Exchange) UpdateOrderExecutionLimits(ctx context.Context, a asset.Item) error {
|
||||
if a != asset.Spot {
|
||||
return common.ErrNotYetImplemented
|
||||
}
|
||||
symbols, err := b.GetTradingPairs(ctx)
|
||||
symbols, err := e.GetTradingPairs(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -232,25 +232,25 @@ func (b *Bitstamp) UpdateOrderExecutionLimits(ctx context.Context, a asset.Item)
|
||||
MinimumQuoteAmount: info.MinimumOrder,
|
||||
})
|
||||
}
|
||||
if err := b.LoadLimits(limits); err != nil {
|
||||
return fmt.Errorf("%s Error loading exchange limits: %v", b.Name, err)
|
||||
if err := e.LoadLimits(limits); err != nil {
|
||||
return fmt.Errorf("%s Error loading exchange limits: %v", e.Name, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpdateTickers updates the ticker for all currency pairs of a given asset type
|
||||
func (b *Bitstamp) UpdateTickers(_ context.Context, _ asset.Item) error {
|
||||
func (e *Exchange) UpdateTickers(_ context.Context, _ asset.Item) error {
|
||||
return common.ErrFunctionNotSupported
|
||||
}
|
||||
|
||||
// UpdateTicker updates and returns the ticker for a currency pair
|
||||
func (b *Bitstamp) UpdateTicker(ctx context.Context, p currency.Pair, a asset.Item) (*ticker.Price, error) {
|
||||
fPair, err := b.FormatExchangeCurrency(p, a)
|
||||
func (e *Exchange) UpdateTicker(ctx context.Context, p currency.Pair, a asset.Item) (*ticker.Price, error) {
|
||||
fPair, err := e.FormatExchangeCurrency(p, a)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tick, err := b.GetTicker(ctx, fPair.String(), false)
|
||||
tick, err := e.GetTicker(ctx, fPair.String(), false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -265,48 +265,48 @@ func (b *Bitstamp) UpdateTicker(ctx context.Context, p currency.Pair, a asset.It
|
||||
Open: tick.Open,
|
||||
Pair: fPair,
|
||||
LastUpdated: tick.Timestamp.Time(),
|
||||
ExchangeName: b.Name,
|
||||
ExchangeName: e.Name,
|
||||
AssetType: a,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return ticker.GetTicker(b.Name, fPair, a)
|
||||
return ticker.GetTicker(e.Name, fPair, a)
|
||||
}
|
||||
|
||||
// GetFeeByType returns an estimate of fee based on type of transaction
|
||||
func (b *Bitstamp) GetFeeByType(ctx context.Context, feeBuilder *exchange.FeeBuilder) (float64, error) {
|
||||
func (e *Exchange) GetFeeByType(ctx context.Context, feeBuilder *exchange.FeeBuilder) (float64, error) {
|
||||
if feeBuilder == nil {
|
||||
return 0, fmt.Errorf("%T %w", feeBuilder, common.ErrNilPointer)
|
||||
}
|
||||
if (!b.AreCredentialsValid(ctx) || b.SkipAuthCheck) && // Todo check connection status
|
||||
if (!e.AreCredentialsValid(ctx) || e.SkipAuthCheck) && // Todo check connection status
|
||||
feeBuilder.FeeType == exchange.CryptocurrencyTradeFee {
|
||||
feeBuilder.FeeType = exchange.OfflineTradeFee
|
||||
}
|
||||
return b.GetFee(ctx, feeBuilder)
|
||||
return e.GetFee(ctx, feeBuilder)
|
||||
}
|
||||
|
||||
// UpdateOrderbook updates and returns the orderbook for a currency pair
|
||||
func (b *Bitstamp) UpdateOrderbook(ctx context.Context, p currency.Pair, assetType asset.Item) (*orderbook.Book, error) {
|
||||
func (e *Exchange) UpdateOrderbook(ctx context.Context, p currency.Pair, assetType asset.Item) (*orderbook.Book, error) {
|
||||
if p.IsEmpty() {
|
||||
return nil, currency.ErrCurrencyPairEmpty
|
||||
}
|
||||
if err := b.CurrencyPairs.IsAssetEnabled(assetType); err != nil {
|
||||
if err := e.CurrencyPairs.IsAssetEnabled(assetType); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
book := &orderbook.Book{
|
||||
Exchange: b.Name,
|
||||
Exchange: e.Name,
|
||||
Pair: p,
|
||||
Asset: assetType,
|
||||
ValidateOrderbook: b.ValidateOrderbook,
|
||||
ValidateOrderbook: e.ValidateOrderbook,
|
||||
}
|
||||
fPair, err := b.FormatExchangeCurrency(p, assetType)
|
||||
fPair, err := e.FormatExchangeCurrency(p, assetType)
|
||||
if err != nil {
|
||||
return book, err
|
||||
}
|
||||
|
||||
orderbookNew, err := b.GetOrderbook(ctx, fPair.String())
|
||||
orderbookNew, err := e.GetOrderbook(ctx, fPair.String())
|
||||
if err != nil {
|
||||
return book, err
|
||||
}
|
||||
@@ -333,15 +333,15 @@ func (b *Bitstamp) UpdateOrderbook(ctx context.Context, p currency.Pair, assetTy
|
||||
if err != nil {
|
||||
return book, err
|
||||
}
|
||||
return orderbook.Get(b.Name, fPair, assetType)
|
||||
return orderbook.Get(e.Name, fPair, assetType)
|
||||
}
|
||||
|
||||
// UpdateAccountInfo retrieves balances for all enabled currencies for the
|
||||
// Bitstamp exchange
|
||||
func (b *Bitstamp) UpdateAccountInfo(ctx context.Context, assetType asset.Item) (account.Holdings, error) {
|
||||
func (e *Exchange) UpdateAccountInfo(ctx context.Context, assetType asset.Item) (account.Holdings, error) {
|
||||
var response account.Holdings
|
||||
response.Exchange = b.Name
|
||||
accountBalance, err := b.GetBalance(ctx)
|
||||
response.Exchange = e.Name
|
||||
accountBalance, err := e.GetBalance(ctx)
|
||||
if err != nil {
|
||||
return response, err
|
||||
}
|
||||
@@ -360,7 +360,7 @@ func (b *Bitstamp) UpdateAccountInfo(ctx context.Context, assetType asset.Item)
|
||||
Currencies: currencies,
|
||||
})
|
||||
|
||||
creds, err := b.GetCredentials(ctx)
|
||||
creds, err := e.GetCredentials(ctx)
|
||||
if err != nil {
|
||||
return account.Holdings{}, err
|
||||
}
|
||||
@@ -374,13 +374,13 @@ func (b *Bitstamp) UpdateAccountInfo(ctx context.Context, assetType asset.Item)
|
||||
|
||||
// GetAccountFundingHistory returns funding history, deposits and
|
||||
// withdrawals
|
||||
func (b *Bitstamp) GetAccountFundingHistory(_ context.Context) ([]exchange.FundingHistory, error) {
|
||||
func (e *Exchange) GetAccountFundingHistory(_ context.Context) ([]exchange.FundingHistory, error) {
|
||||
return nil, common.ErrFunctionNotSupported
|
||||
}
|
||||
|
||||
// GetWithdrawalsHistory returns previous withdrawals data
|
||||
func (b *Bitstamp) GetWithdrawalsHistory(ctx context.Context, c currency.Code, _ asset.Item) ([]exchange.WithdrawalHistory, error) {
|
||||
withdrawals, err := b.GetWithdrawalRequests(ctx, 0)
|
||||
func (e *Exchange) GetWithdrawalsHistory(ctx context.Context, c currency.Code, _ asset.Item) ([]exchange.WithdrawalHistory, error) {
|
||||
withdrawals, err := e.GetWithdrawalRequests(ctx, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -402,13 +402,13 @@ func (b *Bitstamp) GetWithdrawalsHistory(ctx context.Context, c currency.Code, _
|
||||
}
|
||||
|
||||
// GetRecentTrades returns the most recent trades for a currency and asset
|
||||
func (b *Bitstamp) GetRecentTrades(ctx context.Context, p currency.Pair, assetType asset.Item) ([]trade.Data, error) {
|
||||
p, err := b.FormatExchangeCurrency(p, assetType)
|
||||
func (e *Exchange) GetRecentTrades(ctx context.Context, p currency.Pair, assetType asset.Item) ([]trade.Data, error) {
|
||||
p, err := e.FormatExchangeCurrency(p, assetType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tradeData, err := b.GetTransactions(ctx, p.String(), "")
|
||||
tradeData, err := e.GetTransactions(ctx, p.String(), "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -420,7 +420,7 @@ func (b *Bitstamp) GetRecentTrades(ctx context.Context, p currency.Pair, assetTy
|
||||
s = order.Sell
|
||||
}
|
||||
resp[i] = trade.Data{
|
||||
Exchange: b.Name,
|
||||
Exchange: e.Name,
|
||||
TID: strconv.FormatInt(tradeData[i].TradeID, 10),
|
||||
CurrencyPair: p,
|
||||
AssetType: assetType,
|
||||
@@ -431,7 +431,7 @@ func (b *Bitstamp) GetRecentTrades(ctx context.Context, p currency.Pair, assetTy
|
||||
}
|
||||
}
|
||||
|
||||
err = b.AddTradesToBuffer(resp...)
|
||||
err = e.AddTradesToBuffer(resp...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -441,22 +441,22 @@ func (b *Bitstamp) GetRecentTrades(ctx context.Context, p currency.Pair, assetTy
|
||||
}
|
||||
|
||||
// GetHistoricTrades returns historic trade data within the timeframe provided
|
||||
func (b *Bitstamp) GetHistoricTrades(_ context.Context, _ currency.Pair, _ asset.Item, _, _ time.Time) ([]trade.Data, error) {
|
||||
func (e *Exchange) GetHistoricTrades(_ context.Context, _ currency.Pair, _ asset.Item, _, _ time.Time) ([]trade.Data, error) {
|
||||
return nil, common.ErrFunctionNotSupported
|
||||
}
|
||||
|
||||
// SubmitOrder submits a new order
|
||||
func (b *Bitstamp) SubmitOrder(ctx context.Context, s *order.Submit) (*order.SubmitResponse, error) {
|
||||
if err := s.Validate(b.GetTradingRequirements()); err != nil {
|
||||
func (e *Exchange) SubmitOrder(ctx context.Context, s *order.Submit) (*order.SubmitResponse, error) {
|
||||
if err := s.Validate(e.GetTradingRequirements()); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
fPair, err := b.FormatExchangeCurrency(s.Pair, s.AssetType)
|
||||
fPair, err := e.FormatExchangeCurrency(s.Pair, s.AssetType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
response, err := b.PlaceOrder(ctx,
|
||||
response, err := e.PlaceOrder(ctx,
|
||||
fPair.String(),
|
||||
s.Price,
|
||||
s.Amount,
|
||||
@@ -470,12 +470,12 @@ func (b *Bitstamp) SubmitOrder(ctx context.Context, s *order.Submit) (*order.Sub
|
||||
|
||||
// ModifyOrder will allow of changing orderbook placement and limit to
|
||||
// market conversion
|
||||
func (b *Bitstamp) ModifyOrder(_ context.Context, _ *order.Modify) (*order.ModifyResponse, error) {
|
||||
func (e *Exchange) ModifyOrder(_ context.Context, _ *order.Modify) (*order.ModifyResponse, error) {
|
||||
return nil, common.ErrFunctionNotSupported
|
||||
}
|
||||
|
||||
// CancelOrder cancels an order by its corresponding ID number
|
||||
func (b *Bitstamp) CancelOrder(ctx context.Context, o *order.Cancel) error {
|
||||
func (e *Exchange) CancelOrder(ctx context.Context, o *order.Cancel) error {
|
||||
if err := o.Validate(o.StandardCancel()); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -484,18 +484,18 @@ func (b *Bitstamp) CancelOrder(ctx context.Context, o *order.Cancel) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = b.CancelExistingOrder(ctx, orderIDInt)
|
||||
_, err = e.CancelExistingOrder(ctx, orderIDInt)
|
||||
return err
|
||||
}
|
||||
|
||||
// CancelBatchOrders cancels an orders by their corresponding ID numbers
|
||||
func (b *Bitstamp) CancelBatchOrders(_ context.Context, _ []order.Cancel) (*order.CancelBatchResponse, error) {
|
||||
func (e *Exchange) CancelBatchOrders(_ context.Context, _ []order.Cancel) (*order.CancelBatchResponse, error) {
|
||||
return nil, common.ErrFunctionNotSupported
|
||||
}
|
||||
|
||||
// CancelAllOrders cancels all orders associated with a currency pair
|
||||
func (b *Bitstamp) CancelAllOrders(ctx context.Context, _ *order.Cancel) (order.CancelAllResponse, error) {
|
||||
success, err := b.CancelAllExistingOrders(ctx)
|
||||
func (e *Exchange) CancelAllOrders(ctx context.Context, _ *order.Cancel) (order.CancelAllResponse, error) {
|
||||
success, err := e.CancelAllExistingOrders(ctx)
|
||||
if err != nil {
|
||||
return order.CancelAllResponse{}, err
|
||||
}
|
||||
@@ -507,12 +507,12 @@ func (b *Bitstamp) CancelAllOrders(ctx context.Context, _ *order.Cancel) (order.
|
||||
}
|
||||
|
||||
// GetOrderInfo returns order information based on order ID
|
||||
func (b *Bitstamp) GetOrderInfo(ctx context.Context, orderID string, _ currency.Pair, _ asset.Item) (*order.Detail, error) {
|
||||
func (e *Exchange) GetOrderInfo(ctx context.Context, orderID string, _ currency.Pair, _ asset.Item) (*order.Detail, error) {
|
||||
iOID, err := strconv.ParseInt(orderID, 10, 64)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
o, err := b.GetOrderStatus(ctx, iOID)
|
||||
o, err := e.GetOrderStatus(ctx, iOID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -540,8 +540,8 @@ func (b *Bitstamp) GetOrderInfo(ctx context.Context, orderID string, _ currency.
|
||||
}
|
||||
|
||||
// GetDepositAddress returns a deposit address for a specified currency
|
||||
func (b *Bitstamp) GetDepositAddress(ctx context.Context, cryptocurrency currency.Code, _, _ string) (*deposit.Address, error) {
|
||||
addr, err := b.GetCryptoDepositAddress(ctx, cryptocurrency)
|
||||
func (e *Exchange) GetDepositAddress(ctx context.Context, cryptocurrency currency.Code, _, _ string) (*deposit.Address, error) {
|
||||
addr, err := e.GetCryptoDepositAddress(ctx, cryptocurrency)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -559,11 +559,11 @@ func (b *Bitstamp) GetDepositAddress(ctx context.Context, cryptocurrency currenc
|
||||
|
||||
// WithdrawCryptocurrencyFunds returns a withdrawal ID when a withdrawal is
|
||||
// submitted
|
||||
func (b *Bitstamp) WithdrawCryptocurrencyFunds(ctx context.Context, withdrawRequest *withdraw.Request) (*withdraw.ExchangeResponse, error) {
|
||||
func (e *Exchange) WithdrawCryptocurrencyFunds(ctx context.Context, withdrawRequest *withdraw.Request) (*withdraw.ExchangeResponse, error) {
|
||||
if err := withdrawRequest.Validate(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resp, err := b.CryptoWithdrawal(ctx,
|
||||
resp, err := e.CryptoWithdrawal(ctx,
|
||||
withdrawRequest.Amount,
|
||||
withdrawRequest.Crypto.Address,
|
||||
withdrawRequest.Currency.String(),
|
||||
@@ -579,11 +579,11 @@ func (b *Bitstamp) WithdrawCryptocurrencyFunds(ctx context.Context, withdrawRequ
|
||||
|
||||
// WithdrawFiatFunds returns a withdrawal ID when a
|
||||
// withdrawal is submitted
|
||||
func (b *Bitstamp) WithdrawFiatFunds(ctx context.Context, withdrawRequest *withdraw.Request) (*withdraw.ExchangeResponse, error) {
|
||||
func (e *Exchange) WithdrawFiatFunds(ctx context.Context, withdrawRequest *withdraw.Request) (*withdraw.ExchangeResponse, error) {
|
||||
if err := withdrawRequest.Validate(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resp, err := b.OpenBankWithdrawal(ctx,
|
||||
resp, err := e.OpenBankWithdrawal(ctx,
|
||||
withdrawRequest.Amount,
|
||||
withdrawRequest.Currency.String(),
|
||||
withdrawRequest.Fiat.Bank.AccountName,
|
||||
@@ -606,11 +606,11 @@ func (b *Bitstamp) WithdrawFiatFunds(ctx context.Context, withdrawRequest *withd
|
||||
|
||||
// WithdrawFiatFundsToInternationalBank returns a withdrawal ID when a
|
||||
// withdrawal is submitted
|
||||
func (b *Bitstamp) WithdrawFiatFundsToInternationalBank(ctx context.Context, withdrawRequest *withdraw.Request) (*withdraw.ExchangeResponse, error) {
|
||||
func (e *Exchange) WithdrawFiatFundsToInternationalBank(ctx context.Context, withdrawRequest *withdraw.Request) (*withdraw.ExchangeResponse, error) {
|
||||
if err := withdrawRequest.Validate(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resp, err := b.OpenInternationalBankWithdrawal(ctx,
|
||||
resp, err := e.OpenInternationalBankWithdrawal(ctx,
|
||||
withdrawRequest.Amount,
|
||||
withdrawRequest.Currency.String(),
|
||||
withdrawRequest.Fiat.Bank.AccountName,
|
||||
@@ -638,7 +638,7 @@ func (b *Bitstamp) WithdrawFiatFundsToInternationalBank(ctx context.Context, wit
|
||||
}
|
||||
|
||||
// GetActiveOrders retrieves any orders that are active/open
|
||||
func (b *Bitstamp) GetActiveOrders(ctx context.Context, req *order.MultiOrderRequest) (order.FilteredOrders, error) {
|
||||
func (e *Exchange) GetActiveOrders(ctx context.Context, req *order.MultiOrderRequest) (order.FilteredOrders, error) {
|
||||
err := req.Validate()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -649,14 +649,14 @@ func (b *Bitstamp) GetActiveOrders(ctx context.Context, req *order.MultiOrderReq
|
||||
currPair = "all"
|
||||
} else {
|
||||
var fPair currency.Pair
|
||||
fPair, err = b.FormatExchangeCurrency(req.Pairs[0], asset.Spot)
|
||||
fPair, err = e.FormatExchangeCurrency(req.Pairs[0], asset.Spot)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
currPair = fPair.String()
|
||||
}
|
||||
|
||||
resp, err := b.GetOpenOrders(ctx, currPair)
|
||||
resp, err := e.GetOpenOrders(ctx, currPair)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -688,15 +688,15 @@ func (b *Bitstamp) GetActiveOrders(ctx context.Context, req *order.MultiOrderReq
|
||||
Side: orderSide,
|
||||
Date: resp[i].DateTime.Time(),
|
||||
Pair: p,
|
||||
Exchange: b.Name,
|
||||
Exchange: e.Name,
|
||||
}
|
||||
}
|
||||
return req.Filter(b.Name, orders), nil
|
||||
return req.Filter(e.Name, orders), nil
|
||||
}
|
||||
|
||||
// GetOrderHistory retrieves account order information
|
||||
// Can Limit response to specific order status
|
||||
func (b *Bitstamp) GetOrderHistory(ctx context.Context, req *order.MultiOrderRequest) (order.FilteredOrders, error) {
|
||||
func (e *Exchange) GetOrderHistory(ctx context.Context, req *order.MultiOrderRequest) (order.FilteredOrders, error) {
|
||||
err := req.Validate()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -705,19 +705,19 @@ func (b *Bitstamp) GetOrderHistory(ctx context.Context, req *order.MultiOrderReq
|
||||
var currPair string
|
||||
if len(req.Pairs) == 1 {
|
||||
var fPair currency.Pair
|
||||
fPair, err = b.FormatExchangeCurrency(req.Pairs[0], asset.Spot)
|
||||
fPair, err = e.FormatExchangeCurrency(req.Pairs[0], asset.Spot)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
currPair = fPair.String()
|
||||
}
|
||||
|
||||
format, err := b.GetPairFormat(asset.Spot, false)
|
||||
format, err := e.GetPairFormat(asset.Spot, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp, err := b.GetUserTransactions(ctx, currPair)
|
||||
resp, err := e.GetUserTransactions(ctx, currPair)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -737,7 +737,7 @@ func (b *Bitstamp) GetOrderHistory(ctx context.Context, req *order.MultiOrderReq
|
||||
default:
|
||||
log.Warnf(log.ExchangeSys,
|
||||
"%s No base currency found for ID '%d'\n",
|
||||
b.Name,
|
||||
e.Name,
|
||||
resp[i].OrderID)
|
||||
}
|
||||
|
||||
@@ -749,7 +749,7 @@ func (b *Bitstamp) GetOrderHistory(ctx context.Context, req *order.MultiOrderReq
|
||||
default:
|
||||
log.Warnf(log.ExchangeSys,
|
||||
"%s No quote currency found for orderID '%d'\n",
|
||||
b.Name,
|
||||
e.Name,
|
||||
resp[i].OrderID)
|
||||
}
|
||||
|
||||
@@ -763,32 +763,32 @@ func (b *Bitstamp) GetOrderHistory(ctx context.Context, req *order.MultiOrderReq
|
||||
orders = append(orders, order.Detail{
|
||||
OrderID: strconv.FormatInt(resp[i].OrderID, 10),
|
||||
Date: resp[i].Date.Time(),
|
||||
Exchange: b.Name,
|
||||
Exchange: e.Name,
|
||||
Pair: currPair,
|
||||
})
|
||||
}
|
||||
return req.Filter(b.Name, orders), nil
|
||||
return req.Filter(e.Name, orders), nil
|
||||
}
|
||||
|
||||
// ValidateAPICredentials validates current credentials used for wrapper
|
||||
// functionality
|
||||
func (b *Bitstamp) ValidateAPICredentials(ctx context.Context, assetType asset.Item) error {
|
||||
_, err := b.UpdateAccountInfo(ctx, assetType)
|
||||
return b.CheckTransientError(err)
|
||||
func (e *Exchange) ValidateAPICredentials(ctx context.Context, assetType asset.Item) error {
|
||||
_, err := e.UpdateAccountInfo(ctx, assetType)
|
||||
return e.CheckTransientError(err)
|
||||
}
|
||||
|
||||
// GetHistoricCandles returns candles between a time period for a set time interval
|
||||
func (b *Bitstamp) GetHistoricCandles(ctx context.Context, pair currency.Pair, a asset.Item, interval kline.Interval, start, end time.Time) (*kline.Item, error) {
|
||||
req, err := b.GetKlineRequest(pair, a, interval, start, end, false)
|
||||
func (e *Exchange) GetHistoricCandles(ctx context.Context, pair currency.Pair, a asset.Item, interval kline.Interval, start, end time.Time) (*kline.Item, error) {
|
||||
req, err := e.GetKlineRequest(pair, a, interval, start, end, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
candles, err := b.OHLC(ctx,
|
||||
candles, err := e.OHLC(ctx,
|
||||
req.RequestFormatted.String(),
|
||||
req.Start,
|
||||
req.End,
|
||||
b.FormatExchangeKlineInterval(req.ExchangeInterval),
|
||||
e.FormatExchangeKlineInterval(req.ExchangeInterval),
|
||||
strconv.FormatUint(req.RequestLimit, 10))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -813,8 +813,8 @@ func (b *Bitstamp) GetHistoricCandles(ctx context.Context, pair currency.Pair, a
|
||||
}
|
||||
|
||||
// GetHistoricCandlesExtended returns candles between a time period for a set time interval
|
||||
func (b *Bitstamp) GetHistoricCandlesExtended(ctx context.Context, pair currency.Pair, a asset.Item, interval kline.Interval, start, end time.Time) (*kline.Item, error) {
|
||||
req, err := b.GetKlineExtendedRequest(pair, a, interval, start, end)
|
||||
func (e *Exchange) GetHistoricCandlesExtended(ctx context.Context, pair currency.Pair, a asset.Item, interval kline.Interval, start, end time.Time) (*kline.Item, error) {
|
||||
req, err := e.GetKlineExtendedRequest(pair, a, interval, start, end)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -822,11 +822,11 @@ func (b *Bitstamp) GetHistoricCandlesExtended(ctx context.Context, pair currency
|
||||
timeSeries := make([]kline.Candle, 0, req.Size())
|
||||
for x := range req.RangeHolder.Ranges {
|
||||
var candles OHLCResponse
|
||||
candles, err = b.OHLC(ctx,
|
||||
candles, err = e.OHLC(ctx,
|
||||
req.RequestFormatted.String(),
|
||||
req.RangeHolder.Ranges[x].Start.Time,
|
||||
req.RangeHolder.Ranges[x].End.Time,
|
||||
b.FormatExchangeKlineInterval(req.ExchangeInterval),
|
||||
e.FormatExchangeKlineInterval(req.ExchangeInterval),
|
||||
strconv.FormatUint(req.RequestLimit, 10),
|
||||
)
|
||||
if err != nil {
|
||||
@@ -853,23 +853,23 @@ func (b *Bitstamp) GetHistoricCandlesExtended(ctx context.Context, pair currency
|
||||
}
|
||||
|
||||
// GetServerTime returns the current exchange server time.
|
||||
func (b *Bitstamp) GetServerTime(_ context.Context, _ asset.Item) (time.Time, error) {
|
||||
func (e *Exchange) GetServerTime(_ context.Context, _ asset.Item) (time.Time, error) {
|
||||
return time.Time{}, common.ErrFunctionNotSupported
|
||||
}
|
||||
|
||||
// GetFuturesContractDetails returns all contracts from the exchange by asset type
|
||||
func (b *Bitstamp) GetFuturesContractDetails(context.Context, asset.Item) ([]futures.Contract, error) {
|
||||
func (e *Exchange) GetFuturesContractDetails(context.Context, asset.Item) ([]futures.Contract, error) {
|
||||
return nil, common.ErrFunctionNotSupported
|
||||
}
|
||||
|
||||
// GetLatestFundingRates returns the latest funding rates data
|
||||
func (b *Bitstamp) GetLatestFundingRates(context.Context, *fundingrate.LatestRateRequest) ([]fundingrate.LatestRateResponse, error) {
|
||||
func (e *Exchange) GetLatestFundingRates(context.Context, *fundingrate.LatestRateRequest) ([]fundingrate.LatestRateResponse, error) {
|
||||
return nil, common.ErrFunctionNotSupported
|
||||
}
|
||||
|
||||
// GetCurrencyTradeURL returns the URL to the exchange's trade page for the given asset and currency pair
|
||||
func (b *Bitstamp) GetCurrencyTradeURL(_ context.Context, a asset.Item, cp currency.Pair) (string, error) {
|
||||
_, err := b.CurrencyPairs.IsPairEnabled(cp, a)
|
||||
func (e *Exchange) GetCurrencyTradeURL(_ context.Context, a asset.Item, cp currency.Pair) (string, error) {
|
||||
_, err := e.CurrencyPairs.IsPairEnabled(cp, a)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user