mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-05-21 07:26:48 +00:00
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:
committed by
Adrian Gallagher
parent
05f9f40723
commit
4ca3fd5b00
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -55,6 +55,7 @@ const (
|
||||
|
||||
// HUOBIHADAX is the overarching type across this package
|
||||
type HUOBIHADAX struct {
|
||||
AccountID string
|
||||
exchange.Base
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"`
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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",
|
||||
}
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user