mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-05-13 23:16:45 +00:00
Merge branch 'master' into engine
This commit is contained in:
@@ -8,8 +8,8 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"github.com/thrasher-corp/gocryptotrader/communications/base"
|
||||
@@ -39,9 +39,16 @@ const (
|
||||
talkRoot = "GoCryptoTrader bot"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrWaiter is the default timer to wait if an err occurs
|
||||
// before retrying after successfully connecting
|
||||
ErrWaiter = time.Second * 30
|
||||
)
|
||||
|
||||
// Telegram is the overarching type across this package
|
||||
type Telegram struct {
|
||||
base.Base
|
||||
initConnected bool
|
||||
Token string
|
||||
Offset int64
|
||||
AuthorisedClients []int64
|
||||
@@ -63,6 +70,8 @@ func (t *Telegram) Connect() error {
|
||||
if err := t.TestConnection(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Debugln(log.CommunicationMgr, "Telegram: Connected successfully!")
|
||||
t.Connected = true
|
||||
go t.PollerStart()
|
||||
return nil
|
||||
@@ -70,9 +79,10 @@ func (t *Telegram) Connect() error {
|
||||
|
||||
// PushEvent sends an event to a supplied recipient list via telegram
|
||||
func (t *Telegram) PushEvent(event base.Event) error {
|
||||
msg := fmt.Sprintf("Type: %s Message: %s",
|
||||
event.Type, event.Message)
|
||||
for i := range t.AuthorisedClients {
|
||||
err := t.SendMessage(fmt.Sprintf("Type: %s Message: %s",
|
||||
event.Type, event.Message), t.AuthorisedClients[i])
|
||||
err := t.SendMessage(msg, t.AuthorisedClients[i])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -82,12 +92,25 @@ func (t *Telegram) PushEvent(event base.Event) error {
|
||||
|
||||
// PollerStart starts the long polling sequence
|
||||
func (t *Telegram) PollerStart() {
|
||||
t.InitialConnect()
|
||||
errWait := func(err error) {
|
||||
log.Errorln(log.CommunicationMgr, err)
|
||||
time.Sleep(ErrWaiter)
|
||||
}
|
||||
|
||||
for {
|
||||
if !t.initConnected {
|
||||
err := t.InitialConnect()
|
||||
if err != nil {
|
||||
errWait(err)
|
||||
continue
|
||||
}
|
||||
t.initConnected = true
|
||||
}
|
||||
|
||||
resp, err := t.GetUpdates()
|
||||
if err != nil {
|
||||
log.Errorln(log.CommunicationMgr, err)
|
||||
errWait(err)
|
||||
continue
|
||||
}
|
||||
|
||||
for i := range resp.Result {
|
||||
@@ -95,7 +118,8 @@ func (t *Telegram) PollerStart() {
|
||||
if string(resp.Result[i].Message.Text[0]) == "/" {
|
||||
err = t.HandleMessages(resp.Result[i].Message.Text, resp.Result[i].Message.From.ID)
|
||||
if err != nil {
|
||||
log.Errorln(log.CommunicationMgr, err)
|
||||
log.Errorf(log.CommunicationMgr, "Telegram: Unable to HandleMessages. Error: %s\n", err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
t.Offset = resp.Result[i].UpdateID
|
||||
@@ -106,16 +130,14 @@ func (t *Telegram) PollerStart() {
|
||||
|
||||
// InitialConnect sets offset, and sends a welcome greeting to any associated
|
||||
// IDs
|
||||
func (t *Telegram) InitialConnect() {
|
||||
func (t *Telegram) InitialConnect() error {
|
||||
resp, err := t.GetUpdates()
|
||||
if err != nil {
|
||||
log.Errorln(log.CommunicationMgr, err)
|
||||
os.Exit(1)
|
||||
return err
|
||||
}
|
||||
|
||||
if !resp.Ok {
|
||||
log.Errorln(log.CommunicationMgr, resp.Description)
|
||||
os.Exit(1)
|
||||
return errors.New(resp.Description)
|
||||
}
|
||||
|
||||
warmWelcomeList := make(map[string]int64)
|
||||
@@ -128,18 +150,25 @@ func (t *Telegram) InitialConnect() {
|
||||
for userName, ID := range warmWelcomeList {
|
||||
err = t.SendMessage(fmt.Sprintf("GoCryptoTrader bot has connected: Hello, %s!", userName), ID)
|
||||
if err != nil {
|
||||
log.Errorln(log.CommunicationMgr, err)
|
||||
os.Exit(1)
|
||||
log.Errorf(log.CommunicationMgr, "Telegram: Unable to send welcome message. Error: %s\n", err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
if len(resp.Result) == 0 {
|
||||
return
|
||||
return nil
|
||||
}
|
||||
|
||||
t.Offset = resp.Result[len(resp.Result)-1].UpdateID
|
||||
return nil
|
||||
}
|
||||
|
||||
// HandleMessages handles incoming message from the long polling routine
|
||||
func (t *Telegram) HandleMessages(text string, chatID int64) error {
|
||||
if t.Verbose {
|
||||
log.Debugf(log.CommunicationMgr, "Telegram: Received message: %s\n", text)
|
||||
}
|
||||
|
||||
switch {
|
||||
case strings.Contains(text, cmdHelp):
|
||||
return t.SendMessage(fmt.Sprintf("%s: %s", talkRoot, cmdHelpReply), chatID)
|
||||
@@ -151,7 +180,7 @@ func (t *Telegram) HandleMessages(text string, chatID int64) error {
|
||||
return t.SendMessage(fmt.Sprintf("%s: %s", talkRoot, t.GetStatus()), chatID)
|
||||
|
||||
default:
|
||||
return t.SendMessage(fmt.Sprintf("command %s not recognized", text), chatID)
|
||||
return t.SendMessage(fmt.Sprintf("Command %s not recognized", text), chatID)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -204,6 +233,10 @@ func (t *Telegram) SendMessage(text string, chatID int64) error {
|
||||
if !resp.Ok {
|
||||
return errors.New(resp.Description)
|
||||
}
|
||||
|
||||
if t.Verbose {
|
||||
log.Debugf(log.CommunicationMgr, "Telegram: Sent '%s'\n", text)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -16,7 +16,6 @@ import (
|
||||
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
|
||||
log "github.com/thrasher-corp/gocryptotrader/logger"
|
||||
)
|
||||
|
||||
// Coinmarketcap account plan bitmasks, url and enpoint consts
|
||||
@@ -80,19 +79,16 @@ func (c *Coinmarketcap) SetDefaults() {
|
||||
}
|
||||
|
||||
// Setup sets user configuration
|
||||
func (c *Coinmarketcap) Setup(conf Settings) {
|
||||
func (c *Coinmarketcap) Setup(conf Settings) error {
|
||||
if !conf.Enabled {
|
||||
c.Enabled = false
|
||||
} else {
|
||||
err := c.SetAccountPlan(conf.AccountPlan)
|
||||
if err != nil {
|
||||
log.Errorf(log.Global, "CoinMarketCap enabled but SetAccountPlan failed. Err: %s\n", err)
|
||||
return
|
||||
}
|
||||
c.Enabled = true
|
||||
c.Verbose = conf.Verbose
|
||||
c.APIkey = conf.APIkey
|
||||
return nil
|
||||
}
|
||||
|
||||
c.Enabled = true
|
||||
c.Verbose = conf.Verbose
|
||||
c.APIkey = conf.APIkey
|
||||
return c.SetAccountPlan(conf.AccountPlan)
|
||||
}
|
||||
|
||||
// GetCryptocurrencyInfo returns all static metadata for one or more
|
||||
|
||||
@@ -41,7 +41,14 @@ func TestSetup(t *testing.T) {
|
||||
cfg.Enabled = true
|
||||
cfg.AccountPlan = "basic"
|
||||
|
||||
c.Setup(cfg)
|
||||
if err := c.Setup(cfg); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
cfg.AccountPlan = "meow"
|
||||
if err := c.Setup(cfg); err == nil {
|
||||
t.Error("expected err when invalid account plan is specified")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCheckAccountPlan(t *testing.T) {
|
||||
|
||||
@@ -122,15 +122,21 @@ func (s *Storage) RunUpdater(overrides BotOverrides, settings *MainConfiguration
|
||||
"Setting up currency analysis system with Coinmarketcap...")
|
||||
c := &coinmarketcap.Coinmarketcap{}
|
||||
c.SetDefaults()
|
||||
c.Setup(coinmarketcap.Settings{
|
||||
err := c.Setup(coinmarketcap.Settings{
|
||||
Name: settings.CryptocurrencyProvider.Name,
|
||||
Enabled: true,
|
||||
AccountPlan: settings.CryptocurrencyProvider.AccountPlan,
|
||||
APIkey: settings.CryptocurrencyProvider.APIkey,
|
||||
Verbose: settings.CryptocurrencyProvider.Verbose,
|
||||
})
|
||||
|
||||
s.currencyAnalysis = c
|
||||
if err != nil {
|
||||
log.Errorf(log.Global,
|
||||
"Unable to setup CoinMarketCap analysis. Error: %s", err)
|
||||
c = nil
|
||||
settings.CryptocurrencyProvider.Enabled = false
|
||||
} else {
|
||||
s.currencyAnalysis = c
|
||||
}
|
||||
}
|
||||
|
||||
if filePath == "" {
|
||||
|
||||
@@ -257,6 +257,7 @@ func PrintSettings(s *Settings) {
|
||||
|
||||
// Start starts the engine
|
||||
func (e *Engine) Start() {
|
||||
// TO-DO: move this out of here
|
||||
if e == nil {
|
||||
log.Errorln(log.Global, "Engine instance is nil")
|
||||
os.Exit(1)
|
||||
@@ -301,6 +302,11 @@ func (e *Engine) Start() {
|
||||
|
||||
log.Debugln(log.Global, "Setting up exchanges..")
|
||||
SetupExchanges()
|
||||
// TO-DO: move this out of here
|
||||
if len(Bot.Exchanges) == 0 {
|
||||
log.Errorln(log.Global, "No exchanges were able to be loaded. Exiting")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if e.Settings.EnableCommsRelayer {
|
||||
if err := e.CommsManager.Start(); err != nil {
|
||||
|
||||
@@ -2,7 +2,6 @@ package engine
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
@@ -313,8 +312,4 @@ func SetupExchanges() {
|
||||
)
|
||||
}
|
||||
wg.Wait()
|
||||
if len(Bot.Exchanges) == 0 {
|
||||
log.Errorln(log.Global, "No exchanges were able to be loaded. Exiting")
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,7 +58,6 @@ const (
|
||||
// Bitstamp is the overarching type across the bitstamp package
|
||||
type Bitstamp struct {
|
||||
exchange.Base
|
||||
Balance Balances
|
||||
WebsocketConn *wshandler.WebsocketConnection
|
||||
}
|
||||
|
||||
@@ -68,15 +67,15 @@ func (b *Bitstamp) GetFee(feeBuilder *exchange.FeeBuilder) (float64, error) {
|
||||
|
||||
switch feeBuilder.FeeType {
|
||||
case exchange.CryptocurrencyTradeFee:
|
||||
var err error
|
||||
b.Balance, err = b.GetBalance()
|
||||
balance, err := b.GetBalance()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
fee = b.CalculateTradingFee(feeBuilder.Pair.Base,
|
||||
feeBuilder.Pair.Quote,
|
||||
feeBuilder.PurchasePrice,
|
||||
feeBuilder.Amount)
|
||||
feeBuilder.Amount,
|
||||
balance)
|
||||
case exchange.CyptocurrencyDepositFee:
|
||||
fee = 0
|
||||
case exchange.InternationalBankDepositFee:
|
||||
@@ -121,20 +120,20 @@ func getInternationalBankDepositFee(amount float64) float64 {
|
||||
}
|
||||
|
||||
// CalculateTradingFee returns fee on a currency pair
|
||||
func (b *Bitstamp) CalculateTradingFee(base, quote currency.Code, purchasePrice, amount float64) float64 {
|
||||
func (b *Bitstamp) CalculateTradingFee(base, quote currency.Code, purchasePrice, amount float64, balances *Balances) float64 {
|
||||
var fee float64
|
||||
|
||||
switch base.String() + quote.String() {
|
||||
case currency.BTC.String() + currency.USD.String():
|
||||
fee = b.Balance.BTCUSDFee
|
||||
fee = balances.BTCUSDFee
|
||||
case currency.BTC.String() + currency.EUR.String():
|
||||
fee = b.Balance.BTCEURFee
|
||||
fee = balances.BTCEURFee
|
||||
case currency.XRP.String() + currency.EUR.String():
|
||||
fee = b.Balance.XRPEURFee
|
||||
fee = balances.XRPEURFee
|
||||
case currency.XRP.String() + currency.USD.String():
|
||||
fee = b.Balance.XRPUSDFee
|
||||
fee = balances.XRPUSDFee
|
||||
case currency.EUR.String() + currency.USD.String():
|
||||
fee = b.Balance.EURUSDFee
|
||||
fee = balances.EURUSDFee
|
||||
default:
|
||||
fee = 0
|
||||
}
|
||||
@@ -259,9 +258,9 @@ func (b *Bitstamp) GetEURUSDConversionRate() (EURUSDConversionRate, error) {
|
||||
}
|
||||
|
||||
// GetBalance returns full balance of currency held on the exchange
|
||||
func (b *Bitstamp) GetBalance() (Balances, error) {
|
||||
func (b *Bitstamp) GetBalance() (*Balances, error) {
|
||||
var balance Balances
|
||||
return balance,
|
||||
return &balance,
|
||||
b.SendAuthenticatedHTTPRequest(bitstampAPIBalance, true, nil, &balance)
|
||||
}
|
||||
|
||||
|
||||
@@ -141,21 +141,23 @@ func TestGetFee(t *testing.T) {
|
||||
|
||||
func TestCalculateTradingFee(t *testing.T) {
|
||||
t.Parallel()
|
||||
b.Balance.BTCUSDFee = 1
|
||||
b.Balance.BTCEURFee = 0
|
||||
|
||||
if resp := b.CalculateTradingFee(currency.BTC, currency.USD, 0, 0); resp != 0 {
|
||||
var newBalance = new(Balances)
|
||||
newBalance.BTCUSDFee = 1
|
||||
newBalance.BTCEURFee = 0
|
||||
|
||||
if resp := b.CalculateTradingFee(currency.BTC, currency.USD, 0, 0, newBalance); resp != 0 {
|
||||
t.Error("Test Failed - GetFee() error")
|
||||
}
|
||||
if resp := b.CalculateTradingFee(currency.BTC, currency.USD, 2, 2); resp != float64(4) {
|
||||
if resp := b.CalculateTradingFee(currency.BTC, currency.USD, 2, 2, newBalance); resp != float64(4) {
|
||||
t.Errorf("Test Failed - GetFee() error. Expected: %f, Received: %f", float64(4), resp)
|
||||
}
|
||||
if resp := b.CalculateTradingFee(currency.BTC, currency.EUR, 2, 2); resp != float64(0) {
|
||||
if resp := b.CalculateTradingFee(currency.BTC, currency.EUR, 2, 2, newBalance); resp != float64(0) {
|
||||
t.Errorf("Test Failed - GetFee() error. Expected: %f, Received: %f", float64(0), resp)
|
||||
}
|
||||
|
||||
dummy1, dummy2 := currency.NewCode(""), currency.NewCode("")
|
||||
if resp := b.CalculateTradingFee(dummy1, dummy2, 0, 0); resp != 0 {
|
||||
if resp := b.CalculateTradingFee(dummy1, dummy2, 0, 0, newBalance); resp != 0 {
|
||||
t.Error("Test Failed - GetFee() error")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
@@ -164,7 +163,7 @@ func HTTPRecord(res *http.Response, service string, respContents []byte) error {
|
||||
|
||||
mockRespVals, urlErr := url.ParseQuery(mockResponses[i].BodyParams)
|
||||
if urlErr != nil {
|
||||
log.Fatal(urlErr)
|
||||
return urlErr
|
||||
}
|
||||
|
||||
if MatchURLVals(respQueryVals, mockRespVals) {
|
||||
|
||||
57
testdata/configtest.json
vendored
57
testdata/configtest.json
vendored
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user