GetAccountInfo wrapper update (#220)

* Added untested [cloudflare issue] changes to accountinfo for ANX

* Add alphapoint comment for future implementation

* Adds GetAccountInfo for Binance

* Adds GetAccountInfo update for Bithumb

* Updates GetAccountInfo for GateIO.
Adds error handling feature for authenticated requests.

* Updates GetAccountInfo function for Huobi.
Adds function for getting account ID.

* Updates GetAccountInfo function
Adds GetAccountID function

* Updates GetAccountInfo [un-tested, no access to keys at this time]

* Updates GetAccountInfo for Kraken

* Updates GetAccountInfo func for OKEX

* Updates GetAccountInfo for exchange ZB

* Updates GetAccountInfo func for Bitmex

* Updates GetAccountInfo func for Coinut

* Updates GetAccountInfo for ANX exchange

* Fixes incorrect hold currency issue

* Fixes type name

* Fixes issue with unneeded code in wrapper for Bithumb

* Change strings to type symbol string

* Fixes nit for Gateio

* Fixes GetAccountInfo issue
Fixes SpotCancelOrder issue
This commit is contained in:
Ryan O'Hara-Reid
2018-12-13 16:53:19 +11:00
committed by Adrian Gallagher
parent 05f9f40723
commit 4ca3fd5b00
40 changed files with 981 additions and 143 deletions

View File

@@ -1510,6 +1510,8 @@ const (
UAH = "UAH" // Ukrainian hryvnia
JPY = "JPY" // Japanese yen
ZJPY = "ZJPY" // Japanese yen, but with a Z in front of it
LCH = "LCH"
MYR = "MYR"
)
// symbols map holds the currency name and symbol mappings

View File

@@ -95,7 +95,8 @@ func (a *Alphapoint) GetOrderbookEx(p pair.CurrencyPair, assetType string) (orde
// withdrawals
func (a *Alphapoint) GetFundingHistory() ([]exchange.FundHistory, error) {
var fundHistory []exchange.FundHistory
return fundHistory, common.ErrFunctionNotSupported
// https://alphapoint.github.io/slate/#generatetreasuryactivityreport
return fundHistory, common.ErrNotYetImplemented
}
// GetExchangeHistory returns historic trade data since exchange opening.

View File

@@ -406,7 +406,6 @@ func (a *ANX) SendAuthenticatedHTTPRequest(path string, params map[string]interf
}
PayloadJSON, err := common.JSONEncode(request)
if err != nil {
return errors.New("SendAuthenticatedHTTPRequest: Unable to JSON request")
}
@@ -471,7 +470,7 @@ func getInternationalBankWithdrawalFee(currency string, amount float64) float64
// GetAccountInformation retrieves details including API permissions
func (a *ANX) GetAccountInformation() (AccountInformation, error) {
var response AccountInformation
err := a.SendAuthenticatedHTTPRequest(anxOrderInfo, nil, &response)
err := a.SendAuthenticatedHTTPRequest(anxAccount, nil, &response)
if err != nil {
return response, err
}

View File

@@ -283,3 +283,17 @@ func TestCancelExchangeOrder(t *testing.T) {
t.Errorf("Test Failed - ANX CancelOrder() error: %s", err)
}
}
func TestGetAccountInfo(t *testing.T) {
if testAPIKey != "" || testAPISecret != "" {
_, err := a.GetAccountInfo()
if err != nil {
t.Error("test failed - GetAccountInfo() error:", err)
}
} else {
_, err := a.GetAccountInfo()
if err == nil {
t.Error("test failed - GetAccountInfo() error")
}
}
}

View File

@@ -63,12 +63,12 @@ type AccountInformation struct {
UserUUID string `json:"userUuid"`
Rights []string `json:"Rights"`
ResultCode string `json:"resultCode"`
Wallets struct {
Wallets map[string]struct {
Balance Amount `json:"Balance"`
AvailableBalance Amount `json:"Available_Balance"`
DailyWithdrawalLimit Amount `json:"Daily_Withdrawal_Limit"`
MaxWithdraw Amount `json:"Max_Withdraw"`
}
} `json:"Wallets"`
}
// Amount basic storage of wallet details

View File

@@ -162,11 +162,17 @@ func (a *ANX) UpdateOrderbook(p pair.CurrencyPair, assetType string) (orderbook.
}
for x := range orderbookNew.Data.Asks {
orderBook.Asks = append(orderBook.Asks, orderbook.Item{Price: orderbookNew.Data.Asks[x].Price, Amount: orderbookNew.Data.Asks[x].Amount})
orderBook.Asks = append(orderBook.Asks,
orderbook.Item{
Price: orderbookNew.Data.Asks[x].Price,
Amount: orderbookNew.Data.Asks[x].Amount})
}
for x := range orderbookNew.Data.Bids {
orderBook.Bids = append(orderBook.Bids, orderbook.Item{Price: orderbookNew.Data.Bids[x].Price, Amount: orderbookNew.Data.Bids[x].Amount})
orderBook.Bids = append(orderBook.Bids,
orderbook.Item{
Price: orderbookNew.Data.Bids[x].Price,
Amount: orderbookNew.Data.Bids[x].Amount})
}
orderbook.ProcessOrderbook(a.GetName(), p, orderBook, assetType)
@@ -177,7 +183,25 @@ func (a *ANX) UpdateOrderbook(p pair.CurrencyPair, assetType string) (orderbook.
// exchange
func (a *ANX) GetAccountInfo() (exchange.AccountInfo, error) {
var info exchange.AccountInfo
return info, common.ErrNotYetImplemented
raw, err := a.GetAccountInformation()
if err != nil {
return info, err
}
var balance []exchange.AccountCurrencyInfo
for currency, info := range raw.Wallets {
balance = append(balance, exchange.AccountCurrencyInfo{
CurrencyName: currency,
TotalValue: info.AvailableBalance.Value,
Hold: info.Balance.Value,
})
}
info.ExchangeName = a.GetName()
info.Currencies = balance
return info, nil
}
// GetFundingHistory returns funding history, deposits and
@@ -209,7 +233,17 @@ func (a *ANX) SubmitOrder(p pair.CurrencyPair, side exchange.OrderSide, orderTyp
limitPriceInSettlementCurrency = price
}
response, err := a.NewOrder(orderType.ToString(), isBuying, p.FirstCurrency.String(), amount, p.SecondCurrency.String(), amount, limitPriceInSettlementCurrency, false, "", false)
response, err := a.NewOrder(orderType.ToString(),
isBuying,
p.FirstCurrency.String(),
amount,
p.SecondCurrency.String(),
amount,
limitPriceInSettlementCurrency,
false,
"",
false)
if response != "" {
submitOrderResponse.OrderID = response
}

View File

@@ -166,7 +166,7 @@ func TestCancelExistingOrder(t *testing.T) {
}
_, err := b.CancelExistingOrder("BTCUSDT", 82584683, "")
if err == nil {
if err != nil {
t.Error("Test Failed - Binance CancelExistingOrder() error", err)
}
}
@@ -179,7 +179,7 @@ func TestQueryOrder(t *testing.T) {
}
_, err := b.QueryOrder("BTCUSDT", "", 1337)
if err != nil {
if err == nil {
t.Error("Test Failed - Binance QueryOrder() error", err)
}
}
@@ -386,8 +386,19 @@ func TestCancelExchangeOrder(t *testing.T) {
// Act
err := b.CancelOrder(orderCancellation)
// Assert
// Assert
if err != nil {
t.Errorf("Could not cancel order: %s", err)
}
}
func TestGetAccountInfo(t *testing.T) {
if testAPIKey == "" || testAPISecret == "" {
t.Skip()
}
_, err := b.GetAccountInfo()
if err != nil {
t.Error("test failed - GetAccountInfo() error:", err)
}
}

View File

@@ -36,7 +36,8 @@ func (b *Binance) Run() {
log.Printf("%s Failed to get exchange info.\n", b.GetName())
} else {
forceUpgrade := false
if !common.StringDataContains(b.EnabledPairs, "-") || !common.StringDataContains(b.AvailablePairs, "-") {
if !common.StringDataContains(b.EnabledPairs, "-") ||
!common.StringDataContains(b.AvailablePairs, "-") {
forceUpgrade = true
}
@@ -110,11 +111,13 @@ func (b *Binance) UpdateOrderbook(p pair.CurrencyPair, assetType string) (orderb
}
for _, bids := range orderbookNew.Bids {
orderBook.Bids = append(orderBook.Bids, orderbook.Item{Amount: bids.Quantity, Price: bids.Price})
orderBook.Bids = append(orderBook.Bids,
orderbook.Item{Amount: bids.Quantity, Price: bids.Price})
}
for _, asks := range orderbookNew.Asks {
orderBook.Asks = append(orderBook.Asks, orderbook.Item{Amount: asks.Quantity, Price: asks.Price})
orderBook.Asks = append(orderBook.Asks,
orderbook.Item{Amount: asks.Quantity, Price: asks.Price})
}
orderbook.ProcessOrderbook(b.GetName(), p, orderBook, assetType)
@@ -124,8 +127,35 @@ func (b *Binance) UpdateOrderbook(p pair.CurrencyPair, assetType string) (orderb
// GetAccountInfo retrieves balances for all enabled currencies for the
// Bithumb exchange
func (b *Binance) GetAccountInfo() (exchange.AccountInfo, error) {
var response exchange.AccountInfo
return response, common.ErrNotYetImplemented
var info exchange.AccountInfo
raw, err := b.GetAccount()
if err != nil {
return info, err
}
var currencyBalance []exchange.AccountCurrencyInfo
for _, balance := range raw.Balances {
freeCurrency, err := strconv.ParseFloat(balance.Free, 64)
if err != nil {
return info, err
}
lockedCurrency, err := strconv.ParseFloat(balance.Locked, 64)
if err != nil {
return info, err
}
currencyBalance = append(currencyBalance, exchange.AccountCurrencyInfo{
CurrencyName: balance.Asset,
TotalValue: freeCurrency + lockedCurrency,
Hold: freeCurrency,
})
}
info.ExchangeName = b.GetName()
info.Currencies = currencyBalance
return info, nil
}
// GetFundingHistory returns funding history, deposits and

View File

@@ -238,11 +238,16 @@ func (b *Bithumb) GetTransactionHistory(symbol string) (TransactionHistory, erro
return response, nil
}
// GetAccountInformation returns account information
func (b *Bithumb) GetAccountInformation() (Account, error) {
// GetAccountInformation returns account information by singular currency
func (b *Bithumb) GetAccountInformation(currency string) (Account, error) {
response := Account{}
err := b.SendAuthenticatedHTTPRequest(privateAccInfo, nil, &response)
val := url.Values{}
if currency != "" {
val.Set("currency", currency)
}
err := b.SendAuthenticatedHTTPRequest(privateAccInfo, val, &response)
if err != nil {
return response, err
}
@@ -254,18 +259,68 @@ func (b *Bithumb) GetAccountInformation() (Account, error) {
}
// GetAccountBalance returns customer wallet information
func (b *Bithumb) GetAccountBalance() (Balance, error) {
response := Balance{}
func (b *Bithumb) GetAccountBalance(c string) (FullBalance, error) {
var response Balance
var fullBalance = FullBalance{
make(map[string]float64),
make(map[string]float64),
make(map[string]float64),
make(map[string]float64),
make(map[string]float64),
}
err := b.SendAuthenticatedHTTPRequest(privateAccBalance, nil, &response)
vals := url.Values{}
if c != "" {
vals.Set("currency", c)
}
err := b.SendAuthenticatedHTTPRequest(privateAccBalance, vals, &response)
if err != nil {
return response, err
return fullBalance, err
}
if response.Status != noError {
return response, errors.New(response.Message)
return fullBalance, errors.New(response.Message)
}
return response, nil
// Added due to increasing of the usuable currencies on exchange, usually
// without notificatation, so we dont need to update structs later on
for tag, datum := range response.Data {
splitTag := common.SplitStrings(tag, "_")
c := splitTag[len(splitTag)-1]
var val float64
if reflect.TypeOf(datum).String() != "float64" {
val, err = strconv.ParseFloat(datum.(string), 64)
if err != nil {
return fullBalance, err
}
} else {
val = datum.(float64)
}
switch splitTag[0] {
case "available":
fullBalance.Available[c] = val
case "in":
fullBalance.InUse[c] = val
case "total":
fullBalance.Total[c] = val
case "misu":
fullBalance.Misu[c] = val
case "xcoin":
fullBalance.Xcoin[c] = val
default:
return fullBalance, fmt.Errorf("GetAccountBalance error tag name %s unhandled",
splitTag)
}
}
return fullBalance, nil
}
// GetWalletAddress returns customer wallet address

View File

@@ -77,23 +77,23 @@ func TestGetTransactionHistory(t *testing.T) {
}
}
func TestGetAccountInfo(t *testing.T) {
t.Parallel()
_, err := b.GetAccountInfo()
if err == nil {
t.Error("test failed - Bithumb GetAccountInfo() error", err)
}
}
func TestGetAccountBalance(t *testing.T) {
t.Parallel()
_, err := b.GetAccountBalance()
if testAPIKey == "" || testAPISecret == "" {
t.Skip()
}
_, err := b.GetAccountBalance("BTC")
if err == nil {
t.Error("test failed - Bithumb GetAccountBalance() error", err)
}
}
func TestGetWalletAddress(t *testing.T) {
if testAPIKey == "" || testAPISecret == "" {
t.Skip()
}
t.Parallel()
_, err := b.GetWalletAddress("")
if err == nil {
@@ -159,6 +159,9 @@ func TestWithdrawCrypto(t *testing.T) {
func TestRequestKRWDepositDetails(t *testing.T) {
t.Parallel()
if testAPIKey == "" || testAPISecret == "" {
t.Skip()
}
_, err := b.RequestKRWDepositDetails()
if err == nil {
t.Error("test failed - Bithumb RequestKRWDepositDetails() error", err)
@@ -341,3 +344,18 @@ func TestCancelExchangeOrder(t *testing.T) {
t.Errorf("Could not cancel order: %s", err)
}
}
func TestGetAccountInfo(t *testing.T) {
t.Parallel()
if testAPIKey != "" || testAPISecret != "" {
_, err := b.GetAccountInfo()
if err != nil {
t.Error("test failed - Bithumb GetAccountInfo() error", err)
}
} else {
_, err := b.GetAccountInfo()
if err == nil {
t.Error("test failed - Bithumb GetAccountInfo() error")
}
}
}

View File

@@ -79,19 +79,9 @@ type Account struct {
// Balance holds balance details
type Balance struct {
Status string `json:"status"`
Data struct {
TotalBTC float64 `json:"total_btc,string"`
TotalKRW float64 `json:"total_krw"`
InUseBTC float64 `json:"in_use_btc,string"`
InUseKRW float64 `json:"in_use_krw"`
AvailableBTC float64 `json:"available_btc,string"`
AvailableKRW float64 `json:"available_krw"`
MisuKRW float64 `json:"misu_krw"`
MisuBTC float64 `json:"misu_btc,string"`
XcoinLast float64 `json:"xcoin_last,string"`
} `json:"data"`
Message string `json:"message"`
Status string `json:"status"`
Data map[string]interface{} `json:"data"`
Message string `json:"message"`
}
// WalletAddressRes contains wallet address information
@@ -278,3 +268,12 @@ var WithdrawalFees = map[string]float64{
symbol.ENJ: 35,
symbol.PST: 30,
}
// FullBalance defines a return type with full balance data
type FullBalance struct {
InUse map[string]float64
Misu map[string]float64
Total map[string]float64
Xcoin map[string]float64
Available map[string]float64
}

View File

@@ -1,7 +1,6 @@
package bithumb
import (
"errors"
"fmt"
"log"
"sync"
@@ -122,8 +121,30 @@ func (b *Bithumb) UpdateOrderbook(p pair.CurrencyPair, assetType string) (orderb
// GetAccountInfo retrieves balances for all enabled currencies for the
// Bithumb exchange
func (b *Bithumb) GetAccountInfo() (exchange.AccountInfo, error) {
var response exchange.AccountInfo
return response, errors.New("not implemented")
var info exchange.AccountInfo
bal, err := b.GetAccountBalance("ALL")
if err != nil {
return info, err
}
var exchangeBalances []exchange.AccountCurrencyInfo
for key, totalAmount := range bal.Total {
hold, ok := bal.InUse[key]
if !ok {
return info, fmt.Errorf("GetAccountInfo error - in use item not found for currency %s",
key)
}
exchangeBalances = append(exchangeBalances, exchange.AccountCurrencyInfo{
CurrencyName: key,
TotalValue: totalAmount,
Hold: hold,
})
}
info.Currencies = exchangeBalances
info.ExchangeName = b.GetName()
return info, nil
}
// GetFundingHistory returns funding history, deposits and

View File

@@ -744,6 +744,16 @@ func (b *Bitmex) GetUserMargin(currency string) (UserMargin, error) {
&info)
}
// GetAllUserMargin returns user margin information
func (b *Bitmex) GetAllUserMargin() ([]UserMargin, error) {
var info []UserMargin
return info, b.SendAuthenticatedHTTPRequest("GET",
bitmexEndpointUserMargin,
UserCurrencyParams{Currency: "all"},
&info)
}
// GetMinimumWithdrawalFee returns minimum withdrawal fee information
func (b *Bitmex) GetMinimumWithdrawalFee(currency string) (MinWithdrawalFee, error) {
var fee MinWithdrawalFee

View File

@@ -521,3 +521,17 @@ func TestCancelExchangeOrder(t *testing.T) {
t.Errorf("Could not cancel order: %s", err)
}
}
func TestGetAccountInfo(t *testing.T) {
if testAPIKey != "" || testAPISecret != "" {
_, err := b.GetAccountInfo()
if err != nil {
t.Error("Test Failed - GetAccountInfo() error", err)
}
} else {
_, err := b.GetAccountInfo()
if err == nil {
t.Error("Test Failed - GetAccountInfo() error")
}
}
}

View File

@@ -125,8 +125,25 @@ func (b *Bitmex) UpdateOrderbook(p pair.CurrencyPair, assetType string) (orderbo
// GetAccountInfo retrieves balances for all enabled currencies for the
// Bitmex exchange
func (b *Bitmex) GetAccountInfo() (exchange.AccountInfo, error) {
var response exchange.AccountInfo
return response, common.ErrNotYetImplemented
var info exchange.AccountInfo
bal, err := b.GetAllUserMargin()
if err != nil {
return info, err
}
// Need to update to add Margin/Liquidity availibilty
var balances []exchange.AccountCurrencyInfo
for _, data := range bal {
balances = append(balances, exchange.AccountCurrencyInfo{
CurrencyName: data.Currency,
TotalValue: float64(data.WalletBalance),
})
}
info.ExchangeName = b.GetName()
info.Currencies = balances
return info, nil
}
// GetFundingHistory returns funding history, deposits and

View File

@@ -15,7 +15,7 @@ var c COINUT
// Please supply your own keys here to do better tests
const (
apiKey = ""
apiSecret = ""
clientID = ""
canManipulateRealOrders = false
)
@@ -31,7 +31,8 @@ func TestSetup(t *testing.T) {
t.Error("Test Failed - Coinut Setup() init error")
}
bConfig.AuthenticatedAPISupport = true
bConfig.APISecret = apiSecret
bConfig.APIKey = apiKey
bConfig.ClientID = clientID
bConfig.Verbose = true
c.Setup(bConfig)
@@ -250,3 +251,17 @@ func TestCancelExchangeOrder(t *testing.T) {
t.Errorf("Could not cancel order: %s", err)
}
}
func TestGetAccountInfo(t *testing.T) {
if apiKey != "" || clientID != "" {
_, err := c.GetAccountInfo()
if err != nil {
t.Error("Test Failed - GetAccountInfo() error", err)
}
} else {
_, err := c.GetAccountInfo()
if err == nil {
t.Error("Test Failed - GetAccountInfo() error")
}
}
}

View File

@@ -68,16 +68,24 @@ type Trades struct {
// UserBalance holds user balances on the exchange
type UserBalance struct {
BTC float64 `json:"btc,string"`
ETC float64 `json:"etc,string"`
ETH float64 `json:"eth,string"`
LTC float64 `json:"ltc,string"`
Equity float64 `json:"equity,string,string"`
InitialMargin float64 `json:"initial_margin,string"`
MaintenanceMargin float64 `json:"maintenance_margin,string"`
RealizedPL float64 `json:"realized_pl,string"`
TransID int64 `json:"trans_id"`
UnrealizedPL float64 `json:"unrealized_pl,string"`
BCH float64 `json:"BCH,string"`
BTC float64 `json:"BTC,string"`
BTG float64 `json:"BTG,string"`
CAD float64 `json:"CAD,string"`
ETC float64 `json:"ETC,string"`
ETH float64 `json:"ETH,string"`
LCH float64 `json:"LCH,string"`
LTC float64 `json:"LTC,string"`
MYR float64 `json:"MYR,string"`
SGD float64 `json:"SGD,string"`
USD float64 `json:"USD,string"`
USDT float64 `json:"USDT,string"`
XMR float64 `json:"XMR,string"`
ZEC float64 `json:"ZEC,string"`
Nonce int64 `json:"nonce"`
Reply string `json:"reply"`
Status []string `json:"status"`
TransID int64 `json:"trans_id"`
}
// Order holds order information

View File

@@ -7,6 +7,8 @@ import (
"strconv"
"sync"
"github.com/thrasher-/gocryptotrader/currency/symbol"
"github.com/thrasher-/gocryptotrader/common"
"github.com/thrasher-/gocryptotrader/currency/pair"
"github.com/thrasher-/gocryptotrader/exchanges"
@@ -53,23 +55,86 @@ func (c *COINUT) Run() {
// GetAccountInfo retrieves balances for all enabled currencies for the
// COINUT exchange
func (c *COINUT) GetAccountInfo() (exchange.AccountInfo, error) {
var response exchange.AccountInfo
/*
response.ExchangeName = e.GetName()
accountBalance, err := e.GetAccounts()
if err != nil {
return response, err
}
for i := 0; i < len(accountBalance); i++ {
var exchangeCurrency exchange.AccountCurrencyInfo
exchangeCurrency.CurrencyName = accountBalance[i].Currency
exchangeCurrency.TotalValue = accountBalance[i].Available
exchangeCurrency.Hold = accountBalance[i].Hold
var info exchange.AccountInfo
bal, err := c.GetUserBalance()
if err != nil {
return info, err
}
response.Currencies = append(response.Currencies, exchangeCurrency)
}
*/
return response, nil
var balances []exchange.AccountCurrencyInfo
balances = append(balances, exchange.AccountCurrencyInfo{
CurrencyName: symbol.BCH,
TotalValue: bal.BCH,
})
balances = append(balances, exchange.AccountCurrencyInfo{
CurrencyName: symbol.BTC,
TotalValue: bal.BTC,
})
balances = append(balances, exchange.AccountCurrencyInfo{
CurrencyName: symbol.BTG,
TotalValue: bal.BTG,
})
balances = append(balances, exchange.AccountCurrencyInfo{
CurrencyName: symbol.CAD,
TotalValue: bal.CAD,
})
balances = append(balances, exchange.AccountCurrencyInfo{
CurrencyName: symbol.ETC,
TotalValue: bal.ETC,
})
balances = append(balances, exchange.AccountCurrencyInfo{
CurrencyName: symbol.ETH,
TotalValue: bal.ETH,
})
balances = append(balances, exchange.AccountCurrencyInfo{
CurrencyName: symbol.LCH,
TotalValue: bal.LCH,
})
balances = append(balances, exchange.AccountCurrencyInfo{
CurrencyName: symbol.LTC,
TotalValue: bal.LTC,
})
balances = append(balances, exchange.AccountCurrencyInfo{
CurrencyName: symbol.MYR,
TotalValue: bal.MYR,
})
balances = append(balances, exchange.AccountCurrencyInfo{
CurrencyName: symbol.SGD,
TotalValue: bal.SGD,
})
balances = append(balances, exchange.AccountCurrencyInfo{
CurrencyName: symbol.USD,
TotalValue: bal.USD,
})
balances = append(balances, exchange.AccountCurrencyInfo{
CurrencyName: symbol.USDT,
TotalValue: bal.USDT,
})
balances = append(balances, exchange.AccountCurrencyInfo{
CurrencyName: symbol.XMR,
TotalValue: bal.XMR,
})
balances = append(balances, exchange.AccountCurrencyInfo{
CurrencyName: symbol.ZEC,
TotalValue: bal.ZEC,
})
info.ExchangeName = c.GetName()
info.Currencies = balances
return info, nil
}
// UpdateTicker updates and returns the ticker for a currency pair

View File

@@ -322,15 +322,10 @@ func (g *Gateio) GetSpotKline(arg KlinesRequestParams) ([]*KLineResponse, error)
// GetBalances obtains the users account balance
func (g *Gateio) GetBalances() (BalancesResponse, error) {
var result BalancesResponse
err := g.SendAuthenticatedHTTPRequest("POST", gateioBalances, "", &result)
if err != nil {
return result, err
}
return result, nil
return result,
g.SendAuthenticatedHTTPRequest("POST", gateioBalances, "", &result)
}
// SpotNewOrder places a new order
@@ -402,7 +397,28 @@ func (g *Gateio) SendAuthenticatedHTTPRequest(method, endpoint, param string, re
url := fmt.Sprintf("%s/%s/%s", g.APIUrl, gateioAPIVersion, endpoint)
return g.SendPayload(method, url, headers, strings.NewReader(param), result, true, g.Verbose)
var intermidiary json.RawMessage
err := g.SendPayload(method, url, headers, strings.NewReader(param), &intermidiary, true, g.Verbose)
if err != nil {
return err
}
errCap := struct {
Result bool `json:"result,string"`
Code int `json:"code"`
Message string `json:"message"`
}{}
if err := common.JSONDecode(intermidiary, &errCap); err == nil {
if !errCap.Result {
return fmt.Errorf("GateIO auth request error, code: %d message: %s",
errCap.Code,
errCap.Message)
}
}
return common.JSONDecode(intermidiary, result)
}
// GetFee returns an estimate of fee based on type of transaction

View File

@@ -308,3 +308,17 @@ func TestCancelExchangeOrder(t *testing.T) {
t.Errorf("Could not cancel order: %s", err)
}
}
func TestGetAccountInfo(t *testing.T) {
if apiSecret == "" || apiKey == "" {
_, err := g.GetAccountInfo()
if err == nil {
t.Error("Test Failed - GetAccountInfo() error")
}
} else {
_, err := g.GetAccountInfo()
if err != nil {
t.Error("Test Failed - GetAccountInfo() error", err)
}
}
}

View File

@@ -53,9 +53,9 @@ type MarketInfoPairsResponse struct {
// BalancesResponse holds the user balances
type BalancesResponse struct {
Result string `json:"result"`
Available map[string]string `json:"available"`
Locked map[string]string `json:"locked"`
Result string `json:"result"`
Available []map[string]string `json:"available"`
Locked []map[string]string `json:"locked"`
}
// KlinesRequestParams represents Klines request data.

View File

@@ -1,7 +1,6 @@
package gateio
import (
"errors"
"fmt"
"log"
"strconv"
@@ -110,8 +109,62 @@ func (g *Gateio) UpdateOrderbook(p pair.CurrencyPair, assetType string) (orderbo
// GetAccountInfo retrieves balances for all enabled currencies for the
// ZB exchange
func (g *Gateio) GetAccountInfo() (exchange.AccountInfo, error) {
var response exchange.AccountInfo
return response, errors.New("not implemented")
var info exchange.AccountInfo
balance, err := g.GetBalances()
if err != nil {
return info, err
}
if len(balance.Available) == 0 && len(balance.Locked) == 0 {
return info, nil
}
var balances []exchange.AccountCurrencyInfo
for _, data := range balance.Locked {
for key, amountStr := range data {
lockedF, err := strconv.ParseFloat(amountStr, 64)
if err != nil {
return info, err
}
balances = append(balances, exchange.AccountCurrencyInfo{
CurrencyName: key,
Hold: lockedF,
})
}
}
for _, data := range balance.Available {
for key, amountStr := range data {
availAmount, err := strconv.ParseFloat(amountStr, 64)
if err != nil {
return info, err
}
var updated bool
for i := range balances {
if balances[i].CurrencyName == key {
balances[i].TotalValue = balances[i].Hold + availAmount
updated = true
break
}
}
if !updated {
balances = append(balances, exchange.AccountCurrencyInfo{
CurrencyName: key,
TotalValue: availAmount,
})
}
}
}
info.Currencies = balances
info.ExchangeName = g.GetName()
return info, nil
}
// GetFundingHistory returns funding history, deposits and

View File

@@ -63,6 +63,7 @@ const (
// HUOBI is the overarching type across this package
type HUOBI struct {
exchange.Base
AccountID string
WebsocketConn *websocket.Conn
}
@@ -367,7 +368,11 @@ func (h *HUOBI) GetAccountBalance(accountID string) ([]AccountBalanceDetail, err
var result response
endpoint := fmt.Sprintf(huobiAccountBalance, accountID)
err := h.SendAuthenticatedHTTPRequest("GET", endpoint, url.Values{}, nil, &result)
v := url.Values{}
v.Set("account-id", accountID)
err := h.SendAuthenticatedHTTPRequest("GET", endpoint, v, nil, &result)
if result.ErrorMessage != "" {
return nil, errors.New(result.ErrorMessage)

View File

@@ -456,3 +456,17 @@ func TestCancelExchangeOrder(t *testing.T) {
t.Errorf("Could not cancel order: %s", err)
}
}
func TestGetAccountInfo(t *testing.T) {
if apiKey == "" || apiSecret == "" {
_, err := h.GetAccountInfo()
if err == nil {
t.Error("Test Failed - GetAccountInfo() error")
}
} else {
_, err := h.GetAccountInfo()
if err != nil {
t.Error("Test Failed - GetAccountInfo() error", err)
}
}
}

View File

@@ -149,12 +149,77 @@ func (h *HUOBI) UpdateOrderbook(p pair.CurrencyPair, assetType string) (orderboo
return orderbook.GetOrderbook(h.Name, p, assetType)
}
var mtx sync.Mutex
// GetAccountID returns the account ID for trades NOTE interim implementation
// does not account for multiple account IDs
func (h *HUOBI) GetAccountID() (string, error) {
mtx.Lock()
defer mtx.Unlock()
if h.AccountID == "" {
acc, err := h.GetAccounts()
if err != nil {
return "", err
}
if len(acc) > 0 {
return strconv.FormatInt(acc[0].ID, 10), nil
}
return "", errors.New("no user ID fetched")
}
return h.AccountID, nil
}
//GetAccountInfo retrieves balances for all enabled currencies for the
// HUOBI exchange - to-do
func (h *HUOBI) GetAccountInfo() (exchange.AccountInfo, error) {
var response exchange.AccountInfo
response.ExchangeName = h.GetName()
return response, nil
var info exchange.AccountInfo
info.ExchangeName = h.GetName()
accID, err := h.GetAccountID()
if err != nil {
return info, err
}
acc, err := h.GetAccountBalance(accID)
if err != nil {
return info, err
}
type hold struct {
Avail float64
Hold float64
}
var currencyData = make(map[string]*hold)
for _, data := range acc {
_, ok := currencyData[data.Currency]
if !ok {
currencyData[data.Currency] = &hold{}
}
if data.Type == "trade" {
currencyData[data.Currency].Avail = data.Balance
} else {
currencyData[data.Currency].Hold = data.Balance
}
}
var balances []exchange.AccountCurrencyInfo
for key, data := range currencyData {
balances = append(balances, exchange.AccountCurrencyInfo{
CurrencyName: key,
TotalValue: data.Avail + data.Hold,
Hold: data.Hold,
})
}
info.Currencies = balances
return info, nil
}
// GetFundingHistory returns funding history, deposits and

View File

@@ -55,6 +55,7 @@ const (
// HUOBIHADAX is the overarching type across this package
type HUOBIHADAX struct {
AccountID string
exchange.Base
}

View File

@@ -435,3 +435,17 @@ func TestCancelExchangeOrder(t *testing.T) {
t.Errorf("Could not cancel order: %s", err)
}
}
func TestGetAccountInfo(t *testing.T) {
if apiKey == "" || apiSecret == "" {
_, err := h.GetAccountInfo()
if err == nil {
t.Error("Test Failed - GetAccountInfo() error")
}
} else {
_, err := h.GetAccountInfo()
if err != nil {
t.Error("Test Failed - GetAccountInfo() error", err)
}
}
}

View File

@@ -114,12 +114,77 @@ func (h *HUOBIHADAX) UpdateOrderbook(p pair.CurrencyPair, assetType string) (ord
return orderbook.GetOrderbook(h.Name, p, assetType)
}
var mtx sync.Mutex
// GetAccountID returns the account ID for trades NOTE interim implementation
// does not account for multiple account IDs
func (h *HUOBIHADAX) GetAccountID() (string, error) {
mtx.Lock()
defer mtx.Unlock()
if h.AccountID == "" {
acc, err := h.GetAccounts()
if err != nil {
return "", err
}
if len(acc) > 0 {
return strconv.FormatInt(acc[0].ID, 10), nil
}
return "", errors.New("no account ID fetched")
}
return h.AccountID, nil
}
//GetAccountInfo retrieves balances for all enabled currencies for the
// HUOBIHADAX exchange - to-do
func (h *HUOBIHADAX) GetAccountInfo() (exchange.AccountInfo, error) {
var response exchange.AccountInfo
response.ExchangeName = h.GetName()
return response, nil
var info exchange.AccountInfo
info.ExchangeName = h.GetName()
accID, err := h.GetAccountID()
if err != nil {
return info, err
}
acc, err := h.GetAccountBalance(accID)
if err != nil {
return info, err
}
type hold struct {
Avail float64
Hold float64
}
var currencyData = make(map[string]*hold)
for _, data := range acc {
_, ok := currencyData[data.Currency]
if !ok {
currencyData[data.Currency] = &hold{}
}
if data.Type == "trade" {
currencyData[data.Currency].Avail = data.Balance
} else {
currencyData[data.Currency].Hold = data.Balance
}
}
var balances []exchange.AccountCurrencyInfo
for key, data := range currencyData {
balances = append(balances, exchange.AccountCurrencyInfo{
CurrencyName: key,
TotalValue: data.Avail + data.Hold,
Hold: data.Hold,
})
}
info.Currencies = balances
return info, nil
}
// GetFundingHistory returns funding history, deposits and

View File

@@ -2,6 +2,7 @@ package itbit
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"log"
@@ -326,6 +327,10 @@ func (i *ItBit) SendAuthenticatedHTTPRequest(method string, path string, params
return fmt.Errorf(exchange.WarningAuthenticatedRequestWithoutCredentialsSet, i.Name)
}
if i.ClientID == "" {
return errors.New("client ID not set")
}
request := make(map[string]interface{})
url := i.APIUrl + path
@@ -368,7 +373,29 @@ func (i *ItBit) SendAuthenticatedHTTPRequest(method string, path string, params
headers["X-Auth-Nonce"] = nonce
headers["Content-Type"] = "application/json"
return i.SendPayload(method, url, headers, bytes.NewBuffer([]byte(PayloadJSON)), result, true, i.Verbose)
var intermediary json.RawMessage
errCheck := struct {
Code int `json:"code"`
Description string `json:"description"`
RequestID string `json:"requestId"`
}{}
err = i.SendPayload(method, url, headers, bytes.NewBuffer([]byte(PayloadJSON)), &intermediary, true, i.Verbose)
if err != nil {
return err
}
err = common.JSONDecode(intermediary, &errCheck)
if err == nil {
if errCheck.Code != 0 || errCheck.Description != "" {
return fmt.Errorf("itbit.go SendAuthRequest error code: %d description: %s",
errCheck.Code,
errCheck.Description)
}
}
return common.JSONDecode(intermediary, result)
}
// GetFee returns an estimate of fee based on type of transaction

View File

@@ -302,3 +302,12 @@ func TestCancelExchangeOrder(t *testing.T) {
t.Errorf("Could not cancel order: %s", err)
}
}
func TestGetAccountInfo(t *testing.T) {
if apiKey != "" || apiSecret != "" || clientID != "" {
_, err := i.GetAccountInfo()
if err == nil {
t.Error("Test Failed - GetAccountInfo() error")
}
}
}

View File

@@ -3,6 +3,7 @@ package itbit
import (
"fmt"
"log"
"net/url"
"strconv"
"sync"
@@ -107,12 +108,45 @@ func (i *ItBit) UpdateOrderbook(p pair.CurrencyPair, assetType string) (orderboo
return orderbook.GetOrderbook(i.Name, p, assetType)
}
// GetAccountInfo retrieves balances for all enabled currencies for the
//ItBit exchange - to-do
// GetAccountInfo retrieves balances for all enabled currencies
func (i *ItBit) GetAccountInfo() (exchange.AccountInfo, error) {
var response exchange.AccountInfo
response.ExchangeName = i.GetName()
return response, nil
var info exchange.AccountInfo
info.ExchangeName = i.GetName()
wallets, err := i.GetWallets(url.Values{})
if err != nil {
return info, err
}
type balance struct {
TotalValue float64
Hold float64
}
var amounts = make(map[string]*balance)
for _, wallet := range wallets {
for _, cb := range wallet.Balances {
if _, ok := amounts[cb.Currency]; !ok {
amounts[cb.Currency] = &balance{}
}
amounts[cb.Currency].TotalValue += cb.TotalBalance
amounts[cb.Currency].Hold += cb.TotalBalance - cb.AvailableBalance
}
}
var fullBalance []exchange.AccountCurrencyInfo
for key, data := range amounts {
fullBalance = append(fullBalance, exchange.AccountCurrencyInfo{
CurrencyName: key,
TotalValue: data.TotalValue,
Hold: data.Hold,
})
}
return info, nil
}
// GetFundingHistory returns funding history, deposits and

View File

@@ -388,3 +388,17 @@ func TestCancelExchangeOrder(t *testing.T) {
t.Errorf("Could not cancel order: %s", err)
}
}
func TestGetAccountInfo(t *testing.T) {
if apiKey != "" || apiSecret != "" || clientID != "" {
_, err := k.GetAccountInfo()
if err != nil {
t.Error("Test Failed - GetAccountInfo() error", err)
}
} else {
_, err := k.GetAccountInfo()
if err == nil {
t.Error("Test Failed - GetAccountInfo() error")
}
}
}

View File

@@ -141,9 +141,24 @@ func (k *Kraken) UpdateOrderbook(p pair.CurrencyPair, assetType string) (orderbo
// GetAccountInfo retrieves balances for all enabled currencies for the
// Kraken exchange - to-do
func (k *Kraken) GetAccountInfo() (exchange.AccountInfo, error) {
var response exchange.AccountInfo
response.ExchangeName = k.GetName()
return response, nil
var info exchange.AccountInfo
info.ExchangeName = k.GetName()
bal, err := k.GetBalance()
if err != nil {
return info, err
}
var balances []exchange.AccountCurrencyInfo
for key, data := range bal {
balances = append(balances, exchange.AccountCurrencyInfo{
CurrencyName: key,
TotalValue: data,
})
}
info.Currencies = balances
return info, nil
}
// GetFundingHistory returns funding history, deposits and

View File

@@ -1,6 +1,7 @@
package okex
import (
"encoding/json"
"errors"
"fmt"
"log"
@@ -70,6 +71,8 @@ const (
spotWithdrawInfo = "withdraw_info"
spotAccountRecords = "account_records"
myWalletInfo = "wallet_info.do"
// just your average return type from okex
returnTypeOne = "map[string]interface {}"
@@ -684,23 +687,22 @@ func (o *OKEX) SpotNewOrder(arg SpotNewOrderRequestParams) (int64, error) {
// orderID orderID
// returns orderID or an error
func (o *OKEX) SpotCancelOrder(symbol string, argOrderID int64) (int64, error) {
type response struct {
var res = struct {
Result bool `json:"result"`
OrderID string `json:"order_id"`
ErrorCode int `json:"error_code"`
}
var res response
}{}
params := url.Values{}
params.Set("symbol", symbol)
params.Set("order_id", strconv.FormatInt(argOrderID, 10))
err := o.SendAuthenticatedHTTPRequest(spotCancelTrade, params, &res)
var returnOrderID int64
if err != nil && res.ErrorCode != 0 {
err := o.SendAuthenticatedHTTPRequest(spotCancelTrade+".do", params, &res)
if err != nil {
return returnOrderID, err
}
if res.ErrorCode != 0 {
return returnOrderID, fmt.Errorf("ErrCode:%d ErrMsg:%s", res.ErrorCode, o.ErrorCodes[strconv.Itoa(res.ErrorCode)])
}
@@ -934,7 +936,27 @@ func (o *OKEX) SendAuthenticatedHTTPRequest(method string, values url.Values, re
headers := make(map[string]string)
headers["Content-Type"] = "application/x-www-form-urlencoded"
return o.SendPayload("POST", path, headers, strings.NewReader(encoded), result, true, o.Verbose)
var intermediary json.RawMessage
errCap := struct {
Result bool `json:"result"`
Error int64 `json:"error_code"`
}{}
err = o.SendPayload("POST", path, headers, strings.NewReader(encoded), &intermediary, true, o.Verbose)
if err != nil {
return err
}
err = common.JSONDecode(intermediary, &errCap)
if err == nil {
if !errCap.Result {
return fmt.Errorf("SendAuthenticatedHTTPRequest error - %s",
o.ErrorCodes[strconv.FormatInt(errCap.Error, 10)])
}
}
return common.JSONDecode(intermediary, result)
}
// SetErrorDefaults sets the full error default list
@@ -944,7 +966,7 @@ func (o *OKEX) SetErrorDefaults() {
"10000": errors.New("Required field, can not be null"),
"10001": errors.New("Request frequency too high to exceed the limit allowed"),
"10002": errors.New("System error"),
"10004": errors.New("Request failed"),
"10004": errors.New("Request failed - Your API key might need to be recreated"),
"10005": errors.New("'SecretKey' does not exist"),
"10006": errors.New("'Api_key' does not exist"),
"10007": errors.New("Signature does not match"),
@@ -1153,3 +1175,39 @@ func calculateTradingFee(purchasePrice, amount float64, isMaker bool) (fee float
func getWithdrawalFee(currency string) float64 {
return WithdrawalFees[currency]
}
// GetBalance returns the full balance accross all wallets
func (o *OKEX) GetBalance() ([]FullBalance, error) {
var resp Balance
var balances []FullBalance
err := o.SendAuthenticatedHTTPRequest(myWalletInfo, url.Values{}, &resp)
if err != nil {
return balances, err
}
for key, available := range resp.Info.Funds.Free {
free, err := strconv.ParseFloat(available, 64)
if err != nil {
return balances, err
}
inUse, ok := resp.Info.Funds.Holds[key]
if !ok {
return balances, fmt.Errorf("hold currency %s not found in map", key)
}
hold, err := strconv.ParseFloat(inUse, 64)
if err != nil {
return balances, err
}
balances = append(balances, FullBalance{
Currency: key,
Available: free,
Hold: hold,
})
}
return balances, nil
}

View File

@@ -411,7 +411,6 @@ func isRealOrderTestEnabled() bool {
func TestSubmitOrder(t *testing.T) {
o.SetDefaults()
TestSetup(t)
o.Verbose = true
if !isRealOrderTestEnabled() {
t.Skip()
@@ -437,7 +436,6 @@ func TestCancelExchangeOrder(t *testing.T) {
t.Skip()
}
o.Verbose = true
currencyPair := pair.NewCurrencyPair(symbol.LTC, symbol.BTC)
var orderCancellation = exchange.OrderCancellation{
@@ -455,3 +453,17 @@ func TestCancelExchangeOrder(t *testing.T) {
t.Errorf("Could not cancel order: %s", err)
}
}
func TestGetAccountInfo(t *testing.T) {
if apiKey != "" || apiSecret != "" {
_, err := o.GetAccountInfo()
if err != nil {
t.Error("Test Failed - GetAccountInfo() error", err)
}
} else {
_, err := o.GetAccountInfo()
if err == nil {
t.Error("Test Failed - GetAccountInfo() error")
}
}
}

View File

@@ -428,3 +428,20 @@ var WithdrawalFees = map[string]float64{
symbol.ZIL: 20,
symbol.ZIP: 1000,
}
// FullBalance defines a structured return type with balance data
type FullBalance struct {
Available float64
Currency string
Hold float64
}
// Balance defines returned balance data
type Balance struct {
Info struct {
Funds struct {
Free map[string]string `json:"free"`
Holds map[string]string `json:"holds"`
} `json:"funds"`
} `json:"info"`
}

View File

@@ -151,8 +151,24 @@ func (o *OKEX) UpdateOrderbook(p pair.CurrencyPair, assetType string) (orderbook
// GetAccountInfo retrieves balances for all enabled currencies for the
// OKEX exchange
func (o *OKEX) GetAccountInfo() (exchange.AccountInfo, error) {
var response exchange.AccountInfo
return response, errors.New("not implemented")
var info exchange.AccountInfo
bal, err := o.GetBalance()
if err != nil {
return info, err
}
var balances []exchange.AccountCurrencyInfo
for _, data := range bal {
balances = append(balances, exchange.AccountCurrencyInfo{
CurrencyName: data.Currency,
TotalValue: data.Available + data.Hold,
Hold: data.Hold,
})
}
info.ExchangeName = o.GetName()
info.Currencies = balances
return info, nil
}
// GetFundingHistory returns funding history, deposits and
@@ -219,13 +235,11 @@ func (o *OKEX) ModifyOrder(orderID int64, action exchange.ModifyOrder) (int64, e
// CancelOrder cancels an order by its corresponding ID number
func (o *OKEX) CancelOrder(order exchange.OrderCancellation) error {
orderIDInt, err := strconv.ParseInt(order.OrderID, 10, 64)
if err != nil {
return err
}
_, err = o.SpotCancelOrder(exchange.FormatExchangeCurrency(o.Name, order.CurrencyPair).String(), orderIDInt)
return err
}

View File

@@ -336,13 +336,34 @@ func (z *ZB) SendAuthenticatedHTTPRequest(method, endpoint string, values url.Va
endpoint,
values.Encode())
return z.SendPayload(method,
var intermediary json.RawMessage
errCap := struct {
Code int64 `json:"code"`
Message string `json:"message"`
}{}
err := z.SendPayload(method,
url,
nil,
strings.NewReader(""),
result,
&intermediary,
true,
z.Verbose)
if err != nil {
return err
}
err = common.JSONDecode(intermediary, &errCap)
if err == nil {
if errCap.Code != 0 {
return fmt.Errorf("SendAuthenticatedHTTPRequest error code: %d message %s",
errCap.Code,
errorCode[errCap.Code])
}
}
return common.JSONDecode(intermediary, result)
}
// GetFee returns an estimate of fee based on type of transaction
@@ -369,3 +390,34 @@ func calculateTradingFee(purchasePrice, amount float64) (fee float64) {
func getWithdrawalFee(currency string) float64 {
return WithdrawalFees[currency]
}
var errorCode = map[int64]string{
1000: "Successful call",
1001: "General error message",
1002: "internal error",
1003: "Verification failed",
1004: "Financial security password lock",
1005: "The fund security password is incorrect. Please confirm and re-enter.",
1006: "Real-name certification is awaiting review or review",
1009: "This interface is being maintained",
1010: "Not open yet",
1012: "Insufficient permissions",
1013: "Can not trade, if you have any questions, please contact online customer service",
1014: "Cannot be sold during the pre-sale period",
2002: "Insufficient balance in Bitcoin account",
2003: "Insufficient balance of Litecoin account",
2005: "Insufficient balance in Ethereum account",
2006: "Insufficient balance in ETC currency account",
2007: "Insufficient balance of BTS currency account",
2009: "Insufficient account balance",
3001: "Pending order not found",
3002: "Invalid amount",
3003: "Invalid quantity",
3004: "User does not exist",
3005: "Invalid parameter",
3006: "Invalid IP or inconsistent with the bound IP",
3007: "Request time has expired",
3008: "Transaction history not found",
4001: "API interface is locked",
4002: "Request too frequently",
}

View File

@@ -112,19 +112,6 @@ func TestGetMarkets(t *testing.T) {
}
}
func TestGetAccountInfo(t *testing.T) {
t.Parallel()
if z.APIKey == "" || z.APISecret == "" {
t.Skip()
}
_, err := z.GetAccountInfo()
if err != nil {
t.Errorf("Test failed - ZB GetAccountInfo: %s", err)
}
}
func TestGetSpotKline(t *testing.T) {
t.Parallel()
@@ -300,3 +287,17 @@ func TestCancelExchangeOrder(t *testing.T) {
t.Errorf("Could not cancel order: %s", err)
}
}
func TestGetAccountInfo(t *testing.T) {
if apiKey != "" || apiSecret != "" {
_, err := z.GetAccountInfo()
if err != nil {
t.Error("Test Failed - GetAccountInfo() error", err)
}
} else {
_, err := z.GetAccountInfo()
if err == nil {
t.Error("Test Failed - GetAccountInfo() error")
}
}
}

View File

@@ -1,7 +1,6 @@
package zb
import (
"errors"
"fmt"
"log"
"strconv"
@@ -119,8 +118,34 @@ func (z *ZB) UpdateOrderbook(p pair.CurrencyPair, assetType string) (orderbook.B
// GetAccountInfo retrieves balances for all enabled currencies for the
// ZB exchange
func (z *ZB) GetAccountInfo() (exchange.AccountInfo, error) {
var response exchange.AccountInfo
return response, errors.New("not implemented")
var info exchange.AccountInfo
bal, err := z.GetAccountInformation()
if err != nil {
return info, err
}
var balances []exchange.AccountCurrencyInfo
for _, data := range bal.Result.Coins {
hold, err := strconv.ParseFloat(data.Freez, 64)
if err != nil {
return info, err
}
avail, err := strconv.ParseFloat(data.Available, 64)
if err != nil {
return info, err
}
balances = append(balances, exchange.AccountCurrencyInfo{
CurrencyName: data.EnName,
TotalValue: hold + avail,
Hold: hold,
})
}
info.ExchangeName = z.GetName()
info.Currencies = balances
return info, nil
}
// GetFundingHistory returns funding history, deposits and