mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-05-13 23:16:45 +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:
@@ -111,7 +111,7 @@ func testWrappers(e exchange.IBotExchange) []string {
|
||||
funcs = append(funcs, "UpdateTradablePairs")
|
||||
}
|
||||
|
||||
_, err = e.GetAccountInfo()
|
||||
_, err = e.FetchAccountInfo()
|
||||
if err == common.ErrNotYetImplemented {
|
||||
funcs = append(funcs, "GetAccountInfo")
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ import (
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
"github.com/thrasher-corp/gocryptotrader/engine"
|
||||
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"
|
||||
@@ -398,15 +399,15 @@ func testWrappers(e exchange.IBotExchange, base *exchange.Base, config *Config)
|
||||
})
|
||||
}
|
||||
|
||||
var r7 exchange.AccountInfo
|
||||
r7, err = e.GetAccountInfo()
|
||||
var r7 account.Holdings
|
||||
r7, err = e.FetchAccountInfo()
|
||||
msg = ""
|
||||
if err != nil {
|
||||
msg = err.Error()
|
||||
responseContainer.ErrorCount++
|
||||
}
|
||||
responseContainer.EndpointResponses = append(responseContainer.EndpointResponses, EndpointResponse{
|
||||
Function: "GetAccountInfo",
|
||||
Function: "FetchAccountInfo",
|
||||
Error: msg,
|
||||
Response: jsonifyInterface([]interface{}{r7}),
|
||||
})
|
||||
|
||||
@@ -770,6 +770,67 @@ func getAccountInfo(c *cli.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
var getAccountInfoStreamCommand = cli.Command{
|
||||
Name: "getaccountinfostream",
|
||||
Usage: "gets the account info stream for a specific exchange",
|
||||
ArgsUsage: "<exchange>",
|
||||
Action: getAccountInfoStream,
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "exchange",
|
||||
Usage: "the exchange to get the account info stream from",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
func getAccountInfoStream(c *cli.Context) error {
|
||||
if c.NArg() == 0 && c.NumFlags() == 0 {
|
||||
cli.ShowCommandHelp(c, "getaccountinfostream")
|
||||
return nil
|
||||
}
|
||||
|
||||
var exchangeName string
|
||||
|
||||
if c.IsSet("exchange") {
|
||||
exchangeName = c.String("exchange")
|
||||
} else {
|
||||
exchangeName = c.Args().First()
|
||||
}
|
||||
|
||||
if !validExchange(exchangeName) {
|
||||
return errInvalidExchange
|
||||
}
|
||||
|
||||
conn, err := setupClient()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
client := gctrpc.NewGoCryptoTraderClient(conn)
|
||||
result, err := client.GetAccountInfoStream(context.Background(),
|
||||
&gctrpc.GetAccountInfoRequest{Exchange: exchangeName})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for {
|
||||
resp, err := result.Recv()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = clearScreen()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Printf("Account balance stream for %s:\n\n", exchangeName)
|
||||
|
||||
fmt.Printf("%+v", resp)
|
||||
}
|
||||
}
|
||||
|
||||
var getConfigCommand = cli.Command{
|
||||
Name: "getconfig",
|
||||
Usage: "gets the config",
|
||||
|
||||
@@ -102,6 +102,7 @@ func main() {
|
||||
getOrderbookCommand,
|
||||
getOrderbooksCommand,
|
||||
getAccountInfoCommand,
|
||||
getAccountInfoStreamCommand,
|
||||
getConfigCommand,
|
||||
getPortfolioCommand,
|
||||
getPortfolioSummaryCommand,
|
||||
|
||||
@@ -59,17 +59,6 @@ func dryrunParamInteraction(param string) {
|
||||
}
|
||||
}
|
||||
|
||||
// CheckExchangeExists returns true whether or not an exchange has already
|
||||
// been loaded
|
||||
func CheckExchangeExists(exchName string) bool {
|
||||
for x := range Bot.Exchanges {
|
||||
if strings.EqualFold(Bot.Exchanges[x].GetName(), exchName) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// GetExchangeByName returns an exchange given an exchange name
|
||||
func GetExchangeByName(exchName string) exchange.IBotExchange {
|
||||
for x := range Bot.Exchanges {
|
||||
@@ -86,7 +75,8 @@ func ReloadExchange(name string) error {
|
||||
return ErrNoExchangesLoaded
|
||||
}
|
||||
|
||||
if !CheckExchangeExists(name) {
|
||||
e := GetExchangeByName(name)
|
||||
if e == nil {
|
||||
return ErrExchangeNotFound
|
||||
}
|
||||
|
||||
@@ -95,7 +85,6 @@ func ReloadExchange(name string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
e := GetExchangeByName(name)
|
||||
e.Setup(exchCfg)
|
||||
log.Debugf(log.ExchangeSys, "%s exchange reloaded successfully.\n", name)
|
||||
return nil
|
||||
@@ -107,7 +96,7 @@ func UnloadExchange(name string) error {
|
||||
return ErrNoExchangesLoaded
|
||||
}
|
||||
|
||||
if !CheckExchangeExists(name) {
|
||||
if GetExchangeByName(name) == nil {
|
||||
return ErrExchangeNotFound
|
||||
}
|
||||
|
||||
@@ -139,7 +128,7 @@ func LoadExchange(name string, useWG bool, wg *sync.WaitGroup) error {
|
||||
var exch exchange.IBotExchange
|
||||
|
||||
if len(Bot.Exchanges) > 0 {
|
||||
if CheckExchangeExists(name) {
|
||||
if GetExchangeByName(name) != nil {
|
||||
return ErrExchangeAlreadyLoaded
|
||||
}
|
||||
}
|
||||
@@ -288,55 +277,65 @@ func LoadExchange(name string, useWG bool, wg *sync.WaitGroup) error {
|
||||
|
||||
Bot.Exchanges = append(Bot.Exchanges, exch)
|
||||
|
||||
base := exch.GetBase()
|
||||
if base.API.AuthenticatedSupport ||
|
||||
base.API.AuthenticatedWebsocketSupport {
|
||||
err = exch.ValidateCredentials()
|
||||
if err != nil {
|
||||
log.Warnf(log.ExchangeSys,
|
||||
"%s: Cannot validate credentials, authenticated support has been disabled, Error: %s\n",
|
||||
base.Name,
|
||||
err)
|
||||
base.API.AuthenticatedSupport = false
|
||||
base.API.AuthenticatedWebsocketSupport = false
|
||||
exchCfg.API.AuthenticatedSupport = false
|
||||
exchCfg.API.AuthenticatedWebsocketSupport = false
|
||||
}
|
||||
}
|
||||
|
||||
if useWG {
|
||||
exch.Start(wg)
|
||||
} else {
|
||||
wg := sync.WaitGroup{}
|
||||
exch.Start(&wg)
|
||||
wg.Wait()
|
||||
tempWG := sync.WaitGroup{}
|
||||
exch.Start(&tempWG)
|
||||
tempWG.Wait()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetupExchanges sets up the exchanges used by the Bot
|
||||
func SetupExchanges() {
|
||||
var wg sync.WaitGroup
|
||||
exchanges := Bot.Config.GetAllExchangeConfigs()
|
||||
for x := range exchanges {
|
||||
exch := exchanges[x]
|
||||
if CheckExchangeExists(exch.Name) {
|
||||
e := GetExchangeByName(exch.Name)
|
||||
if e == nil {
|
||||
log.Errorln(log.ExchangeSys, ErrExchangeNotFound)
|
||||
continue
|
||||
}
|
||||
|
||||
err := ReloadExchange(exch.Name)
|
||||
configs := Bot.Config.GetAllExchangeConfigs()
|
||||
for x := range configs {
|
||||
if e := GetExchangeByName(configs[x].Name); e != nil {
|
||||
err := ReloadExchange(configs[x].Name)
|
||||
if err != nil {
|
||||
log.Errorf(log.ExchangeSys, "ReloadExchange %s failed: %s\n", exch.Name, err)
|
||||
log.Errorf(log.ExchangeSys, "ReloadExchange %s failed: %s\n", configs[x].Name, err)
|
||||
continue
|
||||
}
|
||||
|
||||
if !e.IsEnabled() {
|
||||
UnloadExchange(exch.Name)
|
||||
UnloadExchange(configs[x].Name)
|
||||
continue
|
||||
}
|
||||
return
|
||||
}
|
||||
if !exch.Enabled && !Bot.Settings.EnableAllExchanges {
|
||||
log.Debugf(log.ExchangeSys, "%s: Exchange support: Disabled\n", exch.Name)
|
||||
if !configs[x].Enabled && !Bot.Settings.EnableAllExchanges {
|
||||
log.Debugf(log.ExchangeSys, "%s: Exchange support: Disabled\n", configs[x].Name)
|
||||
continue
|
||||
}
|
||||
err := LoadExchange(exch.Name, true, &wg)
|
||||
err := LoadExchange(configs[x].Name, true, &wg)
|
||||
if err != nil {
|
||||
log.Errorf(log.ExchangeSys, "LoadExchange %s failed: %s\n", exch.Name, err)
|
||||
log.Errorf(log.ExchangeSys, "LoadExchange %s failed: %s\n", configs[x].Name, err)
|
||||
continue
|
||||
}
|
||||
log.Debugf(log.ExchangeSys,
|
||||
"%s: Exchange support: Enabled (Authenticated API support: %s - Verbose mode: %s).\n",
|
||||
exch.Name,
|
||||
common.IsEnabled(exch.API.AuthenticatedSupport),
|
||||
common.IsEnabled(exch.Verbose),
|
||||
configs[x].Name,
|
||||
common.IsEnabled(configs[x].API.AuthenticatedSupport),
|
||||
common.IsEnabled(configs[x].Verbose),
|
||||
)
|
||||
}
|
||||
wg.Wait()
|
||||
|
||||
@@ -21,7 +21,7 @@ func SetupTest(t *testing.T) {
|
||||
testSetup = true
|
||||
}
|
||||
|
||||
if CheckExchangeExists(testExchange) {
|
||||
if GetExchangeByName(testExchange) != nil {
|
||||
return
|
||||
}
|
||||
err := LoadExchange(testExchange, false, nil)
|
||||
@@ -31,7 +31,7 @@ func SetupTest(t *testing.T) {
|
||||
}
|
||||
|
||||
func CleanupTest(t *testing.T) {
|
||||
if !CheckExchangeExists(testExchange) {
|
||||
if GetExchangeByName(testExchange) == nil {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -45,11 +45,11 @@ func CleanupTest(t *testing.T) {
|
||||
func TestCheckExchangeExists(t *testing.T) {
|
||||
SetupTest(t)
|
||||
|
||||
if !CheckExchangeExists(testExchange) {
|
||||
if GetExchangeByName(testExchange) == nil {
|
||||
t.Errorf("TestGetExchangeExists: Unable to find exchange")
|
||||
}
|
||||
|
||||
if CheckExchangeExists("Asdsad") {
|
||||
if GetExchangeByName("Asdsad") != nil {
|
||||
t.Errorf("TestGetExchangeExists: Non-existent exchange found")
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ import (
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
"github.com/thrasher-corp/gocryptotrader/dispatch"
|
||||
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/orderbook"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/stats"
|
||||
@@ -447,18 +448,21 @@ func GetSpecificTicker(p currency.Pair, exchangeName string, assetType asset.Ite
|
||||
// GetCollatedExchangeAccountInfoByCoin collates individual exchange account
|
||||
// information and turns into into a map string of
|
||||
// exchange.AccountCurrencyInfo
|
||||
func GetCollatedExchangeAccountInfoByCoin(exchAccounts []exchange.AccountInfo) map[currency.Code]exchange.AccountCurrencyInfo {
|
||||
result := make(map[currency.Code]exchange.AccountCurrencyInfo)
|
||||
for _, accounts := range exchAccounts {
|
||||
for _, account := range accounts.Accounts {
|
||||
for _, accountCurrencyInfo := range account.Currencies {
|
||||
currencyName := accountCurrencyInfo.CurrencyName
|
||||
avail := accountCurrencyInfo.TotalValue
|
||||
onHold := accountCurrencyInfo.Hold
|
||||
|
||||
func GetCollatedExchangeAccountInfoByCoin(accounts []account.Holdings) map[currency.Code]account.Balance {
|
||||
result := make(map[currency.Code]account.Balance)
|
||||
for x := range accounts {
|
||||
for y := range accounts[x].Accounts {
|
||||
for z := range accounts[x].Accounts[y].Currencies {
|
||||
currencyName := accounts[x].Accounts[y].Currencies[z].CurrencyName
|
||||
avail := accounts[x].Accounts[y].Currencies[z].TotalValue
|
||||
onHold := accounts[x].Accounts[y].Currencies[z].Hold
|
||||
info, ok := result[currencyName]
|
||||
if !ok {
|
||||
accountInfo := exchange.AccountCurrencyInfo{CurrencyName: currencyName, Hold: onHold, TotalValue: avail}
|
||||
accountInfo := account.Balance{
|
||||
CurrencyName: currencyName,
|
||||
Hold: onHold,
|
||||
TotalValue: avail,
|
||||
}
|
||||
result[currencyName] = accountInfo
|
||||
} else {
|
||||
info.Hold += onHold
|
||||
@@ -471,16 +475,6 @@ func GetCollatedExchangeAccountInfoByCoin(exchAccounts []exchange.AccountInfo) m
|
||||
return result
|
||||
}
|
||||
|
||||
// GetAccountCurrencyInfoByExchangeName returns info for an exchange
|
||||
func GetAccountCurrencyInfoByExchangeName(accounts []exchange.AccountInfo, exchangeName string) (exchange.AccountInfo, error) {
|
||||
for i := 0; i < len(accounts); i++ {
|
||||
if accounts[i].Exchange == exchangeName {
|
||||
return accounts[i], nil
|
||||
}
|
||||
}
|
||||
return exchange.AccountInfo{}, ErrExchangeNotFound
|
||||
}
|
||||
|
||||
// GetExchangeHighestPriceByCurrencyPair returns the exchange with the highest
|
||||
// price for a given currency pair and asset type
|
||||
func GetExchangeHighestPriceByCurrencyPair(p currency.Pair, assetType asset.Item) (string, error) {
|
||||
@@ -504,23 +498,23 @@ func GetExchangeLowestPriceByCurrencyPair(p currency.Pair, assetType asset.Item)
|
||||
}
|
||||
|
||||
// SeedExchangeAccountInfo seeds account info
|
||||
func SeedExchangeAccountInfo(data []exchange.AccountInfo) {
|
||||
if len(data) == 0 {
|
||||
func SeedExchangeAccountInfo(accounts []account.Holdings) {
|
||||
if len(accounts) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
port := portfolio.GetPortfolio()
|
||||
|
||||
for _, exchangeData := range data {
|
||||
exchangeName := exchangeData.Exchange
|
||||
var currencies []exchange.AccountCurrencyInfo
|
||||
for _, account := range exchangeData.Accounts {
|
||||
for _, info := range account.Currencies {
|
||||
for x := range accounts {
|
||||
exchangeName := accounts[x].Exchange
|
||||
var currencies []account.Balance
|
||||
for y := range accounts[x].Accounts {
|
||||
for z := range accounts[x].Accounts[y].Currencies {
|
||||
var update bool
|
||||
for i := range currencies {
|
||||
if info.CurrencyName == currencies[i].CurrencyName {
|
||||
currencies[i].Hold += info.Hold
|
||||
currencies[i].TotalValue += info.TotalValue
|
||||
if accounts[x].Accounts[y].Currencies[z].CurrencyName == currencies[i].CurrencyName {
|
||||
currencies[i].Hold += accounts[x].Accounts[y].Currencies[z].Hold
|
||||
currencies[i].TotalValue += accounts[x].Accounts[y].Currencies[z].TotalValue
|
||||
update = true
|
||||
}
|
||||
}
|
||||
@@ -529,17 +523,17 @@ func SeedExchangeAccountInfo(data []exchange.AccountInfo) {
|
||||
continue
|
||||
}
|
||||
|
||||
currencies = append(currencies, exchange.AccountCurrencyInfo{
|
||||
CurrencyName: info.CurrencyName,
|
||||
TotalValue: info.TotalValue,
|
||||
Hold: info.Hold,
|
||||
currencies = append(currencies, account.Balance{
|
||||
CurrencyName: accounts[x].Accounts[y].Currencies[z].CurrencyName,
|
||||
TotalValue: accounts[x].Accounts[y].Currencies[z].TotalValue,
|
||||
Hold: accounts[x].Accounts[y].Currencies[z].Hold,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
for _, total := range currencies {
|
||||
currencyName := total.CurrencyName
|
||||
total := total.TotalValue
|
||||
for x := range currencies {
|
||||
currencyName := currencies[x].CurrencyName
|
||||
total := currencies[x].TotalValue
|
||||
|
||||
if !port.ExchangeAddressExists(exchangeName, currencyName) {
|
||||
if total <= 0 {
|
||||
@@ -768,7 +762,7 @@ func GetAllEnabledExchangeAccountInfo() AllEnabledExchangeAccounts {
|
||||
}
|
||||
continue
|
||||
}
|
||||
individualExchange, err := individualBot.GetAccountInfo()
|
||||
individualExchange, err := individualBot.FetchAccountInfo()
|
||||
if err != nil {
|
||||
log.Errorf(log.ExchangeSys, "Error encountered retrieving exchange account info for %s. Error %s\n",
|
||||
individualBot.GetName(), err)
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"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/orderbook"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/stats"
|
||||
@@ -453,13 +453,13 @@ func TestGetSpecificTicker(t *testing.T) {
|
||||
func TestGetCollatedExchangeAccountInfoByCoin(t *testing.T) {
|
||||
SetupTestHelpers(t)
|
||||
|
||||
var exchangeInfo []exchange.AccountInfo
|
||||
var info exchange.AccountInfo
|
||||
var exchangeInfo []account.Holdings
|
||||
|
||||
info.Exchange = "Bitfinex"
|
||||
info.Accounts = append(info.Accounts,
|
||||
exchange.Account{
|
||||
Currencies: []exchange.AccountCurrencyInfo{
|
||||
var bitfinexHoldings account.Holdings
|
||||
bitfinexHoldings.Exchange = "Bitfinex"
|
||||
bitfinexHoldings.Accounts = append(bitfinexHoldings.Accounts,
|
||||
account.SubAccount{
|
||||
Currencies: []account.Balance{
|
||||
{
|
||||
CurrencyName: currency.BTC,
|
||||
TotalValue: 100,
|
||||
@@ -468,21 +468,27 @@ func TestGetCollatedExchangeAccountInfoByCoin(t *testing.T) {
|
||||
},
|
||||
})
|
||||
|
||||
exchangeInfo = append(exchangeInfo, info)
|
||||
exchangeInfo = append(exchangeInfo, bitfinexHoldings)
|
||||
|
||||
info.Exchange = "Bitstamp"
|
||||
info.Accounts = append(info.Accounts,
|
||||
exchange.Account{
|
||||
Currencies: []exchange.AccountCurrencyInfo{
|
||||
var bitstampHoldings account.Holdings
|
||||
bitstampHoldings.Exchange = "Bitstamp"
|
||||
bitstampHoldings.Accounts = append(bitstampHoldings.Accounts,
|
||||
account.SubAccount{
|
||||
Currencies: []account.Balance{
|
||||
{
|
||||
CurrencyName: currency.LTC,
|
||||
TotalValue: 100,
|
||||
Hold: 0,
|
||||
},
|
||||
{
|
||||
CurrencyName: currency.BTC,
|
||||
TotalValue: 100,
|
||||
Hold: 0,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
exchangeInfo = append(exchangeInfo, info)
|
||||
exchangeInfo = append(exchangeInfo, bitstampHoldings)
|
||||
|
||||
result := GetCollatedExchangeAccountInfoByCoin(exchangeInfo)
|
||||
if len(result) == 0 {
|
||||
@@ -504,40 +510,6 @@ func TestGetCollatedExchangeAccountInfoByCoin(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetAccountCurrencyInfoByExchangeName(t *testing.T) {
|
||||
SetupTestHelpers(t)
|
||||
|
||||
var exchangeInfo []exchange.AccountInfo
|
||||
var info exchange.AccountInfo
|
||||
info.Exchange = "Bitfinex"
|
||||
info.Accounts = append(info.Accounts,
|
||||
exchange.Account{
|
||||
Currencies: []exchange.AccountCurrencyInfo{
|
||||
{
|
||||
CurrencyName: currency.BTC,
|
||||
TotalValue: 100,
|
||||
Hold: 0,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
exchangeInfo = append(exchangeInfo, info)
|
||||
|
||||
result, err := GetAccountCurrencyInfoByExchangeName(exchangeInfo, "Bitfinex")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if result.Exchange != "Bitfinex" {
|
||||
t.Fatal("Unexepcted result")
|
||||
}
|
||||
|
||||
_, err = GetAccountCurrencyInfoByExchangeName(exchangeInfo, "ASDF")
|
||||
if err != ErrExchangeNotFound {
|
||||
t.Fatal("Unexepcted result")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetExchangeHighestPriceByCurrencyPair(t *testing.T) {
|
||||
SetupTestHelpers(t)
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ package engine
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/account"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
|
||||
)
|
||||
@@ -42,5 +42,5 @@ type EnabledExchangeCurrencies struct {
|
||||
|
||||
// AllEnabledExchangeAccounts holds all enabled accounts info
|
||||
type AllEnabledExchangeAccounts struct {
|
||||
Data []exchange.AccountInfo `json:"data"`
|
||||
Data []account.Holdings `json:"data"`
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ import (
|
||||
"github.com/thrasher-corp/gocryptotrader/database/models/postgres"
|
||||
"github.com/thrasher-corp/gocryptotrader/database/models/sqlite3"
|
||||
"github.com/thrasher-corp/gocryptotrader/database/repository/audit"
|
||||
"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"
|
||||
@@ -448,7 +449,7 @@ func (s *RPCServer) GetAccountInfo(ctx context.Context, r *gctrpc.GetAccountInfo
|
||||
return nil, errors.New("exchange is not loaded/doesn't exist")
|
||||
}
|
||||
|
||||
resp, err := exch.GetAccountInfo()
|
||||
resp, err := exch.FetchAccountInfo()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -470,6 +471,87 @@ func (s *RPCServer) GetAccountInfo(ctx context.Context, r *gctrpc.GetAccountInfo
|
||||
return &gctrpc.GetAccountInfoResponse{Exchange: r.Exchange, Accounts: accounts}, nil
|
||||
}
|
||||
|
||||
// GetAccountInfoStream streams an account balance for a specific exchange
|
||||
func (s *RPCServer) GetAccountInfoStream(r *gctrpc.GetAccountInfoRequest, stream gctrpc.GoCryptoTrader_GetAccountInfoStreamServer) error {
|
||||
if r.Exchange == "" {
|
||||
return errors.New(errExchangeNameUnset)
|
||||
}
|
||||
|
||||
exch := GetExchangeByName(r.Exchange)
|
||||
if exch == nil {
|
||||
return errors.New("exchange is not loaded/doesn't exist")
|
||||
}
|
||||
|
||||
initAcc, err := exch.FetchAccountInfo()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var accounts []*gctrpc.Account
|
||||
for x := range initAcc.Accounts {
|
||||
var subAccounts []*gctrpc.AccountCurrencyInfo
|
||||
for y := range initAcc.Accounts[x].Currencies {
|
||||
subAccounts = append(subAccounts, &gctrpc.AccountCurrencyInfo{
|
||||
Currency: initAcc.Accounts[x].Currencies[y].CurrencyName.String(),
|
||||
TotalValue: initAcc.Accounts[x].Currencies[y].TotalValue,
|
||||
Hold: initAcc.Accounts[x].Currencies[y].Hold,
|
||||
})
|
||||
}
|
||||
accounts = append(accounts, &gctrpc.Account{
|
||||
Id: initAcc.Accounts[x].ID,
|
||||
Currencies: subAccounts,
|
||||
})
|
||||
}
|
||||
|
||||
err = stream.Send(&gctrpc.GetAccountInfoResponse{
|
||||
Exchange: initAcc.Exchange,
|
||||
Accounts: accounts,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
pipe, err := account.SubscribeToExchangeAccount(r.Exchange)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer pipe.Release()
|
||||
|
||||
for {
|
||||
data, ok := <-pipe.C
|
||||
if !ok {
|
||||
return errors.New(errDispatchSystem)
|
||||
}
|
||||
|
||||
acc := (*data.(*interface{})).(account.Holdings)
|
||||
|
||||
var accounts []*gctrpc.Account
|
||||
for x := range acc.Accounts {
|
||||
var subAccounts []*gctrpc.AccountCurrencyInfo
|
||||
for y := range acc.Accounts[x].Currencies {
|
||||
subAccounts = append(subAccounts, &gctrpc.AccountCurrencyInfo{
|
||||
Currency: acc.Accounts[x].Currencies[y].CurrencyName.String(),
|
||||
TotalValue: acc.Accounts[x].Currencies[y].TotalValue,
|
||||
Hold: acc.Accounts[x].Currencies[y].Hold,
|
||||
})
|
||||
}
|
||||
accounts = append(accounts, &gctrpc.Account{
|
||||
Id: acc.Accounts[x].ID,
|
||||
Currencies: subAccounts,
|
||||
})
|
||||
}
|
||||
|
||||
err := stream.Send(&gctrpc.GetAccountInfoResponse{
|
||||
Exchange: acc.Exchange,
|
||||
Accounts: accounts,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// GetConfig returns the bots config
|
||||
func (s *RPCServer) GetConfig(ctx context.Context, r *gctrpc.GetConfigRequest) (*gctrpc.GetConfigResponse, error) {
|
||||
return &gctrpc.GetConfigResponse{}, common.ErrNotYetImplemented
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
760
gctrpc/rpc.pb.go
760
gctrpc/rpc.pb.go
@@ -5972,350 +5972,351 @@ func init() {
|
||||
func init() { proto.RegisterFile("rpc.proto", fileDescriptor_77a6da22d6a3feb1) }
|
||||
|
||||
var fileDescriptor_77a6da22d6a3feb1 = []byte{
|
||||
// 5474 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x3c, 0x4d, 0x6f, 0x1c, 0x47,
|
||||
0x76, 0x98, 0x21, 0x45, 0x72, 0x1e, 0xbf, 0x86, 0xc5, 0xaf, 0xd1, 0x88, 0x12, 0xa5, 0xf6, 0x5a,
|
||||
0x96, 0xfc, 0x41, 0xd9, 0xb2, 0x92, 0x75, 0xd6, 0xce, 0x6e, 0x28, 0x4a, 0xa6, 0xb5, 0xd6, 0x5a,
|
||||
0xdc, 0x26, 0x2d, 0x03, 0xde, 0xc0, 0x93, 0xe6, 0x74, 0x71, 0xd8, 0x51, 0x4f, 0x77, 0xbb, 0xbb,
|
||||
0x86, 0x14, 0xbd, 0x09, 0xb2, 0x30, 0x92, 0x20, 0x87, 0x20, 0x39, 0x18, 0x01, 0x12, 0x20, 0x97,
|
||||
0xe4, 0x14, 0x04, 0xc8, 0x25, 0xc8, 0x29, 0x87, 0x45, 0xae, 0x41, 0x8e, 0xb9, 0xe4, 0x07, 0x04,
|
||||
0xb9, 0x25, 0x01, 0x02, 0xe4, 0x92, 0x53, 0x50, 0xaf, 0x3e, 0xba, 0xaa, 0xbb, 0x67, 0x38, 0xb4,
|
||||
0xb5, 0xde, 0x8b, 0x34, 0xfd, 0xea, 0xd5, 0x7b, 0xaf, 0x5e, 0xbd, 0xaa, 0x7a, 0xaf, 0xde, 0x2b,
|
||||
0x42, 0x23, 0x4d, 0xba, 0x5b, 0x49, 0x1a, 0xb3, 0x98, 0x4c, 0xf5, 0xba, 0x2c, 0x4d, 0xba, 0xed,
|
||||
0x8d, 0x5e, 0x1c, 0xf7, 0x42, 0x7a, 0xc7, 0x4b, 0x82, 0x3b, 0x5e, 0x14, 0xc5, 0xcc, 0x63, 0x41,
|
||||
0x1c, 0x65, 0x02, 0xcb, 0x69, 0xc2, 0xc2, 0x2e, 0x65, 0x8f, 0xa2, 0xa3, 0xd8, 0xa5, 0x9f, 0x0f,
|
||||
0x68, 0xc6, 0x9c, 0x7f, 0x98, 0x84, 0x45, 0x0d, 0xca, 0x92, 0x38, 0xca, 0x28, 0x59, 0x83, 0xa9,
|
||||
0x41, 0xc2, 0x82, 0x3e, 0x6d, 0xd5, 0xae, 0xd7, 0x6e, 0x35, 0x5c, 0xf9, 0x45, 0xee, 0xc0, 0xb2,
|
||||
0x77, 0xe2, 0x05, 0xa1, 0x77, 0x18, 0xd2, 0x0e, 0x7d, 0xde, 0x3d, 0xf6, 0xa2, 0x1e, 0xcd, 0x5a,
|
||||
0xf5, 0xeb, 0xb5, 0x5b, 0x13, 0x2e, 0xd1, 0x4d, 0x0f, 0x55, 0x0b, 0x79, 0x0d, 0x96, 0x68, 0xc4,
|
||||
0x41, 0xbe, 0x81, 0x3e, 0x81, 0xe8, 0x4d, 0xd9, 0x90, 0x23, 0xdf, 0x83, 0x35, 0x9f, 0x1e, 0x79,
|
||||
0x83, 0x90, 0x75, 0x8e, 0xe2, 0x94, 0x3e, 0xef, 0x24, 0x69, 0x7c, 0x12, 0xf8, 0x34, 0x6d, 0x4d,
|
||||
0xa2, 0x14, 0x2b, 0xb2, 0xf5, 0x7d, 0xde, 0xb8, 0x27, 0xdb, 0xc8, 0x5d, 0x58, 0xd5, 0xbd, 0x02,
|
||||
0x8f, 0x75, 0xba, 0x83, 0x34, 0xa5, 0x51, 0xf7, 0xac, 0x75, 0x09, 0x3b, 0x2d, 0xab, 0x4e, 0x81,
|
||||
0xc7, 0x76, 0x64, 0x13, 0xf9, 0x04, 0x9a, 0xd9, 0xe0, 0x30, 0x3b, 0xcb, 0x18, 0xed, 0x77, 0x32,
|
||||
0xe6, 0xb1, 0x41, 0xd6, 0x9a, 0xba, 0x3e, 0x71, 0x6b, 0xf6, 0xee, 0xeb, 0x5b, 0x42, 0x8d, 0x5b,
|
||||
0x05, 0x95, 0x6c, 0xed, 0x2b, 0xfc, 0x7d, 0x44, 0x7f, 0x18, 0xb1, 0xf4, 0xcc, 0x5d, 0xcc, 0x6c,
|
||||
0x28, 0xf9, 0x08, 0xe6, 0xd3, 0xa4, 0xdb, 0xa1, 0x91, 0x9f, 0xc4, 0x41, 0xc4, 0xb2, 0xd6, 0x34,
|
||||
0x52, 0xbd, 0x3d, 0x8c, 0xaa, 0x9b, 0x74, 0x1f, 0x2a, 0x5c, 0x41, 0x72, 0x2e, 0x35, 0x40, 0xed,
|
||||
0xfb, 0xb0, 0x52, 0xc5, 0x98, 0x34, 0x61, 0xe2, 0x19, 0x3d, 0x93, 0xb3, 0xc3, 0x7f, 0x92, 0x15,
|
||||
0xb8, 0x74, 0xe2, 0x85, 0x03, 0x8a, 0x93, 0x31, 0xe3, 0x8a, 0x8f, 0xef, 0xd5, 0xdf, 0xa9, 0xb5,
|
||||
0x0f, 0x60, 0xa9, 0xc4, 0xa6, 0x82, 0xc0, 0x6d, 0x93, 0xc0, 0xec, 0xdd, 0x65, 0x25, 0xb2, 0xbb,
|
||||
0xb7, 0xa3, 0xfa, 0x1a, 0x54, 0x9d, 0x1b, 0xb0, 0xb9, 0x4b, 0xd9, 0x4e, 0xdc, 0xef, 0x0f, 0xa2,
|
||||
0xa0, 0x8b, 0x36, 0xe6, 0xd2, 0xd0, 0x3b, 0xa3, 0x69, 0xa6, 0x2c, 0xeb, 0x23, 0x58, 0xa9, 0x6a,
|
||||
0x27, 0x2d, 0x98, 0x96, 0x73, 0x8f, 0xfc, 0x67, 0x5c, 0xf5, 0x49, 0x36, 0xa0, 0xd1, 0x8d, 0xa3,
|
||||
0x88, 0x76, 0x19, 0xf5, 0xe5, 0x40, 0x72, 0x80, 0xf3, 0x87, 0x75, 0xb8, 0x3e, 0x9c, 0xa7, 0x34,
|
||||
0xdd, 0x2f, 0x60, 0xad, 0x6b, 0x22, 0x74, 0x52, 0x89, 0xd1, 0xaa, 0xe1, 0x54, 0xec, 0x18, 0x53,
|
||||
0x31, 0x92, 0xd2, 0x56, 0x65, 0xab, 0x98, 0xa4, 0xd5, 0x6e, 0x55, 0x5b, 0xfb, 0x08, 0xda, 0xc3,
|
||||
0x3b, 0x55, 0xa8, 0xfc, 0xae, 0xad, 0xf2, 0x0d, 0x25, 0x5a, 0x15, 0x11, 0x53, 0xf7, 0xdf, 0x85,
|
||||
0xf5, 0x5d, 0x1a, 0xd1, 0x34, 0xe8, 0x6a, 0xe3, 0x90, 0x3a, 0xe7, 0x1a, 0xd4, 0x36, 0x29, 0x59,
|
||||
0xe5, 0x00, 0xa7, 0x0d, 0xad, 0x72, 0x47, 0x31, 0x5c, 0x67, 0x0d, 0x56, 0x76, 0x29, 0xd3, 0x70,
|
||||
0x3d, 0x8b, 0x3f, 0xaf, 0xc1, 0x2a, 0x36, 0x64, 0x87, 0xd9, 0x99, 0x68, 0x90, 0xaa, 0xfe, 0x2d,
|
||||
0x58, 0xd2, 0xa4, 0x33, 0xb5, 0x8c, 0x84, 0x96, 0xdf, 0x36, 0xb4, 0x5c, 0xee, 0x99, 0x2f, 0xa6,
|
||||
0xcc, 0x5c, 0x4d, 0xf9, 0x9a, 0x94, 0xe0, 0xf6, 0x0e, 0xac, 0x56, 0xa2, 0x5e, 0xc4, 0xfe, 0x9d,
|
||||
0x16, 0xac, 0xed, 0x52, 0x66, 0x98, 0xb1, 0x61, 0xa0, 0xb3, 0x06, 0x98, 0xdb, 0x65, 0xc6, 0xbc,
|
||||
0x94, 0xe5, 0x76, 0x29, 0x3f, 0xc9, 0xcb, 0xb0, 0x10, 0x06, 0x19, 0xa3, 0x51, 0xc7, 0xf3, 0xfd,
|
||||
0x94, 0x66, 0x62, 0xcb, 0x6b, 0xb8, 0xf3, 0x02, 0xba, 0x2d, 0x80, 0xce, 0x3f, 0xd6, 0xf8, 0xc4,
|
||||
0x14, 0x58, 0x49, 0x65, 0x3d, 0x86, 0x46, 0xbe, 0x2b, 0x08, 0x25, 0x6d, 0x19, 0x4a, 0xaa, 0xea,
|
||||
0xb3, 0x55, 0xd8, 0x1a, 0x72, 0x02, 0xed, 0x1f, 0xc3, 0xc2, 0x8b, 0x5e, 0xd0, 0xef, 0x40, 0x5b,
|
||||
0xda, 0x86, 0xda, 0x91, 0x3f, 0xf2, 0xfa, 0x54, 0xd9, 0x55, 0x1b, 0x66, 0xd4, 0x06, 0x2e, 0x79,
|
||||
0xe8, 0x6f, 0xe7, 0x2a, 0x5c, 0xa9, 0xec, 0x29, 0x0d, 0xeb, 0x0e, 0x2c, 0xef, 0x52, 0xa6, 0xb7,
|
||||
0x79, 0x45, 0x71, 0xe8, 0x2e, 0xe0, 0xdc, 0x43, 0x4b, 0x34, 0x3a, 0x48, 0x15, 0x6e, 0x40, 0x23,
|
||||
0x3f, 0x44, 0xa4, 0x6d, 0x6b, 0x80, 0x73, 0x17, 0xcd, 0x54, 0xf5, 0x7a, 0x72, 0xb0, 0xe7, 0x52,
|
||||
0xd1, 0xed, 0x32, 0xcc, 0xc4, 0x2c, 0xe9, 0x74, 0x63, 0x5f, 0x89, 0x3e, 0x1d, 0xb3, 0x64, 0x27,
|
||||
0xf6, 0xa9, 0x34, 0x0d, 0xa3, 0x8f, 0x36, 0x8d, 0xbf, 0x16, 0x53, 0x69, 0x37, 0x49, 0x39, 0x7e,
|
||||
0x08, 0x0d, 0x45, 0x50, 0x4d, 0xe5, 0x1b, 0xc6, 0x54, 0x56, 0xf5, 0xd9, 0x7a, 0x22, 0x38, 0xca,
|
||||
0x99, 0x9c, 0x91, 0x02, 0x64, 0xed, 0x77, 0x61, 0xde, 0x6a, 0x3a, 0xcf, 0xb2, 0x1b, 0xe6, 0x94,
|
||||
0xdd, 0x83, 0xb5, 0x07, 0x41, 0x66, 0x9e, 0xb8, 0xe3, 0x4c, 0xd7, 0x67, 0xb0, 0xb0, 0xe7, 0x05,
|
||||
0x69, 0xb6, 0x3f, 0x48, 0x92, 0x18, 0xcd, 0xfb, 0x15, 0x58, 0xcc, 0x8f, 0xf5, 0x84, 0xb7, 0xc9,
|
||||
0x4e, 0x0b, 0x1a, 0x8c, 0x3d, 0xc8, 0x4b, 0x30, 0xaf, 0x8e, 0x73, 0x81, 0x26, 0x44, 0x9a, 0x93,
|
||||
0x40, 0x44, 0x72, 0xbe, 0x9c, 0xb4, 0x54, 0x67, 0x39, 0x16, 0x04, 0x26, 0x23, 0x4f, 0xbb, 0x15,
|
||||
0xf8, 0xdb, 0x34, 0x84, 0xba, 0x7d, 0x1c, 0xb4, 0x60, 0xfa, 0x84, 0xa6, 0x87, 0x71, 0x46, 0xd1,
|
||||
0x67, 0x98, 0x71, 0xd5, 0x27, 0x17, 0x64, 0x90, 0x05, 0x51, 0xaf, 0x93, 0x79, 0x91, 0x7f, 0x18,
|
||||
0x3f, 0x47, 0x0f, 0x61, 0xc6, 0x9d, 0x43, 0xe0, 0xbe, 0x80, 0x91, 0x1b, 0x30, 0x77, 0xcc, 0x58,
|
||||
0xd2, 0xe1, 0xae, 0x4b, 0x3c, 0x60, 0xd2, 0x21, 0x98, 0xe5, 0xb0, 0x03, 0x01, 0xe2, 0x0b, 0x1b,
|
||||
0x51, 0x06, 0x19, 0x4d, 0xbd, 0x1e, 0x8d, 0x58, 0x6b, 0x4a, 0x2c, 0x6c, 0x0e, 0xfd, 0x58, 0x01,
|
||||
0xc9, 0x55, 0x00, 0x44, 0x4b, 0xd2, 0xf8, 0xf9, 0x59, 0x6b, 0x5a, 0x98, 0x1e, 0x87, 0xec, 0x71,
|
||||
0x00, 0xd7, 0xdf, 0xa1, 0x97, 0x51, 0xe5, 0x7a, 0x04, 0x34, 0x6b, 0xcd, 0x08, 0xfd, 0x71, 0xf0,
|
||||
0x8e, 0x86, 0x92, 0x0e, 0xf7, 0x3b, 0xa4, 0xd6, 0x3b, 0x5e, 0x96, 0x51, 0x96, 0xb5, 0x1a, 0x68,
|
||||
0x40, 0xf7, 0x2a, 0x0c, 0xa8, 0xe0, 0x7f, 0xc8, 0x7e, 0xdb, 0xd8, 0x4d, 0xfb, 0x1f, 0x16, 0x94,
|
||||
0xfb, 0x5b, 0xde, 0x80, 0x1d, 0xd3, 0x88, 0xf1, 0xd3, 0x83, 0x33, 0x49, 0x82, 0x16, 0xa0, 0x6e,
|
||||
0x9a, 0x56, 0xc3, 0x76, 0x12, 0xb4, 0x3f, 0xe5, 0xce, 0x45, 0x99, 0x6a, 0x85, 0x09, 0xbe, 0x6e,
|
||||
0x6f, 0x25, 0x6b, 0x4a, 0x58, 0xdb, 0x8e, 0x4c, 0xd3, 0x3c, 0x85, 0xe6, 0x2e, 0x65, 0x07, 0x41,
|
||||
0xf7, 0x19, 0x4d, 0xc7, 0x30, 0x4a, 0x72, 0x0b, 0x26, 0xb9, 0x45, 0x49, 0x06, 0x2b, 0xfa, 0x24,
|
||||
0x94, 0x1e, 0x1b, 0x67, 0xe4, 0x22, 0x06, 0x9f, 0x0b, 0xd4, 0x5c, 0x87, 0x9d, 0x25, 0xc2, 0x2e,
|
||||
0x1a, 0x6e, 0x03, 0x21, 0x07, 0x67, 0x09, 0x75, 0x9e, 0xc2, 0x9c, 0xd9, 0x89, 0x6f, 0x1a, 0x3e,
|
||||
0x0d, 0x83, 0x7e, 0xc0, 0x68, 0xaa, 0x36, 0x0d, 0x0d, 0xe0, 0xf6, 0xc8, 0xa7, 0x48, 0xda, 0x31,
|
||||
0xfe, 0xe6, 0xeb, 0xed, 0xf3, 0x41, 0xcc, 0x14, 0x6d, 0xf1, 0xe1, 0xfc, 0x59, 0x1d, 0x16, 0xd4,
|
||||
0x70, 0xa4, 0x31, 0x2b, 0x99, 0x6b, 0xe7, 0xca, 0x7c, 0x03, 0xe6, 0x42, 0x2f, 0x63, 0x9d, 0x41,
|
||||
0xe2, 0x7b, 0xca, 0xb5, 0x99, 0x70, 0x67, 0x39, 0xec, 0x63, 0x01, 0xe2, 0x16, 0xad, 0x3c, 0x57,
|
||||
0x5c, 0x5b, 0x92, 0xfb, 0x5c, 0xd7, 0x1c, 0x0c, 0x81, 0x49, 0xde, 0x07, 0xad, 0xbd, 0xe6, 0xe2,
|
||||
0x6f, 0x0e, 0x3b, 0x0e, 0x7a, 0xc7, 0x68, 0xdd, 0x35, 0x17, 0x7f, 0xf3, 0x19, 0x0c, 0xe3, 0x53,
|
||||
0xb4, 0xe5, 0x9a, 0xcb, 0x7f, 0x72, 0xc8, 0x61, 0xe0, 0xa3, 0xe9, 0xd6, 0x5c, 0xfe, 0x93, 0x43,
|
||||
0xbc, 0xec, 0x19, 0x1a, 0x6a, 0xcd, 0xe5, 0x3f, 0xb9, 0xd7, 0x7f, 0x12, 0x87, 0x83, 0x3e, 0x6d,
|
||||
0x35, 0x10, 0x28, 0xbf, 0xc8, 0x15, 0x68, 0x24, 0x69, 0xd0, 0xa5, 0x1d, 0x8f, 0x1d, 0xa3, 0x31,
|
||||
0xd5, 0xdc, 0x19, 0x04, 0x6c, 0xb3, 0x63, 0x67, 0x19, 0x96, 0xf4, 0x44, 0xeb, 0xdd, 0xf3, 0x13,
|
||||
0x98, 0x96, 0x90, 0x91, 0x93, 0xfe, 0x26, 0x4c, 0x33, 0x81, 0xd6, 0xaa, 0xe3, 0x2a, 0xd0, 0x86,
|
||||
0x65, 0x6b, 0xda, 0x55, 0x68, 0xce, 0x0f, 0x80, 0x98, 0xdc, 0xe4, 0x44, 0xdc, 0xce, 0xe9, 0x88,
|
||||
0xed, 0x78, 0xd1, 0xa6, 0x93, 0xe5, 0x04, 0xbe, 0xc0, 0xc3, 0xe8, 0x49, 0xea, 0xf3, 0x8d, 0x24,
|
||||
0x7e, 0xf6, 0xad, 0x9a, 0xe6, 0x8f, 0x60, 0x5e, 0x33, 0x7e, 0xc4, 0x68, 0x9f, 0x2b, 0xdc, 0xeb,
|
||||
0xc7, 0x83, 0x88, 0x21, 0xcf, 0x9a, 0x2b, 0xbf, 0xb8, 0x05, 0xa2, 0x7e, 0x91, 0x65, 0xcd, 0x15,
|
||||
0x1f, 0x64, 0x01, 0xea, 0x81, 0x2f, 0x83, 0xa7, 0x7a, 0xe0, 0x3b, 0xff, 0x57, 0x83, 0x25, 0x63,
|
||||
0x20, 0x17, 0x36, 0xca, 0x92, 0xc5, 0xd5, 0x2b, 0x2c, 0xee, 0x36, 0x4c, 0x1e, 0x06, 0x3e, 0x8f,
|
||||
0xd9, 0xb8, 0x5e, 0x57, 0x15, 0x39, 0x6b, 0x1c, 0x2e, 0xa2, 0x70, 0x54, 0x2f, 0x7b, 0x96, 0xb5,
|
||||
0x26, 0x47, 0xa2, 0x72, 0x94, 0xd2, 0x7a, 0xb8, 0x54, 0x5e, 0x0f, 0xb6, 0x2e, 0xa7, 0x8a, 0xba,
|
||||
0x14, 0xde, 0xaa, 0xa6, 0xad, 0x2d, 0xaf, 0x0b, 0x90, 0x03, 0x47, 0x4e, 0xeb, 0xaf, 0x01, 0xc4,
|
||||
0x1a, 0x53, 0xda, 0xdf, 0xe5, 0x92, 0xd0, 0xda, 0x04, 0x0d, 0x64, 0xe7, 0x43, 0x74, 0x35, 0x4c,
|
||||
0xe6, 0x52, 0xf9, 0x77, 0x2d, 0x9a, 0xc2, 0x16, 0x49, 0x89, 0x66, 0x66, 0x11, 0x7b, 0x1b, 0x89,
|
||||
0x6d, 0x77, 0xbb, 0x7c, 0xea, 0x8d, 0xc0, 0x7c, 0xe4, 0x19, 0xfe, 0x14, 0xa6, 0x65, 0x0f, 0x69,
|
||||
0x16, 0x02, 0xa1, 0x1e, 0xf8, 0xe4, 0x5d, 0x00, 0xe3, 0x1c, 0x12, 0xe3, 0xba, 0xa2, 0x64, 0x90,
|
||||
0x9d, 0x94, 0x35, 0x20, 0x3b, 0x03, 0xdd, 0x39, 0x82, 0xe5, 0x0a, 0x14, 0x2e, 0x8a, 0x0e, 0xab,
|
||||
0xa5, 0x28, 0xea, 0x9b, 0x6c, 0xc2, 0x2c, 0x8b, 0x99, 0x17, 0x76, 0xf2, 0x13, 0xa2, 0xe6, 0x02,
|
||||
0x82, 0x9e, 0x72, 0x08, 0x6e, 0x50, 0x71, 0x28, 0x2c, 0x97, 0x6f, 0x50, 0x71, 0xe8, 0x3b, 0x1e,
|
||||
0x3a, 0x5e, 0xd6, 0xa0, 0xa5, 0x0a, 0x47, 0x4d, 0xd9, 0x6b, 0x30, 0xe3, 0x89, 0x2e, 0x6a, 0x60,
|
||||
0x8b, 0x85, 0x81, 0xb9, 0x1a, 0xc1, 0x21, 0x78, 0x02, 0xed, 0xc4, 0xd1, 0x51, 0xd0, 0x53, 0xd6,
|
||||
0xf1, 0x0a, 0x6e, 0x56, 0x0a, 0x96, 0xfb, 0x24, 0xbe, 0xc7, 0x3c, 0xe4, 0x36, 0xe7, 0xe2, 0x6f,
|
||||
0xe7, 0x0f, 0x6a, 0xd0, 0xdc, 0x8b, 0x53, 0x76, 0x14, 0x87, 0x41, 0x2c, 0xdd, 0x7b, 0xee, 0x8e,
|
||||
0x28, 0xf7, 0x5f, 0xfa, 0x91, 0xf2, 0x93, 0xef, 0x90, 0xdd, 0x38, 0x88, 0x84, 0xad, 0xd6, 0xa5,
|
||||
0x82, 0xe2, 0x20, 0xe2, 0xa6, 0x4a, 0xae, 0xc3, 0xac, 0x4f, 0xb3, 0x6e, 0x1a, 0x24, 0x3c, 0x9c,
|
||||
0x93, 0xdb, 0x82, 0x09, 0xe2, 0x84, 0x0f, 0xbd, 0xd0, 0x8b, 0xba, 0x54, 0xee, 0xec, 0xea, 0xd3,
|
||||
0x59, 0xc5, 0xed, 0x4a, 0x4b, 0x62, 0x44, 0xd6, 0x36, 0x58, 0x0e, 0xe5, 0x57, 0xa1, 0x91, 0x28,
|
||||
0xa0, 0x34, 0xbf, 0x96, 0x3e, 0xab, 0x0b, 0xc3, 0x71, 0x73, 0x54, 0x67, 0x83, 0xfb, 0xfe, 0x39,
|
||||
0xbd, 0xfd, 0x41, 0xbf, 0xef, 0xa5, 0x67, 0x8a, 0x5b, 0x04, 0x93, 0x3b, 0x71, 0x10, 0x71, 0x45,
|
||||
0xf1, 0x41, 0x29, 0xe7, 0x8d, 0xff, 0x36, 0x45, 0xaf, 0x5b, 0xa2, 0x9b, 0xda, 0x9a, 0xb0, 0xb5,
|
||||
0x75, 0x0d, 0x20, 0xa1, 0x69, 0x97, 0x46, 0xcc, 0xeb, 0xa9, 0x11, 0x1b, 0x10, 0xe7, 0x18, 0xc8,
|
||||
0x93, 0xa3, 0xa3, 0x30, 0x88, 0x28, 0x67, 0x2b, 0x85, 0x19, 0xa1, 0xfd, 0xe1, 0x32, 0xd8, 0x9c,
|
||||
0x26, 0x4a, 0x9c, 0x7e, 0x04, 0x4b, 0x4f, 0xa2, 0x0a, 0x46, 0x8a, 0x5c, 0x6d, 0x14, 0xb9, 0x7a,
|
||||
0x89, 0xdc, 0x07, 0x30, 0x67, 0x08, 0x9e, 0x91, 0x77, 0xa0, 0x21, 0x65, 0xd4, 0x81, 0x42, 0x5b,
|
||||
0xef, 0x06, 0xa5, 0x11, 0xba, 0x39, 0xb2, 0xf3, 0xe7, 0x35, 0x98, 0xcd, 0x25, 0xcb, 0xc8, 0x3d,
|
||||
0xb8, 0xc4, 0xd5, 0xad, 0xa8, 0x5c, 0xd3, 0x54, 0x72, 0x9c, 0x2d, 0xfc, 0x57, 0xf8, 0x85, 0x02,
|
||||
0xb9, 0xbd, 0x0f, 0x90, 0x03, 0x2b, 0xdc, 0xba, 0x3b, 0xb6, 0x5b, 0x77, 0xb9, 0x4c, 0x55, 0x89,
|
||||
0x66, 0x78, 0x76, 0xff, 0x32, 0xc9, 0xc3, 0xbd, 0x0a, 0x63, 0x91, 0x36, 0xf8, 0x06, 0xcc, 0x8a,
|
||||
0xb5, 0xc0, 0x77, 0x00, 0x25, 0xf0, 0x5c, 0x7e, 0xb5, 0x11, 0x44, 0x2e, 0xe0, 0xda, 0xc0, 0x76,
|
||||
0xf2, 0x16, 0xcc, 0xa3, 0xb0, 0x9d, 0x58, 0x28, 0x44, 0x2e, 0x6c, 0xbb, 0xc3, 0x1c, 0xa2, 0x48,
|
||||
0x95, 0x91, 0x04, 0x56, 0xad, 0x2e, 0x9d, 0x4c, 0x88, 0x20, 0x0f, 0xa9, 0xf7, 0x0c, 0x57, 0x7a,
|
||||
0x98, 0x94, 0x42, 0x59, 0x92, 0xa0, 0x6c, 0x13, 0xaa, 0x5b, 0xee, 0x96, 0x5b, 0xc8, 0x1d, 0x98,
|
||||
0x93, 0x1c, 0x51, 0x33, 0xf2, 0x88, 0xb3, 0x65, 0x9c, 0x15, 0x1d, 0x11, 0x81, 0xf4, 0x61, 0xc5,
|
||||
0xec, 0xa0, 0x25, 0xbc, 0x84, 0x1d, 0xdf, 0x1d, 0x5f, 0xc2, 0xa8, 0x24, 0x20, 0xe9, 0x96, 0x1a,
|
||||
0xda, 0xbf, 0x09, 0xad, 0x61, 0x03, 0xaa, 0x98, 0xf6, 0x57, 0xed, 0x69, 0x5f, 0xa9, 0x30, 0xc9,
|
||||
0xcc, 0xbc, 0x40, 0xfc, 0x14, 0xd6, 0x87, 0x08, 0x73, 0x81, 0x5b, 0x07, 0xc3, 0x52, 0x4d, 0x6b,
|
||||
0xfa, 0xd3, 0x1a, 0xb4, 0xb7, 0x7d, 0xbf, 0xb4, 0x39, 0xe5, 0x97, 0x04, 0xdf, 0xf6, 0x96, 0x7b,
|
||||
0x15, 0xae, 0x54, 0x0a, 0x24, 0x6f, 0x33, 0x9e, 0xc3, 0x55, 0x97, 0xf6, 0xe3, 0x13, 0xfa, 0x6d,
|
||||
0x8b, 0xec, 0x5c, 0x87, 0x6b, 0xc3, 0x38, 0x4b, 0xd9, 0xf0, 0x7a, 0xcf, 0xbe, 0x1e, 0xd7, 0x8e,
|
||||
0xd1, 0x7f, 0xd6, 0x60, 0xde, 0xbe, 0x38, 0x7f, 0x51, 0xb1, 0xf8, 0xeb, 0x40, 0x52, 0x9a, 0xb1,
|
||||
0x4e, 0x12, 0x87, 0x21, 0x0f, 0xc9, 0x7d, 0x1a, 0x7a, 0x67, 0xf2, 0xca, 0xbe, 0xc9, 0x5b, 0xf6,
|
||||
0x44, 0xc3, 0x03, 0x0e, 0x27, 0xeb, 0x30, 0xed, 0x25, 0x41, 0x87, 0x5b, 0x8d, 0x88, 0xc7, 0xa7,
|
||||
0xbc, 0x24, 0xf8, 0x90, 0x9e, 0x11, 0x07, 0xe6, 0x65, 0x43, 0x27, 0xa4, 0x27, 0x34, 0x44, 0x9f,
|
||||
0x6f, 0xc2, 0x9d, 0x15, 0xcd, 0x8f, 0x39, 0x88, 0xdc, 0x86, 0x66, 0x92, 0x06, 0xdc, 0xfc, 0xf2,
|
||||
0xdc, 0xc0, 0x34, 0x4a, 0xb3, 0x28, 0xe1, 0x6a, 0x74, 0xce, 0x4f, 0xe0, 0x72, 0x85, 0x2e, 0xe4,
|
||||
0x1e, 0xf5, 0x7d, 0x58, 0xb4, 0x33, 0x0c, 0x6a, 0x9f, 0xd2, 0x5e, 0xab, 0xd5, 0xd1, 0x5d, 0x38,
|
||||
0xb2, 0xe8, 0x48, 0xef, 0x13, 0x71, 0x5c, 0x8f, 0xe9, 0x3b, 0x2d, 0xe7, 0x73, 0x58, 0xc9, 0x81,
|
||||
0x3b, 0x71, 0x74, 0x42, 0xd3, 0x8c, 0x5b, 0x1b, 0x81, 0xc9, 0xa3, 0x34, 0x56, 0x17, 0xb2, 0xf8,
|
||||
0x9b, 0xfb, 0x6d, 0x2c, 0x96, 0x66, 0x50, 0x67, 0x31, 0xc7, 0x49, 0x3d, 0xa6, 0x4e, 0x29, 0xfc,
|
||||
0xcd, 0xfd, 0xe4, 0x00, 0x89, 0xd0, 0x0e, 0xb6, 0x09, 0x53, 0x9d, 0x95, 0x30, 0xce, 0xc5, 0x79,
|
||||
0x8a, 0xee, 0xa3, 0x29, 0x8a, 0x1c, 0xe3, 0xaf, 0xc3, 0xac, 0x18, 0x23, 0xef, 0xa9, 0xc6, 0xb7,
|
||||
0x61, 0x8d, 0xaf, 0x20, 0xa6, 0x0b, 0x47, 0x1a, 0xea, 0xfc, 0x77, 0x1d, 0xe6, 0xd0, 0x63, 0x7d,
|
||||
0x40, 0x99, 0x17, 0x84, 0xa3, 0x7d, 0x69, 0xe1, 0x83, 0xd6, 0xb5, 0x0f, 0xfa, 0x12, 0xcc, 0x9b,
|
||||
0x17, 0x22, 0x67, 0x2a, 0x98, 0x35, 0xae, 0x43, 0xce, 0xc8, 0xcb, 0xb0, 0x80, 0xa1, 0x75, 0x8e,
|
||||
0x25, 0x6c, 0x66, 0x1e, 0xa1, 0x1a, 0xcd, 0x0e, 0x04, 0x2e, 0x15, 0x02, 0x01, 0xde, 0x8c, 0xce,
|
||||
0x74, 0x27, 0x0b, 0x7c, 0x1d, 0x27, 0x20, 0x64, 0x3f, 0xf0, 0x8d, 0x66, 0xec, 0x3d, 0x6d, 0x34,
|
||||
0x63, 0x6f, 0x1e, 0x03, 0xa5, 0x54, 0x24, 0x0a, 0x30, 0xdf, 0x35, 0x83, 0x46, 0x37, 0xa7, 0x80,
|
||||
0x07, 0x41, 0x1f, 0xb3, 0x61, 0xf2, 0x72, 0xbb, 0x21, 0x2c, 0x56, 0x7c, 0xe5, 0x61, 0x1a, 0x98,
|
||||
0x61, 0x5a, 0x1e, 0xd4, 0xcd, 0x5a, 0x41, 0xdd, 0x26, 0xcc, 0xc6, 0x09, 0x8d, 0x3a, 0x32, 0xc4,
|
||||
0x9e, 0x13, 0xde, 0x03, 0x07, 0x3d, 0x45, 0x88, 0xbc, 0x32, 0x41, 0x9d, 0x67, 0xe3, 0xc4, 0xa5,
|
||||
0xb6, 0x62, 0xea, 0x45, 0xc5, 0xa8, 0x40, 0x70, 0xe2, 0xbc, 0x40, 0xd0, 0xd9, 0x46, 0xaf, 0x58,
|
||||
0x31, 0x96, 0xe6, 0xf3, 0x3a, 0x4c, 0xa1, 0x9a, 0x94, 0xe5, 0xac, 0x58, 0x61, 0x8c, 0x34, 0x0a,
|
||||
0x57, 0xe2, 0x38, 0x1f, 0x60, 0x0e, 0x11, 0x9b, 0xc6, 0x11, 0xfd, 0x32, 0xcc, 0x88, 0x59, 0xd1,
|
||||
0x56, 0x33, 0x8d, 0xdf, 0x8f, 0x7c, 0xe7, 0xdf, 0x6a, 0x40, 0xf6, 0x07, 0x87, 0xfd, 0x60, 0x7c,
|
||||
0x6a, 0xe3, 0x07, 0xe8, 0x04, 0x26, 0xd1, 0x4c, 0x84, 0x39, 0xe2, 0xef, 0x82, 0x85, 0x4c, 0x16,
|
||||
0x2d, 0x24, 0x9f, 0xce, 0x4b, 0xd5, 0x31, 0xfa, 0x94, 0x39, 0xf9, 0x7c, 0x8b, 0x0f, 0x03, 0x1a,
|
||||
0xb1, 0x8e, 0xbc, 0x6c, 0xe1, 0x5b, 0x3c, 0x02, 0x1e, 0xf9, 0xce, 0x3e, 0x2c, 0x5b, 0x23, 0x93,
|
||||
0x9a, 0xbe, 0x01, 0x73, 0x42, 0x80, 0x24, 0xf4, 0xba, 0xfa, 0x36, 0x7c, 0x16, 0x61, 0x7b, 0x08,
|
||||
0x1a, 0xa5, 0xaf, 0x3f, 0xaa, 0xc1, 0xca, 0x7e, 0xd0, 0x1f, 0x84, 0x1e, 0xa3, 0xbf, 0x00, 0x8d,
|
||||
0xe5, 0xc3, 0x9f, 0xb0, 0x86, 0xaf, 0x34, 0x39, 0x99, 0x6b, 0xd2, 0xf9, 0x9f, 0x1a, 0xac, 0x16,
|
||||
0x44, 0xd1, 0x3e, 0xa1, 0x6d, 0x4c, 0x43, 0x2e, 0x07, 0x24, 0x92, 0xc1, 0xb4, 0x6e, 0x31, 0x7d,
|
||||
0x09, 0xe6, 0xfb, 0x41, 0x14, 0xf4, 0x07, 0xfd, 0x8e, 0xd0, 0xbd, 0x90, 0x69, 0x4e, 0x02, 0xf7,
|
||||
0x70, 0x0a, 0x38, 0x92, 0xf7, 0xdc, 0x40, 0x9a, 0x94, 0x48, 0x02, 0x28, 0x90, 0xde, 0x84, 0x95,
|
||||
0xdc, 0x6f, 0xef, 0xf4, 0xbc, 0x20, 0xea, 0x84, 0x71, 0x96, 0xc9, 0x39, 0x26, 0x79, 0xdb, 0xae,
|
||||
0x17, 0x44, 0x8f, 0xe3, 0x2c, 0x33, 0x36, 0x81, 0x29, 0x73, 0x13, 0xe0, 0x0e, 0x4c, 0xf3, 0x93,
|
||||
0x63, 0x2f, 0xa4, 0xf7, 0xe3, 0xfe, 0xe1, 0x8b, 0xd5, 0xfd, 0x0d, 0x98, 0x13, 0xf7, 0x6e, 0xcc,
|
||||
0x4b, 0x7b, 0x54, 0xcd, 0xc0, 0x2c, 0xc2, 0x0e, 0x10, 0x54, 0x39, 0x0d, 0xff, 0x55, 0x03, 0xb2,
|
||||
0xc3, 0x5d, 0x99, 0x70, 0x6c, 0x7b, 0xe0, 0x5b, 0x89, 0x88, 0x9b, 0x73, 0x0b, 0x6b, 0x48, 0xc8,
|
||||
0x23, 0xdb, 0xfc, 0x26, 0x2c, 0xf3, 0xd3, 0xa3, 0x99, 0xbc, 0xe0, 0xe5, 0x58, 0x69, 0x1f, 0x7f,
|
||||
0x19, 0x16, 0x4e, 0xbd, 0x30, 0xa4, 0x4c, 0xa7, 0xd8, 0xe4, 0x4d, 0xbc, 0x80, 0xaa, 0x18, 0x5c,
|
||||
0x0d, 0x78, 0xda, 0x18, 0xf0, 0x2a, 0x2c, 0x5b, 0xe3, 0x95, 0xde, 0xd0, 0x3d, 0x58, 0x13, 0xe0,
|
||||
0xed, 0x30, 0x1c, 0x7b, 0x57, 0x75, 0xfe, 0xb2, 0x0e, 0xeb, 0xa5, 0x6e, 0xda, 0x6d, 0xb0, 0xcd,
|
||||
0xf8, 0xa6, 0x1e, 0x6e, 0x75, 0x87, 0x2d, 0xf9, 0x29, 0x7b, 0xb5, 0xff, 0xa9, 0x06, 0x53, 0x02,
|
||||
0x34, 0x72, 0x36, 0x3e, 0x55, 0x1b, 0x82, 0x34, 0x38, 0x11, 0x11, 0x7d, 0x77, 0x3c, 0x66, 0xe2,
|
||||
0x3f, 0x33, 0xad, 0x2a, 0x76, 0x12, 0x99, 0x51, 0xfd, 0x3e, 0x34, 0x8b, 0x08, 0x17, 0x4a, 0x39,
|
||||
0x89, 0x5b, 0x95, 0x87, 0x27, 0xd4, 0x48, 0xa3, 0xfe, 0xbc, 0x06, 0x8b, 0x3b, 0x71, 0xe4, 0x07,
|
||||
0xfc, 0xc4, 0xdc, 0xf3, 0x52, 0xaf, 0x9f, 0xc9, 0x4c, 0xbe, 0x00, 0xa9, 0x6b, 0x77, 0x0d, 0x18,
|
||||
0x72, 0xc1, 0x79, 0x15, 0xa0, 0x7b, 0x4c, 0xbb, 0xcf, 0x3a, 0xf2, 0xc6, 0x51, 0xa4, 0xff, 0x39,
|
||||
0xe4, 0x7e, 0xe0, 0x67, 0xe4, 0x0d, 0x58, 0xce, 0x9b, 0x3b, 0x5e, 0xe4, 0x77, 0xe4, 0x75, 0x23,
|
||||
0x66, 0x37, 0x34, 0xde, 0x76, 0xe4, 0x6f, 0x67, 0xcf, 0x32, 0xee, 0x2b, 0xea, 0x5b, 0xb6, 0x8e,
|
||||
0xb5, 0x85, 0x2f, 0x6a, 0xf8, 0x36, 0x82, 0x9d, 0xff, 0xad, 0xe1, 0x09, 0xa8, 0x46, 0x25, 0x67,
|
||||
0x3b, 0xbf, 0x58, 0xc3, 0xfb, 0x56, 0x6b, 0xca, 0xea, 0x85, 0x29, 0x23, 0x30, 0x19, 0x30, 0xda,
|
||||
0x57, 0x07, 0x0b, 0xff, 0x4d, 0xee, 0x43, 0x53, 0x8f, 0xb8, 0x93, 0xa0, 0x5a, 0xe4, 0x32, 0x59,
|
||||
0xcf, 0x03, 0x47, 0x4b, 0x6b, 0xee, 0x62, 0xb7, 0xa0, 0x46, 0xb5, 0xbc, 0x2e, 0x8d, 0xb5, 0x51,
|
||||
0x77, 0x51, 0xdb, 0x72, 0x7f, 0x12, 0x5f, 0x42, 0x6a, 0xda, 0x1d, 0x30, 0xea, 0x4b, 0x57, 0x59,
|
||||
0x7f, 0x3b, 0xff, 0x51, 0x83, 0xc5, 0x6d, 0xdf, 0xc7, 0x71, 0x8f, 0xb3, 0x4d, 0xa8, 0x51, 0xd6,
|
||||
0xcf, 0x19, 0xe5, 0xc4, 0xd7, 0x1c, 0xe5, 0x37, 0xde, 0x44, 0x86, 0x28, 0xc1, 0x71, 0xa0, 0x99,
|
||||
0x8f, 0xb3, 0x7a, 0x7a, 0x9d, 0xef, 0x00, 0x11, 0xe1, 0x95, 0xa5, 0x8e, 0x22, 0xd6, 0x2a, 0x2c,
|
||||
0x5b, 0x58, 0x72, 0xaf, 0x79, 0x1f, 0x6e, 0xed, 0x52, 0xb6, 0x93, 0x9e, 0x25, 0x2c, 0x56, 0xee,
|
||||
0xec, 0x03, 0x9a, 0xc4, 0x59, 0xa0, 0x76, 0x2e, 0x3a, 0xd6, 0xee, 0xf3, 0xcf, 0x35, 0xb8, 0x3d,
|
||||
0x06, 0x21, 0x39, 0x84, 0xcf, 0xca, 0xf7, 0x4b, 0xbf, 0x61, 0x96, 0xb7, 0x8c, 0x45, 0x65, 0x4b,
|
||||
0x43, 0x64, 0x95, 0x81, 0x26, 0xd9, 0x7e, 0x0f, 0x16, 0xec, 0xc6, 0x0b, 0x6d, 0x15, 0x21, 0xdc,
|
||||
0x3c, 0x47, 0x88, 0x71, 0x6c, 0xee, 0x26, 0x2c, 0x74, 0x2d, 0x12, 0x92, 0x51, 0x01, 0xea, 0xec,
|
||||
0xc0, 0x2b, 0xe7, 0x72, 0x93, 0x6a, 0x1b, 0x1a, 0xa1, 0x3b, 0x7f, 0x37, 0x09, 0xeb, 0x9f, 0x04,
|
||||
0xec, 0xd8, 0x4f, 0xbd, 0x53, 0x65, 0x7d, 0xe3, 0x08, 0x59, 0x08, 0xde, 0xeb, 0xe5, 0xfb, 0x86,
|
||||
0x57, 0x61, 0x29, 0x8e, 0x28, 0xc6, 0x18, 0x9d, 0xc4, 0xcb, 0xb2, 0xd3, 0x38, 0x55, 0x67, 0xe9,
|
||||
0x62, 0x1c, 0x51, 0x1e, 0x67, 0xec, 0x49, 0x70, 0xe1, 0x34, 0x9e, 0x2c, 0x9e, 0xc6, 0x4d, 0x98,
|
||||
0x48, 0x82, 0x48, 0xe6, 0x4c, 0xf8, 0x4f, 0x7e, 0x76, 0xb2, 0xd4, 0xf3, 0x0d, 0xca, 0xf2, 0xec,
|
||||
0x44, 0xa8, 0xa6, 0x6b, 0xde, 0xe2, 0x4f, 0x17, 0x6e, 0xf1, 0x0d, 0x9d, 0xcc, 0xd8, 0xb7, 0x16,
|
||||
0x9b, 0x30, 0x2b, 0x7f, 0x76, 0x98, 0xd7, 0x93, 0x21, 0x10, 0x48, 0xd0, 0x81, 0xd7, 0x33, 0xbc,
|
||||
0x35, 0xb0, 0xbc, 0xb5, 0xab, 0x00, 0x47, 0x94, 0x76, 0xac, 0x60, 0xa8, 0x71, 0x44, 0xa9, 0xd8,
|
||||
0x74, 0xb9, 0xab, 0x7c, 0xe8, 0x45, 0xcf, 0x3a, 0x78, 0x07, 0x31, 0x27, 0xc4, 0xe1, 0x80, 0x8f,
|
||||
0xbc, 0x3e, 0xfa, 0xc4, 0xd8, 0xa8, 0x64, 0x9a, 0x17, 0x1a, 0xe5, 0xb0, 0xed, 0xfc, 0x36, 0x05,
|
||||
0x51, 0xba, 0x01, 0x3b, 0x6b, 0x2d, 0xe4, 0xfd, 0x77, 0x02, 0x76, 0xa6, 0xfb, 0xa3, 0xce, 0xd2,
|
||||
0xb3, 0xd6, 0x62, 0xde, 0x7f, 0x47, 0x80, 0xb8, 0x78, 0xd9, 0x69, 0x70, 0x44, 0x45, 0x61, 0x48,
|
||||
0x53, 0x96, 0x4a, 0x71, 0xc8, 0x4e, 0xec, 0xa3, 0x1b, 0x79, 0x1a, 0xa4, 0x46, 0x70, 0xba, 0x24,
|
||||
0x42, 0x58, 0x0e, 0x54, 0xa6, 0xe1, 0xbc, 0x0a, 0x4d, 0x65, 0x2e, 0x66, 0xed, 0x64, 0x4a, 0xb3,
|
||||
0x41, 0xc8, 0x54, 0xed, 0xa4, 0xf8, 0x72, 0xde, 0xc2, 0xaa, 0x88, 0xc7, 0x71, 0xaf, 0x97, 0x87,
|
||||
0x4f, 0xd2, 0xb4, 0xd6, 0x60, 0x2a, 0x44, 0xb8, 0xea, 0x22, 0xbe, 0x9c, 0x08, 0xef, 0x73, 0x0a,
|
||||
0x5d, 0xf2, 0xac, 0x45, 0x10, 0x1d, 0xc5, 0x32, 0x5a, 0xc0, 0xdf, 0x7c, 0x2d, 0xfa, 0xf4, 0x70,
|
||||
0xd0, 0x53, 0x35, 0x50, 0xf8, 0xc1, 0x31, 0x4f, 0xbd, 0x34, 0x92, 0x07, 0x2a, 0xfe, 0xe6, 0x98,
|
||||
0x34, 0x4d, 0xe3, 0x54, 0x9e, 0x9e, 0xe2, 0xc3, 0xd9, 0x85, 0xf5, 0xfd, 0x8b, 0x89, 0xc8, 0x09,
|
||||
0x89, 0xdb, 0x1a, 0xb9, 0xfc, 0xf1, 0xc3, 0xf9, 0xd0, 0xaa, 0x00, 0xc1, 0x2a, 0x81, 0x71, 0x96,
|
||||
0xd1, 0x0a, 0x5c, 0xc2, 0xbd, 0x5c, 0x11, 0xc3, 0x0f, 0x1e, 0x11, 0xb6, 0xca, 0xd4, 0x74, 0x0d,
|
||||
0x5a, 0xb9, 0xa2, 0x42, 0xec, 0x84, 0xbf, 0x52, 0x51, 0x51, 0x61, 0xf5, 0x1d, 0xaf, 0xa4, 0xe2,
|
||||
0x17, 0x5a, 0x25, 0xf1, 0x05, 0x2c, 0x9b, 0xa2, 0x7d, 0xab, 0x51, 0xff, 0xcf, 0x6a, 0x78, 0x43,
|
||||
0xa6, 0x23, 0xb0, 0x7d, 0x96, 0x52, 0xaf, 0xff, 0xad, 0x26, 0xc4, 0x7f, 0x00, 0x37, 0xcc, 0x7a,
|
||||
0xa9, 0x0b, 0x4b, 0xe2, 0xfc, 0x2e, 0xa6, 0x11, 0x45, 0x92, 0xff, 0x97, 0x20, 0xff, 0x7b, 0x70,
|
||||
0xcd, 0x90, 0xff, 0x82, 0x62, 0x38, 0x7f, 0x51, 0xc3, 0x5b, 0xc4, 0xed, 0x81, 0x1f, 0x30, 0xcb,
|
||||
0xe7, 0xe0, 0x3b, 0x13, 0xf3, 0x52, 0xd6, 0xf1, 0x3d, 0x46, 0x75, 0x11, 0x27, 0x87, 0x3c, 0xf0,
|
||||
0x18, 0x5e, 0x9e, 0xd0, 0xc8, 0x17, 0x8d, 0xf2, 0x32, 0x80, 0x46, 0xbe, 0x6a, 0x12, 0x91, 0xc3,
|
||||
0xe1, 0x99, 0x15, 0xa8, 0xdd, 0xc7, 0x73, 0x1a, 0x8b, 0x5e, 0x70, 0xc5, 0x5f, 0x72, 0xc5, 0x07,
|
||||
0x5f, 0xd6, 0xf1, 0xd1, 0x11, 0x5f, 0x72, 0x97, 0x10, 0x2c, 0xbf, 0x9c, 0x1d, 0x91, 0x94, 0x36,
|
||||
0x44, 0x93, 0xeb, 0xed, 0x55, 0x98, 0xa2, 0xe8, 0x26, 0x17, 0xb3, 0xdb, 0x06, 0xae, 0xc4, 0x70,
|
||||
0xfe, 0x4a, 0x58, 0xd8, 0x07, 0x41, 0xc6, 0xe2, 0x34, 0xe8, 0xee, 0x78, 0x91, 0x1f, 0x8e, 0xe5,
|
||||
0x06, 0x5d, 0x60, 0x86, 0x36, 0xa0, 0x91, 0x62, 0xfd, 0x5f, 0xf0, 0x05, 0x95, 0xb5, 0x11, 0x39,
|
||||
0x80, 0x9f, 0xcb, 0xbd, 0xd4, 0x8b, 0x06, 0xa1, 0x97, 0xf2, 0x53, 0x62, 0x52, 0xdc, 0x28, 0x1b,
|
||||
0x20, 0xe7, 0x01, 0x66, 0x3e, 0x4b, 0x22, 0xca, 0xd1, 0xde, 0x84, 0xa9, 0x2e, 0x82, 0xe4, 0x68,
|
||||
0x17, 0x8c, 0x18, 0xcc, 0x0f, 0xa9, 0x2b, 0x5b, 0x9d, 0xdf, 0xaf, 0xc1, 0x94, 0x00, 0xf1, 0xdd,
|
||||
0x56, 0x17, 0xce, 0x4f, 0xb8, 0xf8, 0x5b, 0x95, 0xe3, 0xd4, 0xf3, 0x72, 0x1c, 0x55, 0xb4, 0x33,
|
||||
0x61, 0x14, 0xed, 0x10, 0x98, 0x8c, 0x13, 0x1a, 0xa9, 0xe2, 0x1e, 0xfe, 0x9b, 0xcf, 0x5a, 0x37,
|
||||
0x8c, 0x33, 0x2a, 0x23, 0x17, 0xf1, 0x61, 0x14, 0xea, 0x4c, 0x99, 0x85, 0x3a, 0xce, 0x73, 0x80,
|
||||
0x7c, 0x1a, 0x50, 0x12, 0x6e, 0xb6, 0xf2, 0xd2, 0x99, 0xff, 0x26, 0xd7, 0x00, 0x02, 0x9f, 0x46,
|
||||
0x2c, 0x38, 0x0a, 0xa8, 0x2a, 0xf8, 0x30, 0x20, 0xdc, 0x0d, 0xe8, 0xd3, 0x2c, 0x53, 0xd9, 0xd2,
|
||||
0x86, 0xab, 0x3e, 0xb9, 0xa2, 0xf9, 0x58, 0x32, 0xe6, 0xf5, 0x13, 0xe5, 0x93, 0x68, 0x80, 0x73,
|
||||
0x08, 0x8d, 0xdd, 0x9d, 0x83, 0x7d, 0x74, 0x77, 0x38, 0xe3, 0x8f, 0x3f, 0x7e, 0xf4, 0x40, 0x31,
|
||||
0xe6, 0xbf, 0x75, 0xb2, 0xa1, 0x6e, 0x24, 0x1b, 0x08, 0x9f, 0x65, 0x76, 0xac, 0x82, 0x26, 0xfe,
|
||||
0x9b, 0x5b, 0x70, 0x44, 0x9f, 0xb3, 0x4e, 0x3a, 0x88, 0x24, 0x97, 0x69, 0xfe, 0xed, 0x0e, 0x22,
|
||||
0xe7, 0x01, 0xac, 0x6b, 0x1e, 0x0f, 0x45, 0x08, 0xa3, 0x6c, 0xe9, 0x36, 0x4c, 0x09, 0x57, 0x4b,
|
||||
0x96, 0xbd, 0x2c, 0xe9, 0xbd, 0x5f, 0x75, 0x70, 0x25, 0x82, 0xb3, 0x0d, 0x2b, 0x1a, 0xb8, 0xcf,
|
||||
0xe2, 0xe4, 0x6b, 0x90, 0xb8, 0x6c, 0x08, 0xc2, 0x49, 0x6c, 0x87, 0xa1, 0x0a, 0x85, 0x5b, 0xb0,
|
||||
0x66, 0x34, 0xf1, 0x10, 0x5b, 0xb5, 0x98, 0x9d, 0x1e, 0x07, 0x19, 0x33, 0x3a, 0xfd, 0x4d, 0xcd,
|
||||
0xe8, 0xf5, 0x71, 0x12, 0xc6, 0x9e, 0xaf, 0xa4, 0xda, 0x84, 0x59, 0xc1, 0xb4, 0x63, 0xa4, 0x6a,
|
||||
0x40, 0x80, 0xd0, 0x51, 0xca, 0x11, 0xb0, 0x86, 0xa1, 0x6e, 0x22, 0x3c, 0xf0, 0x98, 0xa7, 0xab,
|
||||
0x1b, 0x26, 0xf2, 0xea, 0x06, 0xbe, 0xf4, 0xbc, 0xb4, 0x7b, 0x1c, 0x9c, 0x50, 0x5f, 0x3a, 0x00,
|
||||
0xfa, 0x9b, 0xcf, 0x73, 0x7c, 0x42, 0xd3, 0xd3, 0x34, 0x60, 0xc2, 0xea, 0x66, 0xdc, 0x1c, 0xe0,
|
||||
0xec, 0x42, 0x3b, 0xd7, 0x07, 0xf5, 0x7c, 0xf5, 0xeb, 0xc2, 0x3a, 0xbc, 0x0f, 0xab, 0x1a, 0xf8,
|
||||
0xe3, 0x01, 0xd5, 0xc5, 0x06, 0x17, 0xa1, 0xf1, 0x43, 0x68, 0x69, 0xe0, 0xf6, 0x80, 0xc5, 0x8f,
|
||||
0x0d, 0xc5, 0xad, 0x59, 0x64, 0x1a, 0xaa, 0x8f, 0x71, 0x8d, 0x27, 0x7c, 0x24, 0x75, 0x8d, 0xf7,
|
||||
0x99, 0x35, 0xa7, 0x62, 0xe2, 0x72, 0x87, 0x4e, 0xd7, 0xb6, 0x9b, 0xd7, 0xff, 0xaf, 0xc1, 0xb4,
|
||||
0x20, 0xaa, 0x6e, 0x68, 0x2a, 0x44, 0x55, 0x18, 0x4e, 0x6c, 0x4c, 0xb1, 0x1c, 0xef, 0x39, 0xe4,
|
||||
0x73, 0x45, 0xd4, 0xcf, 0x51, 0x84, 0x35, 0xc7, 0x0d, 0x59, 0xc1, 0xf2, 0xbe, 0xa1, 0x1c, 0x59,
|
||||
0x9d, 0x7d, 0x2e, 0x4b, 0x45, 0xa7, 0x9e, 0xd3, 0xb9, 0xfb, 0xd5, 0x3d, 0x58, 0xd8, 0x8d, 0x45,
|
||||
0x5c, 0x75, 0xc0, 0xc3, 0x89, 0x94, 0x3c, 0x81, 0x69, 0xf9, 0x8e, 0x85, 0xac, 0x95, 0x1e, 0xb6,
|
||||
0xa0, 0xfa, 0xdb, 0xeb, 0x43, 0x1e, 0xbc, 0x38, 0xcb, 0x5f, 0xfe, 0xeb, 0xbf, 0x7f, 0x55, 0x9f,
|
||||
0x27, 0xb3, 0x77, 0x4e, 0xde, 0xba, 0xd3, 0xa3, 0x0c, 0xfd, 0xd6, 0x1e, 0xcc, 0x5b, 0x4f, 0x0f,
|
||||
0xc8, 0x86, 0xf5, 0x7c, 0xa0, 0xf0, 0x22, 0xa1, 0x7d, 0x75, 0xe4, 0xe3, 0x02, 0xe7, 0x32, 0xb2,
|
||||
0x58, 0x26, 0x4b, 0x92, 0x45, 0xfe, 0xaa, 0x80, 0x7c, 0x0e, 0x8b, 0x0f, 0x31, 0x9f, 0xa9, 0x89,
|
||||
0x92, 0xcd, 0x9c, 0x58, 0xe5, 0x8b, 0x8a, 0xf6, 0xf5, 0xe1, 0x08, 0x92, 0xe1, 0x15, 0x64, 0xb8,
|
||||
0x4a, 0x96, 0x39, 0x43, 0x91, 0x2f, 0xd5, 0x3c, 0x49, 0x06, 0x4d, 0x59, 0xa3, 0xfd, 0x42, 0x79,
|
||||
0x6e, 0x20, 0xcf, 0x35, 0xb2, 0xc2, 0x79, 0xfa, 0x82, 0x41, 0xce, 0x34, 0xc6, 0x74, 0x8c, 0xf9,
|
||||
0xa6, 0x80, 0x5c, 0x1b, 0xfa, 0xd8, 0x40, 0xb0, 0xdc, 0x3c, 0xe7, 0x31, 0x82, 0x3d, 0xca, 0x1e,
|
||||
0xe5, 0xb8, 0xfa, 0x3d, 0x02, 0xf9, 0x4a, 0xf8, 0xe8, 0x95, 0xaf, 0x5f, 0xc8, 0x2b, 0xe7, 0x3f,
|
||||
0xb9, 0x11, 0x32, 0xdc, 0x1a, 0xf7, 0x6d, 0x8e, 0xf3, 0x1d, 0x14, 0xe6, 0x1a, 0xd9, 0x90, 0xc2,
|
||||
0x58, 0xef, 0x71, 0xd4, 0x8b, 0x1f, 0xd2, 0x85, 0x39, 0xf3, 0x21, 0x01, 0xb9, 0x52, 0x11, 0x12,
|
||||
0x68, 0xe6, 0x1b, 0xd5, 0x8d, 0x92, 0x61, 0x0b, 0x19, 0x12, 0xd2, 0x94, 0x0c, 0xf5, 0xbb, 0x03,
|
||||
0xf2, 0x05, 0x2c, 0x16, 0x8a, 0xf0, 0x89, 0x53, 0x98, 0xbe, 0x8a, 0x07, 0x15, 0xed, 0x97, 0x46,
|
||||
0xe2, 0x48, 0xae, 0xd7, 0x90, 0x6b, 0xcb, 0x59, 0x36, 0x66, 0x59, 0x71, 0xfe, 0x5e, 0xed, 0x55,
|
||||
0x92, 0xe1, 0x3c, 0x9b, 0xf5, 0xe2, 0x63, 0xf1, 0xde, 0x3c, 0xa7, 0xd8, 0xbc, 0x34, 0xd7, 0x8a,
|
||||
0x27, 0xae, 0xd6, 0x0c, 0x6b, 0x70, 0x8d, 0x57, 0x0e, 0x18, 0x2f, 0x8f, 0xc3, 0xf7, 0x6a, 0xf5,
|
||||
0x2b, 0x09, 0xf9, 0x50, 0xc3, 0x69, 0x23, 0xd7, 0x15, 0x42, 0x0a, 0x5c, 0x63, 0x96, 0x90, 0xcc,
|
||||
0x7a, 0x44, 0x22, 0x99, 0xda, 0x56, 0x5d, 0xf1, 0x8c, 0xa3, 0x72, 0xa4, 0xe6, 0xbb, 0x8c, 0xa1,
|
||||
0x23, 0x8d, 0x59, 0x92, 0x91, 0xe7, 0xb0, 0x20, 0xb6, 0x8b, 0x17, 0x3f, 0xb3, 0x57, 0x91, 0xef,
|
||||
0xba, 0x43, 0xf2, 0x3d, 0xc3, 0x9c, 0xd8, 0x4f, 0xa0, 0xa1, 0x03, 0x1b, 0xd2, 0x32, 0x06, 0x61,
|
||||
0x55, 0xd4, 0xb7, 0x87, 0xd4, 0x4b, 0x2b, 0x6b, 0x75, 0xe6, 0xe5, 0xa8, 0x44, 0xf5, 0x33, 0x27,
|
||||
0xfc, 0x13, 0x80, 0xbc, 0x80, 0x9a, 0x5c, 0x2e, 0x51, 0xd6, 0x9a, 0x6b, 0x57, 0x35, 0xa9, 0xa7,
|
||||
0x62, 0x48, 0xbe, 0x49, 0x16, 0x2c, 0xf2, 0x6a, 0xbd, 0xe9, 0x38, 0xce, 0x5a, 0x6f, 0xc5, 0x92,
|
||||
0xeb, 0xf6, 0xf0, 0x5a, 0x5b, 0x35, 0x29, 0x8e, 0x5a, 0x6c, 0xfa, 0xbe, 0x9e, 0x8f, 0x40, 0x1c,
|
||||
0x16, 0x46, 0x91, 0xef, 0x46, 0x15, 0x97, 0xca, 0xc3, 0xa2, 0x5c, 0xb1, 0x5b, 0x3a, 0x2c, 0xf2,
|
||||
0xc2, 0x5c, 0xf2, 0x0c, 0x9f, 0xca, 0x1a, 0x35, 0xaa, 0xc4, 0xa4, 0x55, 0x2e, 0xd8, 0x6d, 0x5f,
|
||||
0x1b, 0xd6, 0x9c, 0x55, 0xdb, 0xb7, 0xbc, 0xd2, 0xc3, 0x45, 0x25, 0x26, 0x5c, 0x54, 0xa6, 0x5a,
|
||||
0x13, 0x6e, 0x15, 0xb0, 0xb6, 0x2f, 0x57, 0xb4, 0x48, 0xea, 0xab, 0x48, 0x7d, 0x91, 0xcc, 0xeb,
|
||||
0x2d, 0x11, 0x69, 0x89, 0x39, 0xd1, 0x25, 0x43, 0xd6, 0x9c, 0x14, 0xeb, 0x4a, 0xad, 0x3d, 0xb0,
|
||||
0x54, 0x5d, 0x5a, 0xda, 0x03, 0x75, 0xfd, 0x28, 0xf9, 0x3d, 0xbb, 0x4c, 0x55, 0x95, 0xcd, 0x39,
|
||||
0x23, 0xeb, 0xdc, 0x4a, 0xab, 0x65, 0x68, 0x2d, 0x9c, 0xb3, 0x89, 0x9c, 0x2f, 0x93, 0xf5, 0x22,
|
||||
0x67, 0x59, 0x57, 0x47, 0xbe, 0xac, 0xc1, 0x72, 0x45, 0xd5, 0x56, 0x2e, 0xc1, 0xf0, 0x1a, 0xb3,
|
||||
0x5c, 0x82, 0x51, 0x65, 0x5f, 0x0e, 0x4a, 0xb0, 0xe1, 0xa0, 0x04, 0x9e, 0xef, 0x6b, 0x09, 0xe4,
|
||||
0x0d, 0x25, 0xb7, 0xcc, 0x3f, 0xa9, 0xc1, 0x5a, 0x75, 0x85, 0x16, 0x79, 0x59, 0x3f, 0xbe, 0x1b,
|
||||
0x55, 0x3b, 0xd6, 0xbe, 0x79, 0x1e, 0x9a, 0x94, 0xe6, 0x65, 0x94, 0x66, 0xd3, 0x69, 0x73, 0x69,
|
||||
0x52, 0xc4, 0xad, 0x12, 0xe8, 0x14, 0xd3, 0x5a, 0x76, 0x0d, 0x14, 0x31, 0x7c, 0x8b, 0xea, 0x52,
|
||||
0xb1, 0xf6, 0x8d, 0x11, 0x18, 0xf6, 0xf6, 0x45, 0x56, 0xe5, 0x84, 0x60, 0xe1, 0x90, 0x2e, 0xa6,
|
||||
0x92, 0x6b, 0x34, 0xaf, 0x31, 0xb2, 0xd6, 0x68, 0xa9, 0x6c, 0xca, 0x5a, 0xa3, 0xe5, 0x4a, 0xa6,
|
||||
0xd2, 0x1a, 0x45, 0x66, 0x58, 0xd5, 0x44, 0x3e, 0xc5, 0x65, 0x23, 0x73, 0xaa, 0xad, 0xe2, 0x52,
|
||||
0xcf, 0xaa, 0x96, 0x8d, 0x9d, 0x35, 0x2d, 0x6d, 0x95, 0x22, 0x55, 0xcb, 0xb5, 0xe7, 0xc2, 0x8c,
|
||||
0x42, 0x27, 0xeb, 0x45, 0x02, 0x8a, 0x72, 0x65, 0x59, 0x8c, 0xb3, 0x8e, 0x44, 0x97, 0x9c, 0x39,
|
||||
0x93, 0x28, 0xa7, 0x79, 0x08, 0xb3, 0x46, 0x09, 0x08, 0xd1, 0x9b, 0x6c, 0xb9, 0xe2, 0xa5, 0x7d,
|
||||
0xa5, 0xb2, 0xcd, 0xde, 0x4a, 0x9c, 0x45, 0xce, 0x20, 0x43, 0x04, 0xcd, 0xe3, 0xb7, 0x61, 0xde,
|
||||
0xaa, 0xc2, 0xc8, 0x95, 0x5f, 0x55, 0x27, 0x92, 0x2b, 0xbf, 0xb2, 0x74, 0x43, 0x39, 0x9a, 0x0e,
|
||||
0x2a, 0x3f, 0x93, 0x28, 0x9a, 0xd7, 0x67, 0xd0, 0xd0, 0xc5, 0x0f, 0xb9, 0xfe, 0x8b, 0xf5, 0x10,
|
||||
0xe7, 0xf1, 0xb0, 0xe6, 0xe0, 0x94, 0x77, 0x3e, 0x8c, 0xfb, 0x87, 0x52, 0x5f, 0x46, 0x6a, 0x3f,
|
||||
0xd7, 0x57, 0xb9, 0xbe, 0x21, 0xd7, 0x57, 0x55, 0x2d, 0x80, 0xa5, 0xaf, 0x2e, 0x22, 0xe8, 0x31,
|
||||
0xa4, 0xb0, 0x58, 0x48, 0xa9, 0xe7, 0x6e, 0x45, 0x75, 0x01, 0x41, 0xee, 0x56, 0x0c, 0xc9, 0xc5,
|
||||
0xdb, 0x8e, 0x9b, 0xe0, 0xe7, 0x85, 0x61, 0x6e, 0x5b, 0x62, 0xbb, 0x17, 0x09, 0x67, 0xcb, 0x6e,
|
||||
0xad, 0xcc, 0xba, 0x65, 0xb7, 0x76, 0x76, 0xba, 0xb4, 0xdd, 0x8b, 0x3b, 0x37, 0xf2, 0x14, 0x66,
|
||||
0x54, 0xa6, 0x33, 0x37, 0xda, 0x42, 0x8e, 0xb7, 0xdd, 0x2a, 0x37, 0x48, 0xaa, 0x96, 0xe1, 0x7a,
|
||||
0xbe, 0x8f, 0x54, 0xe5, 0x44, 0x18, 0x79, 0xcf, 0x7c, 0x22, 0xca, 0x29, 0xd3, 0x7c, 0x22, 0xaa,
|
||||
0x12, 0xa5, 0xd6, 0x44, 0x88, 0x9d, 0x4b, 0xf3, 0xf8, 0xfb, 0x1a, 0xde, 0x07, 0x8f, 0x4e, 0x5b,
|
||||
0x92, 0x37, 0x2f, 0x90, 0xe1, 0x14, 0x02, 0xbd, 0x75, 0xe1, 0x9c, 0xa8, 0x73, 0x0b, 0xc5, 0x74,
|
||||
0x9c, 0xab, 0xea, 0x30, 0xc5, 0x6e, 0xbe, 0x40, 0xd7, 0x09, 0x52, 0x2e, 0xf4, 0xdf, 0xd6, 0xc4,
|
||||
0x1f, 0x42, 0x18, 0x41, 0x97, 0x6c, 0x8d, 0x29, 0x80, 0x12, 0xf8, 0xce, 0xd8, 0xf8, 0x52, 0xdc,
|
||||
0x9b, 0x28, 0xee, 0x75, 0xe7, 0xca, 0x08, 0x71, 0xb9, 0xb0, 0xbf, 0x03, 0x57, 0x74, 0x7a, 0xd3,
|
||||
0xa2, 0xfb, 0xfe, 0x20, 0xf2, 0xb3, 0x3c, 0x2e, 0x1d, 0x92, 0x03, 0xcd, 0x0d, 0xa7, 0x98, 0xf5,
|
||||
0xb2, 0xcf, 0xc7, 0x53, 0xd9, 0x2a, 0xc4, 0x38, 0xe2, 0xb4, 0x39, 0xf7, 0x04, 0x96, 0x54, 0xbf,
|
||||
0xf7, 0x03, 0x8f, 0x7d, 0x63, 0x9e, 0xd7, 0x91, 0x67, 0xdb, 0x59, 0x35, 0x79, 0x1e, 0x05, 0x1e,
|
||||
0xd3, 0x1c, 0x33, 0xac, 0x56, 0xb1, 0x12, 0x5a, 0x66, 0xf0, 0x5d, 0x99, 0xea, 0x32, 0x83, 0xef,
|
||||
0xea, 0xdc, 0x9b, 0x1d, 0x7c, 0xf7, 0x28, 0x13, 0xb9, 0x30, 0x5f, 0x32, 0x38, 0x81, 0xe6, 0xfe,
|
||||
0x50, 0xa6, 0xfb, 0x5f, 0x9b, 0xa9, 0xf4, 0x81, 0x1c, 0x64, 0x9a, 0x15, 0x98, 0xf2, 0xc1, 0x9e,
|
||||
0x88, 0xd2, 0x1c, 0x33, 0xd5, 0x45, 0x36, 0x87, 0x27, 0xc1, 0xca, 0x7c, 0x2b, 0xb3, 0x64, 0x36,
|
||||
0x5f, 0x23, 0x42, 0xc2, 0x07, 0xe0, 0x9c, 0xef, 0x19, 0x10, 0x3b, 0x4a, 0xc2, 0x87, 0x83, 0x7a,
|
||||
0x17, 0xa8, 0x48, 0x70, 0x8d, 0x17, 0x22, 0xdd, 0x40, 0xc6, 0x57, 0x9c, 0xb5, 0x72, 0x88, 0xc4,
|
||||
0x79, 0x73, 0xd6, 0x3f, 0x85, 0xe5, 0x42, 0xec, 0xfd, 0x82, 0x78, 0x5b, 0xe6, 0x5c, 0x08, 0xbc,
|
||||
0x15, 0x73, 0x86, 0x71, 0x70, 0x21, 0x6b, 0x45, 0x6e, 0x54, 0xc5, 0x1b, 0x56, 0x52, 0x68, 0x54,
|
||||
0xe4, 0x23, 0xcf, 0x0d, 0xb2, 0x56, 0x0a, 0x47, 0x90, 0xc2, 0x9b, 0x35, 0xf2, 0xc7, 0x35, 0xcc,
|
||||
0x58, 0x0c, 0x49, 0x9a, 0x91, 0xdb, 0x55, 0x01, 0xef, 0x85, 0xc5, 0x90, 0xfb, 0x09, 0xb9, 0x56,
|
||||
0x8c, 0x8a, 0x4b, 0xe2, 0x1c, 0xe3, 0x0d, 0x84, 0x99, 0xfa, 0xb2, 0x62, 0xf2, 0x8a, 0x9c, 0xd8,
|
||||
0xd0, 0xa0, 0xb5, 0x18, 0x8a, 0xcb, 0xa8, 0x52, 0x71, 0xfa, 0x99, 0xfd, 0x17, 0x19, 0x2c, 0x96,
|
||||
0x37, 0x2b, 0x46, 0x7d, 0x11, 0xd6, 0x2f, 0x21, 0xeb, 0xab, 0xe4, 0x4a, 0x61, 0xbc, 0x05, 0x11,
|
||||
0x84, 0x5b, 0x6b, 0xa4, 0x58, 0x4c, 0xb7, 0xb6, 0x94, 0xc7, 0xb3, 0xdc, 0xda, 0x72, 0x2a, 0xad,
|
||||
0xe4, 0xd6, 0x7a, 0x1c, 0x05, 0x0f, 0x43, 0xc2, 0xa0, 0x59, 0x4c, 0x75, 0x18, 0x4b, 0xb9, 0x3a,
|
||||
0x09, 0x62, 0x2c, 0xe5, 0x21, 0xf7, 0xbe, 0x05, 0xaf, 0xbd, 0xcb, 0xc4, 0xf5, 0xf1, 0x1d, 0x59,
|
||||
0x0f, 0x46, 0x18, 0x2c, 0x16, 0xd2, 0x10, 0xc6, 0x5c, 0x56, 0xe6, 0x27, 0xc6, 0xe0, 0x69, 0x6f,
|
||||
0x1f, 0x9a, 0xe7, 0x00, 0xc9, 0xf0, 0x65, 0xf4, 0x1c, 0x96, 0x2b, 0x52, 0x0a, 0x46, 0xec, 0x38,
|
||||
0x34, 0xdf, 0xd0, 0x2e, 0x4b, 0x67, 0x5d, 0xad, 0xdb, 0x97, 0x2c, 0x39, 0xef, 0x94, 0x0a, 0xce,
|
||||
0x89, 0x31, 0x5e, 0xf9, 0xf7, 0x9b, 0xca, 0x14, 0xad, 0x2c, 0x4e, 0x7b, 0x73, 0x68, 0x7b, 0xe5,
|
||||
0xd1, 0xa0, 0x59, 0xca, 0x0b, 0xf6, 0x10, 0x16, 0x6c, 0x51, 0x8d, 0x2b, 0x85, 0xaa, 0x6c, 0xc8,
|
||||
0xb9, 0x23, 0xb4, 0xd7, 0x8c, 0x66, 0xf7, 0x39, 0xd2, 0x8e, 0x60, 0xde, 0xca, 0x53, 0x19, 0xe6,
|
||||
0x5a, 0x91, 0x01, 0x1b, 0xdf, 0x7e, 0x8a, 0xfa, 0xcc, 0x58, 0x9c, 0x88, 0x0d, 0xb1, 0x59, 0xcc,
|
||||
0x8b, 0x91, 0xcd, 0x4a, 0x96, 0x79, 0xf2, 0xeb, 0x9b, 0x73, 0xcd, 0x0c, 0xae, 0x32, 0xb1, 0x56,
|
||||
0xc1, 0xd5, 0x4e, 0xb9, 0x9d, 0x3f, 0x8f, 0xe7, 0x30, 0xc5, 0xcd, 0xa8, 0x98, 0x7b, 0x3a, 0x88,
|
||||
0x7b, 0xbd, 0x90, 0x92, 0xf2, 0x88, 0x0a, 0xc9, 0xa9, 0x31, 0xc6, 0x6c, 0x9d, 0x7d, 0x39, 0x7b,
|
||||
0x6f, 0xc0, 0x62, 0xb5, 0x6e, 0x7e, 0x8a, 0xc7, 0x4f, 0x21, 0x73, 0x6d, 0x1d, 0x3f, 0xd5, 0x89,
|
||||
0xf7, 0xb6, 0x33, 0x0a, 0x65, 0xc8, 0x39, 0x74, 0x2c, 0xf1, 0x44, 0xbe, 0x3b, 0x3b, 0x9c, 0xc2,
|
||||
0xbf, 0x26, 0xf7, 0xf6, 0xff, 0x07, 0x00, 0x00, 0xff, 0xff, 0x6a, 0xb5, 0xd2, 0x87, 0x80, 0x4e,
|
||||
0x00, 0x00,
|
||||
// 5495 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x3c, 0x4d, 0x6f, 0x1c, 0x57,
|
||||
0x72, 0x98, 0x21, 0x45, 0x72, 0x8a, 0x5f, 0xc3, 0xc7, 0xaf, 0xd1, 0x88, 0x12, 0xa5, 0xf6, 0x5a,
|
||||
0x96, 0xfc, 0x41, 0xd9, 0xb2, 0x36, 0xeb, 0xac, 0x9d, 0xdd, 0x50, 0x94, 0x4c, 0x6b, 0xad, 0xb5,
|
||||
0xb8, 0x4d, 0x5a, 0x06, 0xbc, 0x81, 0x27, 0xcd, 0xe9, 0xc7, 0x61, 0x47, 0x3d, 0xdd, 0xed, 0xee,
|
||||
0x37, 0xa4, 0xe8, 0x4d, 0x90, 0x85, 0x91, 0x04, 0x39, 0x04, 0x9b, 0xc3, 0x22, 0x40, 0x02, 0xe4,
|
||||
0x92, 0x9c, 0x82, 0x00, 0xb9, 0x04, 0x39, 0xe5, 0xb0, 0xc8, 0x35, 0xc8, 0x31, 0x97, 0xfc, 0x80,
|
||||
0x20, 0xb7, 0x24, 0x40, 0x80, 0x5c, 0x72, 0x0a, 0x5e, 0xbd, 0x8f, 0x7e, 0xaf, 0xbb, 0x67, 0x38,
|
||||
0xb4, 0xb5, 0xde, 0x8b, 0x34, 0x5d, 0xaf, 0x5e, 0x55, 0xbd, 0x7a, 0xd5, 0xf5, 0xaa, 0x5e, 0x55,
|
||||
0x13, 0x1a, 0x69, 0xd2, 0xdd, 0x4a, 0xd2, 0x98, 0xc5, 0x64, 0xaa, 0xd7, 0x65, 0x69, 0xd2, 0x6d,
|
||||
0x6f, 0xf4, 0xe2, 0xb8, 0x17, 0xd2, 0x3b, 0x5e, 0x12, 0xdc, 0xf1, 0xa2, 0x28, 0x66, 0x1e, 0x0b,
|
||||
0xe2, 0x28, 0x13, 0x58, 0x4e, 0x13, 0x16, 0x76, 0x29, 0x7b, 0x14, 0x1d, 0xc5, 0x2e, 0xfd, 0x7c,
|
||||
0x40, 0x33, 0xe6, 0xfc, 0xc3, 0x24, 0x2c, 0x6a, 0x50, 0x96, 0xc4, 0x51, 0x46, 0xc9, 0x1a, 0x4c,
|
||||
0x0d, 0x12, 0x16, 0xf4, 0x69, 0xab, 0x76, 0xbd, 0x76, 0xab, 0xe1, 0xca, 0x27, 0x72, 0x07, 0x96,
|
||||
0xbd, 0x13, 0x2f, 0x08, 0xbd, 0xc3, 0x90, 0x76, 0xe8, 0xf3, 0xee, 0xb1, 0x17, 0xf5, 0x68, 0xd6,
|
||||
0xaa, 0x5f, 0xaf, 0xdd, 0x9a, 0x70, 0x89, 0x1e, 0x7a, 0xa8, 0x46, 0xc8, 0x6b, 0xb0, 0x44, 0x23,
|
||||
0x0e, 0xf2, 0x0d, 0xf4, 0x09, 0x44, 0x6f, 0xca, 0x81, 0x1c, 0xf9, 0x1e, 0xac, 0xf9, 0xf4, 0xc8,
|
||||
0x1b, 0x84, 0xac, 0x73, 0x14, 0xa7, 0xf4, 0x79, 0x27, 0x49, 0xe3, 0x93, 0xc0, 0xa7, 0x69, 0x6b,
|
||||
0x12, 0xa5, 0x58, 0x91, 0xa3, 0xef, 0xf3, 0xc1, 0x3d, 0x39, 0x46, 0xee, 0xc2, 0xaa, 0x9e, 0x15,
|
||||
0x78, 0xac, 0xd3, 0x1d, 0xa4, 0x29, 0x8d, 0xba, 0x67, 0xad, 0x4b, 0x38, 0x69, 0x59, 0x4d, 0x0a,
|
||||
0x3c, 0xb6, 0x23, 0x87, 0xc8, 0x27, 0xd0, 0xcc, 0x06, 0x87, 0xd9, 0x59, 0xc6, 0x68, 0xbf, 0x93,
|
||||
0x31, 0x8f, 0x0d, 0xb2, 0xd6, 0xd4, 0xf5, 0x89, 0x5b, 0xb3, 0x77, 0x5f, 0xdf, 0x12, 0x6a, 0xdc,
|
||||
0x2a, 0xa8, 0x64, 0x6b, 0x5f, 0xe1, 0xef, 0x23, 0xfa, 0xc3, 0x88, 0xa5, 0x67, 0xee, 0x62, 0x66,
|
||||
0x43, 0xc9, 0x47, 0x30, 0x9f, 0x26, 0xdd, 0x0e, 0x8d, 0xfc, 0x24, 0x0e, 0x22, 0x96, 0xb5, 0xa6,
|
||||
0x91, 0xea, 0xed, 0x61, 0x54, 0xdd, 0xa4, 0xfb, 0x50, 0xe1, 0x0a, 0x92, 0x73, 0xa9, 0x01, 0x6a,
|
||||
0xdf, 0x87, 0x95, 0x2a, 0xc6, 0xa4, 0x09, 0x13, 0xcf, 0xe8, 0x99, 0xdc, 0x1d, 0xfe, 0x93, 0xac,
|
||||
0xc0, 0xa5, 0x13, 0x2f, 0x1c, 0x50, 0xdc, 0x8c, 0x19, 0x57, 0x3c, 0x7c, 0xb7, 0xfe, 0x4e, 0xad,
|
||||
0x7d, 0x00, 0x4b, 0x25, 0x36, 0x15, 0x04, 0x6e, 0x9b, 0x04, 0x66, 0xef, 0x2e, 0x2b, 0x91, 0xdd,
|
||||
0xbd, 0x1d, 0x35, 0xd7, 0xa0, 0xea, 0xdc, 0x80, 0xcd, 0x5d, 0xca, 0x76, 0xe2, 0x7e, 0x7f, 0x10,
|
||||
0x05, 0x5d, 0xb4, 0x31, 0x97, 0x86, 0xde, 0x19, 0x4d, 0x33, 0x65, 0x59, 0x1f, 0xc1, 0x4a, 0xd5,
|
||||
0x38, 0x69, 0xc1, 0xb4, 0xdc, 0x7b, 0xe4, 0x3f, 0xe3, 0xaa, 0x47, 0xb2, 0x01, 0x8d, 0x6e, 0x1c,
|
||||
0x45, 0xb4, 0xcb, 0xa8, 0x2f, 0x17, 0x92, 0x03, 0x9c, 0x3f, 0xaa, 0xc3, 0xf5, 0xe1, 0x3c, 0xa5,
|
||||
0xe9, 0x7e, 0x01, 0x6b, 0x5d, 0x13, 0xa1, 0x93, 0x4a, 0x8c, 0x56, 0x0d, 0xb7, 0x62, 0xc7, 0xd8,
|
||||
0x8a, 0x91, 0x94, 0xb6, 0x2a, 0x47, 0xc5, 0x26, 0xad, 0x76, 0xab, 0xc6, 0xda, 0x47, 0xd0, 0x1e,
|
||||
0x3e, 0xa9, 0x42, 0xe5, 0x77, 0x6d, 0x95, 0x6f, 0x28, 0xd1, 0xaa, 0x88, 0x98, 0xba, 0xff, 0x0e,
|
||||
0xac, 0xef, 0xd2, 0x88, 0xa6, 0x41, 0x57, 0x1b, 0x87, 0xd4, 0x39, 0xd7, 0xa0, 0xb6, 0x49, 0xc9,
|
||||
0x2a, 0x07, 0x38, 0x6d, 0x68, 0x95, 0x27, 0x8a, 0xe5, 0x3a, 0x6b, 0xb0, 0xb2, 0x4b, 0x99, 0x86,
|
||||
0xeb, 0x5d, 0xfc, 0x45, 0x0d, 0x56, 0x71, 0x20, 0x3b, 0xcc, 0xce, 0xc4, 0x80, 0x54, 0xf5, 0x6f,
|
||||
0xc3, 0x92, 0x26, 0x9d, 0xa9, 0xd7, 0x48, 0x68, 0xf9, 0x6d, 0x43, 0xcb, 0xe5, 0x99, 0xf9, 0xcb,
|
||||
0x94, 0x99, 0x6f, 0x53, 0xfe, 0x4e, 0x4a, 0x70, 0x7b, 0x07, 0x56, 0x2b, 0x51, 0x2f, 0x62, 0xff,
|
||||
0x4e, 0x0b, 0xd6, 0x76, 0x29, 0x33, 0xcc, 0xd8, 0x30, 0xd0, 0x59, 0x03, 0xcc, 0xed, 0x32, 0x63,
|
||||
0x5e, 0xca, 0x72, 0xbb, 0x94, 0x8f, 0xe4, 0x65, 0x58, 0x08, 0x83, 0x8c, 0xd1, 0xa8, 0xe3, 0xf9,
|
||||
0x7e, 0x4a, 0x33, 0xe1, 0xf2, 0x1a, 0xee, 0xbc, 0x80, 0x6e, 0x0b, 0xa0, 0xf3, 0x8f, 0x35, 0xbe,
|
||||
0x31, 0x05, 0x56, 0x52, 0x59, 0x8f, 0xa1, 0x91, 0x7b, 0x05, 0xa1, 0xa4, 0x2d, 0x43, 0x49, 0x55,
|
||||
0x73, 0xb6, 0x0a, 0xae, 0x21, 0x27, 0xd0, 0xfe, 0x11, 0x2c, 0xbc, 0xe8, 0x17, 0xfa, 0x1d, 0x68,
|
||||
0x4b, 0xdb, 0x50, 0x1e, 0xf9, 0x23, 0xaf, 0x4f, 0x95, 0x5d, 0xb5, 0x61, 0x46, 0x39, 0x70, 0xc9,
|
||||
0x43, 0x3f, 0x3b, 0x57, 0xe1, 0x4a, 0xe5, 0x4c, 0x69, 0x58, 0x77, 0x60, 0x79, 0x97, 0x32, 0xed,
|
||||
0xe6, 0x15, 0xc5, 0xa1, 0x5e, 0xc0, 0xb9, 0x87, 0x96, 0x68, 0x4c, 0x90, 0x2a, 0xdc, 0x80, 0x46,
|
||||
0x7e, 0x88, 0x48, 0xdb, 0xd6, 0x00, 0xe7, 0x2e, 0x9a, 0xa9, 0x9a, 0xf5, 0xe4, 0x60, 0xcf, 0xa5,
|
||||
0x62, 0xda, 0x65, 0x98, 0x89, 0x59, 0xd2, 0xe9, 0xc6, 0xbe, 0x12, 0x7d, 0x3a, 0x66, 0xc9, 0x4e,
|
||||
0xec, 0x53, 0x69, 0x1a, 0xc6, 0x1c, 0x6d, 0x1a, 0x7f, 0x2d, 0xb6, 0xd2, 0x1e, 0x92, 0x72, 0xfc,
|
||||
0x00, 0x1a, 0x8a, 0xa0, 0xda, 0xca, 0x37, 0x8c, 0xad, 0xac, 0x9a, 0xb3, 0xf5, 0x44, 0x70, 0x94,
|
||||
0x3b, 0x39, 0x23, 0x05, 0xc8, 0xda, 0xef, 0xc2, 0xbc, 0x35, 0x74, 0x9e, 0x65, 0x37, 0xcc, 0x2d,
|
||||
0xbb, 0x07, 0x6b, 0x0f, 0x82, 0xcc, 0x3c, 0x71, 0xc7, 0xd9, 0xae, 0xcf, 0x60, 0x61, 0xcf, 0x0b,
|
||||
0xd2, 0x6c, 0x7f, 0x90, 0x24, 0x31, 0x9a, 0xf7, 0x2b, 0xb0, 0x98, 0x1f, 0xeb, 0x09, 0x1f, 0x93,
|
||||
0x93, 0x16, 0x34, 0x18, 0x67, 0x90, 0x97, 0x60, 0x5e, 0x1d, 0xe7, 0x02, 0x4d, 0x88, 0x34, 0x27,
|
||||
0x81, 0x88, 0xe4, 0x7c, 0x39, 0x69, 0xa9, 0xce, 0x0a, 0x2c, 0x08, 0x4c, 0x46, 0x9e, 0x0e, 0x2b,
|
||||
0xf0, 0xb7, 0x69, 0x08, 0x75, 0xfb, 0x38, 0x68, 0xc1, 0xf4, 0x09, 0x4d, 0x0f, 0xe3, 0x8c, 0x62,
|
||||
0xcc, 0x30, 0xe3, 0xaa, 0x47, 0x2e, 0xc8, 0x20, 0x0b, 0xa2, 0x5e, 0x27, 0xf3, 0x22, 0xff, 0x30,
|
||||
0x7e, 0x8e, 0x11, 0xc2, 0x8c, 0x3b, 0x87, 0xc0, 0x7d, 0x01, 0x23, 0x37, 0x60, 0xee, 0x98, 0xb1,
|
||||
0xa4, 0xc3, 0x43, 0x97, 0x78, 0xc0, 0x64, 0x40, 0x30, 0xcb, 0x61, 0x07, 0x02, 0xc4, 0x5f, 0x6c,
|
||||
0x44, 0x19, 0x64, 0x34, 0xf5, 0x7a, 0x34, 0x62, 0xad, 0x29, 0xf1, 0x62, 0x73, 0xe8, 0xc7, 0x0a,
|
||||
0x48, 0xae, 0x02, 0x20, 0x5a, 0x92, 0xc6, 0xcf, 0xcf, 0x5a, 0xd3, 0xc2, 0xf4, 0x38, 0x64, 0x8f,
|
||||
0x03, 0xb8, 0xfe, 0x0e, 0xbd, 0x8c, 0xaa, 0xd0, 0x23, 0xa0, 0x59, 0x6b, 0x46, 0xe8, 0x8f, 0x83,
|
||||
0x77, 0x34, 0x94, 0x74, 0x78, 0xdc, 0x21, 0xb5, 0xde, 0xf1, 0xb2, 0x8c, 0xb2, 0xac, 0xd5, 0x40,
|
||||
0x03, 0xba, 0x57, 0x61, 0x40, 0x85, 0xf8, 0x43, 0xce, 0xdb, 0xc6, 0x69, 0x3a, 0xfe, 0xb0, 0xa0,
|
||||
0x3c, 0xde, 0xf2, 0x06, 0xec, 0x98, 0x46, 0x8c, 0x9f, 0x1e, 0x9c, 0x49, 0x12, 0xb4, 0x00, 0x75,
|
||||
0xd3, 0xb4, 0x06, 0xb6, 0x93, 0xa0, 0xfd, 0x29, 0x0f, 0x2e, 0xca, 0x54, 0x2b, 0x4c, 0xf0, 0x75,
|
||||
0xdb, 0x95, 0xac, 0x29, 0x61, 0x6d, 0x3b, 0x32, 0x4d, 0xf3, 0x14, 0x9a, 0xbb, 0x94, 0x1d, 0x04,
|
||||
0xdd, 0x67, 0x34, 0x1d, 0xc3, 0x28, 0xc9, 0x2d, 0x98, 0xe4, 0x16, 0x25, 0x19, 0xac, 0xe8, 0x93,
|
||||
0x50, 0x46, 0x6c, 0x9c, 0x91, 0x8b, 0x18, 0x7c, 0x2f, 0x50, 0x73, 0x1d, 0x76, 0x96, 0x08, 0xbb,
|
||||
0x68, 0xb8, 0x0d, 0x84, 0x1c, 0x9c, 0x25, 0xd4, 0x79, 0x0a, 0x73, 0xe6, 0x24, 0xee, 0x34, 0x7c,
|
||||
0x1a, 0x06, 0xfd, 0x80, 0xd1, 0x54, 0x39, 0x0d, 0x0d, 0xe0, 0xf6, 0xc8, 0xb7, 0x48, 0xda, 0x31,
|
||||
0xfe, 0xe6, 0xef, 0xdb, 0xe7, 0x83, 0x98, 0x29, 0xda, 0xe2, 0xc1, 0xf9, 0xb3, 0x3a, 0x2c, 0xa8,
|
||||
0xe5, 0x48, 0x63, 0x56, 0x32, 0xd7, 0xce, 0x95, 0xf9, 0x06, 0xcc, 0x85, 0x5e, 0xc6, 0x3a, 0x83,
|
||||
0xc4, 0xf7, 0x54, 0x68, 0x33, 0xe1, 0xce, 0x72, 0xd8, 0xc7, 0x02, 0xc4, 0x2d, 0x5a, 0x45, 0xae,
|
||||
0xf8, 0x6e, 0x49, 0xee, 0x73, 0x5d, 0x73, 0x31, 0x04, 0x26, 0xf9, 0x1c, 0xb4, 0xf6, 0x9a, 0x8b,
|
||||
0xbf, 0x39, 0xec, 0x38, 0xe8, 0x1d, 0xa3, 0x75, 0xd7, 0x5c, 0xfc, 0xcd, 0x77, 0x30, 0x8c, 0x4f,
|
||||
0xd1, 0x96, 0x6b, 0x2e, 0xff, 0xc9, 0x21, 0x87, 0x81, 0x8f, 0xa6, 0x5b, 0x73, 0xf9, 0x4f, 0x0e,
|
||||
0xf1, 0xb2, 0x67, 0x68, 0xa8, 0x35, 0x97, 0xff, 0xe4, 0x51, 0xff, 0x49, 0x1c, 0x0e, 0xfa, 0xb4,
|
||||
0xd5, 0x40, 0xa0, 0x7c, 0x22, 0x57, 0xa0, 0x91, 0xa4, 0x41, 0x97, 0x76, 0x3c, 0x76, 0x8c, 0xc6,
|
||||
0x54, 0x73, 0x67, 0x10, 0xb0, 0xcd, 0x8e, 0x9d, 0x65, 0x58, 0xd2, 0x1b, 0xad, 0xbd, 0xe7, 0x27,
|
||||
0x30, 0x2d, 0x21, 0x23, 0x37, 0xfd, 0x4d, 0x98, 0x66, 0x02, 0xad, 0x55, 0xc7, 0xb7, 0x40, 0x1b,
|
||||
0x96, 0xad, 0x69, 0x57, 0xa1, 0x39, 0xdf, 0x07, 0x62, 0x72, 0x93, 0x1b, 0x71, 0x3b, 0xa7, 0x23,
|
||||
0xdc, 0xf1, 0xa2, 0x4d, 0x27, 0xcb, 0x09, 0x7c, 0x81, 0x87, 0xd1, 0x93, 0xd4, 0xe7, 0x8e, 0x24,
|
||||
0x7e, 0xf6, 0x8d, 0x9a, 0xe6, 0x0f, 0x61, 0x5e, 0x33, 0x7e, 0xc4, 0x68, 0x9f, 0x2b, 0xdc, 0xeb,
|
||||
0xc7, 0x83, 0x88, 0x21, 0xcf, 0x9a, 0x2b, 0x9f, 0xb8, 0x05, 0xa2, 0x7e, 0x91, 0x65, 0xcd, 0x15,
|
||||
0x0f, 0x64, 0x01, 0xea, 0x81, 0x2f, 0x93, 0xa7, 0x7a, 0xe0, 0x3b, 0xff, 0x57, 0x83, 0x25, 0x63,
|
||||
0x21, 0x17, 0x36, 0xca, 0x92, 0xc5, 0xd5, 0x2b, 0x2c, 0xee, 0x36, 0x4c, 0x1e, 0x06, 0x3e, 0xcf,
|
||||
0xd9, 0xb8, 0x5e, 0x57, 0x15, 0x39, 0x6b, 0x1d, 0x2e, 0xa2, 0x70, 0x54, 0x2f, 0x7b, 0x96, 0xb5,
|
||||
0x26, 0x47, 0xa2, 0x72, 0x94, 0xd2, 0xfb, 0x70, 0xa9, 0xfc, 0x3e, 0xd8, 0xba, 0x9c, 0x2a, 0xea,
|
||||
0x52, 0x44, 0xab, 0x9a, 0xb6, 0xb6, 0xbc, 0x2e, 0x40, 0x0e, 0x1c, 0xb9, 0xad, 0xbf, 0x0e, 0x10,
|
||||
0x6b, 0x4c, 0x69, 0x7f, 0x97, 0x4b, 0x42, 0x6b, 0x13, 0x34, 0x90, 0x9d, 0x0f, 0x31, 0xd4, 0x30,
|
||||
0x99, 0x4b, 0xe5, 0xdf, 0xb5, 0x68, 0x0a, 0x5b, 0x24, 0x25, 0x9a, 0x99, 0x45, 0xec, 0x6d, 0x24,
|
||||
0xb6, 0xdd, 0xed, 0xf2, 0xad, 0x37, 0x12, 0xf3, 0x91, 0x67, 0xf8, 0x53, 0x98, 0x96, 0x33, 0xa4,
|
||||
0x59, 0x08, 0x84, 0x7a, 0xe0, 0x93, 0x77, 0x01, 0x8c, 0x73, 0x48, 0xac, 0xeb, 0x8a, 0x92, 0x41,
|
||||
0x4e, 0x52, 0xd6, 0x80, 0xec, 0x0c, 0x74, 0xe7, 0x08, 0x96, 0x2b, 0x50, 0xb8, 0x28, 0x3a, 0xad,
|
||||
0x96, 0xa2, 0xa8, 0x67, 0xb2, 0x09, 0xb3, 0x2c, 0x66, 0x5e, 0xd8, 0xc9, 0x4f, 0x88, 0x9a, 0x0b,
|
||||
0x08, 0x7a, 0xca, 0x21, 0xe8, 0xa0, 0xe2, 0x50, 0x58, 0x2e, 0x77, 0x50, 0x71, 0xe8, 0x3b, 0x1e,
|
||||
0x06, 0x5e, 0xd6, 0xa2, 0xa5, 0x0a, 0x47, 0x6d, 0xd9, 0x6b, 0x30, 0xe3, 0x89, 0x29, 0x6a, 0x61,
|
||||
0x8b, 0x85, 0x85, 0xb9, 0x1a, 0xc1, 0x21, 0x78, 0x02, 0xed, 0xc4, 0xd1, 0x51, 0xd0, 0x53, 0xd6,
|
||||
0xf1, 0x0a, 0x3a, 0x2b, 0x05, 0xcb, 0x63, 0x12, 0xdf, 0x63, 0x1e, 0x72, 0x9b, 0x73, 0xf1, 0xb7,
|
||||
0xf3, 0x87, 0x35, 0x68, 0xee, 0xc5, 0x29, 0x3b, 0x8a, 0xc3, 0x20, 0x96, 0xe1, 0x3d, 0x0f, 0x47,
|
||||
0x54, 0xf8, 0x2f, 0xe3, 0x48, 0xf9, 0xc8, 0x3d, 0x64, 0x37, 0x0e, 0x22, 0x61, 0xab, 0x75, 0xa9,
|
||||
0xa0, 0x38, 0x88, 0xb8, 0xa9, 0x92, 0xeb, 0x30, 0xeb, 0xd3, 0xac, 0x9b, 0x06, 0x09, 0x4f, 0xe7,
|
||||
0xa4, 0x5b, 0x30, 0x41, 0x9c, 0xf0, 0xa1, 0x17, 0x7a, 0x51, 0x97, 0x4a, 0xcf, 0xae, 0x1e, 0x9d,
|
||||
0x55, 0x74, 0x57, 0x5a, 0x12, 0x23, 0xb3, 0xb6, 0xc1, 0x72, 0x29, 0xbf, 0x06, 0x8d, 0x44, 0x01,
|
||||
0xa5, 0xf9, 0xb5, 0xf4, 0x59, 0x5d, 0x58, 0x8e, 0x9b, 0xa3, 0x3a, 0x1b, 0x3c, 0xf6, 0xcf, 0xe9,
|
||||
0xed, 0x0f, 0xfa, 0x7d, 0x2f, 0x3d, 0x53, 0xdc, 0x22, 0x98, 0xdc, 0x89, 0x83, 0x88, 0x2b, 0x8a,
|
||||
0x2f, 0x4a, 0x05, 0x6f, 0xfc, 0xb7, 0x29, 0x7a, 0xdd, 0x12, 0xdd, 0xd4, 0xd6, 0x84, 0xad, 0xad,
|
||||
0x6b, 0x00, 0x09, 0x4d, 0xbb, 0x34, 0x62, 0x5e, 0x4f, 0xad, 0xd8, 0x80, 0x38, 0xc7, 0x40, 0x9e,
|
||||
0x1c, 0x1d, 0x85, 0x41, 0x44, 0x39, 0x5b, 0x29, 0xcc, 0x08, 0xed, 0x0f, 0x97, 0xc1, 0xe6, 0x34,
|
||||
0x51, 0xe2, 0xf4, 0x43, 0x58, 0x7a, 0x12, 0x55, 0x30, 0x52, 0xe4, 0x6a, 0xa3, 0xc8, 0xd5, 0x4b,
|
||||
0xe4, 0x3e, 0x80, 0x39, 0x43, 0xf0, 0x8c, 0xbc, 0x03, 0x0d, 0x29, 0xa3, 0x4e, 0x14, 0xda, 0xda,
|
||||
0x1b, 0x94, 0x56, 0xe8, 0xe6, 0xc8, 0xce, 0x9f, 0xd7, 0x60, 0x36, 0x97, 0x2c, 0x23, 0xf7, 0xe0,
|
||||
0x12, 0x57, 0xb7, 0xa2, 0x72, 0x4d, 0x53, 0xc9, 0x71, 0xb6, 0xf0, 0x5f, 0x11, 0x17, 0x0a, 0xe4,
|
||||
0xf6, 0x3e, 0x40, 0x0e, 0xac, 0x08, 0xeb, 0xee, 0xd8, 0x61, 0xdd, 0xe5, 0x32, 0x55, 0x25, 0x9a,
|
||||
0x11, 0xd9, 0xfd, 0xcb, 0x24, 0x4f, 0xf7, 0x2a, 0x8c, 0x45, 0xda, 0xe0, 0x1b, 0x30, 0x2b, 0xde,
|
||||
0x05, 0xee, 0x01, 0x94, 0xc0, 0x73, 0xf9, 0xd5, 0x46, 0x10, 0xb9, 0x80, 0xef, 0x06, 0x8e, 0x93,
|
||||
0xb7, 0x60, 0x1e, 0x85, 0xed, 0xc4, 0x42, 0x21, 0xf2, 0xc5, 0xb6, 0x27, 0xcc, 0x21, 0x8a, 0x54,
|
||||
0x19, 0x49, 0x60, 0xd5, 0x9a, 0xd2, 0xc9, 0x84, 0x08, 0xf2, 0x90, 0x7a, 0xcf, 0x08, 0xa5, 0x87,
|
||||
0x49, 0x29, 0x94, 0x25, 0x09, 0xca, 0x31, 0xa1, 0xba, 0xe5, 0x6e, 0x79, 0x84, 0xdc, 0x81, 0x39,
|
||||
0xc9, 0x11, 0x35, 0x23, 0x8f, 0x38, 0x5b, 0xc6, 0x59, 0x31, 0x11, 0x11, 0x48, 0x1f, 0x56, 0xcc,
|
||||
0x09, 0x5a, 0xc2, 0x4b, 0x38, 0xf1, 0xdd, 0xf1, 0x25, 0x8c, 0x4a, 0x02, 0x92, 0x6e, 0x69, 0xa0,
|
||||
0xfd, 0x5b, 0xd0, 0x1a, 0xb6, 0xa0, 0x8a, 0x6d, 0x7f, 0xd5, 0xde, 0xf6, 0x95, 0x0a, 0x93, 0xcc,
|
||||
0xcc, 0x0b, 0xc4, 0x4f, 0x61, 0x7d, 0x88, 0x30, 0x17, 0xb8, 0x75, 0x30, 0x2c, 0xd5, 0xb4, 0xa6,
|
||||
0x3f, 0xad, 0x41, 0x7b, 0xdb, 0xf7, 0x4b, 0xce, 0x29, 0xbf, 0x24, 0xf8, 0xa6, 0x5d, 0xee, 0x55,
|
||||
0xb8, 0x52, 0x29, 0x90, 0xbc, 0xcd, 0x78, 0x0e, 0x57, 0x5d, 0xda, 0x8f, 0x4f, 0xe8, 0x37, 0x2d,
|
||||
0xb2, 0x73, 0x1d, 0xae, 0x0d, 0xe3, 0x2c, 0x65, 0xc3, 0xeb, 0x3d, 0xfb, 0x7a, 0x5c, 0x07, 0x46,
|
||||
0xff, 0x59, 0x83, 0x79, 0xfb, 0xe2, 0xfc, 0x45, 0xe5, 0xe2, 0xaf, 0x03, 0x49, 0x69, 0xc6, 0x3a,
|
||||
0x49, 0x1c, 0x86, 0x3c, 0x25, 0xf7, 0x69, 0xe8, 0x9d, 0xc9, 0x2b, 0xfb, 0x26, 0x1f, 0xd9, 0x13,
|
||||
0x03, 0x0f, 0x38, 0x9c, 0xac, 0xc3, 0xb4, 0x97, 0x04, 0x1d, 0x6e, 0x35, 0x22, 0x1f, 0x9f, 0xf2,
|
||||
0x92, 0xe0, 0x43, 0x7a, 0x46, 0x1c, 0x98, 0x97, 0x03, 0x9d, 0x90, 0x9e, 0xd0, 0x10, 0x63, 0xbe,
|
||||
0x09, 0x77, 0x56, 0x0c, 0x3f, 0xe6, 0x20, 0x72, 0x1b, 0x9a, 0x49, 0x1a, 0x70, 0xf3, 0xcb, 0x6b,
|
||||
0x03, 0xd3, 0x28, 0xcd, 0xa2, 0x84, 0xab, 0xd5, 0x39, 0x3f, 0x86, 0xcb, 0x15, 0xba, 0x90, 0x3e,
|
||||
0xea, 0x7b, 0xb0, 0x68, 0x57, 0x18, 0x94, 0x9f, 0xd2, 0x51, 0xab, 0x35, 0xd1, 0x5d, 0x38, 0xb2,
|
||||
0xe8, 0xc8, 0xe8, 0x13, 0x71, 0x5c, 0x8f, 0xe9, 0x3b, 0x2d, 0xe7, 0x73, 0x58, 0xc9, 0x81, 0x3b,
|
||||
0x71, 0x74, 0x42, 0xd3, 0x8c, 0x5b, 0x1b, 0x81, 0xc9, 0xa3, 0x34, 0x56, 0x17, 0xb2, 0xf8, 0x9b,
|
||||
0xc7, 0x6d, 0x2c, 0x96, 0x66, 0x50, 0x67, 0x31, 0xc7, 0x49, 0x3d, 0xa6, 0x4e, 0x29, 0xfc, 0xcd,
|
||||
0xe3, 0xe4, 0x00, 0x89, 0xd0, 0x0e, 0x8e, 0x09, 0x53, 0x9d, 0x95, 0x30, 0xce, 0xc5, 0x79, 0x8a,
|
||||
0xe1, 0xa3, 0x29, 0x8a, 0x5c, 0xe3, 0x6f, 0xc0, 0xac, 0x58, 0x23, 0x9f, 0xa9, 0xd6, 0xb7, 0x61,
|
||||
0xad, 0xaf, 0x20, 0xa6, 0x0b, 0x47, 0x1a, 0xea, 0xfc, 0x77, 0x1d, 0xe6, 0x30, 0x62, 0x7d, 0x40,
|
||||
0x99, 0x17, 0x84, 0xa3, 0x63, 0x69, 0x11, 0x83, 0xd6, 0x75, 0x0c, 0xfa, 0x12, 0xcc, 0x9b, 0x17,
|
||||
0x22, 0x67, 0x2a, 0x99, 0x35, 0xae, 0x43, 0xce, 0xc8, 0xcb, 0xb0, 0x80, 0xa9, 0x75, 0x8e, 0x25,
|
||||
0x6c, 0x66, 0x1e, 0xa1, 0x1a, 0xcd, 0x4e, 0x04, 0x2e, 0x15, 0x12, 0x01, 0x3e, 0x8c, 0xc1, 0x74,
|
||||
0x27, 0x0b, 0x7c, 0x9d, 0x27, 0x20, 0x64, 0x3f, 0xf0, 0x8d, 0x61, 0x9c, 0x3d, 0x6d, 0x0c, 0xe3,
|
||||
0x6c, 0x9e, 0x03, 0xa5, 0x54, 0x14, 0x0a, 0xb0, 0xde, 0x35, 0x83, 0x46, 0x37, 0xa7, 0x80, 0x07,
|
||||
0x41, 0x1f, 0xab, 0x61, 0xf2, 0x72, 0xbb, 0x21, 0x2c, 0x56, 0x3c, 0xe5, 0x69, 0x1a, 0x98, 0x69,
|
||||
0x5a, 0x9e, 0xd4, 0xcd, 0x5a, 0x49, 0xdd, 0x26, 0xcc, 0xc6, 0x09, 0x8d, 0x3a, 0x32, 0xc5, 0x9e,
|
||||
0x13, 0xd1, 0x03, 0x07, 0x3d, 0x45, 0x88, 0xbc, 0x32, 0x41, 0x9d, 0x67, 0xe3, 0xe4, 0xa5, 0xb6,
|
||||
0x62, 0xea, 0x45, 0xc5, 0xa8, 0x44, 0x70, 0xe2, 0xbc, 0x44, 0xd0, 0xd9, 0xc6, 0xa8, 0x58, 0x31,
|
||||
0x96, 0xe6, 0xf3, 0x3a, 0x4c, 0xa1, 0x9a, 0x94, 0xe5, 0xac, 0x58, 0x69, 0x8c, 0x34, 0x0a, 0x57,
|
||||
0xe2, 0x38, 0x1f, 0x60, 0x0d, 0x11, 0x87, 0xc6, 0x11, 0xfd, 0x32, 0xcc, 0x88, 0x5d, 0xd1, 0x56,
|
||||
0x33, 0x8d, 0xcf, 0x8f, 0x7c, 0xe7, 0xdf, 0x6a, 0x40, 0xf6, 0x07, 0x87, 0xfd, 0x60, 0x7c, 0x6a,
|
||||
0xe3, 0x27, 0xe8, 0x04, 0x26, 0xd1, 0x4c, 0x84, 0x39, 0xe2, 0xef, 0x82, 0x85, 0x4c, 0x16, 0x2d,
|
||||
0x24, 0xdf, 0xce, 0x4b, 0xd5, 0x39, 0xfa, 0x94, 0xb9, 0xf9, 0xdc, 0xc5, 0x87, 0x01, 0x8d, 0x58,
|
||||
0x47, 0x5e, 0xb6, 0x70, 0x17, 0x8f, 0x80, 0x47, 0xbe, 0xb3, 0x0f, 0xcb, 0xd6, 0xca, 0xa4, 0xa6,
|
||||
0x6f, 0xc0, 0x9c, 0x10, 0x20, 0x09, 0xbd, 0xae, 0xbe, 0x0d, 0x9f, 0x45, 0xd8, 0x1e, 0x82, 0x46,
|
||||
0xe9, 0xeb, 0x8f, 0x6b, 0xb0, 0xb2, 0x1f, 0xf4, 0x07, 0xa1, 0xc7, 0xe8, 0x2f, 0x41, 0x63, 0xf9,
|
||||
0xf2, 0x27, 0xac, 0xe5, 0x2b, 0x4d, 0x4e, 0xe6, 0x9a, 0x74, 0xfe, 0xa7, 0x06, 0xab, 0x05, 0x51,
|
||||
0x74, 0x4c, 0x68, 0x1b, 0xd3, 0x90, 0xcb, 0x01, 0x89, 0x64, 0x30, 0xad, 0x5b, 0x4c, 0x5f, 0x82,
|
||||
0xf9, 0x7e, 0x10, 0x05, 0xfd, 0x41, 0xbf, 0x23, 0x74, 0x2f, 0x64, 0x9a, 0x93, 0xc0, 0x3d, 0xdc,
|
||||
0x02, 0x8e, 0xe4, 0x3d, 0x37, 0x90, 0x26, 0x25, 0x92, 0x00, 0x0a, 0xa4, 0x37, 0x61, 0x25, 0x8f,
|
||||
0xdb, 0x3b, 0x3d, 0x2f, 0x88, 0x3a, 0x61, 0x9c, 0x65, 0x72, 0x8f, 0x49, 0x3e, 0xb6, 0xeb, 0x05,
|
||||
0xd1, 0xe3, 0x38, 0xcb, 0x0c, 0x27, 0x30, 0x65, 0x3a, 0x01, 0x1e, 0xc0, 0x34, 0x3f, 0x39, 0xf6,
|
||||
0x42, 0x7a, 0x3f, 0xee, 0x1f, 0xbe, 0x58, 0xdd, 0xdf, 0x80, 0x39, 0x71, 0xef, 0xc6, 0xbc, 0xb4,
|
||||
0x47, 0xd5, 0x0e, 0xcc, 0x22, 0xec, 0x00, 0x41, 0x95, 0xdb, 0xf0, 0x5f, 0x35, 0x20, 0x3b, 0x3c,
|
||||
0x94, 0x09, 0xc7, 0xb6, 0x07, 0xee, 0x4a, 0x44, 0xde, 0x9c, 0x5b, 0x58, 0x43, 0x42, 0x1e, 0xd9,
|
||||
0xe6, 0x37, 0x61, 0x99, 0x9f, 0x5e, 0xcd, 0xe4, 0x05, 0x2f, 0xc7, 0x4a, 0x7e, 0xfc, 0x65, 0x58,
|
||||
0x38, 0xf5, 0xc2, 0x90, 0x32, 0x5d, 0x62, 0x93, 0x37, 0xf1, 0x02, 0xaa, 0x72, 0x70, 0xb5, 0xe0,
|
||||
0x69, 0x63, 0xc1, 0xab, 0xb0, 0x6c, 0xad, 0x57, 0x46, 0x43, 0xf7, 0x60, 0x4d, 0x80, 0xb7, 0xc3,
|
||||
0x70, 0x6c, 0xaf, 0xea, 0xfc, 0x65, 0x1d, 0xd6, 0x4b, 0xd3, 0x74, 0xd8, 0x60, 0x9b, 0xf1, 0x4d,
|
||||
0xbd, 0xdc, 0xea, 0x09, 0x5b, 0xf2, 0x51, 0xce, 0x6a, 0xff, 0x53, 0x0d, 0xa6, 0x04, 0x68, 0xe4,
|
||||
0x6e, 0x7c, 0xaa, 0x1c, 0x82, 0x34, 0x38, 0x91, 0x11, 0x7d, 0x67, 0x3c, 0x66, 0xe2, 0x3f, 0xb3,
|
||||
0xac, 0x2a, 0x3c, 0x89, 0xac, 0xa8, 0x7e, 0x0f, 0x9a, 0x45, 0x84, 0x0b, 0x95, 0x9c, 0xc4, 0xad,
|
||||
0xca, 0xc3, 0x13, 0x6a, 0x94, 0x51, 0x7f, 0x51, 0x83, 0xc5, 0x9d, 0x38, 0xf2, 0x03, 0x7e, 0x62,
|
||||
0xee, 0x79, 0xa9, 0xd7, 0xcf, 0x64, 0x25, 0x5f, 0x80, 0xd4, 0xb5, 0xbb, 0x06, 0x0c, 0xb9, 0xe0,
|
||||
0xbc, 0x0a, 0xd0, 0x3d, 0xa6, 0xdd, 0x67, 0x1d, 0x79, 0xe3, 0x28, 0xca, 0xff, 0x1c, 0x72, 0x3f,
|
||||
0xf0, 0x33, 0xf2, 0x06, 0x2c, 0xe7, 0xc3, 0x1d, 0x2f, 0xf2, 0x3b, 0xf2, 0xba, 0x11, 0xab, 0x1b,
|
||||
0x1a, 0x6f, 0x3b, 0xf2, 0xb7, 0xb3, 0x67, 0x19, 0x8f, 0x15, 0xf5, 0x2d, 0x5b, 0xc7, 0x72, 0xe1,
|
||||
0x8b, 0x1a, 0xbe, 0x8d, 0x60, 0xe7, 0x7f, 0x6b, 0x78, 0x02, 0xaa, 0x55, 0xc9, 0xdd, 0xce, 0x2f,
|
||||
0xd6, 0xf0, 0xbe, 0xd5, 0xda, 0xb2, 0x7a, 0x61, 0xcb, 0x08, 0x4c, 0x06, 0x8c, 0xf6, 0xd5, 0xc1,
|
||||
0xc2, 0x7f, 0x93, 0xfb, 0xd0, 0xd4, 0x2b, 0xee, 0x24, 0xa8, 0x16, 0xf9, 0x9a, 0xac, 0xe7, 0x89,
|
||||
0xa3, 0xa5, 0x35, 0x77, 0xb1, 0x5b, 0x50, 0xa3, 0x7a, 0xbd, 0x2e, 0x8d, 0xe5, 0xa8, 0xbb, 0xa8,
|
||||
0x6d, 0xe9, 0x9f, 0xc4, 0x93, 0x90, 0x9a, 0x76, 0x07, 0x8c, 0xfa, 0x32, 0x54, 0xd6, 0xcf, 0xce,
|
||||
0x7f, 0xd4, 0x60, 0x71, 0xdb, 0xf7, 0x71, 0xdd, 0xe3, 0xb8, 0x09, 0xb5, 0xca, 0xfa, 0x39, 0xab,
|
||||
0x9c, 0xf8, 0x8a, 0xab, 0xfc, 0xda, 0x4e, 0x64, 0x88, 0x12, 0x1c, 0x07, 0x9a, 0xf9, 0x3a, 0xab,
|
||||
0xb7, 0xd7, 0xf9, 0x16, 0x10, 0x91, 0x5e, 0x59, 0xea, 0x28, 0x62, 0xad, 0xc2, 0xb2, 0x85, 0x25,
|
||||
0x7d, 0xcd, 0xfb, 0x70, 0x6b, 0x97, 0xb2, 0x9d, 0xf4, 0x2c, 0x61, 0xb1, 0x0a, 0x67, 0x1f, 0xd0,
|
||||
0x24, 0xce, 0x02, 0xe5, 0xb9, 0xe8, 0x58, 0xde, 0xe7, 0x9f, 0x6b, 0x70, 0x7b, 0x0c, 0x42, 0x72,
|
||||
0x09, 0x9f, 0x95, 0xef, 0x97, 0x7e, 0xd3, 0x6c, 0x6f, 0x19, 0x8b, 0xca, 0x96, 0x86, 0xc8, 0x2e,
|
||||
0x03, 0x4d, 0xb2, 0xfd, 0x1e, 0x2c, 0xd8, 0x83, 0x17, 0x72, 0x15, 0x21, 0xdc, 0x3c, 0x47, 0x88,
|
||||
0x71, 0x6c, 0xee, 0x26, 0x2c, 0x74, 0x2d, 0x12, 0x92, 0x51, 0x01, 0xea, 0xec, 0xc0, 0x2b, 0xe7,
|
||||
0x72, 0x93, 0x6a, 0x1b, 0x9a, 0xa1, 0x3b, 0x7f, 0x37, 0x09, 0xeb, 0x9f, 0x04, 0xec, 0xd8, 0x4f,
|
||||
0xbd, 0x53, 0x65, 0x7d, 0xe3, 0x08, 0x59, 0x48, 0xde, 0xeb, 0xe5, 0xfb, 0x86, 0x57, 0x61, 0x29,
|
||||
0x8e, 0x28, 0xe6, 0x18, 0x9d, 0xc4, 0xcb, 0xb2, 0xd3, 0x38, 0x55, 0x67, 0xe9, 0x62, 0x1c, 0x51,
|
||||
0x9e, 0x67, 0xec, 0x49, 0x70, 0xe1, 0x34, 0x9e, 0x2c, 0x9e, 0xc6, 0x4d, 0x98, 0x48, 0x82, 0x48,
|
||||
0xd6, 0x4c, 0xf8, 0x4f, 0x7e, 0x76, 0xb2, 0xd4, 0xf3, 0x0d, 0xca, 0xf2, 0xec, 0x44, 0xa8, 0xa6,
|
||||
0x6b, 0xde, 0xe2, 0x4f, 0x17, 0x6e, 0xf1, 0x0d, 0x9d, 0xcc, 0xd8, 0xb7, 0x16, 0x9b, 0x30, 0x2b,
|
||||
0x7f, 0x76, 0x98, 0xd7, 0x93, 0x29, 0x10, 0x48, 0xd0, 0x81, 0xd7, 0x33, 0xa2, 0x35, 0xb0, 0xa2,
|
||||
0xb5, 0xab, 0x00, 0x47, 0x94, 0x76, 0xac, 0x64, 0xa8, 0x71, 0x44, 0xa9, 0x70, 0xba, 0x3c, 0x54,
|
||||
0x3e, 0xf4, 0xa2, 0x67, 0x1d, 0xbc, 0x83, 0x98, 0x13, 0xe2, 0x70, 0xc0, 0x47, 0x5e, 0x1f, 0x63,
|
||||
0x62, 0x1c, 0x54, 0x32, 0xcd, 0x0b, 0x8d, 0x72, 0xd8, 0x76, 0x7e, 0x9b, 0x82, 0x28, 0xdd, 0x80,
|
||||
0x9d, 0xb5, 0x16, 0xf2, 0xf9, 0x3b, 0x01, 0x3b, 0xd3, 0xf3, 0x51, 0x67, 0xe9, 0x59, 0x6b, 0x31,
|
||||
0x9f, 0xbf, 0x23, 0x40, 0x5c, 0xbc, 0xec, 0x34, 0x38, 0xa2, 0xa2, 0x31, 0xa4, 0x29, 0x5b, 0xa5,
|
||||
0x38, 0x64, 0x27, 0xf6, 0x31, 0x8c, 0x3c, 0x0d, 0x52, 0x23, 0x39, 0x5d, 0x12, 0x29, 0x2c, 0x07,
|
||||
0x2a, 0xd3, 0x70, 0x5e, 0x85, 0xa6, 0x32, 0x17, 0xb3, 0x77, 0x32, 0xa5, 0xd9, 0x20, 0x64, 0xaa,
|
||||
0x77, 0x52, 0x3c, 0x39, 0x6f, 0x61, 0x57, 0xc4, 0xe3, 0xb8, 0xd7, 0xcb, 0xd3, 0x27, 0x69, 0x5a,
|
||||
0x6b, 0x30, 0x15, 0x22, 0x5c, 0x4d, 0x11, 0x4f, 0x4e, 0x84, 0xf7, 0x39, 0x85, 0x29, 0x79, 0xd5,
|
||||
0x22, 0x88, 0x8e, 0x62, 0x99, 0x2d, 0xe0, 0x6f, 0xfe, 0x2e, 0xfa, 0xf4, 0x70, 0xd0, 0x53, 0x3d,
|
||||
0x50, 0xf8, 0xc0, 0x31, 0x4f, 0xbd, 0x34, 0x92, 0x07, 0x2a, 0xfe, 0xe6, 0x98, 0x34, 0x4d, 0xe3,
|
||||
0x54, 0x9e, 0x9e, 0xe2, 0xc1, 0xd9, 0x85, 0xf5, 0xfd, 0x8b, 0x89, 0xc8, 0x09, 0x89, 0xdb, 0x1a,
|
||||
0xf9, 0xfa, 0xe3, 0x83, 0xf3, 0xa1, 0xd5, 0x01, 0x82, 0x5d, 0x02, 0xe3, 0xbc, 0x46, 0x2b, 0x70,
|
||||
0x09, 0x7d, 0xb9, 0x22, 0x86, 0x0f, 0x3c, 0x23, 0x6c, 0x95, 0xa9, 0xe9, 0x1e, 0xb4, 0x72, 0x47,
|
||||
0x85, 0xf0, 0x84, 0xdf, 0xae, 0xe8, 0xa8, 0xb0, 0xe6, 0x8e, 0xd7, 0x52, 0xf1, 0x4b, 0xed, 0x92,
|
||||
0xf8, 0x02, 0x96, 0x4d, 0xd1, 0xbe, 0xd1, 0xac, 0xff, 0xa7, 0x35, 0xbc, 0x21, 0xd3, 0x19, 0xd8,
|
||||
0x3e, 0x4b, 0xa9, 0xd7, 0xff, 0x46, 0x0b, 0xe2, 0xdf, 0x87, 0x1b, 0x66, 0xbf, 0xd4, 0x85, 0x25,
|
||||
0x71, 0x7e, 0x0f, 0xcb, 0x88, 0xa2, 0xc8, 0xff, 0x2b, 0x90, 0xff, 0x3d, 0xb8, 0x66, 0xc8, 0x7f,
|
||||
0x41, 0x31, 0x9c, 0xbf, 0xa8, 0xe1, 0x2d, 0xe2, 0xf6, 0xc0, 0x0f, 0x98, 0x15, 0x73, 0x70, 0xcf,
|
||||
0xc4, 0xbc, 0x94, 0x75, 0x7c, 0x8f, 0x51, 0xdd, 0xc4, 0xc9, 0x21, 0x0f, 0x3c, 0x86, 0x97, 0x27,
|
||||
0x34, 0xf2, 0xc5, 0xa0, 0xbc, 0x0c, 0xa0, 0x91, 0xaf, 0x86, 0x44, 0xe6, 0x70, 0x78, 0x66, 0x25,
|
||||
0x6a, 0xf7, 0xf1, 0x9c, 0xc6, 0xa6, 0x17, 0x7c, 0xe3, 0x2f, 0xb9, 0xe2, 0x81, 0xbf, 0xd6, 0xf1,
|
||||
0xd1, 0x11, 0x7f, 0xe5, 0x2e, 0x21, 0x58, 0x3e, 0x39, 0x3b, 0xa2, 0x28, 0x6d, 0x88, 0x26, 0xdf,
|
||||
0xb7, 0x57, 0x61, 0x8a, 0x62, 0x98, 0x5c, 0xac, 0x6e, 0x1b, 0xb8, 0x12, 0xc3, 0xf9, 0x2b, 0x61,
|
||||
0x61, 0x1f, 0x04, 0x19, 0x8b, 0xd3, 0xa0, 0xbb, 0xe3, 0x45, 0x7e, 0x38, 0x56, 0x18, 0x74, 0x81,
|
||||
0x1d, 0xda, 0x80, 0x46, 0x8a, 0xfd, 0x7f, 0xc1, 0x17, 0x54, 0xf6, 0x46, 0xe4, 0x00, 0x7e, 0x2e,
|
||||
0xf7, 0x52, 0x2f, 0x1a, 0x84, 0x5e, 0xca, 0x4f, 0x89, 0x49, 0x71, 0xa3, 0x6c, 0x80, 0x9c, 0x07,
|
||||
0x58, 0xf9, 0x2c, 0x89, 0x28, 0x57, 0x7b, 0x13, 0xa6, 0xba, 0x08, 0x92, 0xab, 0x5d, 0x30, 0x72,
|
||||
0x30, 0x3f, 0xa4, 0xae, 0x1c, 0x75, 0xfe, 0xa0, 0x06, 0x53, 0x02, 0xc4, 0xbd, 0xad, 0x6e, 0x9c,
|
||||
0x9f, 0x70, 0xf1, 0xb7, 0x6a, 0xc7, 0xa9, 0xe7, 0xed, 0x38, 0xaa, 0x69, 0x67, 0xc2, 0x68, 0xda,
|
||||
0x21, 0x30, 0x19, 0x27, 0x34, 0x52, 0xcd, 0x3d, 0xfc, 0x37, 0xdf, 0xb5, 0x6e, 0x18, 0x67, 0x54,
|
||||
0x66, 0x2e, 0xe2, 0xc1, 0x68, 0xd4, 0x99, 0x32, 0x1b, 0x75, 0x9c, 0xe7, 0x00, 0xf9, 0x36, 0xa0,
|
||||
0x24, 0xdc, 0x6c, 0xe5, 0xa5, 0x33, 0xff, 0x4d, 0xae, 0x01, 0x04, 0x3e, 0x8d, 0x58, 0x70, 0x14,
|
||||
0x50, 0xd5, 0xf0, 0x61, 0x40, 0x78, 0x18, 0xd0, 0xa7, 0x59, 0xa6, 0xaa, 0xa5, 0x0d, 0x57, 0x3d,
|
||||
0x72, 0x45, 0xf3, 0xb5, 0x64, 0xcc, 0xeb, 0x27, 0x2a, 0x26, 0xd1, 0x00, 0xe7, 0x10, 0x1a, 0xbb,
|
||||
0x3b, 0x07, 0xfb, 0x18, 0xee, 0x70, 0xc6, 0x1f, 0x7f, 0xfc, 0xe8, 0x81, 0x62, 0xcc, 0x7f, 0xeb,
|
||||
0x62, 0x43, 0xdd, 0x28, 0x36, 0x10, 0xbe, 0xcb, 0xec, 0x58, 0x25, 0x4d, 0xfc, 0x37, 0xb7, 0xe0,
|
||||
0x88, 0x3e, 0x67, 0x9d, 0x74, 0x10, 0x49, 0x2e, 0xd3, 0xfc, 0xd9, 0x1d, 0x44, 0xce, 0x03, 0x58,
|
||||
0xd7, 0x3c, 0x1e, 0x8a, 0x14, 0x46, 0xd9, 0xd2, 0x6d, 0x98, 0x12, 0xa1, 0x96, 0x6c, 0x7b, 0x59,
|
||||
0xd2, 0xbe, 0x5f, 0x4d, 0x70, 0x25, 0x82, 0xb3, 0x0d, 0x2b, 0x1a, 0xb8, 0xcf, 0xe2, 0xe4, 0x2b,
|
||||
0x90, 0xb8, 0x6c, 0x08, 0xc2, 0x49, 0x6c, 0x87, 0xa1, 0x4a, 0x85, 0x5b, 0xb0, 0x66, 0x0c, 0xf1,
|
||||
0x14, 0x5b, 0x8d, 0x98, 0x93, 0x1e, 0x07, 0x19, 0x33, 0x26, 0xfd, 0x4d, 0xcd, 0x98, 0xf5, 0x71,
|
||||
0x12, 0xc6, 0x9e, 0xaf, 0xa4, 0xda, 0x84, 0x59, 0xc1, 0xb4, 0x63, 0x94, 0x6a, 0x40, 0x80, 0x30,
|
||||
0x50, 0xca, 0x11, 0xb0, 0x87, 0xa1, 0x6e, 0x22, 0x3c, 0xf0, 0x98, 0xa7, 0xbb, 0x1b, 0x26, 0xf2,
|
||||
0xee, 0x06, 0xfe, 0xea, 0x79, 0x69, 0xf7, 0x38, 0x38, 0xa1, 0xbe, 0x0c, 0x00, 0xf4, 0x33, 0xdf,
|
||||
0xe7, 0xf8, 0x84, 0xa6, 0xa7, 0x69, 0xc0, 0x84, 0xd5, 0xcd, 0xb8, 0x39, 0xc0, 0xd9, 0x85, 0x76,
|
||||
0xae, 0x0f, 0xea, 0xf9, 0xea, 0xd7, 0x85, 0x75, 0x78, 0x1f, 0x56, 0x35, 0xf0, 0x47, 0x03, 0xaa,
|
||||
0x9b, 0x0d, 0x2e, 0x42, 0xe3, 0x07, 0xd0, 0xd2, 0xc0, 0xed, 0x01, 0x8b, 0x1f, 0x1b, 0x8a, 0x5b,
|
||||
0xb3, 0xc8, 0x34, 0xd4, 0x1c, 0xe3, 0x1a, 0x4f, 0xc4, 0x48, 0xea, 0x1a, 0xef, 0x33, 0x6b, 0x4f,
|
||||
0xc5, 0xc6, 0xe5, 0x01, 0x9d, 0xee, 0x6d, 0x37, 0xaf, 0xff, 0x5f, 0x83, 0x69, 0x41, 0x54, 0xdd,
|
||||
0xd0, 0x54, 0x88, 0xaa, 0x30, 0x9c, 0xd8, 0xd8, 0x62, 0xb9, 0xde, 0x73, 0xc8, 0xe7, 0x8a, 0xa8,
|
||||
0x9f, 0xa3, 0x08, 0x6b, 0x8f, 0x1b, 0xb2, 0x83, 0xe5, 0x7d, 0x43, 0x39, 0xb2, 0x3b, 0xfb, 0x5c,
|
||||
0x96, 0x8a, 0x4e, 0x3d, 0xa7, 0x73, 0xf7, 0x67, 0xdf, 0x86, 0x85, 0xdd, 0x58, 0xe4, 0x55, 0x07,
|
||||
0x3c, 0x9d, 0x48, 0xc9, 0x13, 0x98, 0x96, 0xdf, 0xb1, 0x90, 0xb5, 0xd2, 0x87, 0x2d, 0xa8, 0xfe,
|
||||
0xf6, 0xfa, 0x90, 0x0f, 0x5e, 0x9c, 0xe5, 0x2f, 0xff, 0xf5, 0xdf, 0x7f, 0x5e, 0x9f, 0x27, 0xb3,
|
||||
0x77, 0x4e, 0xde, 0xba, 0xd3, 0xa3, 0x0c, 0xe3, 0xd6, 0x1e, 0xcc, 0x5b, 0x9f, 0x1e, 0x90, 0x0d,
|
||||
0xeb, 0xf3, 0x81, 0xc2, 0x17, 0x09, 0xed, 0xab, 0x23, 0x3f, 0x2e, 0x70, 0x2e, 0x23, 0x8b, 0x65,
|
||||
0xb2, 0x24, 0x59, 0xe4, 0x5f, 0x15, 0x90, 0xcf, 0x61, 0xf1, 0x21, 0xd6, 0x33, 0x35, 0x51, 0xb2,
|
||||
0x99, 0x13, 0xab, 0xfc, 0xa2, 0xa2, 0x7d, 0x7d, 0x38, 0x82, 0x64, 0x78, 0x05, 0x19, 0xae, 0x92,
|
||||
0x65, 0xce, 0x50, 0xd4, 0x4b, 0x35, 0x4f, 0x92, 0x41, 0x53, 0xf6, 0x68, 0xbf, 0x50, 0x9e, 0x1b,
|
||||
0xc8, 0x73, 0x8d, 0xac, 0x70, 0x9e, 0xbe, 0x60, 0x90, 0x33, 0x8d, 0xb1, 0x1c, 0x63, 0x7e, 0x53,
|
||||
0x40, 0xae, 0x0d, 0xfd, 0xd8, 0x40, 0xb0, 0xdc, 0x3c, 0xe7, 0x63, 0x04, 0x7b, 0x95, 0x3d, 0xca,
|
||||
0x71, 0xf5, 0xf7, 0x08, 0xe4, 0xe7, 0x22, 0x46, 0xaf, 0xfc, 0xfa, 0x85, 0xbc, 0x72, 0xfe, 0x27,
|
||||
0x37, 0x42, 0x86, 0x5b, 0xe3, 0x7e, 0x9b, 0xe3, 0x7c, 0x0b, 0x85, 0xb9, 0x46, 0x36, 0xa4, 0x30,
|
||||
0xd6, 0xf7, 0x38, 0xea, 0x8b, 0x1f, 0xd2, 0x85, 0x39, 0xf3, 0x43, 0x02, 0x72, 0xa5, 0x22, 0x25,
|
||||
0xd0, 0xcc, 0x37, 0xaa, 0x07, 0x25, 0xc3, 0x16, 0x32, 0x24, 0xa4, 0x29, 0x19, 0xea, 0xef, 0x0e,
|
||||
0xc8, 0x17, 0xb0, 0x58, 0x68, 0xc2, 0x27, 0x4e, 0x61, 0xfb, 0x2a, 0x3e, 0xa8, 0x68, 0xbf, 0x34,
|
||||
0x12, 0x47, 0x72, 0xbd, 0x86, 0x5c, 0x5b, 0xce, 0xb2, 0xb1, 0xcb, 0x8a, 0xf3, 0x77, 0x6b, 0xaf,
|
||||
0x92, 0x0c, 0xf7, 0xd9, 0xec, 0x17, 0x1f, 0x8b, 0xf7, 0xe6, 0x39, 0xcd, 0xe6, 0xa5, 0xbd, 0x56,
|
||||
0x3c, 0xf1, 0x6d, 0xcd, 0xb0, 0x07, 0xd7, 0xf8, 0xca, 0x01, 0xf3, 0xe5, 0x71, 0xf8, 0x5e, 0xad,
|
||||
0xfe, 0x4a, 0x42, 0x7e, 0xa8, 0xe1, 0xb4, 0x91, 0xeb, 0x0a, 0x21, 0x05, 0xae, 0x31, 0x4b, 0x48,
|
||||
0x66, 0x7d, 0x44, 0x22, 0x99, 0xda, 0x56, 0x5d, 0xf1, 0x19, 0x47, 0xe5, 0x4a, 0xcd, 0xef, 0x32,
|
||||
0x86, 0xae, 0x34, 0x66, 0x49, 0x46, 0x9e, 0xc3, 0x82, 0x70, 0x17, 0x2f, 0x7e, 0x67, 0xaf, 0x22,
|
||||
0xdf, 0x75, 0x87, 0xe4, 0x3e, 0xc3, 0xdc, 0xd8, 0x4f, 0xa0, 0xa1, 0x13, 0x1b, 0xd2, 0x32, 0x16,
|
||||
0x61, 0x75, 0xd4, 0xb7, 0x87, 0xf4, 0x4b, 0x2b, 0x6b, 0x75, 0xe6, 0xe5, 0xaa, 0x44, 0xf7, 0x33,
|
||||
0x27, 0xfc, 0x63, 0x80, 0xbc, 0x81, 0x9a, 0x5c, 0x2e, 0x51, 0xd6, 0x9a, 0x6b, 0x57, 0x0d, 0xa9,
|
||||
0x4f, 0xc5, 0x90, 0x7c, 0x93, 0x2c, 0x58, 0xe4, 0xd5, 0xfb, 0xa6, 0xf3, 0x38, 0xeb, 0x7d, 0x2b,
|
||||
0xb6, 0x5c, 0xb7, 0x87, 0xf7, 0xda, 0xaa, 0x4d, 0x71, 0xd4, 0xcb, 0xa6, 0xef, 0xeb, 0xf9, 0x0a,
|
||||
0xc4, 0x61, 0x61, 0x34, 0xf9, 0x6e, 0x54, 0x71, 0xa9, 0x3c, 0x2c, 0xca, 0x1d, 0xbb, 0xa5, 0xc3,
|
||||
0x22, 0x6f, 0xcc, 0x25, 0xcf, 0xf0, 0x53, 0x59, 0xa3, 0x47, 0x95, 0x98, 0xb4, 0xca, 0x0d, 0xbb,
|
||||
0xed, 0x6b, 0xc3, 0x86, 0xb3, 0x6a, 0xfb, 0x96, 0x57, 0x7a, 0xf8, 0x52, 0x9d, 0x89, 0x5c, 0x30,
|
||||
0x9f, 0x25, 0xf2, 0xc8, 0xaf, 0xcb, 0xf2, 0x3a, 0xb2, 0x6c, 0x93, 0x56, 0x99, 0x65, 0x86, 0x0c,
|
||||
0xde, 0xac, 0x49, 0x5b, 0x13, 0x4d, 0xb1, 0x96, 0xad, 0x59, 0xbd, 0xb3, 0xed, 0xcb, 0x15, 0x23,
|
||||
0x92, 0xcb, 0x2a, 0x72, 0x59, 0x24, 0xf3, 0xda, 0x1b, 0x23, 0x2d, 0x61, 0x0e, 0xba, 0x5b, 0xc9,
|
||||
0x32, 0x87, 0x62, 0x4b, 0xab, 0xe5, 0x7e, 0x4b, 0x8d, 0xad, 0x25, 0xf7, 0xab, 0x5b, 0x57, 0xc9,
|
||||
0xef, 0xdb, 0x1d, 0xb2, 0xaa, 0x63, 0xcf, 0x19, 0xd9, 0x62, 0x57, 0x7a, 0x51, 0x87, 0xb6, 0xe1,
|
||||
0x39, 0x9b, 0xc8, 0xf9, 0x32, 0x59, 0x2f, 0x72, 0x96, 0x2d, 0x7d, 0xe4, 0xcb, 0x1a, 0x2c, 0x57,
|
||||
0x34, 0x8c, 0xe5, 0x12, 0x0c, 0x6f, 0x6f, 0xcb, 0x25, 0x18, 0xd5, 0x71, 0xe6, 0xa0, 0x04, 0x1b,
|
||||
0x0e, 0x4a, 0xe0, 0xf9, 0xbe, 0x96, 0x40, 0x5e, 0x8e, 0xf2, 0x97, 0xe2, 0x67, 0x35, 0x58, 0xab,
|
||||
0x6e, 0x0e, 0x23, 0x2f, 0xeb, 0xef, 0xfe, 0x46, 0xb5, 0xad, 0xb5, 0x6f, 0x9e, 0x87, 0x26, 0xa5,
|
||||
0x79, 0x19, 0xa5, 0xd9, 0x74, 0xda, 0x5c, 0x9a, 0x14, 0x71, 0xab, 0x04, 0x3a, 0xc5, 0x8a, 0x9a,
|
||||
0xdd, 0x7e, 0x45, 0x8c, 0xb0, 0xa6, 0xba, 0x4b, 0xad, 0x7d, 0x63, 0x04, 0x86, 0xed, 0x39, 0xc9,
|
||||
0xaa, 0xdc, 0x10, 0xec, 0x59, 0xd2, 0x7d, 0x5c, 0xd2, 0x3d, 0xe4, 0xed, 0x4d, 0x96, 0x7b, 0x28,
|
||||
0x75, 0x6c, 0x59, 0xee, 0xa1, 0xdc, 0x44, 0x55, 0x72, 0x0f, 0xc8, 0x0c, 0x1b, 0xaa, 0xc8, 0xa7,
|
||||
0xf8, 0xda, 0xc8, 0x72, 0x6e, 0xab, 0xe8, 0x65, 0xb2, 0xaa, 0xd7, 0xc6, 0x2e, 0xd8, 0x96, 0xbc,
|
||||
0xb4, 0xa8, 0x12, 0x73, 0xed, 0xb9, 0x30, 0xa3, 0xd0, 0xc9, 0x7a, 0x91, 0x80, 0xa2, 0x5c, 0xd9,
|
||||
0x91, 0xe3, 0xac, 0x23, 0xd1, 0x25, 0x67, 0xce, 0x24, 0xca, 0x69, 0x1e, 0xc2, 0xac, 0xd1, 0x7d,
|
||||
0x42, 0xb4, 0x7f, 0x2f, 0x37, 0xdb, 0xb4, 0xaf, 0x54, 0x8e, 0xd9, 0x5e, 0xcc, 0x59, 0xe4, 0x0c,
|
||||
0x32, 0x44, 0xd0, 0x3c, 0x7e, 0x07, 0xe6, 0xad, 0x06, 0x90, 0x5c, 0xf9, 0x55, 0x2d, 0x2a, 0xb9,
|
||||
0xf2, 0x2b, 0xbb, 0x46, 0x54, 0x8c, 0xeb, 0xa0, 0xf2, 0x33, 0x89, 0xa2, 0x79, 0x7d, 0x06, 0x0d,
|
||||
0xdd, 0x77, 0x91, 0xeb, 0xbf, 0xd8, 0x8a, 0x71, 0x1e, 0x0f, 0x6b, 0x0f, 0x4e, 0xf9, 0xe4, 0xc3,
|
||||
0xb8, 0x7f, 0x28, 0xf5, 0x65, 0x74, 0x15, 0xe4, 0xfa, 0x2a, 0xb7, 0x56, 0xe4, 0xfa, 0xaa, 0x6a,
|
||||
0x43, 0xb0, 0xf4, 0xd5, 0x45, 0x04, 0xbd, 0x86, 0x14, 0x16, 0x0b, 0xd5, 0xfc, 0x3c, 0xa2, 0xa9,
|
||||
0xee, 0x5d, 0xc8, 0x23, 0x9a, 0x21, 0x6d, 0x00, 0x76, 0xcc, 0x28, 0xf8, 0x79, 0x61, 0x98, 0xdb,
|
||||
0x96, 0x70, 0xf7, 0xa2, 0xd6, 0x6d, 0xd9, 0xad, 0x55, 0xd4, 0xb7, 0xec, 0xd6, 0x2e, 0x8c, 0x97,
|
||||
0xdc, 0xbd, 0xb8, 0xee, 0x23, 0x4f, 0x61, 0x46, 0x15, 0x59, 0x73, 0xa3, 0x2d, 0x94, 0x97, 0xdb,
|
||||
0xad, 0xf2, 0x80, 0xa4, 0x6a, 0x19, 0xae, 0xe7, 0xfb, 0x48, 0x55, 0x6e, 0x84, 0x51, 0x72, 0xcd,
|
||||
0x37, 0xa2, 0x5c, 0xad, 0xcd, 0x37, 0xa2, 0xaa, 0x46, 0x6b, 0x6d, 0x84, 0xf0, 0x5c, 0x9a, 0xc7,
|
||||
0xdf, 0xd7, 0xf0, 0x2a, 0x7a, 0x74, 0xc5, 0x94, 0xbc, 0x79, 0x81, 0xe2, 0xaa, 0x10, 0xe8, 0xad,
|
||||
0x0b, 0x97, 0x63, 0x9d, 0x5b, 0x28, 0xa6, 0xe3, 0x5c, 0x55, 0x87, 0x29, 0x4e, 0xf3, 0x05, 0xba,
|
||||
0xae, 0xcd, 0x72, 0xa1, 0xff, 0xb6, 0x26, 0xfe, 0x06, 0xc3, 0x08, 0xba, 0x64, 0x6b, 0x4c, 0x01,
|
||||
0x94, 0xc0, 0x77, 0xc6, 0xc6, 0x97, 0xe2, 0xde, 0x44, 0x71, 0xaf, 0x3b, 0x57, 0x46, 0x88, 0xcb,
|
||||
0x85, 0xfd, 0x5d, 0xb8, 0xa2, 0x2b, 0xab, 0x16, 0xdd, 0xf7, 0x07, 0x91, 0x9f, 0xe5, 0x29, 0xf1,
|
||||
0x90, 0xf2, 0x6b, 0x6e, 0x38, 0xc5, 0x82, 0x9b, 0x7d, 0x3e, 0x9e, 0xca, 0x51, 0x21, 0xc6, 0x11,
|
||||
0xa7, 0xcd, 0xb9, 0x27, 0xb0, 0xa4, 0xe6, 0xbd, 0x1f, 0x78, 0xec, 0x6b, 0xf3, 0x94, 0x71, 0x95,
|
||||
0xb3, 0x6a, 0xf2, 0x3c, 0x0a, 0x3c, 0xa6, 0x39, 0x66, 0xd8, 0x28, 0x63, 0xd5, 0xd2, 0xcc, 0xbc,
|
||||
0xbf, 0xb2, 0xca, 0x66, 0xe6, 0xfd, 0xd5, 0x65, 0x3f, 0x3b, 0xef, 0xef, 0x51, 0x26, 0xca, 0x70,
|
||||
0xbe, 0x64, 0x70, 0x02, 0xcd, 0xfd, 0xa1, 0x4c, 0xf7, 0xbf, 0x32, 0x53, 0x19, 0x03, 0x39, 0xc8,
|
||||
0x34, 0x2b, 0x30, 0xe5, 0x8b, 0x3d, 0x11, 0x5d, 0x41, 0x66, 0x95, 0x8d, 0x6c, 0x0e, 0xaf, 0xbf,
|
||||
0x95, 0xf9, 0x56, 0x16, 0xe8, 0x6c, 0xbe, 0x46, 0x72, 0x86, 0xdf, 0x9e, 0x73, 0xbe, 0x67, 0x40,
|
||||
0xec, 0x04, 0x0d, 0xbf, 0x59, 0xd4, 0x5e, 0xa0, 0xa2, 0xb6, 0x36, 0x5e, 0x76, 0x76, 0x03, 0x19,
|
||||
0x5f, 0x71, 0xd6, 0xca, 0xd9, 0x19, 0xe7, 0xcd, 0x59, 0xff, 0x04, 0x96, 0x0b, 0x69, 0xff, 0x0b,
|
||||
0xe2, 0x6d, 0x99, 0x73, 0x21, 0xe7, 0x57, 0xcc, 0x19, 0xa6, 0xe0, 0x85, 0x82, 0x19, 0xb9, 0x51,
|
||||
0x95, 0xea, 0x58, 0xf5, 0xa8, 0x51, 0x49, 0x97, 0x3c, 0x37, 0xc8, 0x5a, 0x29, 0x13, 0x52, 0x89,
|
||||
0xc2, 0x9f, 0xd4, 0xb0, 0x58, 0x32, 0xa4, 0x5e, 0x47, 0x6e, 0x57, 0xe5, 0xda, 0x17, 0x16, 0x43,
|
||||
0xfa, 0x13, 0x72, 0xad, 0x98, 0x90, 0x97, 0xc4, 0x39, 0xc6, 0xcb, 0x0f, 0xb3, 0xea, 0x66, 0x5d,
|
||||
0x07, 0x54, 0x94, 0xe3, 0x86, 0xe6, 0xcb, 0xc5, 0x5b, 0x00, 0x99, 0xd0, 0x2a, 0x4e, 0x3f, 0xb5,
|
||||
0xff, 0x18, 0x84, 0xc5, 0xf2, 0x66, 0xc5, 0xaa, 0x2f, 0xc2, 0xfa, 0x25, 0x64, 0x7d, 0x95, 0x5c,
|
||||
0x29, 0xac, 0xb7, 0x20, 0x82, 0x08, 0x6b, 0x8d, 0xea, 0x8e, 0x19, 0xd6, 0x96, 0x4a, 0x88, 0x56,
|
||||
0x58, 0x5b, 0xae, 0xe2, 0x95, 0xc2, 0x5a, 0x8f, 0xa3, 0xe0, 0x61, 0x48, 0x18, 0x34, 0x8b, 0x55,
|
||||
0x16, 0xe3, 0x55, 0xae, 0xae, 0xbf, 0x18, 0xaf, 0xf2, 0x90, 0x2b, 0xe7, 0x42, 0xd4, 0xde, 0x65,
|
||||
0xe2, 0xe6, 0xfa, 0x8e, 0x6c, 0x45, 0x23, 0x0c, 0x16, 0x0b, 0x15, 0x10, 0x63, 0x2f, 0x2b, 0x4b,
|
||||
0x23, 0x63, 0xf0, 0xb4, 0xdd, 0x87, 0xe6, 0x39, 0x40, 0x32, 0xfc, 0x35, 0x7a, 0x0e, 0xcb, 0x15,
|
||||
0xd5, 0x0c, 0x23, 0x77, 0x1c, 0x5a, 0xea, 0x68, 0x97, 0xa5, 0xb3, 0x6e, 0xf5, 0xed, 0xfb, 0x9d,
|
||||
0x9c, 0x77, 0x4a, 0x05, 0xe7, 0xc4, 0x58, 0xaf, 0xfc, 0xd3, 0x51, 0x65, 0x8a, 0x56, 0x01, 0xa9,
|
||||
0xbd, 0x39, 0x74, 0xbc, 0xf2, 0x68, 0xd0, 0x2c, 0xe5, 0xdd, 0x7e, 0x08, 0x0b, 0xb6, 0xa8, 0xc6,
|
||||
0xd5, 0x42, 0x55, 0x21, 0xe6, 0xdc, 0x15, 0xda, 0xef, 0x8c, 0x66, 0xf7, 0x39, 0xd2, 0x8e, 0x60,
|
||||
0xde, 0x2a, 0x91, 0x19, 0xe6, 0x5a, 0x51, 0x7c, 0x1b, 0xdf, 0x7e, 0x8a, 0xfa, 0xcc, 0x58, 0x9c,
|
||||
0x08, 0x87, 0xd8, 0x2c, 0x96, 0xe4, 0xc8, 0x66, 0x25, 0xcb, 0xbc, 0xee, 0xf6, 0xf5, 0xb9, 0x66,
|
||||
0x06, 0x57, 0x59, 0xd3, 0xab, 0xe0, 0x6a, 0x57, 0xfb, 0xce, 0xdf, 0xc7, 0x73, 0x98, 0xa2, 0x33,
|
||||
0x2a, 0x96, 0xbd, 0x0e, 0xe2, 0x5e, 0x2f, 0xa4, 0xa4, 0xbc, 0xa2, 0x42, 0x5d, 0x6c, 0x8c, 0x35,
|
||||
0x5b, 0x67, 0x5f, 0xce, 0xde, 0x1b, 0xb0, 0x58, 0xbd, 0x37, 0x3f, 0xc1, 0xe3, 0xa7, 0x50, 0x34,
|
||||
0xb7, 0x8e, 0x9f, 0xea, 0x9a, 0x7f, 0xdb, 0x19, 0x85, 0x32, 0xe4, 0x1c, 0x3a, 0x96, 0x78, 0xa2,
|
||||
0xd4, 0x9e, 0x1d, 0x4e, 0xe1, 0x1f, 0xb2, 0x7b, 0xfb, 0xff, 0x03, 0x00, 0x00, 0xff, 0xff, 0x43,
|
||||
0x1f, 0xbd, 0xbb, 0xfb, 0x4e, 0x00, 0x00,
|
||||
}
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
@@ -6347,6 +6348,7 @@ type GoCryptoTraderClient interface {
|
||||
GetOrderbook(ctx context.Context, in *GetOrderbookRequest, opts ...grpc.CallOption) (*OrderbookResponse, error)
|
||||
GetOrderbooks(ctx context.Context, in *GetOrderbooksRequest, opts ...grpc.CallOption) (*GetOrderbooksResponse, error)
|
||||
GetAccountInfo(ctx context.Context, in *GetAccountInfoRequest, opts ...grpc.CallOption) (*GetAccountInfoResponse, error)
|
||||
GetAccountInfoStream(ctx context.Context, in *GetAccountInfoRequest, opts ...grpc.CallOption) (GoCryptoTrader_GetAccountInfoStreamClient, error)
|
||||
GetConfig(ctx context.Context, in *GetConfigRequest, opts ...grpc.CallOption) (*GetConfigResponse, error)
|
||||
GetPortfolio(ctx context.Context, in *GetPortfolioRequest, opts ...grpc.CallOption) (*GetPortfolioResponse, error)
|
||||
GetPortfolioSummary(ctx context.Context, in *GetPortfolioSummaryRequest, opts ...grpc.CallOption) (*GetPortfolioSummaryResponse, error)
|
||||
@@ -6551,6 +6553,38 @@ func (c *goCryptoTraderClient) GetAccountInfo(ctx context.Context, in *GetAccoun
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *goCryptoTraderClient) GetAccountInfoStream(ctx context.Context, in *GetAccountInfoRequest, opts ...grpc.CallOption) (GoCryptoTrader_GetAccountInfoStreamClient, error) {
|
||||
stream, err := c.cc.NewStream(ctx, &_GoCryptoTrader_serviceDesc.Streams[0], "/gctrpc.GoCryptoTrader/GetAccountInfoStream", opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
x := &goCryptoTraderGetAccountInfoStreamClient{stream}
|
||||
if err := x.ClientStream.SendMsg(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := x.ClientStream.CloseSend(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return x, nil
|
||||
}
|
||||
|
||||
type GoCryptoTrader_GetAccountInfoStreamClient interface {
|
||||
Recv() (*GetAccountInfoResponse, error)
|
||||
grpc.ClientStream
|
||||
}
|
||||
|
||||
type goCryptoTraderGetAccountInfoStreamClient struct {
|
||||
grpc.ClientStream
|
||||
}
|
||||
|
||||
func (x *goCryptoTraderGetAccountInfoStreamClient) Recv() (*GetAccountInfoResponse, error) {
|
||||
m := new(GetAccountInfoResponse)
|
||||
if err := x.ClientStream.RecvMsg(m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func (c *goCryptoTraderClient) GetConfig(ctx context.Context, in *GetConfigRequest, opts ...grpc.CallOption) (*GetConfigResponse, error) {
|
||||
out := new(GetConfigResponse)
|
||||
err := c.cc.Invoke(ctx, "/gctrpc.GoCryptoTrader/GetConfig", in, out, opts...)
|
||||
@@ -6786,7 +6820,7 @@ func (c *goCryptoTraderClient) DisableExchangePair(ctx context.Context, in *Exch
|
||||
}
|
||||
|
||||
func (c *goCryptoTraderClient) GetOrderbookStream(ctx context.Context, in *GetOrderbookStreamRequest, opts ...grpc.CallOption) (GoCryptoTrader_GetOrderbookStreamClient, error) {
|
||||
stream, err := c.cc.NewStream(ctx, &_GoCryptoTrader_serviceDesc.Streams[0], "/gctrpc.GoCryptoTrader/GetOrderbookStream", opts...)
|
||||
stream, err := c.cc.NewStream(ctx, &_GoCryptoTrader_serviceDesc.Streams[1], "/gctrpc.GoCryptoTrader/GetOrderbookStream", opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -6818,7 +6852,7 @@ func (x *goCryptoTraderGetOrderbookStreamClient) Recv() (*OrderbookResponse, err
|
||||
}
|
||||
|
||||
func (c *goCryptoTraderClient) GetExchangeOrderbookStream(ctx context.Context, in *GetExchangeOrderbookStreamRequest, opts ...grpc.CallOption) (GoCryptoTrader_GetExchangeOrderbookStreamClient, error) {
|
||||
stream, err := c.cc.NewStream(ctx, &_GoCryptoTrader_serviceDesc.Streams[1], "/gctrpc.GoCryptoTrader/GetExchangeOrderbookStream", opts...)
|
||||
stream, err := c.cc.NewStream(ctx, &_GoCryptoTrader_serviceDesc.Streams[2], "/gctrpc.GoCryptoTrader/GetExchangeOrderbookStream", opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -6850,7 +6884,7 @@ func (x *goCryptoTraderGetExchangeOrderbookStreamClient) Recv() (*OrderbookRespo
|
||||
}
|
||||
|
||||
func (c *goCryptoTraderClient) GetTickerStream(ctx context.Context, in *GetTickerStreamRequest, opts ...grpc.CallOption) (GoCryptoTrader_GetTickerStreamClient, error) {
|
||||
stream, err := c.cc.NewStream(ctx, &_GoCryptoTrader_serviceDesc.Streams[2], "/gctrpc.GoCryptoTrader/GetTickerStream", opts...)
|
||||
stream, err := c.cc.NewStream(ctx, &_GoCryptoTrader_serviceDesc.Streams[3], "/gctrpc.GoCryptoTrader/GetTickerStream", opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -6882,7 +6916,7 @@ func (x *goCryptoTraderGetTickerStreamClient) Recv() (*TickerResponse, error) {
|
||||
}
|
||||
|
||||
func (c *goCryptoTraderClient) GetExchangeTickerStream(ctx context.Context, in *GetExchangeTickerStreamRequest, opts ...grpc.CallOption) (GoCryptoTrader_GetExchangeTickerStreamClient, error) {
|
||||
stream, err := c.cc.NewStream(ctx, &_GoCryptoTrader_serviceDesc.Streams[3], "/gctrpc.GoCryptoTrader/GetExchangeTickerStream", opts...)
|
||||
stream, err := c.cc.NewStream(ctx, &_GoCryptoTrader_serviceDesc.Streams[4], "/gctrpc.GoCryptoTrader/GetExchangeTickerStream", opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -7031,6 +7065,7 @@ type GoCryptoTraderServer interface {
|
||||
GetOrderbook(context.Context, *GetOrderbookRequest) (*OrderbookResponse, error)
|
||||
GetOrderbooks(context.Context, *GetOrderbooksRequest) (*GetOrderbooksResponse, error)
|
||||
GetAccountInfo(context.Context, *GetAccountInfoRequest) (*GetAccountInfoResponse, error)
|
||||
GetAccountInfoStream(*GetAccountInfoRequest, GoCryptoTrader_GetAccountInfoStreamServer) error
|
||||
GetConfig(context.Context, *GetConfigRequest) (*GetConfigResponse, error)
|
||||
GetPortfolio(context.Context, *GetPortfolioRequest) (*GetPortfolioResponse, error)
|
||||
GetPortfolioSummary(context.Context, *GetPortfolioSummaryRequest) (*GetPortfolioSummaryResponse, error)
|
||||
@@ -7129,6 +7164,9 @@ func (*UnimplementedGoCryptoTraderServer) GetOrderbooks(ctx context.Context, req
|
||||
func (*UnimplementedGoCryptoTraderServer) GetAccountInfo(ctx context.Context, req *GetAccountInfoRequest) (*GetAccountInfoResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetAccountInfo not implemented")
|
||||
}
|
||||
func (*UnimplementedGoCryptoTraderServer) GetAccountInfoStream(req *GetAccountInfoRequest, srv GoCryptoTrader_GetAccountInfoStreamServer) error {
|
||||
return status.Errorf(codes.Unimplemented, "method GetAccountInfoStream not implemented")
|
||||
}
|
||||
func (*UnimplementedGoCryptoTraderServer) GetConfig(ctx context.Context, req *GetConfigRequest) (*GetConfigResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetConfig not implemented")
|
||||
}
|
||||
@@ -7563,6 +7601,27 @@ func _GoCryptoTrader_GetAccountInfo_Handler(srv interface{}, ctx context.Context
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _GoCryptoTrader_GetAccountInfoStream_Handler(srv interface{}, stream grpc.ServerStream) error {
|
||||
m := new(GetAccountInfoRequest)
|
||||
if err := stream.RecvMsg(m); err != nil {
|
||||
return err
|
||||
}
|
||||
return srv.(GoCryptoTraderServer).GetAccountInfoStream(m, &goCryptoTraderGetAccountInfoStreamServer{stream})
|
||||
}
|
||||
|
||||
type GoCryptoTrader_GetAccountInfoStreamServer interface {
|
||||
Send(*GetAccountInfoResponse) error
|
||||
grpc.ServerStream
|
||||
}
|
||||
|
||||
type goCryptoTraderGetAccountInfoStreamServer struct {
|
||||
grpc.ServerStream
|
||||
}
|
||||
|
||||
func (x *goCryptoTraderGetAccountInfoStreamServer) Send(m *GetAccountInfoResponse) error {
|
||||
return x.ServerStream.SendMsg(m)
|
||||
}
|
||||
|
||||
func _GoCryptoTrader_GetConfig_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(GetConfigRequest)
|
||||
if err := dec(in); err != nil {
|
||||
@@ -8535,6 +8594,11 @@ var _GoCryptoTrader_serviceDesc = grpc.ServiceDesc{
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{
|
||||
{
|
||||
StreamName: "GetAccountInfoStream",
|
||||
Handler: _GoCryptoTrader_GetAccountInfoStream_Handler,
|
||||
ServerStreams: true,
|
||||
},
|
||||
{
|
||||
StreamName: "GetOrderbookStream",
|
||||
Handler: _GoCryptoTrader_GetOrderbookStream_Handler,
|
||||
|
||||
@@ -491,6 +491,34 @@ func local_request_GoCryptoTrader_GetAccountInfo_0(ctx context.Context, marshale
|
||||
|
||||
}
|
||||
|
||||
var (
|
||||
filter_GoCryptoTrader_GetAccountInfoStream_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
|
||||
)
|
||||
|
||||
func request_GoCryptoTrader_GetAccountInfoStream_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (GoCryptoTrader_GetAccountInfoStreamClient, runtime.ServerMetadata, error) {
|
||||
var protoReq GetAccountInfoRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
if err := req.ParseForm(); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_GoCryptoTrader_GetAccountInfoStream_0); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
stream, err := client.GetAccountInfoStream(ctx, &protoReq)
|
||||
if err != nil {
|
||||
return nil, metadata, err
|
||||
}
|
||||
header, err := stream.Header()
|
||||
if err != nil {
|
||||
return nil, metadata, err
|
||||
}
|
||||
metadata.HeaderMD = header
|
||||
return stream, metadata, nil
|
||||
|
||||
}
|
||||
|
||||
func request_GoCryptoTrader_GetConfig_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq GetConfigRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
@@ -2089,6 +2117,13 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("GET", pattern_GoCryptoTrader_GetAccountInfoStream_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
err := status.Error(codes.Unimplemented, "streaming calls are not yet supported in the in-process transport")
|
||||
_, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
})
|
||||
|
||||
mux.Handle("GET", pattern_GoCryptoTrader_GetConfig_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
@@ -3238,6 +3273,26 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("GET", pattern_GoCryptoTrader_GetAccountInfoStream_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
rctx, err := runtime.AnnotateContext(ctx, mux, req)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := request_GoCryptoTrader_GetAccountInfoStream_0(rctx, inboundMarshaler, client, req, pathParams)
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_GoCryptoTrader_GetAccountInfoStream_0(ctx, mux, outboundMarshaler, w, req, func() (proto.Message, error) { return resp.Recv() }, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("GET", pattern_GoCryptoTrader_GetConfig_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
@@ -4096,6 +4151,8 @@ var (
|
||||
|
||||
pattern_GoCryptoTrader_GetAccountInfo_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"v1", "getaccountinfo"}, "", runtime.AssumeColonVerbOpt(true)))
|
||||
|
||||
pattern_GoCryptoTrader_GetAccountInfoStream_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"v1", "getaccountinfostream"}, "", runtime.AssumeColonVerbOpt(true)))
|
||||
|
||||
pattern_GoCryptoTrader_GetConfig_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"v1", "getconfig"}, "", runtime.AssumeColonVerbOpt(true)))
|
||||
|
||||
pattern_GoCryptoTrader_GetPortfolio_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"v1", "getportfolio"}, "", runtime.AssumeColonVerbOpt(true)))
|
||||
@@ -4214,6 +4271,8 @@ var (
|
||||
|
||||
forward_GoCryptoTrader_GetAccountInfo_0 = runtime.ForwardResponseMessage
|
||||
|
||||
forward_GoCryptoTrader_GetAccountInfoStream_0 = runtime.ForwardResponseStream
|
||||
|
||||
forward_GoCryptoTrader_GetConfig_0 = runtime.ForwardResponseMessage
|
||||
|
||||
forward_GoCryptoTrader_GetPortfolio_0 = runtime.ForwardResponseMessage
|
||||
|
||||
@@ -542,7 +542,7 @@ message Candle {
|
||||
}
|
||||
|
||||
message AuditEvent {
|
||||
string type = 1 ;
|
||||
string type = 1;
|
||||
string identifier = 2;
|
||||
string message = 3;
|
||||
string timestamp = 4;
|
||||
@@ -711,6 +711,12 @@ service GoCryptoTrader {
|
||||
};
|
||||
}
|
||||
|
||||
rpc GetAccountInfoStream (GetAccountInfoRequest) returns (stream GetAccountInfoResponse) {
|
||||
option (google.api.http) = {
|
||||
get: "/v1/getaccountinfostream"
|
||||
};
|
||||
}
|
||||
|
||||
rpc GetConfig (GetConfigRequest) returns (GetConfigResponse) {
|
||||
option (google.api.http) = {
|
||||
get: "/v1/getconfig"
|
||||
|
||||
@@ -495,6 +495,39 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
"/v1/getaccountinfostream": {
|
||||
"get": {
|
||||
"operationId": "GetAccountInfoStream",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A successful response.(streaming responses)",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"result": {
|
||||
"$ref": "#/definitions/gctrpcGetAccountInfoResponse"
|
||||
},
|
||||
"error": {
|
||||
"$ref": "#/definitions/runtimeStreamError"
|
||||
}
|
||||
},
|
||||
"title": "Stream result of gctrpcGetAccountInfoResponse"
|
||||
}
|
||||
}
|
||||
},
|
||||
"parameters": [
|
||||
{
|
||||
"name": "exchange",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
"GoCryptoTrader"
|
||||
]
|
||||
}
|
||||
},
|
||||
"/v1/getauditevent": {
|
||||
"get": {
|
||||
"operationId": "GetAuditEvent",
|
||||
@@ -676,7 +709,16 @@
|
||||
"200": {
|
||||
"description": "A successful response.(streaming responses)",
|
||||
"schema": {
|
||||
"$ref": "#/x-stream-definitions/gctrpcOrderbookResponse"
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"result": {
|
||||
"$ref": "#/definitions/gctrpcOrderbookResponse"
|
||||
},
|
||||
"error": {
|
||||
"$ref": "#/definitions/runtimeStreamError"
|
||||
}
|
||||
},
|
||||
"title": "Stream result of gctrpcOrderbookResponse"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -791,7 +833,16 @@
|
||||
"200": {
|
||||
"description": "A successful response.(streaming responses)",
|
||||
"schema": {
|
||||
"$ref": "#/x-stream-definitions/gctrpcTickerResponse"
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"result": {
|
||||
"$ref": "#/definitions/gctrpcTickerResponse"
|
||||
},
|
||||
"error": {
|
||||
"$ref": "#/definitions/runtimeStreamError"
|
||||
}
|
||||
},
|
||||
"title": "Stream result of gctrpcTickerResponse"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -1011,7 +1062,16 @@
|
||||
"200": {
|
||||
"description": "A successful response.(streaming responses)",
|
||||
"schema": {
|
||||
"$ref": "#/x-stream-definitions/gctrpcOrderbookResponse"
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"result": {
|
||||
"$ref": "#/definitions/gctrpcOrderbookResponse"
|
||||
},
|
||||
"error": {
|
||||
"$ref": "#/definitions/runtimeStreamError"
|
||||
}
|
||||
},
|
||||
"title": "Stream result of gctrpcOrderbookResponse"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -1191,7 +1251,16 @@
|
||||
"200": {
|
||||
"description": "A successful response.(streaming responses)",
|
||||
"schema": {
|
||||
"$ref": "#/x-stream-definitions/gctrpcTickerResponse"
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"result": {
|
||||
"$ref": "#/definitions/gctrpcTickerResponse"
|
||||
},
|
||||
"error": {
|
||||
"$ref": "#/definitions/runtimeStreamError"
|
||||
}
|
||||
},
|
||||
"title": "Stream result of gctrpcTickerResponse"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -2844,31 +2913,5 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"x-stream-definitions": {
|
||||
"gctrpcOrderbookResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"result": {
|
||||
"$ref": "#/definitions/gctrpcOrderbookResponse"
|
||||
},
|
||||
"error": {
|
||||
"$ref": "#/definitions/runtimeStreamError"
|
||||
}
|
||||
},
|
||||
"title": "Stream result of gctrpcOrderbookResponse"
|
||||
},
|
||||
"gctrpcTickerResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"result": {
|
||||
"$ref": "#/definitions/gctrpcTickerResponse"
|
||||
},
|
||||
"error": {
|
||||
"$ref": "#/definitions/runtimeStreamError"
|
||||
}
|
||||
},
|
||||
"title": "Stream result of gctrpcTickerResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package modules
|
||||
|
||||
import (
|
||||
"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"
|
||||
@@ -27,7 +28,7 @@ type Exchange interface {
|
||||
QueryOrder(exch, orderid string) (*order.Detail, error)
|
||||
SubmitOrder(exch string, submit *order.Submit) (*order.SubmitResponse, error)
|
||||
CancelOrder(exch, orderid string) (bool, error)
|
||||
AccountInformation(exch string) (*AccountInfo, error)
|
||||
AccountInformation(exch string) (account.Holdings, error)
|
||||
DepositAddress(exch string, currencyCode currency.Code) (string, error)
|
||||
WithdrawalFiatFunds(exch, bankaccountid string, request *withdraw.FiatRequest) (out string, err error)
|
||||
WithdrawalCryptoFunds(exch string, request *withdraw.CryptoRequest) (out string, err error)
|
||||
@@ -37,23 +38,3 @@ type Exchange interface {
|
||||
func SetModuleWrapper(wrapper GCT) {
|
||||
Wrapper = wrapper
|
||||
}
|
||||
|
||||
// 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 associated 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
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package exchange
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
@@ -9,12 +8,12 @@ import (
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
"github.com/thrasher-corp/gocryptotrader/engine"
|
||||
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/ticker"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/withdraw"
|
||||
"github.com/thrasher-corp/gocryptotrader/gctscript/modules"
|
||||
)
|
||||
|
||||
// Exchange implements all required methods for Wrapper
|
||||
@@ -120,29 +119,18 @@ func (e Exchange) CancelOrder(exch, orderID string) (bool, error) {
|
||||
}
|
||||
|
||||
// AccountInformation returns account information (balance etc) for requested exchange
|
||||
func (e Exchange) AccountInformation(exch string) (*modules.AccountInfo, error) {
|
||||
func (e Exchange) AccountInformation(exch string) (account.Holdings, error) {
|
||||
ex, err := e.GetExchange(exch)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return account.Holdings{}, err
|
||||
}
|
||||
|
||||
r, err := ex.GetAccountInfo()
|
||||
accountInfo, err := ex.FetchAccountInfo()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return account.Holdings{}, err
|
||||
}
|
||||
|
||||
temp, err := json.Marshal(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
accountInfo := modules.AccountInfo{}
|
||||
err = json.Unmarshal(temp, &accountInfo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &accountInfo, nil
|
||||
return accountInfo, nil
|
||||
}
|
||||
|
||||
// DepositAddress gets the address required to deposit funds for currency type
|
||||
|
||||
@@ -4,12 +4,12 @@ import (
|
||||
"time"
|
||||
|
||||
"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"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/withdraw"
|
||||
"github.com/thrasher-corp/gocryptotrader/gctscript/modules"
|
||||
)
|
||||
|
||||
// Exchanges validator for test execution/scripts
|
||||
@@ -152,17 +152,17 @@ func (w Wrapper) CancelOrder(exch, orderid string) (bool, error) {
|
||||
}
|
||||
|
||||
// AccountInformation validator for test execution/scripts
|
||||
func (w Wrapper) AccountInformation(exch string) (*modules.AccountInfo, error) {
|
||||
func (w Wrapper) AccountInformation(exch string) (account.Holdings, error) {
|
||||
if exch == exchError.String() {
|
||||
return &modules.AccountInfo{}, errTestFailed
|
||||
return account.Holdings{}, errTestFailed
|
||||
}
|
||||
|
||||
return &modules.AccountInfo{
|
||||
return account.Holdings{
|
||||
Exchange: exch,
|
||||
Accounts: []modules.Account{
|
||||
Accounts: []account.SubAccount{
|
||||
{
|
||||
ID: exch,
|
||||
Currencies: []modules.AccountCurrencyInfo{
|
||||
Currencies: []account.Balance{
|
||||
{
|
||||
CurrencyName: currency.Code{
|
||||
Item: ¤cy.Item{
|
||||
|
||||
Reference in New Issue
Block a user