mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-06-02 07:26:53 +00:00
Expose auth validator functionality for wrapper (#416)
* expose auth validator functionality for wrapper * Add REST validation after keys set, package account types for future syncing * Add transient error checking for initial creddemtial validation * fix command types * Addressed nits from glorious person * Amalgamate body within error when not between 2xx status, added btcmarket specific auth error check * nit fix for glorious person * Format fix * removed unused code * check transient first then validate if its an exchange specific authentication error, all others will be disregarded * Addressed glorious nits * Addressed glorious nits * Moved account processing to updateaccountinfo func and added in fetch account info * Add GRPC Account streaming (NOTE: could not complete until sync item added) * RM exchange check * Address xtda nits * RM comment code * Fix linter issues * used most recent protoc version * lbank linter issues fixed * Addressed nits and changed len check to range in for loops * Fixed timeout issue * thrasher nits addressed * add string holdings
This commit is contained in:
86
exchanges/account/account.go
Normal file
86
exchanges/account/account.go
Normal file
@@ -0,0 +1,86 @@
|
||||
package account
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/gofrs/uuid"
|
||||
"github.com/thrasher-corp/gocryptotrader/dispatch"
|
||||
)
|
||||
|
||||
func init() {
|
||||
service = new(Service)
|
||||
service.accounts = make(map[string]*Account)
|
||||
service.mux = dispatch.GetNewMux()
|
||||
}
|
||||
|
||||
// SubscribeToExchangeAccount subcribes to your exchange account
|
||||
func SubscribeToExchangeAccount(exchange string) (dispatch.Pipe, error) {
|
||||
exchange = strings.ToLower(exchange)
|
||||
service.Lock()
|
||||
|
||||
acc, ok := service.accounts[exchange]
|
||||
if !ok {
|
||||
service.Unlock()
|
||||
return dispatch.Pipe{},
|
||||
fmt.Errorf("%s exchange account holdings not found", exchange)
|
||||
}
|
||||
|
||||
defer service.Unlock()
|
||||
return service.mux.Subscribe(acc.ID)
|
||||
}
|
||||
|
||||
// Process processes new account holdings updates
|
||||
func Process(h *Holdings) error {
|
||||
if h == nil {
|
||||
return errors.New("cannot be nil")
|
||||
}
|
||||
|
||||
if h.Exchange == "" {
|
||||
return errors.New("exchange name unset")
|
||||
}
|
||||
|
||||
return service.Update(h)
|
||||
}
|
||||
|
||||
// GetHoldings returns full holdings for an exchange
|
||||
func GetHoldings(exch string) (Holdings, error) {
|
||||
if exch == "" {
|
||||
return Holdings{}, errors.New("exchange name unset")
|
||||
}
|
||||
|
||||
exch = strings.ToLower(exch)
|
||||
|
||||
service.Lock()
|
||||
h, ok := service.accounts[exch]
|
||||
if !ok {
|
||||
service.Unlock()
|
||||
return Holdings{}, errors.New("exchange account holdings not found")
|
||||
}
|
||||
defer service.Unlock()
|
||||
return *h.h, nil
|
||||
}
|
||||
|
||||
// Update updates holdings with new account info
|
||||
func (s *Service) Update(a *Holdings) error {
|
||||
exch := strings.ToLower(a.Exchange)
|
||||
s.Lock()
|
||||
acc, ok := s.accounts[exch]
|
||||
if !ok {
|
||||
id, err := s.mux.GetID()
|
||||
if err != nil {
|
||||
s.Unlock()
|
||||
return err
|
||||
}
|
||||
|
||||
s.accounts[exch] = &Account{h: a, ID: id}
|
||||
s.Unlock()
|
||||
return nil
|
||||
}
|
||||
|
||||
acc.h.Accounts = a.Accounts
|
||||
defer s.Unlock()
|
||||
|
||||
return s.mux.Publish([]uuid.UUID{acc.ID}, acc.h)
|
||||
}
|
||||
129
exchanges/account/account_test.go
Normal file
129
exchanges/account/account_test.go
Normal file
@@ -0,0 +1,129 @@
|
||||
package account
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
"github.com/thrasher-corp/gocryptotrader/dispatch"
|
||||
)
|
||||
|
||||
func TestHoldings(t *testing.T) {
|
||||
err := dispatch.Start(1, 1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = Process(nil)
|
||||
if err == nil {
|
||||
t.Error("error cannot be nil")
|
||||
}
|
||||
|
||||
err = Process(&Holdings{})
|
||||
if err == nil {
|
||||
t.Error("error cannot be nil")
|
||||
}
|
||||
|
||||
holdings := Holdings{
|
||||
Exchange: "Test",
|
||||
}
|
||||
|
||||
err = Process(&holdings)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
err = Process(&Holdings{
|
||||
Exchange: "Test",
|
||||
Accounts: []SubAccount{{
|
||||
ID: "1337",
|
||||
Currencies: []Balance{
|
||||
{
|
||||
CurrencyName: currency.BTC,
|
||||
TotalValue: 100,
|
||||
Hold: 20,
|
||||
},
|
||||
},
|
||||
}},
|
||||
})
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
_, err = GetHoldings("")
|
||||
if err == nil {
|
||||
t.Error("error cannot be nil")
|
||||
}
|
||||
|
||||
_, err = GetHoldings("bla")
|
||||
if err == nil {
|
||||
t.Error("error cannot be nil")
|
||||
}
|
||||
|
||||
u, err := GetHoldings("Test")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if u.Accounts[0].ID != "1337" {
|
||||
t.Errorf("expecting 1337 but receieved %s", u.Accounts[0].ID)
|
||||
}
|
||||
|
||||
if u.Accounts[0].Currencies[0].CurrencyName != currency.BTC {
|
||||
t.Errorf("expecting BTC but receieved %s",
|
||||
u.Accounts[0].Currencies[0].CurrencyName)
|
||||
}
|
||||
|
||||
if u.Accounts[0].Currencies[0].TotalValue != 100 {
|
||||
t.Errorf("expecting 100 but receieved %f",
|
||||
u.Accounts[0].Currencies[0].TotalValue)
|
||||
}
|
||||
|
||||
if u.Accounts[0].Currencies[0].Hold != 20 {
|
||||
t.Errorf("expecting 20 but receieved %f",
|
||||
u.Accounts[0].Currencies[0].Hold)
|
||||
}
|
||||
|
||||
_, err = SubscribeToExchangeAccount("nonsense")
|
||||
if err == nil {
|
||||
t.Fatal("error cannot be nil")
|
||||
}
|
||||
|
||||
p, err := SubscribeToExchangeAccount("Test")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(1)
|
||||
go func(p dispatch.Pipe, wg *sync.WaitGroup) {
|
||||
for i := 0; i < 2; i++ {
|
||||
c := time.NewTimer(time.Second)
|
||||
select {
|
||||
case <-p.C:
|
||||
case <-c.C:
|
||||
}
|
||||
}
|
||||
|
||||
wg.Done()
|
||||
}(p, &wg)
|
||||
|
||||
err = Process(&Holdings{
|
||||
Exchange: "Test",
|
||||
Accounts: []SubAccount{{
|
||||
ID: "1337",
|
||||
Currencies: []Balance{
|
||||
{
|
||||
CurrencyName: currency.BTC,
|
||||
TotalValue: 100000,
|
||||
Hold: 20,
|
||||
},
|
||||
},
|
||||
}},
|
||||
})
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
}
|
||||
47
exchanges/account/account_types.go
Normal file
47
exchanges/account/account_types.go
Normal file
@@ -0,0 +1,47 @@
|
||||
package account
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/gofrs/uuid"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
"github.com/thrasher-corp/gocryptotrader/dispatch"
|
||||
)
|
||||
|
||||
// Vars for the ticker package
|
||||
var (
|
||||
service *Service
|
||||
)
|
||||
|
||||
// Service holds ticker information for each individual exchange
|
||||
type Service struct {
|
||||
accounts map[string]*Account
|
||||
mux *dispatch.Mux
|
||||
sync.Mutex
|
||||
}
|
||||
|
||||
// Account holds a stream ID and a pointer to the exchange holdings
|
||||
type Account struct {
|
||||
h *Holdings
|
||||
ID uuid.UUID
|
||||
}
|
||||
|
||||
// Holdings is a generic type to hold each exchange's holdings for all enabled
|
||||
// currencies
|
||||
type Holdings struct {
|
||||
Exchange string
|
||||
Accounts []SubAccount
|
||||
}
|
||||
|
||||
// SubAccount defines a singular account type with asocciated currency balances
|
||||
type SubAccount struct {
|
||||
ID string
|
||||
Currencies []Balance
|
||||
}
|
||||
|
||||
// Balance is a sub type to store currency name and individual totals
|
||||
type Balance struct {
|
||||
CurrencyName currency.Code
|
||||
TotalValue float64
|
||||
Hold float64
|
||||
}
|
||||
@@ -324,7 +324,7 @@ func TestGetAccountInfo(t *testing.T) {
|
||||
t.Skip("API keys not set, skipping")
|
||||
}
|
||||
|
||||
_, err := a.GetAccountInfo()
|
||||
_, err := a.UpdateAccountInfo()
|
||||
if err == nil {
|
||||
t.Error("GetUserInfo() Expected error")
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"github.com/thrasher-corp/gocryptotrader/config"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/account"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
|
||||
@@ -85,33 +86,49 @@ func (a *Alphapoint) UpdateTradablePairs(forceUpdate bool) error {
|
||||
return common.ErrFunctionNotSupported
|
||||
}
|
||||
|
||||
// GetAccountInfo retrieves balances for all enabled currencies on the
|
||||
// UpdateAccountInfo retrieves balances for all enabled currencies on the
|
||||
// Alphapoint exchange
|
||||
func (a *Alphapoint) GetAccountInfo() (exchange.AccountInfo, error) {
|
||||
var response exchange.AccountInfo
|
||||
func (a *Alphapoint) UpdateAccountInfo() (account.Holdings, error) {
|
||||
var response account.Holdings
|
||||
response.Exchange = a.Name
|
||||
account, err := a.GetAccountInformation()
|
||||
acc, err := a.GetAccountInformation()
|
||||
if err != nil {
|
||||
return response, err
|
||||
}
|
||||
|
||||
var currencies []exchange.AccountCurrencyInfo
|
||||
for i := 0; i < len(account.Currencies); i++ {
|
||||
var exchangeCurrency exchange.AccountCurrencyInfo
|
||||
exchangeCurrency.CurrencyName = currency.NewCode(account.Currencies[i].Name)
|
||||
exchangeCurrency.TotalValue = float64(account.Currencies[i].Balance)
|
||||
exchangeCurrency.Hold = float64(account.Currencies[i].Hold)
|
||||
var balances []account.Balance
|
||||
for i := range acc.Currencies {
|
||||
var balance account.Balance
|
||||
balance.CurrencyName = currency.NewCode(acc.Currencies[i].Name)
|
||||
balance.TotalValue = float64(acc.Currencies[i].Balance)
|
||||
balance.Hold = float64(acc.Currencies[i].Hold)
|
||||
|
||||
currencies = append(currencies, exchangeCurrency)
|
||||
balances = append(balances, balance)
|
||||
}
|
||||
|
||||
response.Accounts = append(response.Accounts, exchange.Account{
|
||||
Currencies: currencies,
|
||||
response.Accounts = append(response.Accounts, account.SubAccount{
|
||||
Currencies: balances,
|
||||
})
|
||||
|
||||
err = account.Process(&response)
|
||||
if err != nil {
|
||||
return account.Holdings{}, err
|
||||
}
|
||||
|
||||
return response, nil
|
||||
}
|
||||
|
||||
// FetchAccountInfo retrieves balances for all enabled currencies on the
|
||||
// Alphapoint exchange
|
||||
func (a *Alphapoint) FetchAccountInfo() (account.Holdings, error) {
|
||||
acc, err := account.GetHoldings(a.Name)
|
||||
if err != nil {
|
||||
return a.UpdateAccountInfo()
|
||||
}
|
||||
|
||||
return acc, nil
|
||||
}
|
||||
|
||||
// UpdateTicker updates and returns the ticker for a currency pair
|
||||
func (a *Alphapoint) UpdateTicker(p currency.Pair, assetType asset.Item) (*ticker.Price, error) {
|
||||
tickerPrice := new(ticker.Price)
|
||||
@@ -412,3 +429,10 @@ func (a *Alphapoint) GetSubscriptions() ([]wshandler.WebsocketChannelSubscriptio
|
||||
func (a *Alphapoint) AuthenticateWebsocket() error {
|
||||
return common.ErrFunctionNotSupported
|
||||
}
|
||||
|
||||
// ValidateCredentials validates current credentials used for wrapper
|
||||
// functionality
|
||||
func (a *Alphapoint) ValidateCredentials() error {
|
||||
_, err := a.UpdateAccountInfo()
|
||||
return a.CheckTransientError(err)
|
||||
}
|
||||
|
||||
@@ -427,7 +427,7 @@ func TestCancelAllExchangeOrders(t *testing.T) {
|
||||
func TestGetAccountInfo(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
_, err := b.GetAccountInfo()
|
||||
_, err := b.UpdateAccountInfo()
|
||||
switch {
|
||||
case areTestAPIKeysSet() && err != nil:
|
||||
t.Error("GetAccountInfo() error", err)
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
"github.com/thrasher-corp/gocryptotrader/config"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/account"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
|
||||
@@ -345,28 +346,28 @@ func (b *Binance) UpdateOrderbook(p currency.Pair, assetType asset.Item) (*order
|
||||
return orderbook.Get(b.Name, p, assetType)
|
||||
}
|
||||
|
||||
// GetAccountInfo retrieves balances for all enabled currencies for the
|
||||
// UpdateAccountInfo retrieves balances for all enabled currencies for the
|
||||
// Bithumb exchange
|
||||
func (b *Binance) GetAccountInfo() (exchange.AccountInfo, error) {
|
||||
var info exchange.AccountInfo
|
||||
func (b *Binance) UpdateAccountInfo() (account.Holdings, error) {
|
||||
var info account.Holdings
|
||||
raw, err := b.GetAccount()
|
||||
if err != nil {
|
||||
return info, err
|
||||
}
|
||||
|
||||
var currencyBalance []exchange.AccountCurrencyInfo
|
||||
var currencyBalance []account.Balance
|
||||
for i := range raw.Balances {
|
||||
freeCurrency, err := strconv.ParseFloat(raw.Balances[i].Free, 64)
|
||||
if err != nil {
|
||||
return info, err
|
||||
freeCurrency, parseErr := strconv.ParseFloat(raw.Balances[i].Free, 64)
|
||||
if parseErr != nil {
|
||||
return info, parseErr
|
||||
}
|
||||
|
||||
lockedCurrency, err := strconv.ParseFloat(raw.Balances[i].Locked, 64)
|
||||
if err != nil {
|
||||
return info, err
|
||||
lockedCurrency, parseErr := strconv.ParseFloat(raw.Balances[i].Locked, 64)
|
||||
if parseErr != nil {
|
||||
return info, parseErr
|
||||
}
|
||||
|
||||
currencyBalance = append(currencyBalance, exchange.AccountCurrencyInfo{
|
||||
currencyBalance = append(currencyBalance, account.Balance{
|
||||
CurrencyName: currency.NewCode(raw.Balances[i].Asset),
|
||||
TotalValue: freeCurrency + lockedCurrency,
|
||||
Hold: freeCurrency,
|
||||
@@ -374,13 +375,28 @@ func (b *Binance) GetAccountInfo() (exchange.AccountInfo, error) {
|
||||
}
|
||||
|
||||
info.Exchange = b.Name
|
||||
info.Accounts = append(info.Accounts, exchange.Account{
|
||||
info.Accounts = append(info.Accounts, account.SubAccount{
|
||||
Currencies: currencyBalance,
|
||||
})
|
||||
|
||||
err = account.Process(&info)
|
||||
if err != nil {
|
||||
return account.Holdings{}, err
|
||||
}
|
||||
|
||||
return info, nil
|
||||
}
|
||||
|
||||
// FetchAccountInfo retrieves balances for all enabled currencies
|
||||
func (b *Binance) FetchAccountInfo() (account.Holdings, error) {
|
||||
acc, err := account.GetHoldings(b.Name)
|
||||
if err != nil {
|
||||
return b.UpdateAccountInfo()
|
||||
}
|
||||
|
||||
return acc, nil
|
||||
}
|
||||
|
||||
// GetFundingHistory returns funding history, deposits and
|
||||
// withdrawals
|
||||
func (b *Binance) GetFundingHistory() ([]exchange.FundHistory, error) {
|
||||
@@ -636,3 +652,10 @@ func (b *Binance) GetSubscriptions() ([]wshandler.WebsocketChannelSubscription,
|
||||
func (b *Binance) AuthenticateWebsocket() error {
|
||||
return common.ErrFunctionNotSupported
|
||||
}
|
||||
|
||||
// ValidateCredentials validates current credentials used for wrapper
|
||||
// functionality
|
||||
func (b *Binance) ValidateCredentials() error {
|
||||
_, err := b.UpdateAccountInfo()
|
||||
return b.CheckTransientError(err)
|
||||
}
|
||||
|
||||
@@ -277,7 +277,7 @@ func TestGetAccountInfo(t *testing.T) {
|
||||
}
|
||||
t.Parallel()
|
||||
|
||||
_, err := b.GetAccountInfo()
|
||||
_, err := b.UpdateAccountInfo()
|
||||
if err != nil {
|
||||
t.Error("GetAccountInfo error", err)
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"github.com/thrasher-corp/gocryptotrader/config"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/account"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
|
||||
@@ -329,10 +330,10 @@ func (b *Bitfinex) UpdateOrderbook(p currency.Pair, assetType asset.Item) (*orde
|
||||
return orderbook.Get(b.Name, p, assetType)
|
||||
}
|
||||
|
||||
// GetAccountInfo retrieves balances for all enabled currencies on the
|
||||
// UpdateAccountInfo retrieves balances for all enabled currencies on the
|
||||
// Bitfinex exchange
|
||||
func (b *Bitfinex) GetAccountInfo() (exchange.AccountInfo, error) {
|
||||
var response exchange.AccountInfo
|
||||
func (b *Bitfinex) UpdateAccountInfo() (account.Holdings, error) {
|
||||
var response account.Holdings
|
||||
response.Exchange = b.Name
|
||||
|
||||
accountBalance, err := b.GetAccountBalance()
|
||||
@@ -340,7 +341,7 @@ func (b *Bitfinex) GetAccountInfo() (exchange.AccountInfo, error) {
|
||||
return response, err
|
||||
}
|
||||
|
||||
var Accounts = []exchange.Account{
|
||||
var Accounts = []account.SubAccount{
|
||||
{ID: "deposit"},
|
||||
{ID: "exchange"},
|
||||
{ID: "trading"},
|
||||
@@ -350,7 +351,7 @@ func (b *Bitfinex) GetAccountInfo() (exchange.AccountInfo, error) {
|
||||
for i := range Accounts {
|
||||
if Accounts[i].ID == accountBalance[x].Type {
|
||||
Accounts[i].Currencies = append(Accounts[i].Currencies,
|
||||
exchange.AccountCurrencyInfo{
|
||||
account.Balance{
|
||||
CurrencyName: currency.NewCode(accountBalance[x].Currency),
|
||||
TotalValue: accountBalance[x].Amount,
|
||||
Hold: accountBalance[x].Amount - accountBalance[x].Available,
|
||||
@@ -360,9 +361,24 @@ func (b *Bitfinex) GetAccountInfo() (exchange.AccountInfo, error) {
|
||||
}
|
||||
|
||||
response.Accounts = Accounts
|
||||
err = account.Process(&response)
|
||||
if err != nil {
|
||||
return account.Holdings{}, err
|
||||
}
|
||||
|
||||
return response, nil
|
||||
}
|
||||
|
||||
// FetchAccountInfo retrieves balances for all enabled currencies
|
||||
func (b *Bitfinex) FetchAccountInfo() (account.Holdings, error) {
|
||||
acc, err := account.GetHoldings(b.Name)
|
||||
if err != nil {
|
||||
return b.UpdateAccountInfo()
|
||||
}
|
||||
|
||||
return acc, nil
|
||||
}
|
||||
|
||||
// GetFundingHistory returns funding history, deposits and
|
||||
// withdrawals
|
||||
func (b *Bitfinex) GetFundingHistory() ([]exchange.FundHistory, error) {
|
||||
@@ -719,3 +735,10 @@ func (b *Bitfinex) appendOptionalDelimiter(p *currency.Pair) {
|
||||
p.Delimiter = ":"
|
||||
}
|
||||
}
|
||||
|
||||
// ValidateCredentials validates current credentials used for wrapper
|
||||
// functionality
|
||||
func (b *Bitfinex) ValidateCredentials() error {
|
||||
_, err := b.UpdateAccountInfo()
|
||||
return b.CheckTransientError(err)
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"github.com/thrasher-corp/gocryptotrader/config"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/account"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
|
||||
@@ -257,10 +258,20 @@ func (b *Bitflyer) UpdateOrderbook(p currency.Pair, assetType asset.Item) (*orde
|
||||
return orderbook.Get(b.Name, p, assetType)
|
||||
}
|
||||
|
||||
// GetAccountInfo retrieves balances for all enabled currencies on the
|
||||
// UpdateAccountInfo retrieves balances for all enabled currencies on the
|
||||
// Bitflyer exchange
|
||||
func (b *Bitflyer) GetAccountInfo() (exchange.AccountInfo, error) {
|
||||
return exchange.AccountInfo{}, common.ErrNotYetImplemented
|
||||
func (b *Bitflyer) UpdateAccountInfo() (account.Holdings, error) {
|
||||
return account.Holdings{}, common.ErrNotYetImplemented
|
||||
}
|
||||
|
||||
// FetchAccountInfo retrieves balances for all enabled currencies
|
||||
func (b *Bitflyer) FetchAccountInfo() (account.Holdings, error) {
|
||||
acc, err := account.GetHoldings(b.Name)
|
||||
if err != nil {
|
||||
return b.UpdateAccountInfo()
|
||||
}
|
||||
|
||||
return acc, nil
|
||||
}
|
||||
|
||||
// GetFundingHistory returns funding history, deposits and
|
||||
@@ -372,3 +383,10 @@ func (b *Bitflyer) GetSubscriptions() ([]wshandler.WebsocketChannelSubscription,
|
||||
func (b *Bitflyer) AuthenticateWebsocket() error {
|
||||
return common.ErrFunctionNotSupported
|
||||
}
|
||||
|
||||
// ValidateCredentials validates current credentials used for wrapper
|
||||
// functionality
|
||||
func (b *Bitflyer) ValidateCredentials() error {
|
||||
_, err := b.UpdateAccountInfo()
|
||||
return b.CheckTransientError(err)
|
||||
}
|
||||
|
||||
@@ -417,12 +417,12 @@ func TestCancelAllExchangeOrders(t *testing.T) {
|
||||
func TestGetAccountInfo(t *testing.T) {
|
||||
t.Parallel()
|
||||
if areTestAPIKeysSet() {
|
||||
_, err := b.GetAccountInfo()
|
||||
_, err := b.UpdateAccountInfo()
|
||||
if err != nil {
|
||||
t.Error("Bithumb GetAccountInfo() error", err)
|
||||
}
|
||||
} else {
|
||||
_, err := b.GetAccountInfo()
|
||||
_, err := b.UpdateAccountInfo()
|
||||
if err == nil {
|
||||
t.Error("Bithumb GetAccountInfo() Expected error")
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"github.com/thrasher-corp/gocryptotrader/config"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/account"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
|
||||
@@ -257,16 +258,16 @@ func (b *Bithumb) UpdateOrderbook(p currency.Pair, assetType asset.Item) (*order
|
||||
return orderbook.Get(b.Name, p, assetType)
|
||||
}
|
||||
|
||||
// GetAccountInfo retrieves balances for all enabled currencies for the
|
||||
// UpdateAccountInfo retrieves balances for all enabled currencies for the
|
||||
// Bithumb exchange
|
||||
func (b *Bithumb) GetAccountInfo() (exchange.AccountInfo, error) {
|
||||
var info exchange.AccountInfo
|
||||
func (b *Bithumb) UpdateAccountInfo() (account.Holdings, error) {
|
||||
var info account.Holdings
|
||||
bal, err := b.GetAccountBalance("ALL")
|
||||
if err != nil {
|
||||
return info, err
|
||||
}
|
||||
|
||||
var exchangeBalances []exchange.AccountCurrencyInfo
|
||||
var exchangeBalances []account.Balance
|
||||
for key, totalAmount := range bal.Total {
|
||||
hold, ok := bal.InUse[key]
|
||||
if !ok {
|
||||
@@ -274,21 +275,36 @@ func (b *Bithumb) GetAccountInfo() (exchange.AccountInfo, error) {
|
||||
key)
|
||||
}
|
||||
|
||||
exchangeBalances = append(exchangeBalances, exchange.AccountCurrencyInfo{
|
||||
exchangeBalances = append(exchangeBalances, account.Balance{
|
||||
CurrencyName: currency.NewCode(key),
|
||||
TotalValue: totalAmount,
|
||||
Hold: hold,
|
||||
})
|
||||
}
|
||||
|
||||
info.Accounts = append(info.Accounts, exchange.Account{
|
||||
info.Accounts = append(info.Accounts, account.SubAccount{
|
||||
Currencies: exchangeBalances,
|
||||
})
|
||||
|
||||
info.Exchange = b.Name
|
||||
err = account.Process(&info)
|
||||
if err != nil {
|
||||
return account.Holdings{}, err
|
||||
}
|
||||
|
||||
return info, nil
|
||||
}
|
||||
|
||||
// FetchAccountInfo retrieves balances for all enabled currencies
|
||||
func (b *Bithumb) FetchAccountInfo() (account.Holdings, error) {
|
||||
acc, err := account.GetHoldings(b.Name)
|
||||
if err != nil {
|
||||
return b.UpdateAccountInfo()
|
||||
}
|
||||
|
||||
return acc, nil
|
||||
}
|
||||
|
||||
// GetFundingHistory returns funding history, deposits and
|
||||
// withdrawals
|
||||
func (b *Bithumb) GetFundingHistory() ([]exchange.FundHistory, error) {
|
||||
@@ -562,3 +578,10 @@ func (b *Bithumb) GetSubscriptions() ([]wshandler.WebsocketChannelSubscription,
|
||||
func (b *Bithumb) AuthenticateWebsocket() error {
|
||||
return common.ErrFunctionNotSupported
|
||||
}
|
||||
|
||||
// ValidateCredentials validates current credentials used for wrapper
|
||||
// functionality
|
||||
func (b *Bithumb) ValidateCredentials() error {
|
||||
_, err := b.UpdateAccountInfo()
|
||||
return b.CheckTransientError(err)
|
||||
}
|
||||
|
||||
@@ -584,12 +584,12 @@ func TestCancelAllExchangeOrders(t *testing.T) {
|
||||
|
||||
func TestGetAccountInfo(t *testing.T) {
|
||||
if areTestAPIKeysSet() {
|
||||
_, err := b.GetAccountInfo()
|
||||
_, err := b.UpdateAccountInfo()
|
||||
if err != nil {
|
||||
t.Error("GetAccountInfo() error", err)
|
||||
}
|
||||
} else {
|
||||
_, err := b.GetAccountInfo()
|
||||
_, err := b.UpdateAccountInfo()
|
||||
if err == nil {
|
||||
t.Error("GetAccountInfo() error")
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
"github.com/thrasher-corp/gocryptotrader/config"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/account"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
|
||||
@@ -370,10 +371,10 @@ func (b *Bitmex) UpdateOrderbook(p currency.Pair, assetType asset.Item) (*orderb
|
||||
return orderbook.Get(b.Name, p, assetType)
|
||||
}
|
||||
|
||||
// GetAccountInfo retrieves balances for all enabled currencies for the
|
||||
// UpdateAccountInfo retrieves balances for all enabled currencies for the
|
||||
// Bitmex exchange
|
||||
func (b *Bitmex) GetAccountInfo() (exchange.AccountInfo, error) {
|
||||
var info exchange.AccountInfo
|
||||
func (b *Bitmex) UpdateAccountInfo() (account.Holdings, error) {
|
||||
var info account.Holdings
|
||||
|
||||
bal, err := b.GetAllUserMargin()
|
||||
if err != nil {
|
||||
@@ -381,22 +382,37 @@ func (b *Bitmex) GetAccountInfo() (exchange.AccountInfo, error) {
|
||||
}
|
||||
|
||||
// Need to update to add Margin/Liquidity availibilty
|
||||
var balances []exchange.AccountCurrencyInfo
|
||||
var balances []account.Balance
|
||||
for i := range bal {
|
||||
balances = append(balances, exchange.AccountCurrencyInfo{
|
||||
balances = append(balances, account.Balance{
|
||||
CurrencyName: currency.NewCode(bal[i].Currency),
|
||||
TotalValue: float64(bal[i].WalletBalance),
|
||||
})
|
||||
}
|
||||
|
||||
info.Exchange = b.Name
|
||||
info.Accounts = append(info.Accounts, exchange.Account{
|
||||
info.Accounts = append(info.Accounts, account.SubAccount{
|
||||
Currencies: balances,
|
||||
})
|
||||
|
||||
err = account.Process(&info)
|
||||
if err != nil {
|
||||
return account.Holdings{}, err
|
||||
}
|
||||
|
||||
return info, nil
|
||||
}
|
||||
|
||||
// FetchAccountInfo retrieves balances for all enabled currencies
|
||||
func (b *Bitmex) FetchAccountInfo() (account.Holdings, error) {
|
||||
acc, err := account.GetHoldings(b.Name)
|
||||
if err != nil {
|
||||
return b.UpdateAccountInfo()
|
||||
}
|
||||
|
||||
return acc, nil
|
||||
}
|
||||
|
||||
// GetFundingHistory returns funding history, deposits and
|
||||
// withdrawals
|
||||
func (b *Bitmex) GetFundingHistory() ([]exchange.FundHistory, error) {
|
||||
@@ -660,3 +676,10 @@ func (b *Bitmex) GetSubscriptions() ([]wshandler.WebsocketChannelSubscription, e
|
||||
func (b *Bitmex) AuthenticateWebsocket() error {
|
||||
return b.websocketSendAuth()
|
||||
}
|
||||
|
||||
// ValidateCredentials validates current credentials used for wrapper
|
||||
// functionality
|
||||
func (b *Bitmex) ValidateCredentials() error {
|
||||
_, err := b.UpdateAccountInfo()
|
||||
return b.CheckTransientError(err)
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
"github.com/thrasher-corp/gocryptotrader/config"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/account"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
|
||||
@@ -315,31 +316,46 @@ func (b *Bitstamp) UpdateOrderbook(p currency.Pair, assetType asset.Item) (*orde
|
||||
return orderbook.Get(b.Name, p, assetType)
|
||||
}
|
||||
|
||||
// GetAccountInfo retrieves balances for all enabled currencies for the
|
||||
// UpdateAccountInfo retrieves balances for all enabled currencies for the
|
||||
// Bitstamp exchange
|
||||
func (b *Bitstamp) GetAccountInfo() (exchange.AccountInfo, error) {
|
||||
var response exchange.AccountInfo
|
||||
func (b *Bitstamp) UpdateAccountInfo() (account.Holdings, error) {
|
||||
var response account.Holdings
|
||||
response.Exchange = b.Name
|
||||
accountBalance, err := b.GetBalance()
|
||||
if err != nil {
|
||||
return response, err
|
||||
}
|
||||
|
||||
var currencies []exchange.AccountCurrencyInfo
|
||||
var currencies []account.Balance
|
||||
for k, v := range accountBalance {
|
||||
currencies = append(currencies, exchange.AccountCurrencyInfo{
|
||||
currencies = append(currencies, account.Balance{
|
||||
CurrencyName: currency.NewCode(k),
|
||||
TotalValue: v.Available,
|
||||
Hold: v.Reserved,
|
||||
})
|
||||
}
|
||||
response.Accounts = append(response.Accounts, exchange.Account{
|
||||
response.Accounts = append(response.Accounts, account.SubAccount{
|
||||
Currencies: currencies,
|
||||
})
|
||||
|
||||
err = account.Process(&response)
|
||||
if err != nil {
|
||||
return account.Holdings{}, err
|
||||
}
|
||||
|
||||
return response, nil
|
||||
}
|
||||
|
||||
// FetchAccountInfo retrieves balances for all enabled currencies
|
||||
func (b *Bitstamp) FetchAccountInfo() (account.Holdings, error) {
|
||||
acc, err := account.GetHoldings(b.Name)
|
||||
if err != nil {
|
||||
return b.UpdateAccountInfo()
|
||||
}
|
||||
|
||||
return acc, nil
|
||||
}
|
||||
|
||||
// GetFundingHistory returns funding history, deposits and
|
||||
// withdrawals
|
||||
func (b *Bitstamp) GetFundingHistory() ([]exchange.FundHistory, error) {
|
||||
@@ -644,3 +660,10 @@ func (b *Bitstamp) GetSubscriptions() ([]wshandler.WebsocketChannelSubscription,
|
||||
func (b *Bitstamp) AuthenticateWebsocket() error {
|
||||
return common.ErrFunctionNotSupported
|
||||
}
|
||||
|
||||
// ValidateCredentials validates current credentials used for wrapper
|
||||
// functionality
|
||||
func (b *Bitstamp) ValidateCredentials() error {
|
||||
_, err := b.UpdateAccountInfo()
|
||||
return b.CheckTransientError(err)
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"github.com/thrasher-corp/gocryptotrader/config"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/account"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
|
||||
@@ -195,32 +196,47 @@ func (b *Bittrex) UpdateTradablePairs(forceUpdate bool) error {
|
||||
return b.UpdatePairs(currency.NewPairsFromStrings(pairs), asset.Spot, false, forceUpdate)
|
||||
}
|
||||
|
||||
// GetAccountInfo Retrieves balances for all enabled currencies for the
|
||||
// UpdateAccountInfo Retrieves balances for all enabled currencies for the
|
||||
// Bittrex exchange
|
||||
func (b *Bittrex) GetAccountInfo() (exchange.AccountInfo, error) {
|
||||
var response exchange.AccountInfo
|
||||
func (b *Bittrex) UpdateAccountInfo() (account.Holdings, error) {
|
||||
var response account.Holdings
|
||||
response.Exchange = b.Name
|
||||
accountBalance, err := b.GetAccountBalances()
|
||||
if err != nil {
|
||||
return response, err
|
||||
}
|
||||
|
||||
var currencies []exchange.AccountCurrencyInfo
|
||||
for i := 0; i < len(accountBalance.Result); i++ {
|
||||
var exchangeCurrency exchange.AccountCurrencyInfo
|
||||
var currencies []account.Balance
|
||||
for i := range accountBalance.Result {
|
||||
var exchangeCurrency account.Balance
|
||||
exchangeCurrency.CurrencyName = currency.NewCode(accountBalance.Result[i].Currency)
|
||||
exchangeCurrency.TotalValue = accountBalance.Result[i].Balance
|
||||
exchangeCurrency.Hold = accountBalance.Result[i].Balance - accountBalance.Result[i].Available
|
||||
currencies = append(currencies, exchangeCurrency)
|
||||
}
|
||||
|
||||
response.Accounts = append(response.Accounts, exchange.Account{
|
||||
response.Accounts = append(response.Accounts, account.SubAccount{
|
||||
Currencies: currencies,
|
||||
})
|
||||
|
||||
err = account.Process(&response)
|
||||
if err != nil {
|
||||
return account.Holdings{}, err
|
||||
}
|
||||
|
||||
return response, nil
|
||||
}
|
||||
|
||||
// FetchAccountInfo retrieves balances for all enabled currencies
|
||||
func (b *Bittrex) FetchAccountInfo() (account.Holdings, error) {
|
||||
acc, err := account.GetHoldings(b.Name)
|
||||
if err != nil {
|
||||
return b.UpdateAccountInfo()
|
||||
}
|
||||
|
||||
return acc, nil
|
||||
}
|
||||
|
||||
// UpdateTicker updates and returns the ticker for a currency pair
|
||||
func (b *Bittrex) UpdateTicker(p currency.Pair, assetType asset.Item) (*ticker.Price, error) {
|
||||
tickerPrice := new(ticker.Price)
|
||||
@@ -561,3 +577,10 @@ func (b *Bittrex) GetSubscriptions() ([]wshandler.WebsocketChannelSubscription,
|
||||
func (b *Bittrex) AuthenticateWebsocket() error {
|
||||
return common.ErrFunctionNotSupported
|
||||
}
|
||||
|
||||
// ValidateCredentials validates current credentials used for wrapper
|
||||
// functionality
|
||||
func (b *Bittrex) ValidateCredentials() error {
|
||||
_, err := b.UpdateAccountInfo()
|
||||
return b.CheckTransientError(err)
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package btcmarkets
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"testing"
|
||||
@@ -45,6 +46,13 @@ func TestMain(m *testing.M) {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
err = b.ValidateCredentials()
|
||||
if err != nil {
|
||||
fmt.Println("API credentials are invalid:", err)
|
||||
b.API.AuthenticatedSupport = false
|
||||
b.API.AuthenticatedWebsocketSupport = false
|
||||
}
|
||||
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
@@ -443,7 +451,7 @@ func TestGetAccountInfo(t *testing.T) {
|
||||
if !areTestAPIKeysSet() {
|
||||
t.Skip("API keys required but not set, skipping test")
|
||||
}
|
||||
_, err := b.GetAccountInfo()
|
||||
_, err := b.UpdateAccountInfo()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
"github.com/thrasher-corp/gocryptotrader/config"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/account"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
|
||||
@@ -314,28 +315,44 @@ func (b *BTCMarkets) UpdateOrderbook(p currency.Pair, assetType asset.Item) (*or
|
||||
return orderbook.Get(b.Name, p, assetType)
|
||||
}
|
||||
|
||||
// GetAccountInfo retrieves balances for all enabled currencies
|
||||
func (b *BTCMarkets) GetAccountInfo() (exchange.AccountInfo, error) {
|
||||
var resp exchange.AccountInfo
|
||||
// UpdateAccountInfo retrieves balances for all enabled currencies
|
||||
func (b *BTCMarkets) UpdateAccountInfo() (account.Holdings, error) {
|
||||
var resp account.Holdings
|
||||
data, err := b.GetAccountBalance()
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
var account exchange.Account
|
||||
var acc account.SubAccount
|
||||
for key := range data {
|
||||
c := currency.NewCode(data[key].AssetName)
|
||||
hold := data[key].Locked
|
||||
total := data[key].Balance
|
||||
account.Currencies = append(account.Currencies,
|
||||
exchange.AccountCurrencyInfo{CurrencyName: c,
|
||||
acc.Currencies = append(acc.Currencies,
|
||||
account.Balance{CurrencyName: c,
|
||||
TotalValue: total,
|
||||
Hold: hold})
|
||||
}
|
||||
resp.Accounts = append(resp.Accounts, account)
|
||||
resp.Accounts = append(resp.Accounts, acc)
|
||||
resp.Exchange = b.Name
|
||||
|
||||
err = account.Process(&resp)
|
||||
if err != nil {
|
||||
return account.Holdings{}, err
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// FetchAccountInfo retrieves balances for all enabled currencies
|
||||
func (b *BTCMarkets) FetchAccountInfo() (account.Holdings, error) {
|
||||
acc, err := account.GetHoldings(b.Name)
|
||||
if err != nil {
|
||||
return b.UpdateAccountInfo()
|
||||
}
|
||||
|
||||
return acc, nil
|
||||
}
|
||||
|
||||
// GetFundingHistory returns funding history, deposits and
|
||||
// withdrawals
|
||||
func (b *BTCMarkets) GetFundingHistory() ([]exchange.FundHistory, error) {
|
||||
@@ -688,3 +705,24 @@ func (b *BTCMarkets) GetSubscriptions() ([]wshandler.WebsocketChannelSubscriptio
|
||||
func (b *BTCMarkets) AuthenticateWebsocket() error {
|
||||
return common.ErrFunctionNotSupported
|
||||
}
|
||||
|
||||
// ValidateCredentials validates current credentials used for wrapper
|
||||
// functionality
|
||||
func (b *BTCMarkets) ValidateCredentials() error {
|
||||
_, err := b.UpdateAccountInfo()
|
||||
if err != nil {
|
||||
if b.CheckTransientError(err) == nil {
|
||||
return nil
|
||||
}
|
||||
// Check for specific auth errors; all other errors can be disregarded
|
||||
// as this does not affect authenticated requests.
|
||||
if strings.Contains(err.Error(), "InvalidAPIKey") ||
|
||||
strings.Contains(err.Error(), "InvalidAuthTimestamp") ||
|
||||
strings.Contains(err.Error(), "InvalidAuthSignature") ||
|
||||
strings.Contains(err.Error(), "InsufficientAPIPermission") {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"github.com/thrasher-corp/gocryptotrader/config"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/account"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
|
||||
@@ -296,19 +297,19 @@ func (b *BTSE) UpdateOrderbook(p currency.Pair, assetType asset.Item) (*orderboo
|
||||
return orderbook.Get(b.Name, p, assetType)
|
||||
}
|
||||
|
||||
// GetAccountInfo retrieves balances for all enabled currencies for the
|
||||
// UpdateAccountInfo retrieves balances for all enabled currencies for the
|
||||
// BTSE exchange
|
||||
func (b *BTSE) GetAccountInfo() (exchange.AccountInfo, error) {
|
||||
var a exchange.AccountInfo
|
||||
func (b *BTSE) UpdateAccountInfo() (account.Holdings, error) {
|
||||
var a account.Holdings
|
||||
balance, err := b.GetAccountBalance()
|
||||
if err != nil {
|
||||
return a, err
|
||||
}
|
||||
|
||||
var currencies []exchange.AccountCurrencyInfo
|
||||
var currencies []account.Balance
|
||||
for b := range balance {
|
||||
currencies = append(currencies,
|
||||
exchange.AccountCurrencyInfo{
|
||||
account.Balance{
|
||||
CurrencyName: currency.NewCode(balance[b].Currency),
|
||||
TotalValue: balance[b].Total,
|
||||
Hold: balance[b].Available,
|
||||
@@ -316,14 +317,30 @@ func (b *BTSE) GetAccountInfo() (exchange.AccountInfo, error) {
|
||||
)
|
||||
}
|
||||
a.Exchange = b.Name
|
||||
a.Accounts = []exchange.Account{
|
||||
a.Accounts = []account.SubAccount{
|
||||
{
|
||||
Currencies: currencies,
|
||||
},
|
||||
}
|
||||
|
||||
err = account.Process(&a)
|
||||
if err != nil {
|
||||
return account.Holdings{}, err
|
||||
}
|
||||
|
||||
return a, nil
|
||||
}
|
||||
|
||||
// FetchAccountInfo retrieves balances for all enabled currencies
|
||||
func (b *BTSE) FetchAccountInfo() (account.Holdings, error) {
|
||||
acc, err := account.GetHoldings(b.Name)
|
||||
if err != nil {
|
||||
return b.UpdateAccountInfo()
|
||||
}
|
||||
|
||||
return acc, nil
|
||||
}
|
||||
|
||||
// GetFundingHistory returns funding history, deposits and
|
||||
// withdrawals
|
||||
func (b *BTSE) GetFundingHistory() ([]exchange.FundHistory, error) {
|
||||
@@ -626,3 +643,10 @@ func (b *BTSE) GetSubscriptions() ([]wshandler.WebsocketChannelSubscription, err
|
||||
func (b *BTSE) AuthenticateWebsocket() error {
|
||||
return common.ErrFunctionNotSupported
|
||||
}
|
||||
|
||||
// ValidateCredentials validates current credentials used for wrapper
|
||||
// functionality
|
||||
func (b *BTSE) ValidateCredentials() error {
|
||||
_, err := b.UpdateAccountInfo()
|
||||
return b.CheckTransientError(err)
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
"github.com/thrasher-corp/gocryptotrader/config"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/account"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
|
||||
@@ -254,19 +255,19 @@ func (c *CoinbasePro) UpdateTradablePairs(forceUpdate bool) error {
|
||||
return c.UpdatePairs(currency.NewPairsFromStrings(pairs), asset.Spot, false, forceUpdate)
|
||||
}
|
||||
|
||||
// GetAccountInfo retrieves balances for all enabled currencies for the
|
||||
// UpdateAccountInfo retrieves balances for all enabled currencies for the
|
||||
// coinbasepro exchange
|
||||
func (c *CoinbasePro) GetAccountInfo() (exchange.AccountInfo, error) {
|
||||
var response exchange.AccountInfo
|
||||
func (c *CoinbasePro) UpdateAccountInfo() (account.Holdings, error) {
|
||||
var response account.Holdings
|
||||
response.Exchange = c.Name
|
||||
accountBalance, err := c.GetAccounts()
|
||||
if err != nil {
|
||||
return response, err
|
||||
}
|
||||
|
||||
var currencies []exchange.AccountCurrencyInfo
|
||||
for i := 0; i < len(accountBalance); i++ {
|
||||
var exchangeCurrency exchange.AccountCurrencyInfo
|
||||
var currencies []account.Balance
|
||||
for i := range accountBalance {
|
||||
var exchangeCurrency account.Balance
|
||||
exchangeCurrency.CurrencyName = currency.NewCode(accountBalance[i].Currency)
|
||||
exchangeCurrency.TotalValue = accountBalance[i].Available
|
||||
exchangeCurrency.Hold = accountBalance[i].Hold
|
||||
@@ -274,13 +275,28 @@ func (c *CoinbasePro) GetAccountInfo() (exchange.AccountInfo, error) {
|
||||
currencies = append(currencies, exchangeCurrency)
|
||||
}
|
||||
|
||||
response.Accounts = append(response.Accounts, exchange.Account{
|
||||
response.Accounts = append(response.Accounts, account.SubAccount{
|
||||
Currencies: currencies,
|
||||
})
|
||||
|
||||
err = account.Process(&response)
|
||||
if err != nil {
|
||||
return account.Holdings{}, err
|
||||
}
|
||||
|
||||
return response, nil
|
||||
}
|
||||
|
||||
// FetchAccountInfo retrieves balances for all enabled currencies
|
||||
func (c *CoinbasePro) FetchAccountInfo() (account.Holdings, error) {
|
||||
acc, err := account.GetHoldings(c.Name)
|
||||
if err != nil {
|
||||
return c.UpdateAccountInfo()
|
||||
}
|
||||
|
||||
return acc, nil
|
||||
}
|
||||
|
||||
// UpdateTicker updates and returns the ticker for a currency pair
|
||||
func (c *CoinbasePro) UpdateTicker(p currency.Pair, assetType asset.Item) (*ticker.Price, error) {
|
||||
tick, err := c.GetTicker(c.FormatExchangeCurrency(p, assetType).String())
|
||||
@@ -639,3 +655,10 @@ func (c *CoinbasePro) GetHistoricCandles(p currency.Pair, rangesize, granularity
|
||||
}
|
||||
return candles, nil
|
||||
}
|
||||
|
||||
// ValidateCredentials validates current credentials used for wrapper
|
||||
// functionality
|
||||
func (c *CoinbasePro) ValidateCredentials() error {
|
||||
_, err := c.UpdateAccountInfo()
|
||||
return c.CheckTransientError(err)
|
||||
}
|
||||
|
||||
@@ -239,7 +239,7 @@ func TestGetAccountInfo(t *testing.T) {
|
||||
if !areTestAPIKeysSet() {
|
||||
t.Skip("API keys required but not set, skipping test")
|
||||
}
|
||||
_, err := c.GetAccountInfo()
|
||||
_, err := c.UpdateAccountInfo()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"github.com/thrasher-corp/gocryptotrader/config"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/account"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
|
||||
@@ -411,29 +412,47 @@ func (c *Coinbene) UpdateOrderbook(p currency.Pair, assetType asset.Item) (*orde
|
||||
return orderbook.Get(c.Name, p, assetType)
|
||||
}
|
||||
|
||||
// GetAccountInfo retrieves balances for all enabled currencies for the
|
||||
// UpdateAccountInfo retrieves balances for all enabled currencies for the
|
||||
// Coinbene exchange
|
||||
func (c *Coinbene) GetAccountInfo() (exchange.AccountInfo, error) {
|
||||
var info exchange.AccountInfo
|
||||
func (c *Coinbene) UpdateAccountInfo() (account.Holdings, error) {
|
||||
var info account.Holdings
|
||||
balance, err := c.GetAccountBalances()
|
||||
if err != nil {
|
||||
return info, err
|
||||
}
|
||||
var account exchange.Account
|
||||
var acc account.SubAccount
|
||||
for key := range balance {
|
||||
c := currency.NewCode(balance[key].Asset)
|
||||
hold := balance[key].Reserved
|
||||
available := balance[key].Available
|
||||
account.Currencies = append(account.Currencies,
|
||||
exchange.AccountCurrencyInfo{CurrencyName: c,
|
||||
TotalValue: hold + available,
|
||||
Hold: hold})
|
||||
acc.Currencies = append(acc.Currencies,
|
||||
account.Balance{
|
||||
CurrencyName: c,
|
||||
TotalValue: hold + available,
|
||||
Hold: hold,
|
||||
})
|
||||
}
|
||||
info.Accounts = append(info.Accounts, account)
|
||||
info.Accounts = append(info.Accounts, acc)
|
||||
info.Exchange = c.Name
|
||||
|
||||
err = account.Process(&info)
|
||||
if err != nil {
|
||||
return account.Holdings{}, err
|
||||
}
|
||||
|
||||
return info, nil
|
||||
}
|
||||
|
||||
// FetchAccountInfo retrieves balances for all enabled currencies
|
||||
func (c *Coinbene) FetchAccountInfo() (account.Holdings, error) {
|
||||
acc, err := account.GetHoldings(c.Name)
|
||||
if err != nil {
|
||||
return c.UpdateAccountInfo()
|
||||
}
|
||||
|
||||
return acc, nil
|
||||
}
|
||||
|
||||
// GetFundingHistory returns funding history, deposits and
|
||||
// withdrawals
|
||||
func (c *Coinbene) GetFundingHistory() ([]exchange.FundHistory, error) {
|
||||
@@ -717,3 +736,10 @@ func (c *Coinbene) GetSubscriptions() ([]wshandler.WebsocketChannelSubscription,
|
||||
func (c *Coinbene) AuthenticateWebsocket() error {
|
||||
return c.Login()
|
||||
}
|
||||
|
||||
// ValidateCredentials validates current credentials used for wrapper
|
||||
// functionality
|
||||
func (c *Coinbene) ValidateCredentials() error {
|
||||
_, err := c.UpdateAccountInfo()
|
||||
return c.CheckTransientError(err)
|
||||
}
|
||||
|
||||
@@ -360,12 +360,12 @@ func TestCancelAllExchangeOrders(t *testing.T) {
|
||||
|
||||
func TestGetAccountInfo(t *testing.T) {
|
||||
if apiKey != "" || clientID != "" {
|
||||
_, err := c.GetAccountInfo()
|
||||
_, err := c.UpdateAccountInfo()
|
||||
if err != nil {
|
||||
t.Error("GetAccountInfo() error", err)
|
||||
}
|
||||
} else {
|
||||
_, err := c.GetAccountInfo()
|
||||
_, err := c.UpdateAccountInfo()
|
||||
if err == nil {
|
||||
t.Error("GetAccountInfo() Expected error")
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"github.com/thrasher-corp/gocryptotrader/config"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/account"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
|
||||
@@ -260,10 +261,10 @@ func (c *COINUT) UpdateTradablePairs(forceUpdate bool) error {
|
||||
asset.Spot, false, forceUpdate)
|
||||
}
|
||||
|
||||
// GetAccountInfo retrieves balances for all enabled currencies for the
|
||||
// UpdateAccountInfo retrieves balances for all enabled currencies for the
|
||||
// COINUT exchange
|
||||
func (c *COINUT) GetAccountInfo() (exchange.AccountInfo, error) {
|
||||
var info exchange.AccountInfo
|
||||
func (c *COINUT) UpdateAccountInfo() (account.Holdings, error) {
|
||||
var info account.Holdings
|
||||
var bal *UserBalance
|
||||
var err error
|
||||
if c.Websocket.CanUseAuthenticatedWebsocketForWrapper() {
|
||||
@@ -280,7 +281,7 @@ func (c *COINUT) GetAccountInfo() (exchange.AccountInfo, error) {
|
||||
}
|
||||
}
|
||||
|
||||
var balances = []exchange.AccountCurrencyInfo{
|
||||
var balances = []account.Balance{
|
||||
{
|
||||
CurrencyName: currency.BCH,
|
||||
TotalValue: bal.BCH,
|
||||
@@ -339,13 +340,28 @@ func (c *COINUT) GetAccountInfo() (exchange.AccountInfo, error) {
|
||||
},
|
||||
}
|
||||
info.Exchange = c.Name
|
||||
info.Accounts = append(info.Accounts, exchange.Account{
|
||||
info.Accounts = append(info.Accounts, account.SubAccount{
|
||||
Currencies: balances,
|
||||
})
|
||||
|
||||
err = account.Process(&info)
|
||||
if err != nil {
|
||||
return account.Holdings{}, err
|
||||
}
|
||||
|
||||
return info, nil
|
||||
}
|
||||
|
||||
// FetchAccountInfo retrieves balances for all enabled currencies
|
||||
func (c *COINUT) FetchAccountInfo() (account.Holdings, error) {
|
||||
acc, err := account.GetHoldings(c.Name)
|
||||
if err != nil {
|
||||
return c.UpdateAccountInfo()
|
||||
}
|
||||
|
||||
return acc, nil
|
||||
}
|
||||
|
||||
// UpdateTicker updates and returns the ticker for a currency pair
|
||||
func (c *COINUT) UpdateTicker(p currency.Pair, assetType asset.Item) (*ticker.Price, error) {
|
||||
tickerPrice := new(ticker.Price)
|
||||
@@ -887,3 +903,10 @@ func (c *COINUT) loadInstrumentsIfNotLoaded() error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ValidateCredentials validates current credentials used for wrapper
|
||||
// functionality
|
||||
func (c *COINUT) ValidateCredentials() error {
|
||||
_, err := c.UpdateAccountInfo()
|
||||
return c.CheckTransientError(err)
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package exchange
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
@@ -203,7 +204,8 @@ func (e *Base) SupportsRESTTickerBatchUpdates() bool {
|
||||
// SupportsAutoPairUpdates returns whether or not the exchange supports
|
||||
// auto currency pair updating
|
||||
func (e *Base) SupportsAutoPairUpdates() bool {
|
||||
if e.Features.Supports.RESTCapabilities.AutoPairUpdates || e.Features.Supports.WebsocketCapabilities.AutoPairUpdates {
|
||||
if e.Features.Supports.RESTCapabilities.AutoPairUpdates ||
|
||||
e.Features.Supports.WebsocketCapabilities.AutoPairUpdates {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
@@ -423,7 +425,9 @@ func (e *Base) SetAPIKeys(apiKey, apiSecret, clientID string) {
|
||||
if err != nil {
|
||||
e.API.AuthenticatedSupport = false
|
||||
e.API.AuthenticatedWebsocketSupport = false
|
||||
log.Warnf(log.ExchangeSys, warningBase64DecryptSecretKeyFailed, e.Name)
|
||||
log.Warnf(log.ExchangeSys,
|
||||
warningBase64DecryptSecretKeyFailed,
|
||||
e.Name)
|
||||
return
|
||||
}
|
||||
e.API.Credentials.Secret = string(result)
|
||||
@@ -442,7 +446,9 @@ func (e *Base) SetupDefaults(exch *config.ExchangeConfig) error {
|
||||
e.API.AuthenticatedSupport = exch.API.AuthenticatedSupport
|
||||
e.API.AuthenticatedWebsocketSupport = exch.API.AuthenticatedWebsocketSupport
|
||||
if e.API.AuthenticatedSupport || e.API.AuthenticatedWebsocketSupport {
|
||||
e.SetAPIKeys(exch.API.Credentials.Key, exch.API.Credentials.Secret, exch.API.Credentials.ClientID)
|
||||
e.SetAPIKeys(exch.API.Credentials.Key,
|
||||
exch.API.Credentials.Secret,
|
||||
exch.API.Credentials.ClientID)
|
||||
}
|
||||
|
||||
if exch.HTTPTimeout <= time.Duration(0) {
|
||||
@@ -475,33 +481,28 @@ func (e *Base) SetupDefaults(exch *config.ExchangeConfig) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// AllowAuthenticatedRequest checks to see if the required fields have been set before sending an authenticated
|
||||
// API request
|
||||
// AllowAuthenticatedRequest checks to see if the required fields have been set
|
||||
// before sending an authenticated API request
|
||||
func (e *Base) AllowAuthenticatedRequest() bool {
|
||||
// Skip auth check
|
||||
if e.SkipAuthCheck {
|
||||
return true
|
||||
}
|
||||
|
||||
// Individual package usage, allow request if API credentials are valid a
|
||||
// and without needing to set AuthenticatedSupport to true
|
||||
if !e.LoadedByConfig && !e.ValidateAPICredentials() {
|
||||
if !e.LoadedByConfig {
|
||||
return e.ValidateAPICredentials()
|
||||
}
|
||||
|
||||
// Bot usage, AuthenticatedSupport can be disabled by user if desired, so
|
||||
// don't allow authenticated requests.
|
||||
if !e.API.AuthenticatedSupport && !e.API.AuthenticatedWebsocketSupport {
|
||||
return false
|
||||
}
|
||||
|
||||
// Bot usage, AuthenticatedSupport can be disabled by user if desired, so don't
|
||||
// allow authenticated requests.
|
||||
if (!e.API.AuthenticatedSupport && !e.API.AuthenticatedWebsocketSupport) && e.LoadedByConfig {
|
||||
return false
|
||||
}
|
||||
|
||||
// Check to see if the user has enabled AuthenticatedSupport, but has invalid
|
||||
// API credentials set and loaded by config
|
||||
if (e.API.AuthenticatedSupport || e.API.AuthenticatedWebsocketSupport) && e.LoadedByConfig && !e.ValidateAPICredentials() {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
// Check to see if the user has enabled AuthenticatedSupport, but has
|
||||
// invalid API credentials set and loaded by config
|
||||
return e.ValidateAPICredentials()
|
||||
}
|
||||
|
||||
// ValidateAPICredentials validates the exchanges API credentials
|
||||
@@ -781,3 +782,16 @@ func (e *Base) PrintEnabledPairs() {
|
||||
|
||||
// GetBase returns the exchange base
|
||||
func (e *Base) GetBase() *Base { return e }
|
||||
|
||||
// CheckTransientError catches transient errors and returns nil if found, used
|
||||
// for validation of API credentials
|
||||
func (e *Base) CheckTransientError(err error) error {
|
||||
if _, ok := err.(net.Error); ok {
|
||||
log.Warnf(log.ExchangeSys,
|
||||
"%s net error captured, will not disable authentication %s",
|
||||
e.Name,
|
||||
err)
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -107,26 +107,6 @@ type FeeBuilder struct {
|
||||
Amount float64
|
||||
}
|
||||
|
||||
// AccountInfo is a Generic type to hold each exchange's holdings in
|
||||
// all enabled currencies
|
||||
type AccountInfo struct {
|
||||
Exchange string
|
||||
Accounts []Account
|
||||
}
|
||||
|
||||
// Account defines a singular account type with asocciated currencies
|
||||
type Account struct {
|
||||
ID string
|
||||
Currencies []AccountCurrencyInfo
|
||||
}
|
||||
|
||||
// AccountCurrencyInfo is a sub type to store currency name and value
|
||||
type AccountCurrencyInfo struct {
|
||||
CurrencyName currency.Code
|
||||
TotalValue float64
|
||||
Hold float64
|
||||
}
|
||||
|
||||
// TradeHistory holds exchange history data
|
||||
type TradeHistory struct {
|
||||
Timestamp time.Time
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"github.com/thrasher-corp/gocryptotrader/config"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/account"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
|
||||
@@ -279,19 +280,19 @@ func (e *EXMO) UpdateOrderbook(p currency.Pair, assetType asset.Item) (*orderboo
|
||||
return orderbook.Get(e.Name, p, assetType)
|
||||
}
|
||||
|
||||
// GetAccountInfo retrieves balances for all enabled currencies for the
|
||||
// UpdateAccountInfo retrieves balances for all enabled currencies for the
|
||||
// Exmo exchange
|
||||
func (e *EXMO) GetAccountInfo() (exchange.AccountInfo, error) {
|
||||
var response exchange.AccountInfo
|
||||
func (e *EXMO) UpdateAccountInfo() (account.Holdings, error) {
|
||||
var response account.Holdings
|
||||
response.Exchange = e.Name
|
||||
result, err := e.GetUserInfo()
|
||||
if err != nil {
|
||||
return response, err
|
||||
}
|
||||
|
||||
var currencies []exchange.AccountCurrencyInfo
|
||||
var currencies []account.Balance
|
||||
for x, y := range result.Balances {
|
||||
var exchangeCurrency exchange.AccountCurrencyInfo
|
||||
var exchangeCurrency account.Balance
|
||||
exchangeCurrency.CurrencyName = currency.NewCode(x)
|
||||
for z, w := range result.Reserved {
|
||||
if z == x {
|
||||
@@ -304,13 +305,28 @@ func (e *EXMO) GetAccountInfo() (exchange.AccountInfo, error) {
|
||||
currencies = append(currencies, exchangeCurrency)
|
||||
}
|
||||
|
||||
response.Accounts = append(response.Accounts, exchange.Account{
|
||||
response.Accounts = append(response.Accounts, account.SubAccount{
|
||||
Currencies: currencies,
|
||||
})
|
||||
|
||||
err = account.Process(&response)
|
||||
if err != nil {
|
||||
return account.Holdings{}, err
|
||||
}
|
||||
|
||||
return response, nil
|
||||
}
|
||||
|
||||
// FetchAccountInfo retrieves balances for all enabled currencies
|
||||
func (e *EXMO) FetchAccountInfo() (account.Holdings, error) {
|
||||
acc, err := account.GetHoldings(e.Name)
|
||||
if err != nil {
|
||||
return e.UpdateAccountInfo()
|
||||
}
|
||||
|
||||
return acc, nil
|
||||
}
|
||||
|
||||
// GetFundingHistory returns funding history, deposits and
|
||||
// withdrawals
|
||||
func (e *EXMO) GetFundingHistory() ([]exchange.FundHistory, error) {
|
||||
@@ -542,3 +558,10 @@ func (e *EXMO) GetSubscriptions() ([]wshandler.WebsocketChannelSubscription, err
|
||||
func (e *EXMO) AuthenticateWebsocket() error {
|
||||
return common.ErrFunctionNotSupported
|
||||
}
|
||||
|
||||
// ValidateCredentials validates current credentials used for wrapper
|
||||
// functionality
|
||||
func (e *EXMO) ValidateCredentials() error {
|
||||
_, err := e.UpdateAccountInfo()
|
||||
return e.CheckTransientError(err)
|
||||
}
|
||||
|
||||
@@ -383,12 +383,12 @@ func TestCancelAllExchangeOrders(t *testing.T) {
|
||||
|
||||
func TestGetAccountInfo(t *testing.T) {
|
||||
if apiSecret == "" || apiKey == "" {
|
||||
_, err := g.GetAccountInfo()
|
||||
_, err := g.UpdateAccountInfo()
|
||||
if err == nil {
|
||||
t.Error("GetAccountInfo() Expected error")
|
||||
}
|
||||
} else {
|
||||
_, err := g.GetAccountInfo()
|
||||
_, err := g.UpdateAccountInfo()
|
||||
if err != nil {
|
||||
t.Error("GetAccountInfo() error", err)
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
"github.com/thrasher-corp/gocryptotrader/config"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/account"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
|
||||
@@ -306,26 +307,26 @@ func (g *Gateio) UpdateOrderbook(p currency.Pair, assetType asset.Item) (*orderb
|
||||
return orderbook.Get(g.Name, p, assetType)
|
||||
}
|
||||
|
||||
// GetAccountInfo retrieves balances for all enabled currencies for the
|
||||
// UpdateAccountInfo retrieves balances for all enabled currencies for the
|
||||
// ZB exchange
|
||||
func (g *Gateio) GetAccountInfo() (exchange.AccountInfo, error) {
|
||||
var info exchange.AccountInfo
|
||||
var balances []exchange.AccountCurrencyInfo
|
||||
func (g *Gateio) UpdateAccountInfo() (account.Holdings, error) {
|
||||
var info account.Holdings
|
||||
var balances []account.Balance
|
||||
|
||||
if g.Websocket.CanUseAuthenticatedWebsocketForWrapper() {
|
||||
resp, err := g.wsGetBalance([]string{})
|
||||
if err != nil {
|
||||
return info, err
|
||||
}
|
||||
var currData []exchange.AccountCurrencyInfo
|
||||
var currData []account.Balance
|
||||
for k := range resp.Result {
|
||||
currData = append(currData, exchange.AccountCurrencyInfo{
|
||||
currData = append(currData, account.Balance{
|
||||
CurrencyName: currency.NewCode(k),
|
||||
TotalValue: resp.Result[k].Available + resp.Result[k].Freeze,
|
||||
Hold: resp.Result[k].Freeze,
|
||||
})
|
||||
}
|
||||
info.Accounts = append(info.Accounts, exchange.Account{
|
||||
info.Accounts = append(info.Accounts, account.SubAccount{
|
||||
Currencies: currData,
|
||||
})
|
||||
} else {
|
||||
@@ -342,7 +343,7 @@ func (g *Gateio) GetAccountInfo() (exchange.AccountInfo, error) {
|
||||
return info, err
|
||||
}
|
||||
|
||||
balances = append(balances, exchange.AccountCurrencyInfo{
|
||||
balances = append(balances, account.Balance{
|
||||
CurrencyName: currency.NewCode(x),
|
||||
Hold: lockedF,
|
||||
})
|
||||
@@ -368,7 +369,7 @@ func (g *Gateio) GetAccountInfo() (exchange.AccountInfo, error) {
|
||||
}
|
||||
}
|
||||
if !updated {
|
||||
balances = append(balances, exchange.AccountCurrencyInfo{
|
||||
balances = append(balances, account.Balance{
|
||||
CurrencyName: currency.NewCode(x),
|
||||
TotalValue: availAmount,
|
||||
})
|
||||
@@ -378,16 +379,30 @@ func (g *Gateio) GetAccountInfo() (exchange.AccountInfo, error) {
|
||||
break
|
||||
}
|
||||
|
||||
info.Accounts = append(info.Accounts, exchange.Account{
|
||||
info.Accounts = append(info.Accounts, account.SubAccount{
|
||||
Currencies: balances,
|
||||
})
|
||||
}
|
||||
|
||||
info.Exchange = g.Name
|
||||
err := account.Process(&info)
|
||||
if err != nil {
|
||||
return account.Holdings{}, err
|
||||
}
|
||||
|
||||
return info, nil
|
||||
}
|
||||
|
||||
// FetchAccountInfo retrieves balances for all enabled currencies
|
||||
func (g *Gateio) FetchAccountInfo() (account.Holdings, error) {
|
||||
acc, err := account.GetHoldings(g.Name)
|
||||
if err != nil {
|
||||
return g.UpdateAccountInfo()
|
||||
}
|
||||
|
||||
return acc, nil
|
||||
}
|
||||
|
||||
// GetFundingHistory returns funding history, deposits and
|
||||
// withdrawals
|
||||
func (g *Gateio) GetFundingHistory() ([]exchange.FundHistory, error) {
|
||||
@@ -693,3 +708,10 @@ func (g *Gateio) AuthenticateWebsocket() error {
|
||||
_, err := g.wsServerSignIn()
|
||||
return err
|
||||
}
|
||||
|
||||
// ValidateCredentials validates current credentials used for wrapper
|
||||
// functionality
|
||||
func (g *Gateio) ValidateCredentials() error {
|
||||
_, err := g.UpdateAccountInfo()
|
||||
return g.CheckTransientError(err)
|
||||
}
|
||||
|
||||
@@ -294,7 +294,7 @@ func (g *Gemini) wsProcessUpdate(result WsMarketUpdateResponse, pair currency.Pa
|
||||
Exchange: g.Name}
|
||||
} else {
|
||||
var asks, bids []orderbook.Item
|
||||
for i := 0; i < len(result.Events); i++ {
|
||||
for i := range result.Events {
|
||||
if result.Events[i].Type == "trade" {
|
||||
g.Websocket.DataHandler <- wshandler.TradeData{
|
||||
Timestamp: time.Unix(0, result.Timestamp),
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"github.com/thrasher-corp/gocryptotrader/config"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/account"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
|
||||
@@ -209,32 +210,47 @@ func (g *Gemini) UpdateTradablePairs(forceUpdate bool) error {
|
||||
return g.UpdatePairs(currency.NewPairsFromStrings(pairs), asset.Spot, false, forceUpdate)
|
||||
}
|
||||
|
||||
// GetAccountInfo Retrieves balances for all enabled currencies for the
|
||||
// UpdateAccountInfo Retrieves balances for all enabled currencies for the
|
||||
// Gemini exchange
|
||||
func (g *Gemini) GetAccountInfo() (exchange.AccountInfo, error) {
|
||||
var response exchange.AccountInfo
|
||||
func (g *Gemini) UpdateAccountInfo() (account.Holdings, error) {
|
||||
var response account.Holdings
|
||||
response.Exchange = g.Name
|
||||
accountBalance, err := g.GetBalances()
|
||||
if err != nil {
|
||||
return response, err
|
||||
}
|
||||
|
||||
var currencies []exchange.AccountCurrencyInfo
|
||||
for i := 0; i < len(accountBalance); i++ {
|
||||
var exchangeCurrency exchange.AccountCurrencyInfo
|
||||
var currencies []account.Balance
|
||||
for i := range accountBalance {
|
||||
var exchangeCurrency account.Balance
|
||||
exchangeCurrency.CurrencyName = currency.NewCode(accountBalance[i].Currency)
|
||||
exchangeCurrency.TotalValue = accountBalance[i].Amount
|
||||
exchangeCurrency.Hold = accountBalance[i].Available
|
||||
currencies = append(currencies, exchangeCurrency)
|
||||
}
|
||||
|
||||
response.Accounts = append(response.Accounts, exchange.Account{
|
||||
response.Accounts = append(response.Accounts, account.SubAccount{
|
||||
Currencies: currencies,
|
||||
})
|
||||
|
||||
err = account.Process(&response)
|
||||
if err != nil {
|
||||
return account.Holdings{}, err
|
||||
}
|
||||
|
||||
return response, nil
|
||||
}
|
||||
|
||||
// FetchAccountInfo retrieves balances for all enabled currencies
|
||||
func (g *Gemini) FetchAccountInfo() (account.Holdings, error) {
|
||||
acc, err := account.GetHoldings(g.Name)
|
||||
if err != nil {
|
||||
return g.UpdateAccountInfo()
|
||||
}
|
||||
|
||||
return acc, nil
|
||||
}
|
||||
|
||||
// UpdateTicker updates and returns the ticker for a currency pair
|
||||
func (g *Gemini) UpdateTicker(p currency.Pair, assetType asset.Item) (*ticker.Price, error) {
|
||||
tickerPrice := new(ticker.Price)
|
||||
@@ -545,3 +561,10 @@ func (g *Gemini) GetSubscriptions() ([]wshandler.WebsocketChannelSubscription, e
|
||||
func (g *Gemini) AuthenticateWebsocket() error {
|
||||
return common.ErrFunctionNotSupported
|
||||
}
|
||||
|
||||
// ValidateCredentials validates current credentials used for wrapper
|
||||
// functionality
|
||||
func (g *Gemini) ValidateCredentials() error {
|
||||
_, err := g.UpdateAccountInfo()
|
||||
return g.CheckTransientError(err)
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"github.com/thrasher-corp/gocryptotrader/config"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/account"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
|
||||
@@ -336,33 +337,47 @@ func (h *HitBTC) UpdateOrderbook(currencyPair currency.Pair, assetType asset.Ite
|
||||
return orderbook.Get(h.Name, currencyPair, assetType)
|
||||
}
|
||||
|
||||
// GetAccountInfo retrieves balances for all enabled currencies for the
|
||||
// UpdateAccountInfo retrieves balances for all enabled currencies for the
|
||||
// HitBTC exchange
|
||||
func (h *HitBTC) GetAccountInfo() (exchange.AccountInfo, error) {
|
||||
var response exchange.AccountInfo
|
||||
func (h *HitBTC) UpdateAccountInfo() (account.Holdings, error) {
|
||||
var response account.Holdings
|
||||
response.Exchange = h.Name
|
||||
accountBalance, err := h.GetBalances()
|
||||
if err != nil {
|
||||
return response, err
|
||||
}
|
||||
|
||||
var currencies []exchange.AccountCurrencyInfo
|
||||
var currencies []account.Balance
|
||||
for i := range accountBalance {
|
||||
var exchangeCurrency exchange.AccountCurrencyInfo
|
||||
var exchangeCurrency account.Balance
|
||||
exchangeCurrency.CurrencyName = currency.NewCode(accountBalance[i].Currency)
|
||||
exchangeCurrency.TotalValue = accountBalance[i].Available
|
||||
exchangeCurrency.Hold = accountBalance[i].Reserved
|
||||
currencies = append(currencies, exchangeCurrency)
|
||||
}
|
||||
|
||||
response.Accounts = append(response.Accounts,
|
||||
exchange.Account{
|
||||
Currencies: currencies,
|
||||
})
|
||||
response.Accounts = append(response.Accounts, account.SubAccount{
|
||||
Currencies: currencies,
|
||||
})
|
||||
|
||||
err = account.Process(&response)
|
||||
if err != nil {
|
||||
return account.Holdings{}, err
|
||||
}
|
||||
|
||||
return response, nil
|
||||
}
|
||||
|
||||
// FetchAccountInfo retrieves balances for all enabled currencies
|
||||
func (h *HitBTC) FetchAccountInfo() (account.Holdings, error) {
|
||||
acc, err := account.GetHoldings(h.Name)
|
||||
if err != nil {
|
||||
return h.UpdateAccountInfo()
|
||||
}
|
||||
|
||||
return acc, nil
|
||||
}
|
||||
|
||||
// GetFundingHistory returns funding history, deposits and
|
||||
// withdrawals
|
||||
func (h *HitBTC) GetFundingHistory() ([]exchange.FundHistory, error) {
|
||||
@@ -598,3 +613,10 @@ func (h *HitBTC) GetSubscriptions() ([]wshandler.WebsocketChannelSubscription, e
|
||||
func (h *HitBTC) AuthenticateWebsocket() error {
|
||||
return h.wsLogin()
|
||||
}
|
||||
|
||||
// ValidateCredentials validates current credentials used for wrapper
|
||||
// functionality
|
||||
func (h *HitBTC) ValidateCredentials() error {
|
||||
_, err := h.UpdateAccountInfo()
|
||||
return h.CheckTransientError(err)
|
||||
}
|
||||
|
||||
@@ -565,12 +565,12 @@ func TestCancelAllExchangeOrders(t *testing.T) {
|
||||
|
||||
func TestGetAccountInfo(t *testing.T) {
|
||||
if !areTestAPIKeysSet() {
|
||||
_, err := h.GetAccountInfo()
|
||||
_, err := h.UpdateAccountInfo()
|
||||
if err == nil {
|
||||
t.Error("GetAccountInfo() Expected error")
|
||||
}
|
||||
} else {
|
||||
_, err := h.GetAccountInfo()
|
||||
_, err := h.UpdateAccountInfo()
|
||||
if err != nil {
|
||||
t.Error("GetAccountInfo() error", err)
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"github.com/thrasher-corp/gocryptotrader/config"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/account"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
|
||||
@@ -391,22 +392,22 @@ func (h *HUOBI) GetAccountID() ([]Account, error) {
|
||||
return acc, nil
|
||||
}
|
||||
|
||||
// GetAccountInfo retrieves balances for all enabled currencies for the
|
||||
// UpdateAccountInfo retrieves balances for all enabled currencies for the
|
||||
// HUOBI exchange - to-do
|
||||
func (h *HUOBI) GetAccountInfo() (exchange.AccountInfo, error) {
|
||||
var info exchange.AccountInfo
|
||||
func (h *HUOBI) UpdateAccountInfo() (account.Holdings, error) {
|
||||
var info account.Holdings
|
||||
info.Exchange = h.Name
|
||||
if h.Websocket.CanUseAuthenticatedWebsocketForWrapper() {
|
||||
resp, err := h.wsGetAccountsList()
|
||||
if err != nil {
|
||||
return info, err
|
||||
}
|
||||
var currencyDetails []exchange.AccountCurrencyInfo
|
||||
var currencyDetails []account.Balance
|
||||
for i := range resp.Data {
|
||||
if len(resp.Data[i].List) == 0 {
|
||||
continue
|
||||
}
|
||||
currData := exchange.AccountCurrencyInfo{
|
||||
currData := account.Balance{
|
||||
CurrencyName: currency.NewCode(resp.Data[i].List[0].Currency),
|
||||
TotalValue: resp.Data[i].List[0].Balance,
|
||||
}
|
||||
@@ -415,7 +416,7 @@ func (h *HUOBI) GetAccountInfo() (exchange.AccountInfo, error) {
|
||||
}
|
||||
currencyDetails = append(currencyDetails, currData)
|
||||
}
|
||||
var acc exchange.Account
|
||||
var acc account.SubAccount
|
||||
acc.Currencies = currencyDetails
|
||||
info.Accounts = append(info.Accounts, acc)
|
||||
} else {
|
||||
@@ -424,14 +425,14 @@ func (h *HUOBI) GetAccountInfo() (exchange.AccountInfo, error) {
|
||||
return info, err
|
||||
}
|
||||
for i := range accounts {
|
||||
var acc exchange.Account
|
||||
var acc account.SubAccount
|
||||
acc.ID = strconv.FormatInt(accounts[i].ID, 10)
|
||||
balances, err := h.GetAccountBalance(acc.ID)
|
||||
if err != nil {
|
||||
return info, err
|
||||
}
|
||||
|
||||
var currencyDetails []exchange.AccountCurrencyInfo
|
||||
var currencyDetails []account.Balance
|
||||
for j := range balances {
|
||||
var frozen bool
|
||||
if balances[j].Type == "frozen" {
|
||||
@@ -456,13 +457,13 @@ func (h *HUOBI) GetAccountInfo() (exchange.AccountInfo, error) {
|
||||
|
||||
if frozen {
|
||||
currencyDetails = append(currencyDetails,
|
||||
exchange.AccountCurrencyInfo{
|
||||
account.Balance{
|
||||
CurrencyName: currency.NewCode(balances[j].Currency),
|
||||
Hold: balances[j].Balance,
|
||||
})
|
||||
} else {
|
||||
currencyDetails = append(currencyDetails,
|
||||
exchange.AccountCurrencyInfo{
|
||||
account.Balance{
|
||||
CurrencyName: currency.NewCode(balances[j].Currency),
|
||||
TotalValue: balances[j].Balance,
|
||||
})
|
||||
@@ -473,9 +474,25 @@ func (h *HUOBI) GetAccountInfo() (exchange.AccountInfo, error) {
|
||||
info.Accounts = append(info.Accounts, acc)
|
||||
}
|
||||
}
|
||||
|
||||
err := account.Process(&info)
|
||||
if err != nil {
|
||||
return account.Holdings{}, err
|
||||
}
|
||||
|
||||
return info, nil
|
||||
}
|
||||
|
||||
// FetchAccountInfo retrieves balances for all enabled currencies
|
||||
func (h *HUOBI) FetchAccountInfo() (account.Holdings, error) {
|
||||
acc, err := account.GetHoldings(h.Name)
|
||||
if err != nil {
|
||||
return h.UpdateAccountInfo()
|
||||
}
|
||||
|
||||
return acc, nil
|
||||
}
|
||||
|
||||
// GetFundingHistory returns funding history, deposits and
|
||||
// withdrawals
|
||||
func (h *HUOBI) GetFundingHistory() ([]exchange.FundHistory, error) {
|
||||
@@ -845,3 +862,10 @@ func (h *HUOBI) GetSubscriptions() ([]wshandler.WebsocketChannelSubscription, er
|
||||
func (h *HUOBI) AuthenticateWebsocket() error {
|
||||
return h.wsLogin()
|
||||
}
|
||||
|
||||
// ValidateCredentials validates current credentials used for wrapper
|
||||
// functionality
|
||||
func (h *HUOBI) ValidateCredentials() error {
|
||||
_, err := h.UpdateAccountInfo()
|
||||
return h.CheckTransientError(err)
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
|
||||
"github.com/thrasher-corp/gocryptotrader/config"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/account"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
|
||||
@@ -22,6 +23,7 @@ type IBotExchange interface {
|
||||
GetName() string
|
||||
IsEnabled() bool
|
||||
SetEnabled(bool)
|
||||
ValidateCredentials() error
|
||||
FetchTicker(currency currency.Pair, assetType asset.Item) (*ticker.Price, error)
|
||||
UpdateTicker(currency currency.Pair, assetType asset.Item) (*ticker.Price, error)
|
||||
FetchOrderbook(currency currency.Pair, assetType asset.Item) (*orderbook.Base, error)
|
||||
@@ -30,7 +32,8 @@ type IBotExchange interface {
|
||||
UpdateTradablePairs(forceUpdate bool) error
|
||||
GetEnabledPairs(assetType asset.Item) currency.Pairs
|
||||
GetAvailablePairs(assetType asset.Item) currency.Pairs
|
||||
GetAccountInfo() (AccountInfo, error)
|
||||
FetchAccountInfo() (account.Holdings, error)
|
||||
UpdateAccountInfo() (account.Holdings, error)
|
||||
GetAuthenticatedAPISupport(endpoint uint8) bool
|
||||
SetPairs(pairs currency.Pairs, assetType asset.Item, enabled bool) error
|
||||
GetAssetTypes() asset.Items
|
||||
|
||||
@@ -372,7 +372,7 @@ func TestCancelAllExchangeOrders(t *testing.T) {
|
||||
|
||||
func TestGetAccountInfo(t *testing.T) {
|
||||
if areTestAPIKeysSet() {
|
||||
_, err := i.GetAccountInfo()
|
||||
_, err := i.UpdateAccountInfo()
|
||||
if err == nil {
|
||||
t.Error("GetAccountInfo() Expected error")
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"github.com/thrasher-corp/gocryptotrader/config"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/account"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
|
||||
@@ -239,9 +240,9 @@ func (i *ItBit) UpdateOrderbook(p currency.Pair, assetType asset.Item) (*orderbo
|
||||
return orderbook.Get(i.Name, p, assetType)
|
||||
}
|
||||
|
||||
// GetAccountInfo retrieves balances for all enabled currencies
|
||||
func (i *ItBit) GetAccountInfo() (exchange.AccountInfo, error) {
|
||||
var info exchange.AccountInfo
|
||||
// UpdateAccountInfo retrieves balances for all enabled currencies
|
||||
func (i *ItBit) UpdateAccountInfo() (account.Holdings, error) {
|
||||
var info account.Holdings
|
||||
info.Exchange = i.Name
|
||||
|
||||
wallets, err := i.GetWallets(url.Values{})
|
||||
@@ -267,22 +268,37 @@ func (i *ItBit) GetAccountInfo() (exchange.AccountInfo, error) {
|
||||
}
|
||||
}
|
||||
|
||||
var fullBalance []exchange.AccountCurrencyInfo
|
||||
var fullBalance []account.Balance
|
||||
for key := range amounts {
|
||||
fullBalance = append(fullBalance, exchange.AccountCurrencyInfo{
|
||||
fullBalance = append(fullBalance, account.Balance{
|
||||
CurrencyName: currency.NewCode(key),
|
||||
TotalValue: amounts[key].TotalValue,
|
||||
Hold: amounts[key].Hold,
|
||||
})
|
||||
}
|
||||
|
||||
info.Accounts = append(info.Accounts, exchange.Account{
|
||||
info.Accounts = append(info.Accounts, account.SubAccount{
|
||||
Currencies: fullBalance,
|
||||
})
|
||||
|
||||
err = account.Process(&info)
|
||||
if err != nil {
|
||||
return account.Holdings{}, err
|
||||
}
|
||||
|
||||
return info, nil
|
||||
}
|
||||
|
||||
// FetchAccountInfo retrieves balances for all enabled currencies
|
||||
func (i *ItBit) FetchAccountInfo() (account.Holdings, error) {
|
||||
acc, err := account.GetHoldings(i.Name)
|
||||
if err != nil {
|
||||
return i.UpdateAccountInfo()
|
||||
}
|
||||
|
||||
return acc, nil
|
||||
}
|
||||
|
||||
// GetFundingHistory returns funding history, deposits and
|
||||
// withdrawals
|
||||
func (i *ItBit) GetFundingHistory() ([]exchange.FundHistory, error) {
|
||||
@@ -547,3 +563,10 @@ func (i *ItBit) GetSubscriptions() ([]wshandler.WebsocketChannelSubscription, er
|
||||
func (i *ItBit) AuthenticateWebsocket() error {
|
||||
return common.ErrFunctionNotSupported
|
||||
}
|
||||
|
||||
// ValidateCredentials validates current credentials used for wrapper
|
||||
// functionality
|
||||
func (i *ItBit) ValidateCredentials() error {
|
||||
_, err := i.UpdateAccountInfo()
|
||||
return i.CheckTransientError(err)
|
||||
}
|
||||
|
||||
@@ -505,12 +505,12 @@ func TestCancelAllExchangeOrders(t *testing.T) {
|
||||
// TestGetAccountInfo wrapper test
|
||||
func TestGetAccountInfo(t *testing.T) {
|
||||
if areTestAPIKeysSet() || clientID != "" {
|
||||
_, err := k.GetAccountInfo()
|
||||
_, err := k.UpdateAccountInfo()
|
||||
if err != nil {
|
||||
t.Error("GetAccountInfo() error", err)
|
||||
}
|
||||
} else {
|
||||
_, err := k.GetAccountInfo()
|
||||
_, err := k.UpdateAccountInfo()
|
||||
if err == nil {
|
||||
t.Error("GetAccountInfo() Expected error")
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"github.com/thrasher-corp/gocryptotrader/config"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/account"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
|
||||
@@ -373,10 +374,10 @@ func (k *Kraken) UpdateOrderbook(p currency.Pair, assetType asset.Item) (*orderb
|
||||
return orderbook.Get(k.Name, p, assetType)
|
||||
}
|
||||
|
||||
// GetAccountInfo retrieves balances for all enabled currencies for the
|
||||
// UpdateAccountInfo retrieves balances for all enabled currencies for the
|
||||
// Kraken exchange - to-do
|
||||
func (k *Kraken) GetAccountInfo() (exchange.AccountInfo, error) {
|
||||
var info exchange.AccountInfo
|
||||
func (k *Kraken) UpdateAccountInfo() (account.Holdings, error) {
|
||||
var info account.Holdings
|
||||
info.Exchange = k.Name
|
||||
|
||||
bal, err := k.GetBalance()
|
||||
@@ -384,21 +385,36 @@ func (k *Kraken) GetAccountInfo() (exchange.AccountInfo, error) {
|
||||
return info, err
|
||||
}
|
||||
|
||||
var balances []exchange.AccountCurrencyInfo
|
||||
var balances []account.Balance
|
||||
for key := range bal {
|
||||
balances = append(balances, exchange.AccountCurrencyInfo{
|
||||
balances = append(balances, account.Balance{
|
||||
CurrencyName: currency.NewCode(key),
|
||||
TotalValue: bal[key],
|
||||
})
|
||||
}
|
||||
|
||||
info.Accounts = append(info.Accounts, exchange.Account{
|
||||
info.Accounts = append(info.Accounts, account.SubAccount{
|
||||
Currencies: balances,
|
||||
})
|
||||
|
||||
err = account.Process(&info)
|
||||
if err != nil {
|
||||
return account.Holdings{}, err
|
||||
}
|
||||
|
||||
return info, nil
|
||||
}
|
||||
|
||||
// FetchAccountInfo retrieves balances for all enabled currencies
|
||||
func (k *Kraken) FetchAccountInfo() (account.Holdings, error) {
|
||||
acc, err := account.GetHoldings(k.Name)
|
||||
if err != nil {
|
||||
return k.UpdateAccountInfo()
|
||||
}
|
||||
|
||||
return acc, nil
|
||||
}
|
||||
|
||||
// GetFundingHistory returns funding history, deposits and
|
||||
// withdrawals
|
||||
func (k *Kraken) GetFundingHistory() ([]exchange.FundHistory, error) {
|
||||
@@ -705,3 +721,10 @@ func (k *Kraken) AuthenticateWebsocket() error {
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// ValidateCredentials validates current credentials used for wrapper
|
||||
// functionality
|
||||
func (k *Kraken) ValidateCredentials() error {
|
||||
_, err := k.UpdateAccountInfo()
|
||||
return k.CheckTransientError(err)
|
||||
}
|
||||
|
||||
@@ -146,7 +146,7 @@ func (l *LakeBTC) processTrades(data, channel string) error {
|
||||
return err
|
||||
}
|
||||
curr := l.getCurrencyFromChannel(channel)
|
||||
for i := 0; i < len(tradeData.Trades); i++ {
|
||||
for i := range tradeData.Trades {
|
||||
l.Websocket.DataHandler <- wshandler.TradeData{
|
||||
Timestamp: time.Unix(tradeData.Trades[i].Date, 0),
|
||||
CurrencyPair: curr,
|
||||
@@ -177,7 +177,7 @@ func (l *LakeBTC) processOrderbook(obUpdate, channel string) error {
|
||||
ExchangeName: l.Name,
|
||||
}
|
||||
|
||||
for i := 0; i < len(update.Asks); i++ {
|
||||
for i := range update.Asks {
|
||||
var amount, price float64
|
||||
amount, err = strconv.ParseFloat(update.Asks[i][1], 64)
|
||||
if err != nil {
|
||||
@@ -195,7 +195,7 @@ func (l *LakeBTC) processOrderbook(obUpdate, channel string) error {
|
||||
})
|
||||
}
|
||||
|
||||
for i := 0; i < len(update.Bids); i++ {
|
||||
for i := range update.Bids {
|
||||
var amount, price float64
|
||||
amount, err = strconv.ParseFloat(update.Bids[i][1], 64)
|
||||
if err != nil {
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"github.com/thrasher-corp/gocryptotrader/config"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/account"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
|
||||
@@ -283,23 +284,23 @@ func (l *LakeBTC) UpdateOrderbook(p currency.Pair, assetType asset.Item) (*order
|
||||
return orderbook.Get(l.Name, p, assetType)
|
||||
}
|
||||
|
||||
// GetAccountInfo retrieves balances for all enabled currencies for the
|
||||
// UpdateAccountInfo retrieves balances for all enabled currencies for the
|
||||
// LakeBTC exchange
|
||||
func (l *LakeBTC) GetAccountInfo() (exchange.AccountInfo, error) {
|
||||
var response exchange.AccountInfo
|
||||
func (l *LakeBTC) UpdateAccountInfo() (account.Holdings, error) {
|
||||
var response account.Holdings
|
||||
response.Exchange = l.Name
|
||||
accountInfo, err := l.GetAccountInformation()
|
||||
if err != nil {
|
||||
return response, err
|
||||
}
|
||||
|
||||
var currencies []exchange.AccountCurrencyInfo
|
||||
var currencies []account.Balance
|
||||
for x, y := range accountInfo.Balance {
|
||||
for z, w := range accountInfo.Locked {
|
||||
if z != x {
|
||||
continue
|
||||
}
|
||||
var exchangeCurrency exchange.AccountCurrencyInfo
|
||||
var exchangeCurrency account.Balance
|
||||
exchangeCurrency.CurrencyName = currency.NewCode(x)
|
||||
exchangeCurrency.TotalValue, _ = strconv.ParseFloat(y, 64)
|
||||
exchangeCurrency.Hold, _ = strconv.ParseFloat(w, 64)
|
||||
@@ -307,13 +308,28 @@ func (l *LakeBTC) GetAccountInfo() (exchange.AccountInfo, error) {
|
||||
}
|
||||
}
|
||||
|
||||
response.Accounts = append(response.Accounts, exchange.Account{
|
||||
response.Accounts = append(response.Accounts, account.SubAccount{
|
||||
Currencies: currencies,
|
||||
})
|
||||
|
||||
err = account.Process(&response)
|
||||
if err != nil {
|
||||
return account.Holdings{}, err
|
||||
}
|
||||
|
||||
return response, nil
|
||||
}
|
||||
|
||||
// FetchAccountInfo retrieves balances for all enabled currencies
|
||||
func (l *LakeBTC) FetchAccountInfo() (account.Holdings, error) {
|
||||
acc, err := account.GetHoldings(l.Name)
|
||||
if err != nil {
|
||||
return l.UpdateAccountInfo()
|
||||
}
|
||||
|
||||
return acc, nil
|
||||
}
|
||||
|
||||
// GetFundingHistory returns funding history, deposits and
|
||||
// withdrawals
|
||||
func (l *LakeBTC) GetFundingHistory() ([]exchange.FundHistory, error) {
|
||||
@@ -534,3 +550,10 @@ func (l *LakeBTC) GetSubscriptions() ([]wshandler.WebsocketChannelSubscription,
|
||||
func (l *LakeBTC) AuthenticateWebsocket() error {
|
||||
return common.ErrFunctionNotSupported
|
||||
}
|
||||
|
||||
// ValidateCredentials validates current credentials used for wrapper
|
||||
// functionality
|
||||
func (l *LakeBTC) ValidateCredentials() error {
|
||||
_, err := l.UpdateAccountInfo()
|
||||
return l.CheckTransientError(err)
|
||||
}
|
||||
|
||||
@@ -388,7 +388,7 @@ func TestGetAccountInfo(t *testing.T) {
|
||||
if !areTestAPIKeysSet() {
|
||||
t.Skip("API keys required but not set, skipping test")
|
||||
}
|
||||
_, err := l.GetAccountInfo()
|
||||
_, err := l.UpdateAccountInfo()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
"github.com/thrasher-corp/gocryptotrader/config"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/account"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
|
||||
@@ -249,40 +250,55 @@ func (l *Lbank) UpdateOrderbook(p currency.Pair, assetType asset.Item) (*orderbo
|
||||
return orderbook.Get(l.Name, p, assetType)
|
||||
}
|
||||
|
||||
// GetAccountInfo retrieves balances for all enabled currencies for the
|
||||
// UpdateAccountInfo retrieves balances for all enabled currencies for the
|
||||
// Lbank exchange
|
||||
func (l *Lbank) GetAccountInfo() (exchange.AccountInfo, error) {
|
||||
var info exchange.AccountInfo
|
||||
func (l *Lbank) UpdateAccountInfo() (account.Holdings, error) {
|
||||
var info account.Holdings
|
||||
data, err := l.GetUserInfo()
|
||||
if err != nil {
|
||||
return info, err
|
||||
}
|
||||
var account exchange.Account
|
||||
var acc account.SubAccount
|
||||
for key, val := range data.Info.Asset {
|
||||
c := currency.NewCode(key)
|
||||
hold, ok := data.Info.Freeze[key]
|
||||
if !ok {
|
||||
return info, fmt.Errorf("hold data not found with %s", key)
|
||||
}
|
||||
totalVal, err := strconv.ParseFloat(val, 64)
|
||||
if err != nil {
|
||||
return info, err
|
||||
totalVal, parseErr := strconv.ParseFloat(val, 64)
|
||||
if parseErr != nil {
|
||||
return info, parseErr
|
||||
}
|
||||
totalHold, err := strconv.ParseFloat(hold, 64)
|
||||
if err != nil {
|
||||
return info, err
|
||||
totalHold, parseErr := strconv.ParseFloat(hold, 64)
|
||||
if parseErr != nil {
|
||||
return info, parseErr
|
||||
}
|
||||
account.Currencies = append(account.Currencies,
|
||||
exchange.AccountCurrencyInfo{CurrencyName: c,
|
||||
TotalValue: totalVal,
|
||||
Hold: totalHold})
|
||||
acc.Currencies = append(acc.Currencies, account.Balance{
|
||||
CurrencyName: c,
|
||||
TotalValue: totalVal,
|
||||
Hold: totalHold})
|
||||
}
|
||||
|
||||
info.Accounts = append(info.Accounts, account)
|
||||
info.Accounts = append(info.Accounts, acc)
|
||||
info.Exchange = l.Name
|
||||
|
||||
err = account.Process(&info)
|
||||
if err != nil {
|
||||
return account.Holdings{}, err
|
||||
}
|
||||
return info, nil
|
||||
}
|
||||
|
||||
// FetchAccountInfo retrieves balances for all enabled currencies
|
||||
func (l *Lbank) FetchAccountInfo() (account.Holdings, error) {
|
||||
acc, err := account.GetHoldings(l.Name)
|
||||
if err != nil {
|
||||
return l.UpdateAccountInfo()
|
||||
}
|
||||
|
||||
return acc, nil
|
||||
}
|
||||
|
||||
// GetFundingHistory returns funding history, deposits and
|
||||
// withdrawals
|
||||
func (l *Lbank) GetFundingHistory() ([]exchange.FundHistory, error) {
|
||||
@@ -690,3 +706,10 @@ func (l *Lbank) AuthenticateWebsocket() error {
|
||||
func (l *Lbank) GetSubscriptions() ([]wshandler.WebsocketChannelSubscription, error) {
|
||||
return nil, common.ErrNotYetImplemented
|
||||
}
|
||||
|
||||
// ValidateCredentials validates current credentials used for wrapper
|
||||
// functionality
|
||||
func (l *Lbank) ValidateCredentials() error {
|
||||
_, err := l.UpdateAccountInfo()
|
||||
return l.CheckTransientError(err)
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
"github.com/thrasher-corp/gocryptotrader/config"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/account"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
|
||||
@@ -244,25 +245,41 @@ func (l *LocalBitcoins) UpdateOrderbook(p currency.Pair, assetType asset.Item) (
|
||||
return orderbook.Get(l.Name, p, assetType)
|
||||
}
|
||||
|
||||
// GetAccountInfo retrieves balances for all enabled currencies for the
|
||||
// UpdateAccountInfo retrieves balances for all enabled currencies for the
|
||||
// LocalBitcoins exchange
|
||||
func (l *LocalBitcoins) GetAccountInfo() (exchange.AccountInfo, error) {
|
||||
var response exchange.AccountInfo
|
||||
func (l *LocalBitcoins) UpdateAccountInfo() (account.Holdings, error) {
|
||||
var response account.Holdings
|
||||
response.Exchange = l.Name
|
||||
accountBalance, err := l.GetWalletBalance()
|
||||
if err != nil {
|
||||
return response, err
|
||||
}
|
||||
var exchangeCurrency exchange.AccountCurrencyInfo
|
||||
var exchangeCurrency account.Balance
|
||||
exchangeCurrency.CurrencyName = currency.BTC
|
||||
exchangeCurrency.TotalValue = accountBalance.Total.Balance
|
||||
|
||||
response.Accounts = append(response.Accounts, exchange.Account{
|
||||
Currencies: []exchange.AccountCurrencyInfo{exchangeCurrency},
|
||||
response.Accounts = append(response.Accounts, account.SubAccount{
|
||||
Currencies: []account.Balance{exchangeCurrency},
|
||||
})
|
||||
|
||||
err = account.Process(&response)
|
||||
if err != nil {
|
||||
return account.Holdings{}, err
|
||||
}
|
||||
|
||||
return response, nil
|
||||
}
|
||||
|
||||
// FetchAccountInfo retrieves balances for all enabled currencies
|
||||
func (l *LocalBitcoins) FetchAccountInfo() (account.Holdings, error) {
|
||||
acc, err := account.GetHoldings(l.Name)
|
||||
if err != nil {
|
||||
return l.UpdateAccountInfo()
|
||||
}
|
||||
|
||||
return acc, nil
|
||||
}
|
||||
|
||||
// GetFundingHistory returns funding history, deposits and
|
||||
// withdrawals
|
||||
func (l *LocalBitcoins) GetFundingHistory() ([]exchange.FundHistory, error) {
|
||||
@@ -571,3 +588,10 @@ func (l *LocalBitcoins) GetSubscriptions() ([]wshandler.WebsocketChannelSubscrip
|
||||
func (l *LocalBitcoins) AuthenticateWebsocket() error {
|
||||
return common.ErrFunctionNotSupported
|
||||
}
|
||||
|
||||
// ValidateCredentials validates current credentials used for wrapper
|
||||
// functionality
|
||||
func (l *LocalBitcoins) ValidateCredentials() error {
|
||||
_, err := l.UpdateAccountInfo()
|
||||
return l.CheckTransientError(err)
|
||||
}
|
||||
|
||||
@@ -83,6 +83,7 @@ func areTestAPIKeysSet() bool {
|
||||
}
|
||||
|
||||
func testStandardErrorHandling(t *testing.T, err error) {
|
||||
t.Helper()
|
||||
if !areTestAPIKeysSet() && err == nil {
|
||||
t.Error("Expecting an error when no keys are set")
|
||||
}
|
||||
@@ -1042,7 +1043,7 @@ func TestCancelAllExchangeOrders(t *testing.T) {
|
||||
|
||||
// TestGetAccountInfo Wrapper test
|
||||
func TestGetAccountInfo(t *testing.T) {
|
||||
_, err := o.GetAccountInfo()
|
||||
_, err := o.UpdateAccountInfo()
|
||||
testStandardErrorHandling(t, err)
|
||||
}
|
||||
|
||||
|
||||
@@ -1732,7 +1732,7 @@ func TestCancelAllExchangeOrders(t *testing.T) {
|
||||
|
||||
// TestGetAccountInfo Wrapper test
|
||||
func TestGetAccountInfo(t *testing.T) {
|
||||
_, err := o.GetAccountInfo()
|
||||
_, err := o.UpdateAccountInfo()
|
||||
testStandardErrorHandling(t, err)
|
||||
}
|
||||
|
||||
|
||||
@@ -10,12 +10,12 @@ import (
|
||||
"github.com/thrasher-corp/gocryptotrader/config"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/account"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/withdraw"
|
||||
log "github.com/thrasher-corp/gocryptotrader/logger"
|
||||
)
|
||||
|
||||
// Note: GoCryptoTrader wrapper funcs currently only support SPOT trades.
|
||||
@@ -170,27 +170,28 @@ func (o *OKGroup) UpdateOrderbook(p currency.Pair, a asset.Item) (*orderbook.Bas
|
||||
return orderbook.Get(o.Name, p, a)
|
||||
}
|
||||
|
||||
// GetAccountInfo retrieves balances for all enabled currencies
|
||||
func (o *OKGroup) GetAccountInfo() (resp exchange.AccountInfo, err error) {
|
||||
resp.Exchange = o.Name
|
||||
// UpdateAccountInfo retrieves balances for all enabled currencies
|
||||
func (o *OKGroup) UpdateAccountInfo() (account.Holdings, error) {
|
||||
currencies, err := o.GetSpotTradingAccounts()
|
||||
currencyAccount := exchange.Account{}
|
||||
if err != nil {
|
||||
return account.Holdings{}, err
|
||||
}
|
||||
|
||||
var resp account.Holdings
|
||||
resp.Exchange = o.Name
|
||||
currencyAccount := account.SubAccount{}
|
||||
|
||||
for i := range currencies {
|
||||
hold, err := strconv.ParseFloat(currencies[i].Hold, 64)
|
||||
if err != nil {
|
||||
log.Errorf(log.ExchangeSys,
|
||||
"Could not convert %v to float64",
|
||||
currencies[i].Hold)
|
||||
hold, parseErr := strconv.ParseFloat(currencies[i].Hold, 64)
|
||||
if parseErr != nil {
|
||||
return resp, parseErr
|
||||
}
|
||||
totalValue, err := strconv.ParseFloat(currencies[i].Balance, 64)
|
||||
if err != nil {
|
||||
log.Errorf(log.ExchangeSys,
|
||||
"Could not convert %v to float64",
|
||||
currencies[i].Balance)
|
||||
totalValue, parseErr := strconv.ParseFloat(currencies[i].Balance, 64)
|
||||
if parseErr != nil {
|
||||
return resp, parseErr
|
||||
}
|
||||
currencyAccount.Currencies = append(currencyAccount.Currencies,
|
||||
exchange.AccountCurrencyInfo{
|
||||
account.Balance{
|
||||
CurrencyName: currency.NewCode(currencies[i].Currency),
|
||||
Hold: hold,
|
||||
TotalValue: totalValue,
|
||||
@@ -198,7 +199,23 @@ func (o *OKGroup) GetAccountInfo() (resp exchange.AccountInfo, err error) {
|
||||
}
|
||||
|
||||
resp.Accounts = append(resp.Accounts, currencyAccount)
|
||||
return
|
||||
|
||||
err = account.Process(&resp)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// FetchAccountInfo retrieves balances for all enabled currencies
|
||||
func (o *OKGroup) FetchAccountInfo() (account.Holdings, error) {
|
||||
acc, err := account.GetHoldings(o.Name)
|
||||
if err != nil {
|
||||
return o.UpdateAccountInfo()
|
||||
}
|
||||
|
||||
return acc, nil
|
||||
}
|
||||
|
||||
// GetFundingHistory returns funding history, deposits and
|
||||
@@ -503,3 +520,10 @@ func (o *OKGroup) GetSubscriptions() ([]wshandler.WebsocketChannelSubscription,
|
||||
func (o *OKGroup) AuthenticateWebsocket() error {
|
||||
return o.WsLogin()
|
||||
}
|
||||
|
||||
// ValidateCredentials validates current credentials used for wrapper
|
||||
// functionality
|
||||
func (o *OKGroup) ValidateCredentials() error {
|
||||
_, err := o.UpdateAccountInfo()
|
||||
return o.CheckTransientError(err)
|
||||
}
|
||||
|
||||
@@ -424,7 +424,7 @@ var stringsToOrderSide = []struct {
|
||||
}
|
||||
|
||||
func TestStringToOrderSide(t *testing.T) {
|
||||
for i := 0; i < len(stringsToOrderSide); i++ {
|
||||
for i := range stringsToOrderSide {
|
||||
testData := &stringsToOrderSide[i]
|
||||
t.Run(testData.in, func(t *testing.T) {
|
||||
out, err := StringToOrderSide(testData.in)
|
||||
@@ -466,7 +466,7 @@ var stringsToOrderType = []struct {
|
||||
}
|
||||
|
||||
func TestStringToOrderType(t *testing.T) {
|
||||
for i := 0; i < len(stringsToOrderType); i++ {
|
||||
for i := range stringsToOrderType {
|
||||
testData := &stringsToOrderType[i]
|
||||
t.Run(testData.in, func(t *testing.T) {
|
||||
out, err := StringToOrderType(testData.in)
|
||||
@@ -520,7 +520,7 @@ var stringsToOrderStatus = []struct {
|
||||
}
|
||||
|
||||
func TestStringToOrderStatus(t *testing.T) {
|
||||
for i := 0; i < len(stringsToOrderStatus); i++ {
|
||||
for i := range stringsToOrderStatus {
|
||||
testData := &stringsToOrderStatus[i]
|
||||
t.Run(testData.in, func(t *testing.T) {
|
||||
out, err := StringToOrderStatus(testData.in)
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
"github.com/thrasher-corp/gocryptotrader/config"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/account"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
|
||||
@@ -321,31 +322,46 @@ func (p *Poloniex) UpdateOrderbook(currencyPair currency.Pair, assetType asset.I
|
||||
return orderbook.Get(p.Name, currencyPair, assetType)
|
||||
}
|
||||
|
||||
// GetAccountInfo retrieves balances for all enabled currencies for the
|
||||
// UpdateAccountInfo retrieves balances for all enabled currencies for the
|
||||
// Poloniex exchange
|
||||
func (p *Poloniex) GetAccountInfo() (exchange.AccountInfo, error) {
|
||||
var response exchange.AccountInfo
|
||||
func (p *Poloniex) UpdateAccountInfo() (account.Holdings, error) {
|
||||
var response account.Holdings
|
||||
response.Exchange = p.Name
|
||||
accountBalance, err := p.GetBalances()
|
||||
if err != nil {
|
||||
return response, err
|
||||
}
|
||||
|
||||
var currencies []exchange.AccountCurrencyInfo
|
||||
var currencies []account.Balance
|
||||
for x, y := range accountBalance.Currency {
|
||||
var exchangeCurrency exchange.AccountCurrencyInfo
|
||||
var exchangeCurrency account.Balance
|
||||
exchangeCurrency.CurrencyName = currency.NewCode(x)
|
||||
exchangeCurrency.TotalValue = y
|
||||
currencies = append(currencies, exchangeCurrency)
|
||||
}
|
||||
|
||||
response.Accounts = append(response.Accounts, exchange.Account{
|
||||
response.Accounts = append(response.Accounts, account.SubAccount{
|
||||
Currencies: currencies,
|
||||
})
|
||||
|
||||
err = account.Process(&response)
|
||||
if err != nil {
|
||||
return account.Holdings{}, err
|
||||
}
|
||||
|
||||
return response, nil
|
||||
}
|
||||
|
||||
// FetchAccountInfo retrieves balances for all enabled currencies
|
||||
func (p *Poloniex) FetchAccountInfo() (account.Holdings, error) {
|
||||
acc, err := account.GetHoldings(p.Name)
|
||||
if err != nil {
|
||||
return p.UpdateAccountInfo()
|
||||
}
|
||||
|
||||
return acc, nil
|
||||
}
|
||||
|
||||
// GetFundingHistory returns funding history, deposits and
|
||||
// withdrawals
|
||||
func (p *Poloniex) GetFundingHistory() ([]exchange.FundHistory, error) {
|
||||
@@ -606,3 +622,10 @@ func (p *Poloniex) GetSubscriptions() ([]wshandler.WebsocketChannelSubscription,
|
||||
func (p *Poloniex) AuthenticateWebsocket() error {
|
||||
return common.ErrFunctionNotSupported
|
||||
}
|
||||
|
||||
// ValidateCredentials validates current credentials used for wrapper
|
||||
// functionality
|
||||
func (p *Poloniex) ValidateCredentials() error {
|
||||
_, err := p.UpdateAccountInfo()
|
||||
return p.CheckTransientError(err)
|
||||
}
|
||||
|
||||
@@ -302,14 +302,11 @@ func (r *Requester) DoRequest(req *http.Request, path string, body io.Reader, re
|
||||
}
|
||||
}
|
||||
|
||||
if resp.StatusCode != 200 && resp.StatusCode != 201 && resp.StatusCode != 202 {
|
||||
err = fmt.Errorf("unsuccessful HTTP status code: %d", resp.StatusCode)
|
||||
if verbose {
|
||||
err = fmt.Errorf("%s\n%s", err.Error(),
|
||||
fmt.Sprintf("%s exchange raw response: %s", r.Name, string(contents)))
|
||||
}
|
||||
|
||||
return err
|
||||
if resp.StatusCode < http.StatusOK ||
|
||||
resp.StatusCode > http.StatusAccepted {
|
||||
return fmt.Errorf("unsuccessful HTTP status code: %d body: %s",
|
||||
resp.StatusCode,
|
||||
string(contents))
|
||||
}
|
||||
|
||||
if httpDebug {
|
||||
|
||||
@@ -479,7 +479,7 @@ func (w *Websocket) manageSubscriptions() {
|
||||
func (w *Websocket) appendSubscribedChannels() error {
|
||||
w.subscriptionMutex.Lock()
|
||||
defer w.subscriptionMutex.Unlock()
|
||||
for i := 0; i < len(w.channelsToSubscribe); i++ {
|
||||
for i := range w.channelsToSubscribe {
|
||||
channelIsSubscribed := false
|
||||
for j := 0; j < len(w.subscribedChannels); j++ {
|
||||
if w.subscribedChannels[j].Equal(&w.channelsToSubscribe[i]) {
|
||||
@@ -506,7 +506,7 @@ func (w *Websocket) appendSubscribedChannels() error {
|
||||
func (w *Websocket) unsubscribeToChannels() error {
|
||||
w.subscriptionMutex.Lock()
|
||||
defer w.subscriptionMutex.Unlock()
|
||||
for i := 0; i < len(w.subscribedChannels); i++ {
|
||||
for i := range w.subscribedChannels {
|
||||
subscriptionFound := false
|
||||
for j := 0; j < len(w.channelsToSubscribe); j++ {
|
||||
if w.channelsToSubscribe[j].Equal(&w.subscribedChannels[i]) {
|
||||
|
||||
@@ -542,7 +542,7 @@ func TestDial(t *testing.T) {
|
||||
{Error: errors.New(" Error: malformed ws or wss URL"), WC: WebsocketConnection{ExchangeName: "test2", Verbose: true, URL: "", ResponseCheckTimeout: 30000000, ResponseMaxLimit: 7000000000}},
|
||||
{Error: nil, WC: WebsocketConnection{ExchangeName: "test3", Verbose: true, URL: websocketTestURL, ProxyURL: proxyURL, ResponseCheckTimeout: 30000000, ResponseMaxLimit: 7000000000}},
|
||||
}
|
||||
for i := 0; i < len(testCases); i++ {
|
||||
for i := range testCases {
|
||||
testData := &testCases[i]
|
||||
t.Run(testData.WC.ExchangeName, func(t *testing.T) {
|
||||
if testData.WC.ProxyURL != "" && !useProxyTests {
|
||||
@@ -566,7 +566,7 @@ func TestSendMessage(t *testing.T) {
|
||||
{Error: errors.New(" Error: malformed ws or wss URL"), WC: WebsocketConnection{ExchangeName: "test2", Verbose: true, URL: "", ResponseCheckTimeout: 30000000, ResponseMaxLimit: 7000000000}},
|
||||
{Error: nil, WC: WebsocketConnection{ExchangeName: "test3", Verbose: true, URL: websocketTestURL, ProxyURL: proxyURL, ResponseCheckTimeout: 30000000, ResponseMaxLimit: 7000000000}},
|
||||
}
|
||||
for i := 0; i < len(testCases); i++ {
|
||||
for i := range testCases {
|
||||
testData := &testCases[i]
|
||||
t.Run(testData.WC.ExchangeName, func(t *testing.T) {
|
||||
if testData.WC.ProxyURL != "" && !useProxyTests {
|
||||
|
||||
@@ -86,7 +86,7 @@ func (w *WebsocketOrderbookLocal) processBufferUpdate(o *orderbook.Base, u *Webs
|
||||
})
|
||||
}
|
||||
}
|
||||
for i := 0; i < len(bufferLookup); i++ {
|
||||
for i := range bufferLookup {
|
||||
w.processObUpdate(o, bufferLookup[i])
|
||||
}
|
||||
w.buffer[u.Pair][u.Asset] = bufferLookup
|
||||
|
||||
@@ -280,7 +280,7 @@ func TestHittingTheBuffer(t *testing.T) {
|
||||
}
|
||||
obl.bufferEnabled = true
|
||||
obl.obBufferLimit = 5
|
||||
for i := 0; i < len(itemArray); i++ {
|
||||
for i := range itemArray {
|
||||
asks := itemArray[i]
|
||||
bids := itemArray[i]
|
||||
err = obl.Update(&WebsocketOrderbookUpdate{
|
||||
@@ -314,7 +314,7 @@ func TestInsertWithIDs(t *testing.T) {
|
||||
obl.bufferEnabled = true
|
||||
obl.updateEntriesByID = true
|
||||
obl.obBufferLimit = 5
|
||||
for i := 0; i < len(itemArray); i++ {
|
||||
for i := range itemArray {
|
||||
asks := itemArray[i]
|
||||
bids := itemArray[i]
|
||||
err = obl.Update(&WebsocketOrderbookUpdate{
|
||||
@@ -349,7 +349,7 @@ func TestSortIDs(t *testing.T) {
|
||||
obl.sortBufferByUpdateIDs = true
|
||||
obl.sortBuffer = true
|
||||
obl.obBufferLimit = 5
|
||||
for i := 0; i < len(itemArray); i++ {
|
||||
for i := range itemArray {
|
||||
asks := itemArray[i]
|
||||
bids := itemArray[i]
|
||||
err = obl.Update(&WebsocketOrderbookUpdate{
|
||||
@@ -394,7 +394,7 @@ func TestDeleteWithIDs(t *testing.T) {
|
||||
itemArray[1][0])
|
||||
|
||||
obl.updateEntriesByID = true
|
||||
for i := 0; i < len(itemArray); i++ {
|
||||
for i := range itemArray {
|
||||
asks := itemArray[i]
|
||||
bids := itemArray[i]
|
||||
err = obl.Update(&WebsocketOrderbookUpdate{
|
||||
@@ -427,7 +427,7 @@ func TestUpdateWithIDs(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
obl.updateEntriesByID = true
|
||||
for i := 0; i < len(itemArray); i++ {
|
||||
for i := range itemArray {
|
||||
asks := itemArray[i]
|
||||
bids := itemArray[i]
|
||||
err = obl.Update(&WebsocketOrderbookUpdate{
|
||||
@@ -467,7 +467,7 @@ func TestOutOfOrderIDs(t *testing.T) {
|
||||
obl.bufferEnabled = true
|
||||
obl.sortBuffer = true
|
||||
obl.obBufferLimit = 5
|
||||
for i := 0; i < len(itemArray); i++ {
|
||||
for i := range itemArray {
|
||||
asks := itemArray[i]
|
||||
err = obl.Update(&WebsocketOrderbookUpdate{
|
||||
Asks: asks,
|
||||
|
||||
@@ -89,7 +89,7 @@ func TestGetTrades(t *testing.T) {
|
||||
|
||||
func TestGetAccountInfo(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := y.GetAccountInfo()
|
||||
_, err := y.UpdateAccountInfo()
|
||||
if err == nil {
|
||||
t.Error("GetAccountInfo() Expected error")
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"github.com/thrasher-corp/gocryptotrader/config"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/account"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
|
||||
@@ -267,19 +268,19 @@ func (y *Yobit) UpdateOrderbook(p currency.Pair, assetType asset.Item) (*orderbo
|
||||
return orderbook.Get(y.Name, p, assetType)
|
||||
}
|
||||
|
||||
// GetAccountInfo retrieves balances for all enabled currencies for the
|
||||
// UpdateAccountInfo retrieves balances for all enabled currencies for the
|
||||
// Yobit exchange
|
||||
func (y *Yobit) GetAccountInfo() (exchange.AccountInfo, error) {
|
||||
var response exchange.AccountInfo
|
||||
func (y *Yobit) UpdateAccountInfo() (account.Holdings, error) {
|
||||
var response account.Holdings
|
||||
response.Exchange = y.Name
|
||||
accountBalance, err := y.GetAccountInformation()
|
||||
if err != nil {
|
||||
return response, err
|
||||
}
|
||||
|
||||
var currencies []exchange.AccountCurrencyInfo
|
||||
var currencies []account.Balance
|
||||
for x, y := range accountBalance.FundsInclOrders {
|
||||
var exchangeCurrency exchange.AccountCurrencyInfo
|
||||
var exchangeCurrency account.Balance
|
||||
exchangeCurrency.CurrencyName = currency.NewCode(x)
|
||||
exchangeCurrency.TotalValue = y
|
||||
exchangeCurrency.Hold = 0
|
||||
@@ -292,13 +293,28 @@ func (y *Yobit) GetAccountInfo() (exchange.AccountInfo, error) {
|
||||
currencies = append(currencies, exchangeCurrency)
|
||||
}
|
||||
|
||||
response.Accounts = append(response.Accounts, exchange.Account{
|
||||
response.Accounts = append(response.Accounts, account.SubAccount{
|
||||
Currencies: currencies,
|
||||
})
|
||||
|
||||
err = account.Process(&response)
|
||||
if err != nil {
|
||||
return account.Holdings{}, err
|
||||
}
|
||||
|
||||
return response, nil
|
||||
}
|
||||
|
||||
// FetchAccountInfo retrieves balances for all enabled currencies
|
||||
func (y *Yobit) FetchAccountInfo() (account.Holdings, error) {
|
||||
acc, err := account.GetHoldings(y.Name)
|
||||
if err != nil {
|
||||
return y.UpdateAccountInfo()
|
||||
}
|
||||
|
||||
return acc, nil
|
||||
}
|
||||
|
||||
// GetFundingHistory returns funding history, deposits and
|
||||
// withdrawals
|
||||
func (y *Yobit) GetFundingHistory() ([]exchange.FundHistory, error) {
|
||||
@@ -540,3 +556,10 @@ func (y *Yobit) GetSubscriptions() ([]wshandler.WebsocketChannelSubscription, er
|
||||
func (y *Yobit) AuthenticateWebsocket() error {
|
||||
return common.ErrFunctionNotSupported
|
||||
}
|
||||
|
||||
// ValidateCredentials validates current credentials used for wrapper
|
||||
// functionality
|
||||
func (y *Yobit) ValidateCredentials() error {
|
||||
_, err := y.UpdateAccountInfo()
|
||||
return y.CheckTransientError(err)
|
||||
}
|
||||
|
||||
@@ -391,12 +391,12 @@ func TestCancelAllExchangeOrders(t *testing.T) {
|
||||
|
||||
func TestGetAccountInfo(t *testing.T) {
|
||||
if z.ValidateAPICredentials() {
|
||||
_, err := z.GetAccountInfo()
|
||||
_, err := z.UpdateAccountInfo()
|
||||
if err != nil {
|
||||
t.Error("GetAccountInfo() error", err)
|
||||
}
|
||||
} else {
|
||||
_, err := z.GetAccountInfo()
|
||||
_, err := z.UpdateAccountInfo()
|
||||
if err == nil {
|
||||
t.Error("GetAccountInfo() Expected error")
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"github.com/thrasher-corp/gocryptotrader/config"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/account"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
|
||||
@@ -303,11 +304,11 @@ func (z *ZB) UpdateOrderbook(p currency.Pair, assetType asset.Item) (*orderbook.
|
||||
return orderbook.Get(z.Name, p, assetType)
|
||||
}
|
||||
|
||||
// GetAccountInfo retrieves balances for all enabled currencies for the
|
||||
// UpdateAccountInfo retrieves balances for all enabled currencies for the
|
||||
// ZB exchange
|
||||
func (z *ZB) GetAccountInfo() (exchange.AccountInfo, error) {
|
||||
var info exchange.AccountInfo
|
||||
var balances []exchange.AccountCurrencyInfo
|
||||
func (z *ZB) UpdateAccountInfo() (account.Holdings, error) {
|
||||
var info account.Holdings
|
||||
var balances []account.Balance
|
||||
var coins []AccountsResponseCoin
|
||||
if z.Websocket.CanUseAuthenticatedWebsocketForWrapper() {
|
||||
resp, err := z.wsGetAccountInfoRequest()
|
||||
@@ -334,7 +335,7 @@ func (z *ZB) GetAccountInfo() (exchange.AccountInfo, error) {
|
||||
return info, err
|
||||
}
|
||||
|
||||
balances = append(balances, exchange.AccountCurrencyInfo{
|
||||
balances = append(balances, account.Balance{
|
||||
CurrencyName: currency.NewCode(coins[i].EnName),
|
||||
TotalValue: hold + avail,
|
||||
Hold: hold,
|
||||
@@ -342,13 +343,28 @@ func (z *ZB) GetAccountInfo() (exchange.AccountInfo, error) {
|
||||
}
|
||||
|
||||
info.Exchange = z.Name
|
||||
info.Accounts = append(info.Accounts, exchange.Account{
|
||||
info.Accounts = append(info.Accounts, account.SubAccount{
|
||||
Currencies: balances,
|
||||
})
|
||||
|
||||
err := account.Process(&info)
|
||||
if err != nil {
|
||||
return account.Holdings{}, err
|
||||
}
|
||||
|
||||
return info, nil
|
||||
}
|
||||
|
||||
// FetchAccountInfo retrieves balances for all enabled currencies
|
||||
func (z *ZB) FetchAccountInfo() (account.Holdings, error) {
|
||||
acc, err := account.GetHoldings(z.Name)
|
||||
if err != nil {
|
||||
return z.UpdateAccountInfo()
|
||||
}
|
||||
|
||||
return acc, nil
|
||||
}
|
||||
|
||||
// GetFundingHistory returns funding history, deposits and
|
||||
// withdrawals
|
||||
func (z *ZB) GetFundingHistory() ([]exchange.FundHistory, error) {
|
||||
@@ -666,3 +682,10 @@ func (z *ZB) GetSubscriptions() ([]wshandler.WebsocketChannelSubscription, error
|
||||
func (z *ZB) AuthenticateWebsocket() error {
|
||||
return common.ErrFunctionNotSupported
|
||||
}
|
||||
|
||||
// ValidateCredentials validates current credentials used for wrapper
|
||||
// functionality
|
||||
func (z *ZB) ValidateCredentials() error {
|
||||
_, err := z.UpdateAccountInfo()
|
||||
return z.CheckTransientError(err)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user