Files
gocryptotrader/exchanges/binance/binance.go
Scott b1e6534e7c Withdraw Crypto wrapper mapping (#226)
* Initial commit

* Updates signature for all withdrawal methods to use new withdrawRequest struct type

* Implements crypto withdraw features & tests for Alphapoint, ANX, Binance, Bitfinex, Bitflyer, Bithumb, Bitmex, Bitstamp, Bittrex, BTCC, BTCmarkets, CoinbasePro, Coinut. Updates WithdrawRequest type with more members. Breaking change to update real order testing for increased code coverage

* Updates all realOrder tests to run when no API key is present. Updates exchange functions to handle errors better

* Implements crypto withdrawals for Exmo, GateIO, Gemini, HitBTC, Huobi, HuobiHadax, Kraken, LakeBTC, Liqui, Localbitcoins, OKCoin, OKEX, Poloniex, Wex, Yobit and ZB. Updates real order test formatting for all real order tests

* Update alphapoint. Fixes anx typos. Adds function WithdrawFiatFundsToInternationalBank to exchange wrapper interface. Adds WithdrawFiatFundsToInternationalBank to alphapoint, bitmex, coinbasepro. Updates Kraken to use TradePassword property

* Reverts alphapoint to use ErrNotYetImplemented

* Fixes line spacing and removes unnecessary line
2019-01-03 13:15:07 +11:00

758 lines
21 KiB
Go

package binance
import (
"bytes"
"errors"
"fmt"
"log"
"net/url"
"strconv"
"time"
"github.com/gorilla/websocket"
"github.com/thrasher-/gocryptotrader/common"
"github.com/thrasher-/gocryptotrader/config"
exchange "github.com/thrasher-/gocryptotrader/exchanges"
"github.com/thrasher-/gocryptotrader/exchanges/request"
"github.com/thrasher-/gocryptotrader/exchanges/ticker"
)
// Binance is the overarching type across the Bithumb package
type Binance struct {
exchange.Base
WebsocketConn *websocket.Conn
// Valid string list that is required by the exchange
validLimits []int
validIntervals []TimeInterval
}
const (
apiURL = "https://api.binance.com"
// Public endpoints
exchangeInfo = "/api/v1/exchangeInfo"
orderBookDepth = "/api/v1/depth"
recentTrades = "/api/v1/trades"
historicalTrades = "/api/v1/historicalTrades"
aggregatedTrades = "/api/v1/aggTrades"
candleStick = "/api/v1/klines"
averagePrice = "/api/v3/avgPrice"
priceChange = "/api/v1/ticker/24hr"
symbolPrice = "/api/v3/ticker/price"
bestPrice = "/api/v3/ticker/bookTicker"
accountInfo = "/api/v3/account"
// Authenticated endpoints
newOrderTest = "/api/v3/order/test"
newOrder = "/api/v3/order"
cancelOrder = "/api/v3/order"
queryOrder = "/api/v3/order"
openOrders = "/api/v3/openOrders"
allOrders = "/api/v3/allOrders"
// Withdraw API endpoints
withdraw = "/wapi/v3/withdraw.html"
depositHistory = "/wapi/v3/depositHistory.html"
withdrawalHistory = "/wapi/v3/withdrawHistory.html"
depositAddress = "/wapi/v3/depositAddress.html"
accountStatus = "/wapi/v3/accountStatus.html"
systemStatus = "/wapi/v3/systemStatus.html"
dustLog = "/wapi/v3/userAssetDribbletLog.html"
tradeFee = "/wapi/v3/tradeFee.html"
assetDetail = "/wapi/v3/assetDetail.html"
// binance authenticated and unauthenticated limit rates
// to-do
binanceAuthRate = 0
binanceUnauthRate = 0
)
// SetDefaults sets the basic defaults for Binance
func (b *Binance) SetDefaults() {
b.Name = "Binance"
b.Enabled = false
b.Verbose = false
b.RESTPollingDelay = 10
b.RequestCurrencyPairFormat.Delimiter = ""
b.RequestCurrencyPairFormat.Uppercase = true
b.ConfigCurrencyPairFormat.Delimiter = "-"
b.ConfigCurrencyPairFormat.Uppercase = true
b.AssetTypes = []string{ticker.Spot}
b.SupportsAutoPairUpdating = true
b.SupportsRESTTickerBatching = true
b.APIWithdrawPermissions = exchange.AutoWithdrawCrypto
b.SetValues()
b.Requester = request.New(b.Name,
request.NewRateLimit(time.Second, binanceAuthRate),
request.NewRateLimit(time.Second, binanceUnauthRate),
common.NewHTTPClientWithTimeout(exchange.DefaultHTTPTimeout))
b.APIUrlDefault = apiURL
b.APIUrl = b.APIUrlDefault
b.WebsocketInit()
}
// Setup takes in the supplied exchange configuration details and sets params
func (b *Binance) Setup(exch config.ExchangeConfig) {
if !exch.Enabled {
b.SetEnabled(false)
} else {
b.Enabled = true
b.AuthenticatedAPISupport = exch.AuthenticatedAPISupport
b.SetAPIKeys(exch.APIKey, exch.APISecret, "", false)
b.SetHTTPClientTimeout(exch.HTTPTimeout)
b.SetHTTPClientUserAgent(exch.HTTPUserAgent)
b.RESTPollingDelay = exch.RESTPollingDelay
b.Verbose = exch.Verbose
b.BaseCurrencies = common.SplitStrings(exch.BaseCurrencies, ",")
b.AvailablePairs = common.SplitStrings(exch.AvailablePairs, ",")
b.EnabledPairs = common.SplitStrings(exch.EnabledPairs, ",")
err := b.SetCurrencyPairFormat()
if err != nil {
log.Fatal(err)
}
err = b.SetAssetTypes()
if err != nil {
log.Fatal(err)
}
err = b.SetAutoPairDefaults()
if err != nil {
log.Fatal(err)
}
err = b.SetAPIURL(exch)
if err != nil {
log.Fatal(err)
}
err = b.SetClientProxyAddress(exch.ProxyAddress)
if err != nil {
log.Fatal(err)
}
err = b.WebsocketSetup(b.WSConnect,
exch.Name,
exch.Websocket,
binanceDefaultWebsocketURL,
exch.WebsocketURL)
if err != nil {
log.Fatal(err)
}
}
}
// GetExchangeValidCurrencyPairs returns the full pair list from the exchange
// at the moment do not integrate with config currency pairs automatically
func (b *Binance) GetExchangeValidCurrencyPairs() ([]string, error) {
var validCurrencyPairs []string
info, err := b.GetExchangeInfo()
if err != nil {
return nil, err
}
for _, symbol := range info.Symbols {
if symbol.Status == "TRADING" {
validCurrencyPairs = append(validCurrencyPairs, symbol.BaseAsset+"-"+symbol.QuoteAsset)
}
}
return validCurrencyPairs, nil
}
// GetExchangeInfo returns exchange information. Check binance_types for more
// information
func (b *Binance) GetExchangeInfo() (ExchangeInfo, error) {
var resp ExchangeInfo
path := b.APIUrl + exchangeInfo
return resp, b.SendHTTPRequest(path, &resp)
}
// GetOrderBook returns full orderbook information
//
// OrderBookDataRequestParams contains the following members
// symbol: string of currency pair
// limit: returned limit amount
func (b *Binance) GetOrderBook(obd OrderBookDataRequestParams) (OrderBook, error) {
orderbook, resp := OrderBook{}, OrderBookData{}
if err := b.CheckLimit(obd.Limit); err != nil {
return orderbook, err
}
if err := b.CheckSymbol(obd.Symbol); err != nil {
return orderbook, err
}
params := url.Values{}
params.Set("symbol", common.StringToUpper(obd.Symbol))
params.Set("limit", fmt.Sprintf("%d", obd.Limit))
path := fmt.Sprintf("%s%s?%s", b.APIUrl, orderBookDepth, params.Encode())
if err := b.SendHTTPRequest(path, &resp); err != nil {
return orderbook, err
}
for _, asks := range resp.Asks {
var ASK struct {
Price float64
Quantity float64
}
for i, ask := range asks.([]interface{}) {
switch i {
case 0:
ASK.Price, _ = strconv.ParseFloat(ask.(string), 64)
case 1:
ASK.Quantity, _ = strconv.ParseFloat(ask.(string), 64)
orderbook.Asks = append(orderbook.Asks, ASK)
break
}
}
}
for _, bids := range resp.Bids {
var BID struct {
Price float64
Quantity float64
}
for i, bid := range bids.([]interface{}) {
switch i {
case 0:
BID.Price, _ = strconv.ParseFloat(bid.(string), 64)
case 1:
BID.Quantity, _ = strconv.ParseFloat(bid.(string), 64)
orderbook.Bids = append(orderbook.Bids, BID)
break
}
}
}
orderbook.LastUpdateID = resp.LastUpdateID
return orderbook, nil
}
// GetRecentTrades returns recent trade activity
// limit: Up to 500 results returned
func (b *Binance) GetRecentTrades(rtr RecentTradeRequestParams) ([]RecentTrade, error) {
resp := []RecentTrade{}
params := url.Values{}
params.Set("symbol", common.StringToUpper(rtr.Symbol))
params.Set("limit", fmt.Sprintf("%d", rtr.Limit))
path := fmt.Sprintf("%s%s?%s", b.APIUrl, recentTrades, params.Encode())
return resp, b.SendHTTPRequest(path, &resp)
}
// GetHistoricalTrades returns historical trade activity
//
// symbol: string of currency pair
// limit: Optional. Default 500; max 1000.
// fromID:
func (b *Binance) GetHistoricalTrades(symbol string, limit int, fromID int64) ([]HistoricalTrade, error) {
resp := []HistoricalTrade{}
if err := b.CheckLimit(limit); err != nil {
return resp, err
}
params := url.Values{}
params.Set("symbol", common.StringToUpper(symbol))
params.Set("limit", strconv.Itoa(limit))
params.Set("fromid", strconv.FormatInt(fromID, 10))
path := fmt.Sprintf("%s%s?%s", b.APIUrl, historicalTrades, params.Encode())
return resp, b.SendHTTPRequest(path, &resp)
}
// GetAggregatedTrades returns aggregated trade activity
//
// symbol: string of currency pair
// limit: Optional. Default 500; max 1000.
func (b *Binance) GetAggregatedTrades(symbol string, limit int) ([]AggregatedTrade, error) {
resp := []AggregatedTrade{}
if err := b.CheckLimit(limit); err != nil {
return resp, err
}
if err := b.CheckSymbol(symbol); err != nil {
return resp, err
}
params := url.Values{}
params.Set("symbol", common.StringToUpper(symbol))
params.Set("limit", strconv.Itoa(limit))
path := fmt.Sprintf("%s%s?%s", b.APIUrl, aggregatedTrades, params.Encode())
return resp, b.SendHTTPRequest(path, &resp)
}
// GetSpotKline returns kline data
//
// KlinesRequestParams supports 5 parameters
// symbol: the symbol to get the kline data for
// limit: optinal
// interval: the interval time for the data
// startTime: startTime filter for kline data
// endTime: endTime filter for the kline data
func (b *Binance) GetSpotKline(arg KlinesRequestParams) ([]CandleStick, error) {
var resp interface{}
var kline []CandleStick
params := url.Values{}
params.Set("symbol", arg.Symbol)
params.Set("interval", string(arg.Interval))
if arg.Limit != 0 {
params.Set("limit", strconv.Itoa(arg.Limit))
}
if arg.StartTime != 0 {
params.Set("startTime", strconv.FormatInt(arg.StartTime, 10))
}
if arg.EndTime != 0 {
params.Set("endTime", strconv.FormatInt(arg.EndTime, 10))
}
path := fmt.Sprintf("%s%s?%s", b.APIUrl, candleStick, params.Encode())
if err := b.SendHTTPRequest(path, &resp); err != nil {
return kline, err
}
for _, responseData := range resp.([]interface{}) {
var candle CandleStick
for i, individualData := range responseData.([]interface{}) {
switch i {
case 0:
candle.OpenTime = individualData.(float64)
case 1:
candle.Open, _ = strconv.ParseFloat(individualData.(string), 64)
case 2:
candle.High, _ = strconv.ParseFloat(individualData.(string), 64)
case 3:
candle.Low, _ = strconv.ParseFloat(individualData.(string), 64)
case 4:
candle.Close, _ = strconv.ParseFloat(individualData.(string), 64)
case 5:
candle.Volume, _ = strconv.ParseFloat(individualData.(string), 64)
case 6:
candle.CloseTime = individualData.(float64)
case 7:
candle.QuoteAssetVolume, _ = strconv.ParseFloat(individualData.(string), 64)
case 8:
candle.TradeCount = individualData.(float64)
case 9:
candle.TakerBuyAssetVolume, _ = strconv.ParseFloat(individualData.(string), 64)
case 10:
candle.TakerBuyQuoteAssetVolume, _ = strconv.ParseFloat(individualData.(string), 64)
}
}
kline = append(kline, candle)
}
return kline, nil
}
// GetAveragePrice returns current average price for a symbol.
//
// symbol: string of currency pair
func (b *Binance) GetAveragePrice(symbol string) (AveragePrice, error) {
resp := AveragePrice{}
if err := b.CheckSymbol(symbol); err != nil {
return resp, err
}
params := url.Values{}
params.Set("symbol", common.StringToUpper(symbol))
path := fmt.Sprintf("%s%s?%s", b.APIUrl, averagePrice, params.Encode())
return resp, b.SendHTTPRequest(path, &resp)
}
// GetPriceChangeStats returns price change statistics for the last 24 hours
//
// symbol: string of currency pair
func (b *Binance) GetPriceChangeStats(symbol string) (PriceChangeStats, error) {
resp := PriceChangeStats{}
if err := b.CheckSymbol(symbol); err != nil {
return resp, err
}
params := url.Values{}
params.Set("symbol", common.StringToUpper(symbol))
path := fmt.Sprintf("%s%s?%s", b.APIUrl, priceChange, params.Encode())
return resp, b.SendHTTPRequest(path, &resp)
}
// GetTickers returns the ticker data for the last 24 hrs
func (b *Binance) GetTickers() ([]PriceChangeStats, error) {
var resp []PriceChangeStats
path := fmt.Sprintf("%s%s", b.APIUrl, priceChange)
return resp, b.SendHTTPRequest(path, &resp)
}
// GetLatestSpotPrice returns latest spot price of symbol
//
// symbol: string of currency pair
func (b *Binance) GetLatestSpotPrice(symbol string) (SymbolPrice, error) {
resp := SymbolPrice{}
if err := b.CheckSymbol(symbol); err != nil {
return resp, err
}
params := url.Values{}
params.Set("symbol", common.StringToUpper(symbol))
path := fmt.Sprintf("%s%s?%s", b.APIUrl, symbolPrice, params.Encode())
return resp, b.SendHTTPRequest(path, &resp)
}
// GetBestPrice returns the latest best price for symbol
//
// symbol: string of currency pair
func (b *Binance) GetBestPrice(symbol string) (BestPrice, error) {
resp := BestPrice{}
if err := b.CheckSymbol(symbol); err != nil {
return resp, err
}
params := url.Values{}
params.Set("symbol", common.StringToUpper(symbol))
path := fmt.Sprintf("%s%s?%s", b.APIUrl, bestPrice, params.Encode())
return resp, b.SendHTTPRequest(path, &resp)
}
// NewOrder sends a new order to Binance
func (b *Binance) NewOrder(o NewOrderRequest) (NewOrderResponse, error) {
var resp NewOrderResponse
path := fmt.Sprintf("%s%s", b.APIUrl, newOrder)
params := url.Values{}
params.Set("symbol", o.Symbol)
params.Set("side", string(o.Side))
params.Set("type", string(o.TradeType))
params.Set("quantity", strconv.FormatFloat(o.Quantity, 'f', -1, 64))
if o.TradeType == "LIMIT" {
params.Set("price", strconv.FormatFloat(o.Price, 'f', -1, 64))
}
if o.TimeInForce != "" {
params.Set("timeInForce", string(o.TimeInForce))
}
if o.NewClientOrderID != "" {
params.Set("newClientOrderID", o.NewClientOrderID)
}
if o.StopPrice != 0 {
params.Set("stopPrice", strconv.FormatFloat(o.StopPrice, 'f', -1, 64))
}
if o.IcebergQty != 0 {
params.Set("icebergQty", strconv.FormatFloat(o.IcebergQty, 'f', -1, 64))
}
if o.NewOrderRespType != "" {
params.Set("newOrderRespType", o.NewOrderRespType)
}
if err := b.SendAuthHTTPRequest("POST", path, params, &resp); err != nil {
return resp, err
}
if resp.Code != 0 {
return resp, errors.New(resp.Msg)
}
return resp, nil
}
// CancelExistingOrder sends a cancel order to Binance
func (b *Binance) CancelExistingOrder(symbol string, orderID int64, origClientOrderID string) (CancelOrderResponse, error) {
var resp CancelOrderResponse
path := fmt.Sprintf("%s%s", b.APIUrl, cancelOrder)
params := url.Values{}
params.Set("symbol", symbol)
if orderID != 0 {
params.Set("orderId", strconv.FormatInt(orderID, 10))
}
if origClientOrderID != "" {
params.Set("origClientOrderId", origClientOrderID)
}
return resp, b.SendAuthHTTPRequest("DELETE", path, params, &resp)
}
// OpenOrders Current open orders
// Get all open orders on a symbol. Careful when accessing this with no symbol.
func (b *Binance) OpenOrders(symbol string) ([]QueryOrderData, error) {
var resp []QueryOrderData
path := fmt.Sprintf("%s%s", b.APIUrl, openOrders)
params := url.Values{}
if symbol != "" {
params.Set("symbol", common.StringToUpper(symbol))
}
if err := b.SendAuthHTTPRequest("GET", path, params, &resp); err != nil {
return resp, err
}
return resp, nil
}
// AllOrders Get all account orders; active, canceled, or filled.
// orderId optional param
// limit optional param, default 500; max 500
func (b *Binance) AllOrders(symbol, orderID, limit string) ([]QueryOrderData, error) {
var resp []QueryOrderData
path := fmt.Sprintf("%s%s", b.APIUrl, allOrders)
params := url.Values{}
params.Set("symbol", common.StringToUpper(symbol))
if orderID != "" {
params.Set("orderId", orderID)
}
if limit != "" {
params.Set("limit", limit)
}
if err := b.SendAuthHTTPRequest("GET", path, params, &resp); err != nil {
return resp, err
}
return resp, nil
}
// QueryOrder returns information on a past order
func (b *Binance) QueryOrder(symbol, origClientOrderID string, orderID int64) (QueryOrderData, error) {
var resp QueryOrderData
path := fmt.Sprintf("%s%s", b.APIUrl, queryOrder)
params := url.Values{}
params.Set("symbol", common.StringToUpper(symbol))
if origClientOrderID != "" {
params.Set("origClientOrderId", origClientOrderID)
}
if orderID != 0 {
params.Set("orderId", strconv.FormatInt(orderID, 10))
}
if err := b.SendAuthHTTPRequest("GET", path, params, &resp); err != nil {
return resp, err
}
if resp.Code != 0 {
return resp, errors.New(resp.Msg)
}
return resp, nil
}
// GetAccount returns binance user accounts
func (b *Binance) GetAccount() (*Account, error) {
type response struct {
Response
Account
}
var resp response
path := fmt.Sprintf("%s%s", b.APIUrl, accountInfo)
params := url.Values{}
if err := b.SendAuthHTTPRequest("GET", path, params, &resp); err != nil {
return &resp.Account, err
}
if resp.Code != 0 {
return &resp.Account, errors.New(resp.Msg)
}
return &resp.Account, nil
}
// SendHTTPRequest sends an unauthenticated request
func (b *Binance) SendHTTPRequest(path string, result interface{}) error {
return b.SendPayload("GET", path, nil, nil, result, false, b.Verbose)
}
// SendAuthHTTPRequest sends an authenticated HTTP request
func (b *Binance) SendAuthHTTPRequest(method, path string, params url.Values, result interface{}) error {
if !b.AuthenticatedAPISupport {
return fmt.Errorf(exchange.WarningAuthenticatedRequestWithoutCredentialsSet, b.Name)
}
if params == nil {
params = url.Values{}
}
params.Set("recvWindow", strconv.FormatInt(common.RecvWindow(5*time.Second), 10))
params.Set("timestamp", strconv.FormatInt(time.Now().Unix()*1000, 10))
signature := params.Encode()
hmacSigned := common.GetHMAC(common.HashSHA256, []byte(signature), []byte(b.APISecret))
hmacSignedStr := common.HexEncodeToString(hmacSigned)
params.Set("signature", hmacSignedStr)
headers := make(map[string]string)
headers["X-MBX-APIKEY"] = b.APIKey
if b.Verbose {
log.Printf("sent path: \n%s\n", path)
}
path = common.EncodeURLValues(path, params)
return b.SendPayload(method, path, headers, bytes.NewBufferString(""), result, true, b.Verbose)
}
// CheckLimit checks value against a variable list
func (b *Binance) CheckLimit(limit int) error {
for x := range b.validLimits {
if b.validLimits[x] == limit {
return nil
}
}
return errors.New("Incorrect limit values - valid values are 5, 10, 20, 50, 100, 500, 1000")
}
// CheckSymbol checks value against a variable list
func (b *Binance) CheckSymbol(symbol string) error {
enPairs := b.GetAvailableCurrencies()
for x := range enPairs {
if exchange.FormatExchangeCurrency(b.Name, enPairs[x]).String() == symbol {
return nil
}
}
return errors.New("Incorrect symbol values - please check available pairs in configuration")
}
// CheckIntervals checks value against a variable list
func (b *Binance) CheckIntervals(interval string) error {
for x := range b.validIntervals {
if TimeInterval(interval) == b.validIntervals[x] {
return nil
}
}
return errors.New(`Incorrect interval values - valid values are "1m","3m","5m","15m","30m","1h","2h","4h","6h","8h","12h","1d","3d","1w","1M"`)
}
// SetValues sets the default valid values
func (b *Binance) SetValues() {
b.validLimits = []int{5, 10, 20, 50, 100, 500, 1000}
b.validIntervals = []TimeInterval{
TimeIntervalMinute,
TimeIntervalThreeMinutes,
TimeIntervalFiveMinutes,
TimeIntervalFifteenMinutes,
TimeIntervalThirtyMinutes,
TimeIntervalHour,
TimeIntervalTwoHours,
TimeIntervalFourHours,
TimeIntervalSixHours,
TimeIntervalEightHours,
TimeIntervalTwelveHours,
TimeIntervalDay,
TimeIntervalThreeDays,
TimeIntervalWeek,
TimeIntervalMonth,
}
}
// GetFee returns an estimate of fee based on type of transaction
func (b *Binance) GetFee(feeBuilder exchange.FeeBuilder) (float64, error) {
var fee float64
switch feeBuilder.FeeType {
case exchange.CryptocurrencyTradeFee:
multiplier, err := b.getMultiplier(feeBuilder.IsMaker)
if err != nil {
return 0, err
}
fee = calculateTradingFee(feeBuilder.PurchasePrice, feeBuilder.Amount, multiplier)
case exchange.CryptocurrencyWithdrawalFee:
fee = getCryptocurrencyWithdrawalFee(feeBuilder.FirstCurrency, feeBuilder.PurchasePrice, feeBuilder.Amount)
}
if fee < 0 {
fee = 0
}
return fee, nil
}
// getMultiplier retrieves account based taker/maker fees
func (b *Binance) getMultiplier(isMaker bool) (float64, error) {
var multiplier float64
account, err := b.GetAccount()
if err != nil {
return 0, err
}
if isMaker {
multiplier = float64(account.MakerCommission)
} else {
multiplier = float64(account.TakerCommission)
}
return multiplier, nil
}
// calculateTradingFee returns the fee for trading any currency on Bittrex
func calculateTradingFee(purchasePrice, amount, multiplier float64) float64 {
return (multiplier / 100) * purchasePrice * amount
}
// getCryptocurrencyWithdrawalFee returns the fee for withdrawing from the exchange
func getCryptocurrencyWithdrawalFee(currency string, purchasePrice, amount float64) float64 {
return WithdrawalFees[currency]
}
// WithdrawCrypto sends cryptocurrency to the address of your choosing
func (b *Binance) WithdrawCrypto(asset, address, addressTag, name, amount string) (int64, error) {
var resp WithdrawResponse
path := fmt.Sprintf("%s%s", b.APIUrl, withdraw)
params := url.Values{}
params.Set("asset", asset)
params.Set("address", string(address))
params.Set("amount", string(amount))
if len(name) > 0 {
params.Set("name", string(name))
}
if len(addressTag) > 0 {
params.Set("addressTag", string(addressTag))
}
if err := b.SendAuthHTTPRequest("POST", path, params, &resp); err != nil {
return -1, err
}
if !resp.Success {
return resp.ID, errors.New(resp.Msg)
}
return resp.ID, nil
}
//GetDepositAddressForCurrency retrieves the wallet address for a given currency
func (b *Binance) GetDepositAddressForCurrency(currency string) error {
path := fmt.Sprintf("%s%s", b.APIUrl, depositAddress)
var resp interface{}
params := url.Values{}
params.Set("asset", currency)
if err := b.SendAuthHTTPRequest("GET", path, params, &resp); err != nil {
return err
}
return nil
}