diff --git a/anxhttp.go b/anxhttp.go index 3513e622..dd7350c0 100644 --- a/anxhttp.go +++ b/anxhttp.go @@ -9,6 +9,7 @@ import ( "time" "github.com/thrasher-/gocryptotrader/common" + "github.com/thrasher-/gocryptotrader/config" ) const ( @@ -103,7 +104,7 @@ func (a *ANX) SetDefaults() { } //Setup is run on startup to setup exchange with config values -func (a *ANX) Setup(exch Exchanges) { +func (a *ANX) Setup(exch config.ExchangeConfig) { if !exch.Enabled { a.SetEnabled(false) } else { diff --git a/bitfinexhttp.go b/bitfinexhttp.go index 5c3c3900..a0f038b2 100644 --- a/bitfinexhttp.go +++ b/bitfinexhttp.go @@ -11,6 +11,7 @@ import ( "github.com/gorilla/websocket" "github.com/thrasher-/gocryptotrader/common" + "github.com/thrasher-/gocryptotrader/config" ) const ( @@ -197,7 +198,7 @@ func (b *Bitfinex) GetName() string { return b.Name } -func (b *Bitfinex) Setup(exch Exchanges) { +func (b *Bitfinex) Setup(exch config.ExchangeConfig) { if !exch.Enabled { b.SetEnabled(false) } else { @@ -252,13 +253,13 @@ func (b *Bitfinex) Run() { exchangeProducts = common.SplitStrings(common.StringToUpper(common.JoinStrings(exchangeProducts, ",")), ",") diff := common.StringSliceDifference(b.AvailablePairs, exchangeProducts) if len(diff) > 0 { - exch, err := GetExchangeConfig(b.Name) + exch, err := bot.config.GetExchangeConfig(b.Name) if err != nil { log.Println(err) } else { log.Printf("%s Updating available pairs. Difference: %s.\n", b.Name, diff) exch.AvailablePairs = common.JoinStrings(exchangeProducts, ",") - UpdateExchangeConfig(exch) + bot.config.UpdateExchangeConfig(exch) } } } diff --git a/bitstamphttp.go b/bitstamphttp.go index 888a3311..f70000d8 100644 --- a/bitstamphttp.go +++ b/bitstamphttp.go @@ -11,6 +11,7 @@ import ( "time" "github.com/thrasher-/gocryptotrader/common" + "github.com/thrasher-/gocryptotrader/config" ) const ( @@ -181,7 +182,7 @@ func (b *Bitstamp) GetName() string { return b.Name } -func (b *Bitstamp) Setup(exch Exchanges) { +func (b *Bitstamp) Setup(exch config.ExchangeConfig) { if !exch.Enabled { b.SetEnabled(false) } else { diff --git a/btcchttp.go b/btcchttp.go index 01882b82..7be092ec 100644 --- a/btcchttp.go +++ b/btcchttp.go @@ -10,6 +10,7 @@ import ( "time" "github.com/thrasher-/gocryptotrader/common" + "github.com/thrasher-/gocryptotrader/config" ) const ( @@ -184,7 +185,7 @@ func (b *BTCC) SetDefaults() { } //Setup is run on startup to setup exchange with config values -func (b *BTCC) Setup(exch Exchanges) { +func (b *BTCC) Setup(exch config.ExchangeConfig) { if !exch.Enabled { b.SetEnabled(false) } else { diff --git a/btcehttp.go b/btcehttp.go index dabf43e7..3db23516 100644 --- a/btcehttp.go +++ b/btcehttp.go @@ -10,6 +10,7 @@ import ( "time" "github.com/thrasher-/gocryptotrader/common" + "github.com/thrasher-/gocryptotrader/config" ) const ( @@ -101,7 +102,7 @@ func (b *BTCE) IsEnabled() bool { return b.Enabled } -func (b *BTCE) Setup(exch Exchanges) { +func (b *BTCE) Setup(exch config.ExchangeConfig) { if !exch.Enabled { b.SetEnabled(false) } else { diff --git a/btcmarkets.go b/btcmarkets.go index 84817982..0ae65fd4 100644 --- a/btcmarkets.go +++ b/btcmarkets.go @@ -10,6 +10,7 @@ import ( "time" "github.com/thrasher-/gocryptotrader/common" + "github.com/thrasher-/gocryptotrader/config" ) const ( @@ -110,7 +111,7 @@ func (b *BTCMarkets) IsEnabled() bool { return b.Enabled } -func (b *BTCMarkets) Setup(exch Exchanges) { +func (b *BTCMarkets) Setup(exch config.ExchangeConfig) { if !exch.Enabled { b.SetEnabled(false) } else { diff --git a/common/common.go b/common/common.go index 342ee165..353cd066 100644 --- a/common/common.go +++ b/common/common.go @@ -334,3 +334,19 @@ func UnixTimestampStrToTime(timeStr string) (time.Time, error) { return time.Unix(i, 0), nil } + +func ReadFile(path string) ([]byte, error) { + file, err := ioutil.ReadFile(path) + if err != nil { + return nil, err + } + return file, nil +} + +func WriteFile(file string, data []byte) error { + err := ioutil.WriteFile(file, data, 0644) + if err != nil { + return err + } + return nil +} diff --git a/config.go b/config/config.go similarity index 69% rename from config.go rename to config/config.go index a3f79ae2..10c91728 100644 --- a/config.go +++ b/config/config.go @@ -1,10 +1,9 @@ -package main +package config import ( "encoding/json" "errors" "fmt" - "io/ioutil" "log" "os" "strconv" @@ -43,14 +42,14 @@ var ( RenamingConfigFile = "Renaming config file %s to %s." ) -type Webserver struct { +type WebserverConfig struct { Enabled bool AdminUsername string AdminPassword string ListenAddress string } -type SMSGlobal struct { +type SMSGlobalConfig struct { Enabled bool Username string Password string @@ -69,13 +68,13 @@ type Config struct { Name string EncryptConfig int Cryptocurrencies string - Portfolio Portfolio `json:"PortfolioAddresses"` - SMS SMSGlobal `json:"SMSGlobal"` - Webserver Webserver `json:"Webserver"` - Exchanges []Exchanges + Portfolio PortfolioConfig `json:"PortfolioAddresses"` + SMS SMSGlobalConfig `json:"SMSGlobal"` + Webserver WebserverConfig `json:"Webserver"` + Exchanges []ExchangeConfig `json:"Exchanges"` } -type Exchanges struct { +type ExchangeConfig struct { Name string Enabled bool Verbose bool @@ -90,43 +89,53 @@ type Exchanges struct { BaseCurrencies string } -func GetEnabledExchanges() int { +type PortfolioAddressConfig struct { + Address string + CoinType string + Balance float64 +} + +type PortfolioConfig struct { + Addresses []PortfolioAddressConfig +} + +func (c *Config) GetConfigEnabledExchanges() int { counter := 0 - for i := range bot.config.Exchanges { - if bot.config.Exchanges[i].Enabled { + for i := range c.Exchanges { + if c.Exchanges[i].Enabled { counter++ } } return counter } -func GetExchangeConfig(name string) (Exchanges, error) { - for i, _ := range bot.config.Exchanges { - if bot.config.Exchanges[i].Name == name { - return bot.config.Exchanges[i], nil +func (c *Config) GetExchangeConfig(name string) (ExchangeConfig, error) { + for i, _ := range c.Exchanges { + if c.Exchanges[i].Name == name { + return c.Exchanges[i], nil } } - return Exchanges{}, fmt.Errorf(ErrExchangeNotFound, name) + return ExchangeConfig{}, fmt.Errorf(ErrExchangeNotFound, name) } -func UpdateExchangeConfig(e Exchanges) error { - for i, _ := range bot.config.Exchanges { - if bot.config.Exchanges[i].Name == e.Name { - bot.config.Exchanges[i] = e +func (c *Config) UpdateExchangeConfig(e ExchangeConfig) error { + for i, _ := range c.Exchanges { + if c.Exchanges[i].Name == e.Name { + c.Exchanges[i] = e return nil } } return fmt.Errorf(ErrExchangeNotFound, e.Name) } -func CheckSMSGlobalConfigValues() error { - if bot.config.SMS.Username == "" || bot.config.SMS.Username == "Username" || bot.config.SMS.Password == "" || bot.config.SMS.Password == "Password" { +func (c *Config) CheckSMSGlobalConfigValues() error { + if c.SMS.Username == "" || c.SMS.Username == "Username" || c.SMS.Password == "" || c.SMS.Password == "Password" { return errors.New(WarningSMSGlobalDefaultOrEmptyValues) } contacts := 0 - for i := range bot.config.SMS.Contacts { - if bot.config.SMS.Contacts[i].Enabled { - if bot.config.SMS.Contacts[i].Name == "" || bot.config.SMS.Contacts[i].Number == "" || (bot.config.SMS.Contacts[i].Name == "Bob" && bot.config.SMS.Contacts[i].Number == "12345") { + for i := range c.SMS.Contacts { + if c.SMS.Contacts[i].Enabled { + if c.SMS.Contacts[i].Name == "" || c.SMS.Contacts[i].Number == "" || (c.SMS.Contacts[i].Name == "Bob" && c.SMS.Contacts[i].Number == "12345") { log.Printf(WarningSSMSGlobalSMSContactDefaultOrEmptyValues, i) continue } @@ -139,13 +148,13 @@ func CheckSMSGlobalConfigValues() error { return nil } -func CheckExchangeConfigValues() error { - if bot.config.Cryptocurrencies == "" { +func (c *Config) CheckExchangeConfigValues() error { + if c.Cryptocurrencies == "" { return errors.New(ErrCryptocurrenciesEmpty) } exchanges := 0 - for i, exch := range bot.config.Exchanges { + for i, exch := range c.Exchanges { if exch.Enabled { if exch.Name == "" { return fmt.Errorf(ErrExchangeNameEmpty, i) @@ -161,12 +170,12 @@ func CheckExchangeConfigValues() error { } if exch.AuthenticatedAPISupport { // non-fatal error if exch.APIKey == "" || exch.APISecret == "" || exch.APIKey == "Key" || exch.APISecret == "Secret" { - bot.config.Exchanges[i].AuthenticatedAPISupport = false + c.Exchanges[i].AuthenticatedAPISupport = false log.Printf(WarningExchangeAuthAPIDefaultOrEmptyValues, exch.Name) continue } else if exch.Name == "ITBIT" || exch.Name == "Bitstamp" || exch.Name == "Coinbase" { if exch.ClientID == "" || exch.ClientID == "ClientID" { - bot.config.Exchanges[i].AuthenticatedAPISupport = false + c.Exchanges[i].AuthenticatedAPISupport = false log.Printf(WarningExchangeAuthAPIDefaultOrEmptyValues, exch.Name) continue } @@ -181,16 +190,16 @@ func CheckExchangeConfigValues() error { return nil } -func CheckWebserverValues() error { - if bot.config.Webserver.AdminUsername == "" || bot.config.Webserver.AdminPassword == "" { +func (c *Config) CheckWebserverConfigValues() error { + if c.Webserver.AdminUsername == "" || c.Webserver.AdminPassword == "" { return errors.New(WarningWebserverCredentialValuesEmpty) } - if !common.StringContains(bot.config.Webserver.ListenAddress, ":") { + if !common.StringContains(c.Webserver.ListenAddress, ":") { return errors.New(WarningWebserverListenAddressInvalid) } - portStr := common.SplitStrings(bot.config.Webserver.ListenAddress, ":")[1] + portStr := common.SplitStrings(c.Webserver.ListenAddress, ":")[1] port, err := strconv.Atoi(portStr) if err != nil { return errors.New(WarningWebserverListenAddressInvalid) @@ -202,8 +211,8 @@ func CheckWebserverValues() error { return nil } -func ReadConfig() error { - _, err := ioutil.ReadFile(OLD_CONFIG_FILE) +func (c *Config) ReadConfig() error { + _, err := common.ReadFile(OLD_CONFIG_FILE) if err == nil { err = os.Rename(OLD_CONFIG_FILE, CONFIG_FILE) if err != nil { @@ -212,25 +221,25 @@ func ReadConfig() error { log.Printf(RenamingConfigFile+"\n", OLD_CONFIG_FILE, CONFIG_FILE) } - file, err := ioutil.ReadFile(CONFIG_FILE) + file, err := common.ReadFile(CONFIG_FILE) if err != nil { return err } if !ConfirmECS(file) { - err = ConfirmConfigJSON(file, &bot.config) + err = ConfirmConfigJSON(file, &c) if err != nil { return err } - if bot.config.EncryptConfig == CONFIG_FILE_ENCRYPTION_DISABLED { + if c.EncryptConfig == CONFIG_FILE_ENCRYPTION_DISABLED { return nil } - if bot.config.EncryptConfig == CONFIG_FILE_ENCRYPTION_PROMPT { - if PromptForConfigEncryption() { - bot.config.EncryptConfig = CONFIG_FILE_ENCRYPTION_ENABLED - SaveConfig() + if c.EncryptConfig == CONFIG_FILE_ENCRYPTION_PROMPT { + if c.PromptForConfigEncryption() { + c.EncryptConfig = CONFIG_FILE_ENCRYPTION_ENABLED + return c.SaveConfig() } } } else { @@ -244,7 +253,7 @@ func ReadConfig() error { return err } - err = ConfirmConfigJSON(data, &bot.config) + err = ConfirmConfigJSON(data, &c) if err != nil { return err } @@ -252,10 +261,10 @@ func ReadConfig() error { return nil } -func SaveConfig() error { - payload, err := json.MarshalIndent(bot.config, "", " ") +func (c *Config) SaveConfig() error { + payload, err := json.MarshalIndent(c, "", " ") - if bot.config.EncryptConfig == CONFIG_FILE_ENCRYPTION_ENABLED { + if c.EncryptConfig == CONFIG_FILE_ENCRYPTION_ENABLED { key, err := PromptForConfigKey() if err != nil { return err @@ -267,20 +276,20 @@ func SaveConfig() error { } } - err = ioutil.WriteFile(CONFIG_FILE, payload, 0644) + err = common.WriteFile(CONFIG_FILE, payload) if err != nil { return err } return nil } -func LoadConfig() error { - err := ReadConfig() +func (c *Config) LoadConfig() error { + err := c.ReadConfig() if err != nil { return fmt.Errorf(ErrFailureOpeningConfig, CONFIG_FILE, err) } - err = CheckExchangeConfigValues() + err = c.CheckExchangeConfigValues() if err != nil { return fmt.Errorf(ErrCheckingConfigValues, err) } diff --git a/config_encryption.go b/config/config_encryption.go similarity index 78% rename from config_encryption.go rename to config/config_encryption.go index c9383fe1..64eca75d 100644 --- a/config_encryption.go +++ b/config/config_encryption.go @@ -1,4 +1,4 @@ -package main +package config import ( "bytes" @@ -14,10 +14,12 @@ import ( ) const ( - ENCRYPTION_CONFIRMATION_STRING = "THORS-HAMMER" + CONFIG_ENCRYPTION_CONFIRMATION_STRING = "THORS-HAMMER" + + ErrConfigDataLessThenRequiredAESBlockSize = "The config file data is too small for the AES required block size." ) -func PromptForConfigEncryption() bool { +func (c *Config) PromptForConfigEncryption() bool { log.Println("Would you like to encrypt your config file (y/n)?") input := "" @@ -27,8 +29,8 @@ func PromptForConfigEncryption() bool { } if !common.YesOrNo(input) { - bot.config.EncryptConfig = CONFIG_FILE_ENCRYPTION_DISABLED - SaveConfig() + c.EncryptConfig = CONFIG_FILE_ENCRYPTION_DISABLED + c.SaveConfig() return false } return true @@ -73,7 +75,7 @@ func EncryptConfigFile(configData, key []byte) ([]byte, error) { stream := cipher.NewCFBEncrypter(block, iv) stream.XORKeyStream(ciphertext[aes.BlockSize:], configData) - appendedFile := []byte(ENCRYPTION_CONFIRMATION_STRING) + appendedFile := []byte(CONFIG_ENCRYPTION_CONFIRMATION_STRING) appendedFile = append(appendedFile, ciphertext...) return appendedFile, nil } @@ -86,7 +88,7 @@ func DecryptConfigFile(configData, key []byte) ([]byte, error) { } if len(configData) < aes.BlockSize { - return nil, errors.New("The config file data is too small for the AES required block size.") + return nil, errors.New(ErrConfigDataLessThenRequiredAESBlockSize) } iv := configData[:aes.BlockSize] @@ -103,10 +105,10 @@ func ConfirmConfigJSON(file []byte, result interface{}) error { } func ConfirmECS(file []byte) bool { - subslice := []byte(ENCRYPTION_CONFIRMATION_STRING) + subslice := []byte(CONFIG_ENCRYPTION_CONFIRMATION_STRING) return bytes.Contains(file, subslice) } func RemoveECS(file []byte) []byte { - return bytes.Trim(file, ENCRYPTION_CONFIRMATION_STRING) + return bytes.Trim(file, CONFIG_ENCRYPTION_CONFIRMATION_STRING) } diff --git a/configRoutes.go b/configRoutes.go index 6355d16d..898a8bfa 100644 --- a/configRoutes.go +++ b/configRoutes.go @@ -3,6 +3,8 @@ package main import ( "encoding/json" "net/http" + + "github.com/thrasher-/gocryptotrader/config" ) func GetAllSettings(w http.ResponseWriter, r *http.Request) { @@ -16,7 +18,7 @@ func GetAllSettings(w http.ResponseWriter, r *http.Request) { func SaveAllSettings(w http.ResponseWriter, r *http.Request) { //Get the data from the request decoder := json.NewDecoder(r.Body) - var responseData ConfigPost + var responseData config.ConfigPost jsonerr := decoder.Decode(&responseData) if jsonerr != nil { panic(jsonerr) @@ -33,11 +35,11 @@ func SaveAllSettings(w http.ResponseWriter, r *http.Request) { } } //Reload the configuration - err := SaveConfig() + err := bot.config.SaveConfig() if err != nil { panic(err) } - err = LoadConfig() + err = bot.config.LoadConfig() if err != nil { panic(err) } diff --git a/gdaxhttp.go b/gdaxhttp.go index 6e9014f1..9afb04d9 100644 --- a/gdaxhttp.go +++ b/gdaxhttp.go @@ -10,6 +10,7 @@ import ( "time" "github.com/thrasher-/gocryptotrader/common" + "github.com/thrasher-/gocryptotrader/config" ) const ( @@ -145,7 +146,7 @@ func (g *GDAX) IsEnabled() bool { return g.Enabled } -func (g *GDAX) Setup(exch Exchanges) { +func (g *GDAX) Setup(exch config.ExchangeConfig) { if !exch.Enabled { g.SetEnabled(false) } else { @@ -200,13 +201,13 @@ func (g *GDAX) Run() { } diff := common.StringSliceDifference(g.AvailablePairs, currencies) if len(diff) > 0 { - exch, err := GetExchangeConfig(g.Name) + exch, err := bot.config.GetExchangeConfig(g.Name) if err != nil { log.Println(err) } else { log.Printf("%s Updating available pairs. Difference: %s.\n", g.Name, diff) exch.AvailablePairs = common.JoinStrings(currencies, ",") - UpdateExchangeConfig(exch) + bot.config.UpdateExchangeConfig(exch) } } } diff --git a/geminihttp.go b/geminihttp.go index 5aac6ffb..686aa36b 100644 --- a/geminihttp.go +++ b/geminihttp.go @@ -10,6 +10,7 @@ import ( "time" "github.com/thrasher-/gocryptotrader/common" + "github.com/thrasher-/gocryptotrader/config" ) const ( @@ -126,7 +127,7 @@ func (g *Gemini) IsEnabled() bool { return g.Enabled } -func (g *Gemini) Setup(exch Exchanges) { +func (g *Gemini) Setup(exch config.ExchangeConfig) { if !exch.Enabled { g.SetEnabled(false) } else { @@ -168,13 +169,13 @@ func (g *Gemini) Run() { exchangeProducts = common.SplitStrings(common.StringToUpper(common.JoinStrings(exchangeProducts, ",")), ",") diff := common.StringSliceDifference(g.AvailablePairs, exchangeProducts) if len(diff) > 0 { - exch, err := GetExchangeConfig(g.Name) + exch, err := bot.config.GetExchangeConfig(g.Name) if err != nil { log.Println(err) } else { log.Printf("%s Updating available pairs. Difference: %s.\n", g.Name, diff) exch.AvailablePairs = common.JoinStrings(exchangeProducts, ",") - UpdateExchangeConfig(exch) + bot.config.UpdateExchangeConfig(exch) } } } diff --git a/huobihttp.go b/huobihttp.go index 8ec7802c..506c583d 100644 --- a/huobihttp.go +++ b/huobihttp.go @@ -9,6 +9,7 @@ import ( "time" "github.com/thrasher-/gocryptotrader/common" + "github.com/thrasher-/gocryptotrader/config" ) const ( @@ -65,7 +66,7 @@ func (h *HUOBI) IsEnabled() bool { return h.Enabled } -func (h *HUOBI) Setup(exch Exchanges) { +func (h *HUOBI) Setup(exch config.ExchangeConfig) { if !exch.Enabled { h.SetEnabled(false) } else { diff --git a/interfaces.go b/interfaces.go index add2668d..da0f2c57 100644 --- a/interfaces.go +++ b/interfaces.go @@ -1,8 +1,12 @@ package main +import ( + "github.com/thrasher-/gocryptotrader/config" +) + //IBotExchange : Enforces standard functions for all exchanges supported in gocryptotrader type IBotExchange interface { - Setup(exch Exchanges) + Setup(exch config.ExchangeConfig) Start() SetDefaults() GetName() string diff --git a/itbithttp.go b/itbithttp.go index 53f4bd6a..c0909349 100644 --- a/itbithttp.go +++ b/itbithttp.go @@ -9,6 +9,7 @@ import ( "time" "github.com/thrasher-/gocryptotrader/common" + "github.com/thrasher-/gocryptotrader/config" ) const ( @@ -72,7 +73,7 @@ func (i *ItBit) IsEnabled() bool { return i.Enabled } -func (i *ItBit) Setup(exch Exchanges) { +func (i *ItBit) Setup(exch config.ExchangeConfig) { if !exch.Enabled { i.SetEnabled(false) } else { diff --git a/kraken.go b/kraken.go index d5afde83..28dd4ebd 100644 --- a/kraken.go +++ b/kraken.go @@ -10,6 +10,7 @@ import ( "time" "github.com/thrasher-/gocryptotrader/common" + "github.com/thrasher-/gocryptotrader/config" ) const ( @@ -76,7 +77,7 @@ func (k *Kraken) IsEnabled() bool { return k.Enabled } -func (k *Kraken) Setup(exch Exchanges) { +func (k *Kraken) Setup(exch config.ExchangeConfig) { if !exch.Enabled { k.SetEnabled(false) } else { @@ -129,13 +130,13 @@ func (k *Kraken) Run() { } diff := common.StringSliceDifference(k.AvailablePairs, exchangeProducts) if len(diff) > 0 { - exch, err := GetExchangeConfig(k.Name) + exch, err := bot.config.GetExchangeConfig(k.Name) if err != nil { log.Println(err) } else { log.Printf("%s Updating available pairs. Difference: %s.\n", k.Name, diff) exch.AvailablePairs = common.JoinStrings(exchangeProducts, ",") - UpdateExchangeConfig(exch) + bot.config.UpdateExchangeConfig(exch) } } } diff --git a/lakebtchttp.go b/lakebtchttp.go index baf64a7d..a0ecd32d 100644 --- a/lakebtchttp.go +++ b/lakebtchttp.go @@ -9,6 +9,7 @@ import ( "time" "github.com/thrasher-/gocryptotrader/common" + "github.com/thrasher-/gocryptotrader/config" ) const ( @@ -83,7 +84,7 @@ func (l *LakeBTC) IsEnabled() bool { return l.Enabled } -func (l *LakeBTC) Setup(exch Exchanges) { +func (l *LakeBTC) Setup(exch config.ExchangeConfig) { if !exch.Enabled { l.SetEnabled(false) } else { diff --git a/liquihttp.go b/liquihttp.go index 5bd16c3e..7e77ef6b 100644 --- a/liquihttp.go +++ b/liquihttp.go @@ -10,6 +10,7 @@ import ( "time" "github.com/thrasher-/gocryptotrader/common" + "github.com/thrasher-/gocryptotrader/config" ) const ( @@ -99,7 +100,7 @@ func (l *Liqui) IsEnabled() bool { return l.Enabled } -func (l *Liqui) Setup(exch Exchanges) { +func (l *Liqui) Setup(exch config.ExchangeConfig) { if !exch.Enabled { l.SetEnabled(false) } else { @@ -142,13 +143,13 @@ func (l *Liqui) Run() { exchangeProducts := l.GetAvailablePairs(true) diff := common.StringSliceDifference(l.AvailablePairs, exchangeProducts) if len(diff) > 0 { - exch, err := GetExchangeConfig(l.Name) + exch, err := bot.config.GetExchangeConfig(l.Name) if err != nil { log.Println(err) } else { log.Printf("%s Updating available pairs. Difference: %s.\n", l.Name, diff) exch.AvailablePairs = common.JoinStrings(exchangeProducts, ",") - UpdateExchangeConfig(exch) + bot.config.UpdateExchangeConfig(exch) } } } diff --git a/localbitcoinshttp.go b/localbitcoinshttp.go index f6eac19c..8f409aec 100644 --- a/localbitcoinshttp.go +++ b/localbitcoinshttp.go @@ -10,6 +10,7 @@ import ( "time" "github.com/thrasher-/gocryptotrader/common" + "github.com/thrasher-/gocryptotrader/config" ) const ( @@ -60,7 +61,7 @@ func (l *LocalBitcoins) IsEnabled() bool { return l.Enabled } -func (l *LocalBitcoins) Setup(exch Exchanges) { +func (l *LocalBitcoins) Setup(exch config.ExchangeConfig) { if !exch.Enabled { l.SetEnabled(false) } else { diff --git a/main.go b/main.go index 97071ca9..e2572f77 100644 --- a/main.go +++ b/main.go @@ -10,6 +10,7 @@ import ( "syscall" "github.com/thrasher-/gocryptotrader/common" + "github.com/thrasher-/gocryptotrader/config" ) type Exchange struct { @@ -33,7 +34,7 @@ type Exchange struct { } type Bot struct { - config Config + config config.Config exchange Exchange exchanges []IBotExchange tickers []Ticker @@ -63,9 +64,9 @@ func setupBotExchanges() { func main() { HandleInterrupt() - log.Printf("Loading config file %s..\n", CONFIG_FILE) + log.Printf("Loading config file %s..\n", config.CONFIG_FILE) - err := LoadConfig() + err := bot.config.LoadConfig() if err != nil { log.Fatal(err) } @@ -74,7 +75,7 @@ func main() { AdjustGoMaxProcs() if bot.config.SMS.Enabled { - err = CheckSMSGlobalConfigValues() + err = bot.config.CheckSMSGlobalConfigValues() if err != nil { log.Println(err) // non fatal event bot.config.SMS.Enabled = false @@ -85,7 +86,7 @@ func main() { log.Println("SMS support disabled.") } - log.Printf("Available Exchanges: %d. Enabled Exchanges: %d.\n", len(bot.config.Exchanges), GetEnabledExchanges()) + log.Printf("Available Exchanges: %d. Enabled Exchanges: %d.\n", len(bot.config.Exchanges), bot.config.GetConfigEnabledExchanges()) log.Println("Bot Exchange support:") bot.exchanges = []IBotExchange{ @@ -126,7 +127,7 @@ func main() { go StartPortfolioWatcher() if bot.config.Webserver.Enabled { - err := CheckWebserverValues() + err := bot.config.CheckWebserverConfigValues() if err != nil { log.Println(err) // non fatal event //bot.config.Webserver.Enabled = false @@ -177,7 +178,7 @@ func HandleInterrupt() { func Shutdown() { log.Println("Bot shutting down..") - err := SaveConfig() + err := bot.config.SaveConfig() if err != nil { log.Println("Unable to save config.") diff --git a/okcoinhttp.go b/okcoinhttp.go index e2dfe2c2..2b2c1fa0 100644 --- a/okcoinhttp.go +++ b/okcoinhttp.go @@ -10,6 +10,7 @@ import ( "github.com/gorilla/websocket" "github.com/thrasher-/gocryptotrader/common" + "github.com/thrasher-/gocryptotrader/config" ) const ( @@ -222,7 +223,7 @@ func (o *OKCoin) IsEnabled() bool { return o.Enabled } -func (o *OKCoin) Setup(exch Exchanges) { +func (o *OKCoin) Setup(exch config.ExchangeConfig) { if !exch.Enabled { o.SetEnabled(false) } else { diff --git a/poloniexhttp.go b/poloniexhttp.go index 47c88afb..dc74cd95 100644 --- a/poloniexhttp.go +++ b/poloniexhttp.go @@ -10,6 +10,7 @@ import ( "time" "github.com/thrasher-/gocryptotrader/common" + "github.com/thrasher-/gocryptotrader/config" ) const ( @@ -91,7 +92,7 @@ func (p *Poloniex) IsEnabled() bool { return p.Enabled } -func (p *Poloniex) Setup(exch Exchanges) { +func (p *Poloniex) Setup(exch config.ExchangeConfig) { if !exch.Enabled { p.SetEnabled(false) } else { diff --git a/portfolio.go b/portfolio.go index 6226a450..a142590a 100644 --- a/portfolio.go +++ b/portfolio.go @@ -7,6 +7,7 @@ import ( "time" "github.com/thrasher-/gocryptotrader/common" + "github.com/thrasher-/gocryptotrader/config" ) const ( @@ -134,9 +135,10 @@ func UpdatePortfolio(addresses []string, coinType string) bool { if err != nil { return false } + for _, x := range result.Data { if !AddressExists(x.Address) { - bot.config.Portfolio.Addresses = append(bot.config.Portfolio.Addresses, PortfolioAddress{Address: x.Address, CoinType: coinType, Balance: x.Balance / common.WEI_PER_ETHER}) + bot.config.Portfolio.Addresses = append(bot.config.Portfolio.Addresses, config.PortfolioAddressConfig{Address: x.Address, CoinType: coinType, Balance: x.Balance / common.WEI_PER_ETHER}) } else { UpdateAddressBalance(x.Address, x.Balance) } @@ -150,7 +152,7 @@ func UpdatePortfolio(addresses []string, coinType string) bool { } for _, x := range result.Data { if !AddressExists(x.Address) { - bot.config.Portfolio.Addresses = append(bot.config.Portfolio.Addresses, PortfolioAddress{Address: x.Address, CoinType: coinType, Balance: x.Balance}) + bot.config.Portfolio.Addresses = append(bot.config.Portfolio.Addresses, config.PortfolioAddressConfig{Address: x.Address, CoinType: coinType, Balance: x.Balance}) } else { UpdateAddressBalance(x.Address, x.Balance) } @@ -161,7 +163,7 @@ func UpdatePortfolio(addresses []string, coinType string) bool { return false } if !AddressExists(result.Data.Address) { - bot.config.Portfolio.Addresses = append(bot.config.Portfolio.Addresses, PortfolioAddress{Address: result.Data.Address, CoinType: coinType, Balance: result.Data.Balance}) + bot.config.Portfolio.Addresses = append(bot.config.Portfolio.Addresses, config.PortfolioAddressConfig{Address: result.Data.Address, CoinType: coinType, Balance: result.Data.Balance}) } else { UpdateAddressBalance(result.Data.Address, result.Data.Balance) } diff --git a/tools/config/config-helper.go b/tools/config/config-helper.go index 222f8fee..b84ac4ef 100644 --- a/tools/config/config-helper.go +++ b/tools/config/config-helper.go @@ -1,21 +1,11 @@ package main import ( - "bytes" - "crypto/aes" - "crypto/cipher" - "crypto/rand" - "encoding/json" - "errors" "flag" - "fmt" - "io" - "io/ioutil" "log" -) -const ( - ENCRYPTION_CONFIRMATION_STRING = "THORS-HAMMER" + "github.com/thrasher-/gocryptotrader/common" + "github.com/thrasher-/gocryptotrader/config" ) func EncryptOrDecrypt(encrypt bool) string { @@ -38,26 +28,26 @@ func main() { log.Println("GoCryptoTrader: config-helper tool.") if key == "" { - result, err := PromptForConfigKey() + result, err := config.PromptForConfigKey() if err != nil { log.Fatal("Unable to obtain encryption/decryption key.") } key = string(result) } - file, err := ReadFile(inFile) + file, err := common.ReadFile(inFile) if err != nil { log.Fatalf("Unable to read input file %s. Error: %s.", inFile, err) } - if ConfirmECS(file) && encrypt { + if config.ConfirmECS(file) && encrypt { log.Println("File is already encrypted. Decrypting..") encrypt = false } - if !ConfirmECS(file) && !encrypt { + if !config.ConfirmECS(file) && !encrypt { var result interface{} - err := ConfirmConfigJSON(file, result) + err := config.ConfirmConfigJSON(file, result) if err != nil { log.Fatal("File isn't in JSON format") } @@ -67,119 +57,20 @@ func main() { var data []byte if encrypt { - data, err = EncryptConfigFile(file, []byte(key)) + data, err = config.EncryptConfigFile(file, []byte(key)) if err != nil { log.Fatalf("Unable to encrypt config data. Error: %s.", err) } } else { - data, err = DecryptConfigFile(file, []byte(key)) + data, err = config.DecryptConfigFile(file, []byte(key)) if err != nil { log.Fatalf("Unable to decrypt config data. Error: %s.", err) } } - err = WriteFile(outFile, data) + err = common.WriteFile(outFile, data) if err != nil { log.Fatalf("Unable to write output file %s. Error: %s", outFile, err) } log.Printf("Successfully %s input file %s and wrote output to %s.\n", EncryptOrDecrypt(encrypt), inFile, outFile) } - -func ReadFile(path string) ([]byte, error) { - file, err := ioutil.ReadFile(path) - if err != nil { - return nil, err - } - return file, nil -} - -func WriteFile(file string, data []byte) error { - err := ioutil.WriteFile(file, data, 0644) - if err != nil { - return err - } - return nil -} - -func PromptForConfigKey() ([]byte, error) { - var cryptoKey []byte - - for len(cryptoKey) != 32 { - log.Println("Enter password (32 characters):") - - _, err := fmt.Scanln(&cryptoKey) - if err != nil { - return nil, err - } - - if len(cryptoKey) > 32 || len(cryptoKey) < 32 { - continue - } - } - - nonce := make([]byte, 12) - if _, err := io.ReadFull(rand.Reader, nonce); err != nil { - return nil, err - } - - return cryptoKey, nil -} - -func EncryptConfigFile(configData, key []byte) ([]byte, error) { - block, err := aes.NewCipher(key) - if err != nil { - return nil, err - } - - ciphertext := make([]byte, aes.BlockSize+len(configData)) - iv := ciphertext[:aes.BlockSize] - if _, err := io.ReadFull(rand.Reader, iv); err != nil { - return nil, err - } - - stream := cipher.NewCFBEncrypter(block, iv) - stream.XORKeyStream(ciphertext[aes.BlockSize:], configData) - - appendedFile := []byte(ENCRYPTION_CONFIRMATION_STRING) - appendedFile = append(appendedFile, ciphertext...) - return appendedFile, nil -} - -func DecryptConfigFile(configData, key []byte) ([]byte, error) { - configData = RemoveECS(configData) - blockDecrypt, err := aes.NewCipher(key) - if err != nil { - return nil, err - } - - if len(configData) < aes.BlockSize { - return nil, errors.New("The config file data is too small for the AES required block size.") - } - - iv := configData[:aes.BlockSize] - configData = configData[aes.BlockSize:] - - stream := cipher.NewCFBDecrypter(blockDecrypt, iv) - stream.XORKeyStream(configData, configData) - result := configData - return result, nil -} - -func ConfirmConfigJSON(file []byte, result interface{}) error { - err := json.Unmarshal(file, &result) - - if err != nil { - return err - } - - return nil -} - -func ConfirmECS(file []byte) bool { - subslice := []byte(ENCRYPTION_CONFIRMATION_STRING) - return bytes.Contains(file, subslice) -} - -func RemoveECS(file []byte) []byte { - return bytes.Trim(file, ENCRYPTION_CONFIRMATION_STRING) -}