mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-05-14 07:26:47 +00:00
Huobi: Add deposit address and withdraw quota API support (#433)
* Add Huobi deposit and withdraw quota API support Plus perform come code deduplication * Go mod tidy
This commit is contained in:
@@ -24,8 +24,9 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
huobiAPIURL = "https://api.huobi.pro"
|
||||
huobiAPIVersion = "1"
|
||||
huobiAPIURL = "https://api.huobi.pro"
|
||||
huobiAPIVersion = "1"
|
||||
huobiAPIVersion2 = "2"
|
||||
|
||||
huobiMarketHistoryKline = "market/history/kline"
|
||||
huobiMarketDetail = "market/detail"
|
||||
@@ -39,6 +40,8 @@ const (
|
||||
huobiTimestamp = "common/timestamp"
|
||||
huobiAccounts = "account/accounts"
|
||||
huobiAccountBalance = "account/accounts/%s/balance"
|
||||
huobiAccountDepositAddress = "account/deposit/address"
|
||||
huobiAccountWithdrawQuota = "account/withdraw/quota"
|
||||
huobiAggregatedBalance = "subuser/aggregate-balance"
|
||||
huobiOrderPlace = "order/orders/place"
|
||||
huobiOrderCancel = "order/orders/%s/submitcancel"
|
||||
@@ -60,6 +63,8 @@ const (
|
||||
|
||||
huobiAuthRate = 100
|
||||
huobiUnauthRate = 100
|
||||
|
||||
huobiStatusError = "error"
|
||||
)
|
||||
|
||||
// HUOBI is the overarching type across this package
|
||||
@@ -287,61 +292,38 @@ func (h *HUOBI) GetTimestamp() (int64, error) {
|
||||
|
||||
// GetAccounts returns the Huobi user accounts
|
||||
func (h *HUOBI) GetAccounts() ([]Account, error) {
|
||||
type response struct {
|
||||
Response
|
||||
AccountData []Account `json:"data"`
|
||||
}
|
||||
|
||||
var result response
|
||||
err := h.SendAuthenticatedHTTPRequest(http.MethodGet, huobiAccounts, url.Values{}, nil, &result)
|
||||
|
||||
if result.ErrorMessage != "" {
|
||||
return nil, errors.New(result.ErrorMessage)
|
||||
}
|
||||
return result.AccountData, err
|
||||
result := struct {
|
||||
Accounts []Account `json:"data"`
|
||||
}{}
|
||||
err := h.SendAuthenticatedHTTPRequest(http.MethodGet, huobiAccounts, url.Values{}, nil, &result, false)
|
||||
return result.Accounts, err
|
||||
}
|
||||
|
||||
// GetAccountBalance returns the users Huobi account balance
|
||||
func (h *HUOBI) GetAccountBalance(accountID string) ([]AccountBalanceDetail, error) {
|
||||
type response struct {
|
||||
Response
|
||||
result := struct {
|
||||
AccountBalanceData AccountBalance `json:"data"`
|
||||
}
|
||||
|
||||
var result response
|
||||
}{}
|
||||
endpoint := fmt.Sprintf(huobiAccountBalance, accountID)
|
||||
|
||||
v := url.Values{}
|
||||
v.Set("account-id", accountID)
|
||||
|
||||
err := h.SendAuthenticatedHTTPRequest(http.MethodGet, endpoint, v, nil, &result)
|
||||
|
||||
if result.ErrorMessage != "" {
|
||||
return nil, errors.New(result.ErrorMessage)
|
||||
}
|
||||
err := h.SendAuthenticatedHTTPRequest(http.MethodGet, endpoint, v, nil, &result, false)
|
||||
return result.AccountBalanceData.AccountBalanceDetails, err
|
||||
}
|
||||
|
||||
// GetAggregatedBalance returns the balances of all the sub-account aggregated.
|
||||
func (h *HUOBI) GetAggregatedBalance() ([]AggregatedBalance, error) {
|
||||
type response struct {
|
||||
Response
|
||||
result := struct {
|
||||
AggregatedBalances []AggregatedBalance `json:"data"`
|
||||
}
|
||||
|
||||
var result response
|
||||
|
||||
}{}
|
||||
err := h.SendAuthenticatedHTTPRequest(
|
||||
http.MethodGet,
|
||||
huobiAggregatedBalance,
|
||||
nil,
|
||||
nil,
|
||||
&result,
|
||||
false,
|
||||
)
|
||||
|
||||
if result.ErrorMessage != "" {
|
||||
return nil, errors.New(result.ErrorMessage)
|
||||
}
|
||||
return result.AggregatedBalances, err
|
||||
}
|
||||
|
||||
@@ -370,35 +352,28 @@ func (h *HUOBI) SpotNewOrder(arg SpotNewOrderRequestParams) (int64, error) {
|
||||
data.Source = arg.Source
|
||||
}
|
||||
|
||||
type response struct {
|
||||
Response
|
||||
result := struct {
|
||||
OrderID int64 `json:"data,string"`
|
||||
}
|
||||
|
||||
var result response
|
||||
err := h.SendAuthenticatedHTTPRequest(http.MethodPost, huobiOrderPlace, nil, data, &result)
|
||||
|
||||
if result.ErrorMessage != "" {
|
||||
return 0, errors.New(result.ErrorMessage)
|
||||
}
|
||||
}{}
|
||||
err := h.SendAuthenticatedHTTPRequest(
|
||||
http.MethodPost,
|
||||
huobiOrderPlace,
|
||||
nil,
|
||||
data,
|
||||
&result,
|
||||
false,
|
||||
)
|
||||
return result.OrderID, err
|
||||
}
|
||||
|
||||
// CancelExistingOrder cancels an order on Huobi
|
||||
func (h *HUOBI) CancelExistingOrder(orderID int64) (int64, error) {
|
||||
type response struct {
|
||||
Response
|
||||
resp := struct {
|
||||
OrderID int64 `json:"data,string"`
|
||||
}
|
||||
|
||||
var result response
|
||||
}{}
|
||||
endpoint := fmt.Sprintf(huobiOrderCancel, strconv.FormatInt(orderID, 10))
|
||||
err := h.SendAuthenticatedHTTPRequest(http.MethodPost, endpoint, url.Values{}, nil, &result)
|
||||
|
||||
if result.ErrorMessage != "" {
|
||||
return 0, errors.New(result.ErrorMessage)
|
||||
}
|
||||
return result.OrderID, err
|
||||
err := h.SendAuthenticatedHTTPRequest(http.MethodPost, endpoint, url.Values{}, nil, &resp, false)
|
||||
return resp.OrderID, err
|
||||
}
|
||||
|
||||
// CancelOrderBatch cancels a batch of orders -- to-do
|
||||
@@ -409,7 +384,7 @@ func (h *HUOBI) CancelOrderBatch(_ []int64) ([]CancelOrderBatch, error) {
|
||||
}
|
||||
|
||||
var result response
|
||||
err := h.SendAuthenticatedHTTPRequest(http.MethodPost, huobiOrderCancelBatch, url.Values{}, nil, &result)
|
||||
err := h.SendAuthenticatedHTTPRequest(http.MethodPost, huobiOrderCancelBatch, url.Values{}, nil, &result, false)
|
||||
|
||||
if result.ErrorMessage != "" {
|
||||
return nil, errors.New(result.ErrorMessage)
|
||||
@@ -432,7 +407,7 @@ func (h *HUOBI) CancelOpenOrdersBatch(accountID, symbol string) (CancelOpenOrder
|
||||
Symbol: symbol,
|
||||
}
|
||||
|
||||
err := h.SendAuthenticatedHTTPRequest(http.MethodPost, huobiBatchCancelOpenOrders, url.Values{}, data, &result)
|
||||
err := h.SendAuthenticatedHTTPRequest(http.MethodPost, huobiBatchCancelOpenOrders, url.Values{}, data, &result, false)
|
||||
if result.Data.FailedCount > 0 {
|
||||
return result, fmt.Errorf("there were %v failed order cancellations", result.Data.FailedCount)
|
||||
}
|
||||
@@ -442,45 +417,35 @@ func (h *HUOBI) CancelOpenOrdersBatch(accountID, symbol string) (CancelOpenOrder
|
||||
|
||||
// GetOrder returns order information for the specified order
|
||||
func (h *HUOBI) GetOrder(orderID int64) (OrderInfo, error) {
|
||||
type response struct {
|
||||
Response
|
||||
resp := struct {
|
||||
Order OrderInfo `json:"data"`
|
||||
}
|
||||
|
||||
var result response
|
||||
}{}
|
||||
urlVal := url.Values{}
|
||||
urlVal.Set("clientOrderId", strconv.FormatInt(orderID, 10))
|
||||
err := h.SendAuthenticatedHTTPRequest(http.MethodGet, huobiGetOrder, urlVal, nil, &result)
|
||||
|
||||
if result.ErrorMessage != "" {
|
||||
return result.Order, errors.New(result.ErrorMessage)
|
||||
}
|
||||
return result.Order, err
|
||||
err := h.SendAuthenticatedHTTPRequest(http.MethodGet,
|
||||
huobiGetOrder,
|
||||
urlVal,
|
||||
nil,
|
||||
&resp,
|
||||
false)
|
||||
return resp.Order, err
|
||||
}
|
||||
|
||||
// GetOrderMatchResults returns matched order info for the specified order
|
||||
func (h *HUOBI) GetOrderMatchResults(orderID int64) ([]OrderMatchInfo, error) {
|
||||
type response struct {
|
||||
Response
|
||||
resp := struct {
|
||||
Orders []OrderMatchInfo `json:"data"`
|
||||
}
|
||||
|
||||
var result response
|
||||
}{}
|
||||
endpoint := fmt.Sprintf(huobiGetOrderMatch, strconv.FormatInt(orderID, 10))
|
||||
err := h.SendAuthenticatedHTTPRequest(http.MethodGet, endpoint, url.Values{}, nil, &result)
|
||||
|
||||
if result.ErrorMessage != "" {
|
||||
return nil, errors.New(result.ErrorMessage)
|
||||
}
|
||||
return result.Orders, err
|
||||
err := h.SendAuthenticatedHTTPRequest(http.MethodGet, endpoint, url.Values{}, nil, &resp, false)
|
||||
return resp.Orders, err
|
||||
}
|
||||
|
||||
// GetOrders returns a list of orders
|
||||
func (h *HUOBI) GetOrders(symbol, types, start, end, states, from, direct, size string) ([]OrderInfo, error) {
|
||||
type response struct {
|
||||
Response
|
||||
resp := struct {
|
||||
Orders []OrderInfo `json:"data"`
|
||||
}
|
||||
}{}
|
||||
|
||||
vals := url.Values{}
|
||||
vals.Set("symbol", symbol)
|
||||
@@ -510,21 +475,15 @@ func (h *HUOBI) GetOrders(symbol, types, start, end, states, from, direct, size
|
||||
vals.Set("size", size)
|
||||
}
|
||||
|
||||
var result response
|
||||
err := h.SendAuthenticatedHTTPRequest(http.MethodGet, huobiGetOrders, vals, nil, &result)
|
||||
|
||||
if result.ErrorMessage != "" {
|
||||
return nil, errors.New(result.ErrorMessage)
|
||||
}
|
||||
return result.Orders, err
|
||||
err := h.SendAuthenticatedHTTPRequest(http.MethodGet, huobiGetOrders, vals, nil, &resp, false)
|
||||
return resp.Orders, err
|
||||
}
|
||||
|
||||
// GetOpenOrders returns a list of orders
|
||||
func (h *HUOBI) GetOpenOrders(accountID, symbol, side string, size int64) ([]OrderInfo, error) {
|
||||
type response struct {
|
||||
Response
|
||||
resp := struct {
|
||||
Orders []OrderInfo `json:"data"`
|
||||
}
|
||||
}{}
|
||||
|
||||
vals := url.Values{}
|
||||
vals.Set("symbol", symbol)
|
||||
@@ -534,22 +493,15 @@ func (h *HUOBI) GetOpenOrders(accountID, symbol, side string, size int64) ([]Ord
|
||||
}
|
||||
vals.Set("size", strconv.FormatInt(size, 10))
|
||||
|
||||
var result response
|
||||
err := h.SendAuthenticatedHTTPRequest(http.MethodGet, huobiGetOpenOrders, vals, nil, &result)
|
||||
|
||||
if result.ErrorMessage != "" {
|
||||
return nil, errors.New(result.ErrorMessage)
|
||||
}
|
||||
|
||||
return result.Orders, err
|
||||
err := h.SendAuthenticatedHTTPRequest(http.MethodGet, huobiGetOpenOrders, vals, nil, &resp, false)
|
||||
return resp.Orders, err
|
||||
}
|
||||
|
||||
// GetOrdersMatch returns a list of matched orders
|
||||
func (h *HUOBI) GetOrdersMatch(symbol, types, start, end, from, direct, size string) ([]OrderMatchInfo, error) {
|
||||
type response struct {
|
||||
Response
|
||||
resp := struct {
|
||||
Orders []OrderMatchInfo `json:"data"`
|
||||
}
|
||||
}{}
|
||||
|
||||
vals := url.Values{}
|
||||
vals.Set("symbol", symbol)
|
||||
@@ -578,13 +530,8 @@ func (h *HUOBI) GetOrdersMatch(symbol, types, start, end, from, direct, size str
|
||||
vals.Set("size", size)
|
||||
}
|
||||
|
||||
var result response
|
||||
err := h.SendAuthenticatedHTTPRequest(http.MethodGet, huobiGetOrdersMatch, vals, nil, &result)
|
||||
|
||||
if result.ErrorMessage != "" {
|
||||
return nil, errors.New(result.ErrorMessage)
|
||||
}
|
||||
return result.Orders, err
|
||||
err := h.SendAuthenticatedHTTPRequest(http.MethodGet, huobiGetOrdersMatch, vals, nil, &resp, false)
|
||||
return resp.Orders, err
|
||||
}
|
||||
|
||||
// MarginTransfer transfers assets into or out of the margin account
|
||||
@@ -604,18 +551,11 @@ func (h *HUOBI) MarginTransfer(symbol, currency string, amount float64, in bool)
|
||||
path = huobiMarginTransferOut
|
||||
}
|
||||
|
||||
type response struct {
|
||||
Response
|
||||
resp := struct {
|
||||
TransferID int64 `json:"data"`
|
||||
}
|
||||
|
||||
var result response
|
||||
err := h.SendAuthenticatedHTTPRequest(http.MethodPost, path, nil, data, &result)
|
||||
|
||||
if result.ErrorMessage != "" {
|
||||
return 0, errors.New(result.ErrorMessage)
|
||||
}
|
||||
return result.TransferID, err
|
||||
}{}
|
||||
err := h.SendAuthenticatedHTTPRequest(http.MethodPost, path, nil, data, &resp, false)
|
||||
return resp.TransferID, err
|
||||
}
|
||||
|
||||
// MarginOrder submits a margin order application
|
||||
@@ -630,18 +570,11 @@ func (h *HUOBI) MarginOrder(symbol, currency string, amount float64) (int64, err
|
||||
Amount: strconv.FormatFloat(amount, 'f', -1, 64),
|
||||
}
|
||||
|
||||
type response struct {
|
||||
Response
|
||||
resp := struct {
|
||||
MarginOrderID int64 `json:"data"`
|
||||
}
|
||||
|
||||
var result response
|
||||
err := h.SendAuthenticatedHTTPRequest(http.MethodPost, huobiMarginOrders, nil, data, &result)
|
||||
|
||||
if result.ErrorMessage != "" {
|
||||
return 0, errors.New(result.ErrorMessage)
|
||||
}
|
||||
return result.MarginOrderID, err
|
||||
}{}
|
||||
err := h.SendAuthenticatedHTTPRequest(http.MethodPost, huobiMarginOrders, nil, data, &resp, false)
|
||||
return resp.MarginOrderID, err
|
||||
}
|
||||
|
||||
// MarginRepayment repays a margin amount for a margin ID
|
||||
@@ -652,19 +585,13 @@ func (h *HUOBI) MarginRepayment(orderID int64, amount float64) (int64, error) {
|
||||
Amount: strconv.FormatFloat(amount, 'f', -1, 64),
|
||||
}
|
||||
|
||||
type response struct {
|
||||
Response
|
||||
resp := struct {
|
||||
MarginOrderID int64 `json:"data"`
|
||||
}
|
||||
}{}
|
||||
|
||||
var result response
|
||||
endpoint := fmt.Sprintf(huobiMarginRepay, strconv.FormatInt(orderID, 10))
|
||||
err := h.SendAuthenticatedHTTPRequest(http.MethodPost, endpoint, nil, data, &result)
|
||||
|
||||
if result.ErrorMessage != "" {
|
||||
return 0, errors.New(result.ErrorMessage)
|
||||
}
|
||||
return result.MarginOrderID, err
|
||||
err := h.SendAuthenticatedHTTPRequest(http.MethodPost, endpoint, nil, data, &resp, false)
|
||||
return resp.MarginOrderID, err
|
||||
}
|
||||
|
||||
// GetMarginLoanOrders returns the margin loan orders
|
||||
@@ -697,47 +624,31 @@ func (h *HUOBI) GetMarginLoanOrders(symbol, currency, start, end, states, from,
|
||||
vals.Set("size", size)
|
||||
}
|
||||
|
||||
type response struct {
|
||||
Response
|
||||
resp := struct {
|
||||
MarginLoanOrders []MarginOrder `json:"data"`
|
||||
}
|
||||
|
||||
var result response
|
||||
err := h.SendAuthenticatedHTTPRequest(http.MethodGet, huobiMarginLoanOrders, vals, nil, &result)
|
||||
|
||||
if result.ErrorMessage != "" {
|
||||
return nil, errors.New(result.ErrorMessage)
|
||||
}
|
||||
return result.MarginLoanOrders, err
|
||||
}{}
|
||||
err := h.SendAuthenticatedHTTPRequest(http.MethodGet, huobiMarginLoanOrders, vals, nil, &resp, false)
|
||||
return resp.MarginLoanOrders, err
|
||||
}
|
||||
|
||||
// GetMarginAccountBalance returns the margin account balances
|
||||
func (h *HUOBI) GetMarginAccountBalance(symbol string) ([]MarginAccountBalance, error) {
|
||||
type response struct {
|
||||
Response
|
||||
resp := struct {
|
||||
Balances []MarginAccountBalance `json:"data"`
|
||||
}
|
||||
|
||||
}{}
|
||||
vals := url.Values{}
|
||||
if symbol != "" {
|
||||
vals.Set("symbol", symbol)
|
||||
}
|
||||
|
||||
var result response
|
||||
err := h.SendAuthenticatedHTTPRequest(http.MethodGet, huobiMarginAccountBalance, vals, nil, &result)
|
||||
|
||||
if result.ErrorMessage != "" {
|
||||
return nil, errors.New(result.ErrorMessage)
|
||||
}
|
||||
return result.Balances, err
|
||||
err := h.SendAuthenticatedHTTPRequest(http.MethodGet, huobiMarginAccountBalance, vals, nil, &resp, false)
|
||||
return resp.Balances, err
|
||||
}
|
||||
|
||||
// Withdraw withdraws the desired amount and currency
|
||||
func (h *HUOBI) Withdraw(c currency.Code, address, addrTag string, amount, fee float64) (int64, error) {
|
||||
type response struct {
|
||||
Response
|
||||
resp := struct {
|
||||
WithdrawID int64 `json:"data"`
|
||||
}
|
||||
}{}
|
||||
|
||||
data := struct {
|
||||
Address string `json:"address"`
|
||||
@@ -759,33 +670,56 @@ func (h *HUOBI) Withdraw(c currency.Code, address, addrTag string, amount, fee f
|
||||
data.AddrTag = addrTag
|
||||
}
|
||||
|
||||
var result response
|
||||
err := h.SendAuthenticatedHTTPRequest(http.MethodPost, huobiWithdrawCreate, nil, data, &result)
|
||||
|
||||
if result.ErrorMessage != "" {
|
||||
return 0, errors.New(result.ErrorMessage)
|
||||
}
|
||||
return result.WithdrawID, err
|
||||
err := h.SendAuthenticatedHTTPRequest(http.MethodPost, huobiWithdrawCreate, nil, data, &resp.WithdrawID, false)
|
||||
return resp.WithdrawID, err
|
||||
}
|
||||
|
||||
// CancelWithdraw cancels a withdraw request
|
||||
func (h *HUOBI) CancelWithdraw(withdrawID int64) (int64, error) {
|
||||
type response struct {
|
||||
Response
|
||||
resp := struct {
|
||||
WithdrawID int64 `json:"data"`
|
||||
}
|
||||
|
||||
}{}
|
||||
vals := url.Values{}
|
||||
vals.Set("withdraw-id", strconv.FormatInt(withdrawID, 10))
|
||||
|
||||
var result response
|
||||
endpoint := fmt.Sprintf(huobiWithdrawCancel, strconv.FormatInt(withdrawID, 10))
|
||||
err := h.SendAuthenticatedHTTPRequest(http.MethodPost, endpoint, vals, nil, &result)
|
||||
err := h.SendAuthenticatedHTTPRequest(http.MethodPost, endpoint, vals, nil, &resp, false)
|
||||
return resp.WithdrawID, err
|
||||
}
|
||||
|
||||
if result.ErrorMessage != "" {
|
||||
return 0, errors.New(result.ErrorMessage)
|
||||
// QueryDepositAddress returns the deposit address for a specified currency
|
||||
func (h *HUOBI) QueryDepositAddress(cryptocurrency string) (DepositAddress, error) {
|
||||
resp := struct {
|
||||
DepositAddress []DepositAddress `json:"data"`
|
||||
}{}
|
||||
|
||||
vals := url.Values{}
|
||||
vals.Set("currency", cryptocurrency)
|
||||
|
||||
err := h.SendAuthenticatedHTTPRequest(http.MethodGet, huobiAccountDepositAddress, vals, nil, &resp, true)
|
||||
if err != nil {
|
||||
return DepositAddress{}, err
|
||||
}
|
||||
return result.WithdrawID, err
|
||||
if len(resp.DepositAddress) == 0 {
|
||||
return DepositAddress{}, errors.New("deposit address data isn't populated")
|
||||
}
|
||||
return resp.DepositAddress[0], nil
|
||||
}
|
||||
|
||||
// QueryWithdrawQuotas returns the users cryptocurrency withdraw quotas
|
||||
func (h *HUOBI) QueryWithdrawQuotas(cryptocurrency string) (WithdrawQuota, error) {
|
||||
resp := struct {
|
||||
WithdrawQuota WithdrawQuota `json:"data"`
|
||||
}{}
|
||||
|
||||
vals := url.Values{}
|
||||
vals.Set("currency", cryptocurrency)
|
||||
|
||||
err := h.SendAuthenticatedHTTPRequest(http.MethodGet, huobiAccountWithdrawQuota, vals, nil, &resp, true)
|
||||
if err != nil {
|
||||
return WithdrawQuota{}, err
|
||||
}
|
||||
return resp.WithdrawQuota, nil
|
||||
}
|
||||
|
||||
// SendHTTPRequest sends an unauthenticated HTTP request
|
||||
@@ -803,7 +737,7 @@ func (h *HUOBI) SendHTTPRequest(path string, result interface{}) error {
|
||||
}
|
||||
|
||||
// SendAuthenticatedHTTPRequest sends authenticated requests to the HUOBI API
|
||||
func (h *HUOBI) SendAuthenticatedHTTPRequest(method, endpoint string, values url.Values, data, result interface{}) error {
|
||||
func (h *HUOBI) SendAuthenticatedHTTPRequest(method, endpoint string, values url.Values, data, result interface{}, isVersion2API bool) error {
|
||||
if !h.AllowAuthenticatedRequest() {
|
||||
return fmt.Errorf(exchange.WarningAuthenticatedRequestWithoutCredentialsSet, h.Name)
|
||||
}
|
||||
@@ -817,7 +751,12 @@ func (h *HUOBI) SendAuthenticatedHTTPRequest(method, endpoint string, values url
|
||||
values.Set("SignatureVersion", "2")
|
||||
values.Set("Timestamp", time.Now().UTC().Format("2006-01-02T15:04:05"))
|
||||
|
||||
endpoint = fmt.Sprintf("/v%s/%s", huobiAPIVersion, endpoint)
|
||||
if isVersion2API {
|
||||
endpoint = fmt.Sprintf("/v%s/%s", huobiAPIVersion2, endpoint)
|
||||
} else {
|
||||
endpoint = fmt.Sprintf("/v%s/%s", huobiAPIVersion, endpoint)
|
||||
}
|
||||
|
||||
payload := fmt.Sprintf("%s\napi.huobi.pro\n%s\n%s",
|
||||
method, endpoint, values.Encode())
|
||||
|
||||
@@ -864,26 +803,45 @@ func (h *HUOBI) SendAuthenticatedHTTPRequest(method, endpoint string, values url
|
||||
urlPath := h.API.Endpoints.URL + common.EncodeURLValues(endpoint, values)
|
||||
|
||||
var body []byte
|
||||
|
||||
if data != nil {
|
||||
encoded, err := json.Marshal(data)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%s unable to marshal data: %s", h.Name, err)
|
||||
}
|
||||
|
||||
body = encoded
|
||||
}
|
||||
|
||||
return h.SendPayload(method,
|
||||
interim := json.RawMessage{}
|
||||
err := h.SendPayload(method,
|
||||
urlPath,
|
||||
headers,
|
||||
bytes.NewReader(body),
|
||||
result,
|
||||
bytes.NewBuffer(body),
|
||||
&interim,
|
||||
true,
|
||||
false,
|
||||
h.Verbose,
|
||||
h.HTTPDebugging,
|
||||
h.HTTPRecording)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if isVersion2API {
|
||||
var errCap ResponseV2
|
||||
if err = json.Unmarshal(interim, &errCap); err == nil {
|
||||
if errCap.Code != 200 && errCap.Message != "" {
|
||||
return errors.New(errCap.Message)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
var errCap Response
|
||||
if err = json.Unmarshal(interim, &errCap); err == nil {
|
||||
if errCap.Status == huobiStatusError && errCap.ErrorMessage != "" {
|
||||
return errors.New(errCap.ErrorMessage)
|
||||
}
|
||||
}
|
||||
}
|
||||
return json.Unmarshal(interim, result)
|
||||
}
|
||||
|
||||
// GetFee returns an estimate of fee based on type of transaction
|
||||
|
||||
@@ -634,10 +634,23 @@ func TestWithdrawInternationalBank(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetDepositAddress(t *testing.T) {
|
||||
_, err := h.GetDepositAddress(currency.BTC, "")
|
||||
if err == nil {
|
||||
t.Error("GetDepositAddress() error cannot be nil")
|
||||
func TestQueryDepositAddress(t *testing.T) {
|
||||
_, err := h.QueryDepositAddress(currency.BTC.Lower().String())
|
||||
if !areTestAPIKeysSet() && err == nil {
|
||||
t.Error("Expecting an error when no keys are set")
|
||||
}
|
||||
if areTestAPIKeysSet() && err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestQueryWithdrawQuota(t *testing.T) {
|
||||
_, err := h.QueryWithdrawQuotas(currency.BTC.Lower().String())
|
||||
if !areTestAPIKeysSet() && err == nil {
|
||||
t.Error("Expecting an error when no keys are set")
|
||||
}
|
||||
if areTestAPIKeysSet() && err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,12 @@ type Response struct {
|
||||
ErrorMessage string `json:"err-msg"`
|
||||
}
|
||||
|
||||
// ResponseV2 stores the Huobi generic response info
|
||||
type ResponseV2 struct {
|
||||
Code int32 `json:"code"`
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
// KlineItem stores a kline item
|
||||
type KlineItem struct {
|
||||
ID int64 `json:"id"`
|
||||
@@ -246,6 +252,32 @@ type SpotNewOrderRequestParams struct {
|
||||
Type SpotNewOrderRequestParamsType `json:"type"` // 订单类型, buy-market: 市价买, sell-market: 市价卖, buy-limit: 限价买, sell-limit: 限价卖
|
||||
}
|
||||
|
||||
// DepositAddress stores the users deposit address info
|
||||
type DepositAddress struct {
|
||||
Currency string `json:"currency"`
|
||||
Address string `json:"address"`
|
||||
AddressTag string `json:"addressTag"`
|
||||
Chain string `json:"chain"`
|
||||
}
|
||||
|
||||
// ChainQuota stores the users currency chain quota
|
||||
type ChainQuota struct {
|
||||
Chain string `json:"chain"`
|
||||
MaxWithdrawAmount float64 `json:"maxWithdrawAmt,string"`
|
||||
WithdrawQuotaPerDay float64 `json:"withdrawQuotaPerDay,string"`
|
||||
RemainingWithdrawQuotaPerDay float64 `json:"remainWithdrawQuotaPerDay,string"`
|
||||
WithdrawQuotaPerYear float64 `json:"withdrawQuotaPerYear,string"`
|
||||
RemainingWithdrawQuotaPerYear float64 `json:"remainWithdrawQuotaPerYear,string"`
|
||||
WithdrawQuotaTotal float64 `json:"withdrawQuotaTotal,string"`
|
||||
RemainingWithdrawQuotaTotal float64 `json:"remainWithdrawQuotaTotal,string"`
|
||||
}
|
||||
|
||||
// WithdrawQuota stores the users withdraw quotas
|
||||
type WithdrawQuota struct {
|
||||
Currency string `json:"currency"`
|
||||
Chains []ChainQuota `json:"chains"`
|
||||
}
|
||||
|
||||
// SpotNewOrderRequestParamsType order type
|
||||
type SpotNewOrderRequestParamsType string
|
||||
|
||||
|
||||
@@ -87,6 +87,7 @@ func (h *HUOBI) SetDefaults() {
|
||||
CancelOrders: true,
|
||||
CancelOrder: true,
|
||||
SubmitOrder: true,
|
||||
CryptoDeposit: true,
|
||||
CryptoWithdrawal: true,
|
||||
TradeFee: true,
|
||||
},
|
||||
@@ -652,7 +653,8 @@ func (h *HUOBI) GetOrderInfo(orderID string) (order.Detail, error) {
|
||||
|
||||
// GetDepositAddress returns a deposit address for a specified currency
|
||||
func (h *HUOBI) GetDepositAddress(cryptocurrency currency.Code, accountID string) (string, error) {
|
||||
return "", common.ErrFunctionNotSupported
|
||||
resp, err := h.QueryDepositAddress(cryptocurrency.Lower().String())
|
||||
return resp.Address, err
|
||||
}
|
||||
|
||||
// WithdrawCryptocurrencyFunds returns a withdrawal ID when a withdrawal is
|
||||
|
||||
2
go.mod
2
go.mod
@@ -23,9 +23,7 @@ require (
|
||||
github.com/urfave/cli v1.22.2
|
||||
github.com/volatiletech/null v8.0.0+incompatible
|
||||
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5
|
||||
golang.org/x/net v0.0.0-20190606173856-1492cefac77f // indirect
|
||||
golang.org/x/sys v0.0.0-20191003212358-c178f38b412c // indirect
|
||||
google.golang.org/genproto v0.0.0-20191002211648-c459b9ce5143
|
||||
google.golang.org/grpc v1.27.0
|
||||
gopkg.in/yaml.v2 v2.2.4 // indirect
|
||||
)
|
||||
|
||||
17
go.sum
17
go.sum
@@ -69,9 +69,11 @@ github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y
|
||||
github.com/golang/protobuf v1.3.3 h1:gyjaxf+svBWX08ZjK86iN9geUJF0H6gp2IRKX6Nf6/I=
|
||||
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk=
|
||||
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gorilla/mux v1.7.3 h1:gnP5JzjVOuiZD07fKKToCAOjS0yOpj/qPETTXCCS6hw=
|
||||
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||
@@ -85,8 +87,6 @@ github.com/grpc-ecosystem/go-grpc-middleware v1.1.0 h1:THDBEeQ9xZ8JEaCLyLQqXMMdR
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.1.0/go.mod h1:f5nM7jw/oeRSadq3xCzHAvxcr8HZnzsqU6ILg/0NiiE=
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.11.3 h1:h8+NsYENhxNTuq+dobk3+ODoJtwY4Fu0WQXsxJfL8aM=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.11.3/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.12.2 h1:D0EVSTwQoQOyfY35QNSuPJA4jpZRtkoGYWQMB7XNg5o=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.12.2/go.mod h1:8XEsbTttt/W+VvjtQhLACqCisSPWTxCZ7sBRjU6iH9c=
|
||||
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
||||
@@ -94,6 +94,7 @@ github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T
|
||||
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
||||
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
|
||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||
github.com/kat-co/vala v0.0.0-20170210184112-42e1d8b61f12 h1:DQVOxR9qdYEybJUr/c7ku34r3PfajaMYXZwgDM7KuSk=
|
||||
@@ -116,8 +117,6 @@ github.com/lib/pq v1.3.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4=
|
||||
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/mattn/go-sqlite3 v1.11.0 h1:LDdKkqtYlom37fkvqs8rMPFKAMe8+SgjbwZ6ex1/A/Q=
|
||||
github.com/mattn/go-sqlite3 v1.11.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
||||
github.com/mattn/go-sqlite3 v1.13.0 h1:LnJI81JidiW9r7pS/hXe6cFeO5EXNq7KbfvoJLRI69c=
|
||||
github.com/mattn/go-sqlite3 v1.13.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
@@ -160,7 +159,9 @@ github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5I
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
|
||||
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
|
||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
@@ -187,6 +188,7 @@ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
|
||||
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
|
||||
@@ -199,8 +201,6 @@ github.com/toorop/go-pusher v0.0.0-20180521062818-4521e2eb39fb h1:9kcmLvQdiIecpg
|
||||
github.com/toorop/go-pusher v0.0.0-20180521062818-4521e2eb39fb/go.mod h1:VTLqNCX1tXrur6pdIRCl8Q90FR7nw/mEBdyMkWMcsb0=
|
||||
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
|
||||
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
|
||||
github.com/urfave/cli v1.20.0 h1:fDqGv3UG/4jbVl/QkFwEdddtEDjh/5Ov6X+0B/3bPaw=
|
||||
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
||||
github.com/urfave/cli v1.22.2 h1:gsqYFH8bb9ekPA12kRo0hfjngWQjkJPlN9R0N78BoUo=
|
||||
github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||
github.com/volatiletech/inflect v0.0.0-20170731032912-e7201282ae8d h1:gI4/tqP6lCY5k6Sg+4k9qSoBXmPwG+xXgMpK7jivD4M=
|
||||
@@ -233,8 +233,7 @@ golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73r
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
golang.org/x/net v0.0.0-20190606173856-1492cefac77f h1:IWHgpgFqnL5AhBUBZSgBdjl2vkQUEzcY+JNKWfcgAU0=
|
||||
golang.org/x/net v0.0.0-20190606173856-1492cefac77f/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
golang.org/x/net v0.0.0-20191002035440-2ec189313ef0 h1:2mqDk8w/o6UmeUCu5Qiq2y7iMf6anbx+YA8d1JFoFrs=
|
||||
golang.org/x/net v0.0.0-20191002035440-2ec189313ef0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be h1:vEDujvNQGv4jgYKudGeI/+DAX4Jffq6hpD55MmoEvKs=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
@@ -277,8 +276,6 @@ google.golang.org/genproto v0.0.0-20191002211648-c459b9ce5143 h1:tikhlQEJeezbnu0
|
||||
google.golang.org/genproto v0.0.0-20191002211648-c459b9ce5143/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||
google.golang.org/grpc v1.21.1 h1:j6XxA85m/6txkUCHvzlV5f+HBNl/1r5cZ2A/3IEFOO8=
|
||||
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA=
|
||||
google.golang.org/grpc v1.27.0 h1:rRYRFMVgRv6E0D70Skyfsr28tDXIuuPZyWGMPdMcnXg=
|
||||
|
||||
Reference in New Issue
Block a user