diff --git a/exchanges/alphapoint/alphapoint_wrapper.go b/exchanges/alphapoint/alphapoint_wrapper.go index e9e1f34d..dd8465df 100644 --- a/exchanges/alphapoint/alphapoint_wrapper.go +++ b/exchanges/alphapoint/alphapoint_wrapper.go @@ -1,8 +1,6 @@ package alphapoint import ( - "log" - "github.com/thrasher-/gocryptotrader/currency/pair" "github.com/thrasher-/gocryptotrader/exchanges" "github.com/thrasher-/gocryptotrader/exchanges/orderbook" @@ -30,21 +28,32 @@ func (a *Alphapoint) GetExchangeAccountInfo() (exchange.AccountInfo, error) { return response, nil } -// GetTickerPrice returns the current ticker price by currency pair -func (a *Alphapoint) GetTickerPrice(p pair.CurrencyPair) ticker.TickerPrice { +func (a *Alphapoint) UpdateTicker(p pair.CurrencyPair) (ticker.TickerPrice, error) { var tickerPrice ticker.TickerPrice tick, err := a.GetTicker(p.Pair().String()) if err != nil { - log.Println(err) - return ticker.TickerPrice{} + return tickerPrice, err } + tickerPrice.Pair = p tickerPrice.Ask = tick.Ask tickerPrice.Bid = tick.Bid - return tickerPrice + tickerPrice.Low = tick.Low + tickerPrice.High = tick.High + tickerPrice.Volume = tick.Volume + tickerPrice.Last = tick.Last + ticker.ProcessTicker(a.GetName(), p, tickerPrice) + return tickerPrice, nil +} + +func (a *Alphapoint) GetTickerPrice(p pair.CurrencyPair) (ticker.TickerPrice, error) { + tick, err := ticker.GetTicker(a.GetName(), p) + if err != nil { + return a.UpdateTicker(p) + } + return tick, nil } -// GetOrderbookEx returns an orderbookbase by currency pair func (a *Alphapoint) GetOrderbookEx(p pair.CurrencyPair) (orderbook.OrderbookBase, error) { ob, err := orderbook.GetOrderbook(a.GetName(), p) if err == nil { diff --git a/exchanges/anx/anx_wrapper.go b/exchanges/anx/anx_wrapper.go index 23e8795a..87d88824 100644 --- a/exchanges/anx/anx_wrapper.go +++ b/exchanges/anx/anx_wrapper.go @@ -27,7 +27,7 @@ func (a *ANX) Run() { for x := range pairs { currency := pairs[x] go func() { - ticker, err := a.GetTickerPrice(currency) + ticker, err := a.UpdateTicker(currency) if err != nil { log.Println(err) return @@ -40,12 +40,7 @@ func (a *ANX) Run() { } } -func (a *ANX) GetTickerPrice(p pair.CurrencyPair) (ticker.TickerPrice, error) { - tickerNew, err := ticker.GetTicker(a.GetName(), p) - if err == nil { - return tickerNew, nil - } - +func (a *ANX) UpdateTicker(p pair.CurrencyPair) (ticker.TickerPrice, error) { var tickerPrice ticker.TickerPrice tick, err := a.GetTicker(p.Pair().String()) if err != nil { @@ -111,6 +106,14 @@ func (a *ANX) GetTickerPrice(p pair.CurrencyPair) (ticker.TickerPrice, error) { return tickerPrice, nil } +func (a *ANX) GetTickerPrice(p pair.CurrencyPair) (ticker.TickerPrice, error) { + tickerNew, err := ticker.GetTicker(a.GetName(), p) + if err != nil { + return a.UpdateTicker(p) + } + return tickerNew, nil +} + func (e *ANX) GetOrderbookEx(p pair.CurrencyPair) (orderbook.OrderbookBase, error) { return orderbook.OrderbookBase{}, nil } diff --git a/exchanges/bitfinex/bitfinex_wrapper.go b/exchanges/bitfinex/bitfinex_wrapper.go index 95268ce7..4ead2e3c 100644 --- a/exchanges/bitfinex/bitfinex_wrapper.go +++ b/exchanges/bitfinex/bitfinex_wrapper.go @@ -44,7 +44,7 @@ func (b *Bitfinex) Run() { for x := range pairs { currency := pairs[x] go func() { - ticker, err := b.GetTickerPrice(currency) + ticker, err := b.UpdateTicker(currency) if err != nil { return } @@ -56,18 +56,13 @@ func (b *Bitfinex) Run() { } } -// GetTickerPrice returns ticker information -func (b *Bitfinex) GetTickerPrice(p pair.CurrencyPair) (ticker.TickerPrice, error) { - tick, err := ticker.GetTicker(b.GetName(), p) - if err == nil { - return tick, nil - } - +func (b *Bitfinex) UpdateTicker(p pair.CurrencyPair) (ticker.TickerPrice, error) { var tickerPrice ticker.TickerPrice tickerNew, err := b.GetTicker(p.Pair().String(), nil) if err != nil { return tickerPrice, err } + tickerPrice.Pair = p tickerPrice.Ask = tickerNew.Ask tickerPrice.Bid = tickerNew.Bid @@ -79,7 +74,14 @@ func (b *Bitfinex) GetTickerPrice(p pair.CurrencyPair) (ticker.TickerPrice, erro return tickerPrice, nil } -// GetOrderbookEx returns orderbook information based on currency pair +func (b *Bitfinex) GetTickerPrice(p pair.CurrencyPair) (ticker.TickerPrice, error) { + tick, err := ticker.GetTicker(b.GetName(), p) + if err != nil { + return b.UpdateTicker(p) + } + return tick, nil +} + func (b *Bitfinex) GetOrderbookEx(p pair.CurrencyPair) (orderbook.OrderbookBase, error) { ob, err := orderbook.GetOrderbook(b.GetName(), p) if err == nil { diff --git a/exchanges/bitstamp/bitstamp_wrapper.go b/exchanges/bitstamp/bitstamp_wrapper.go index 2be02a59..285f7819 100644 --- a/exchanges/bitstamp/bitstamp_wrapper.go +++ b/exchanges/bitstamp/bitstamp_wrapper.go @@ -34,7 +34,7 @@ func (b *Bitstamp) Run() { for x := range pairs { currency := pairs[x] go func() { - ticker, err := b.GetTickerPrice(currency) + ticker, err := b.UpdateTicker(currency) if err != nil { log.Println(err) return @@ -47,13 +47,7 @@ func (b *Bitstamp) Run() { } } -// GetTickerPrice returns ticker price information -func (b *Bitstamp) GetTickerPrice(p pair.CurrencyPair) (ticker.TickerPrice, error) { - tickerNew, err := ticker.GetTicker(b.GetName(), p) - if err == nil { - return tickerNew, nil - } - +func (b *Bitstamp) UpdateTicker(p pair.CurrencyPair) (ticker.TickerPrice, error) { var tickerPrice ticker.TickerPrice tick, err := b.GetTicker(p.Pair().String(), false) if err != nil { @@ -71,7 +65,14 @@ func (b *Bitstamp) GetTickerPrice(p pair.CurrencyPair) (ticker.TickerPrice, erro return tickerPrice, nil } -// GetOrderbookEx returns base orderbook information +func (b *Bitstamp) GetTickerPrice(p pair.CurrencyPair) (ticker.TickerPrice, error) { + tick, err := ticker.GetTicker(b.GetName(), p) + if err != nil { + return b.UpdateTicker(p) + } + return tick, nil +} + func (b *Bitstamp) GetOrderbookEx(p pair.CurrencyPair) (orderbook.OrderbookBase, error) { ob, err := orderbook.GetOrderbook(b.GetName(), p) if err == nil { diff --git a/exchanges/btcc/btcc_wrapper.go b/exchanges/btcc/btcc_wrapper.go index bc50e887..69a7c173 100644 --- a/exchanges/btcc/btcc_wrapper.go +++ b/exchanges/btcc/btcc_wrapper.go @@ -32,7 +32,7 @@ func (b *BTCC) Run() { for x := range pairs { currency := pairs[x] go func() { - ticker, err := b.GetTickerPrice(currency) + ticker, err := b.UpdateTicker(currency) if err != nil { log.Println(err) return @@ -45,18 +45,12 @@ func (b *BTCC) Run() { } } -func (b *BTCC) GetTickerPrice(p pair.CurrencyPair) (ticker.TickerPrice, error) { - tickerNew, err := ticker.GetTicker(b.GetName(), p) - if err == nil { - return tickerNew, nil - } - +func (b *BTCC) UpdateTicker(p pair.CurrencyPair) (ticker.TickerPrice, error) { var tickerPrice ticker.TickerPrice tick, err := b.GetTicker(exchange.FormatExchangeCurrency(b.GetName(), p).String()) if err != nil { return tickerPrice, err } - tickerPrice.Pair = p tickerPrice.Ask = tick.Sell tickerPrice.Bid = tick.Buy @@ -68,6 +62,14 @@ func (b *BTCC) GetTickerPrice(p pair.CurrencyPair) (ticker.TickerPrice, error) { return tickerPrice, nil } +func (b *BTCC) GetTickerPrice(p pair.CurrencyPair) (ticker.TickerPrice, error) { + tickerNew, err := ticker.GetTicker(b.GetName(), p) + if err != nil { + return b.UpdateTicker(p) + } + return tickerNew, nil +} + func (b *BTCC) GetOrderbookEx(p pair.CurrencyPair) (orderbook.OrderbookBase, error) { ob, err := orderbook.GetOrderbook(b.GetName(), p) if err == nil { diff --git a/exchanges/btce/btce_wrapper.go b/exchanges/btce/btce_wrapper.go index 786fe23c..320e5876 100644 --- a/exchanges/btce/btce_wrapper.go +++ b/exchanges/btce/btce_wrapper.go @@ -50,9 +50,14 @@ func (b *BTCE) Run() { } } -func (b *BTCE) GetTickerPrice(p pair.CurrencyPair) (ticker.TickerPrice, error) { +func (b *BTCE) UpdateTicker(p pair.CurrencyPair) (ticker.TickerPrice, error) { var tickerPrice ticker.TickerPrice - tick, ok := b.Ticker[exchange.FormatExchangeCurrency(b.Name, p).String()] + result, err := b.GetTicker(p.Pair().String()) + if err != nil { + return tickerPrice, err + } + + tick, ok := result[p.Pair().Lower().String()] if !ok { return tickerPrice, errors.New("unable to get currency") } @@ -67,6 +72,14 @@ func (b *BTCE) GetTickerPrice(p pair.CurrencyPair) (ticker.TickerPrice, error) { return tickerPrice, nil } +func (b *BTCE) GetTickerPrice(p pair.CurrencyPair) (ticker.TickerPrice, error) { + tick, err := ticker.GetTicker(b.GetName(), p) + if err != nil { + return b.UpdateTicker(p) + } + return tick, nil +} + func (b *BTCE) GetOrderbookEx(p pair.CurrencyPair) (orderbook.OrderbookBase, error) { ob, err := orderbook.GetOrderbook(b.GetName(), p) if err == nil { diff --git a/exchanges/btcmarkets/btcmarkets_wrapper.go b/exchanges/btcmarkets/btcmarkets_wrapper.go index 047450b6..33e4ce5f 100644 --- a/exchanges/btcmarkets/btcmarkets_wrapper.go +++ b/exchanges/btcmarkets/btcmarkets_wrapper.go @@ -57,7 +57,7 @@ func (b *BTCMarkets) Run() { for x := range pairs { curr := pairs[x] go func() { - ticker, err := b.GetTickerPrice(curr) + ticker, err := b.UpdateTicker(curr) if err != nil { return } @@ -73,13 +73,7 @@ func (b *BTCMarkets) Run() { } } -// GetTickerPrice returns ticker information -func (b *BTCMarkets) GetTickerPrice(p pair.CurrencyPair) (ticker.TickerPrice, error) { - tickerNew, err := ticker.GetTicker(b.GetName(), p) - if err == nil { - return tickerNew, nil - } - +func (b *BTCMarkets) UpdateTicker(p pair.CurrencyPair) (ticker.TickerPrice, error) { var tickerPrice ticker.TickerPrice tick, err := b.GetTicker(p.GetFirstCurrency().String()) if err != nil { @@ -92,6 +86,13 @@ func (b *BTCMarkets) GetTickerPrice(p pair.CurrencyPair) (ticker.TickerPrice, er ticker.ProcessTicker(b.GetName(), p, tickerPrice) return tickerPrice, nil } +func (b *BTCMarkets) GetTickerPrice(p pair.CurrencyPair) (ticker.TickerPrice, error) { + tickerNew, err := ticker.GetTicker(b.GetName(), p) + if err != nil { + return b.UpdateTicker(p) + } + return tickerNew, nil +} // GetOrderbookEx returns orderbook base on the currency pair func (b *BTCMarkets) GetOrderbookEx(p pair.CurrencyPair) (orderbook.OrderbookBase, error) { diff --git a/exchanges/coinut/coinut_wrapper.go b/exchanges/coinut/coinut_wrapper.go index 96c65c86..47854620 100644 --- a/exchanges/coinut/coinut_wrapper.go +++ b/exchanges/coinut/coinut_wrapper.go @@ -50,7 +50,7 @@ func (c *COINUT) Run() { for x := range pairs { currency := pairs[x] go func() { - ticker, err := c.GetTickerPrice(currency) + ticker, err := c.UpdateTicker(currency) if err != nil { log.Println(err) return @@ -84,12 +84,7 @@ func (c *COINUT) GetExchangeAccountInfo() (exchange.AccountInfo, error) { return response, nil } -func (c *COINUT) GetTickerPrice(p pair.CurrencyPair) (ticker.TickerPrice, error) { - tickerNew, err := ticker.GetTicker(c.GetName(), p) - if err == nil { - return tickerNew, nil - } - +func (c *COINUT) UpdateTicker(p pair.CurrencyPair) (ticker.TickerPrice, error) { var tickerPrice ticker.TickerPrice tick, err := c.GetInstrumentTicker(c.InstrumentMap[p.Pair().String()]) if err != nil { @@ -103,6 +98,15 @@ func (c *COINUT) GetTickerPrice(p pair.CurrencyPair) (ticker.TickerPrice, error) tickerPrice.Low = tick.LowestSell ticker.ProcessTicker(c.GetName(), p, tickerPrice) return tickerPrice, nil + +} + +func (c *COINUT) GetTickerPrice(p pair.CurrencyPair) (ticker.TickerPrice, error) { + tickerNew, err := ticker.GetTicker(c.GetName(), p) + if err != nil { + return c.UpdateTicker(p) + } + return tickerNew, nil } func (c *COINUT) GetOrderbookEx(p pair.CurrencyPair) (orderbook.OrderbookBase, error) { diff --git a/exchanges/exchange.go b/exchanges/exchange.go index e89a56a7..ef7a2358 100644 --- a/exchanges/exchange.go +++ b/exchanges/exchange.go @@ -64,6 +64,7 @@ type IBotExchange interface { GetName() string IsEnabled() bool GetTickerPrice(currency pair.CurrencyPair) (ticker.TickerPrice, error) + UpdateTicker(currency pair.CurrencyPair) (ticker.TickerPrice, error) GetOrderbookEx(currency pair.CurrencyPair) (orderbook.OrderbookBase, error) GetEnabledCurrencies() []pair.CurrencyPair GetExchangeAccountInfo() (AccountInfo, error) diff --git a/exchanges/gdax/gdax_wrapper.go b/exchanges/gdax/gdax_wrapper.go index 6c519990..28c6a3cd 100644 --- a/exchanges/gdax/gdax_wrapper.go +++ b/exchanges/gdax/gdax_wrapper.go @@ -48,7 +48,7 @@ func (g *GDAX) Run() { for x := range pairs { currency := pairs[x] go func() { - ticker, err := g.GetTickerPrice(currency) + ticker, err := g.UpdateTicker(currency) if err != nil { log.Println(err) @@ -81,12 +81,7 @@ func (g *GDAX) GetExchangeAccountInfo() (exchange.AccountInfo, error) { return response, nil } -func (g *GDAX) GetTickerPrice(p pair.CurrencyPair) (ticker.TickerPrice, error) { - tickerNew, err := ticker.GetTicker(g.GetName(), p) - if err == nil { - return tickerNew, nil - } - +func (g *GDAX) UpdateTicker(p pair.CurrencyPair) (ticker.TickerPrice, error) { var tickerPrice ticker.TickerPrice tick, err := g.GetTicker(exchange.FormatExchangeCurrency(g.Name, p).String()) if err != nil { @@ -108,6 +103,14 @@ func (g *GDAX) GetTickerPrice(p pair.CurrencyPair) (ticker.TickerPrice, error) { return tickerPrice, nil } +func (g *GDAX) GetTickerPrice(p pair.CurrencyPair) (ticker.TickerPrice, error) { + tickerNew, err := ticker.GetTicker(g.GetName(), p) + if err != nil { + return g.UpdateTicker(p) + } + return tickerNew, nil +} + func (g *GDAX) GetOrderbookEx(p pair.CurrencyPair) (orderbook.OrderbookBase, error) { ob, err := orderbook.GetOrderbook(g.GetName(), p) if err == nil { diff --git a/exchanges/gemini/gemini_wrapper.go b/exchanges/gemini/gemini_wrapper.go index 4e266d66..26277957 100644 --- a/exchanges/gemini/gemini_wrapper.go +++ b/exchanges/gemini/gemini_wrapper.go @@ -37,7 +37,7 @@ func (g *Gemini) Run() { for x := range pairs { currency := pairs[x] go func() { - ticker, err := g.GetTickerPrice(currency) + ticker, err := g.UpdateTicker(currency) if err != nil { log.Println(err) return @@ -63,18 +63,12 @@ func (e *Gemini) GetExchangeAccountInfo() (exchange.AccountInfo, error) { exchangeCurrency.CurrencyName = accountBalance[i].Currency exchangeCurrency.TotalValue = accountBalance[i].Amount exchangeCurrency.Hold = accountBalance[i].Available - response.Currencies = append(response.Currencies, exchangeCurrency) } return response, nil } -func (g *Gemini) GetTickerPrice(p pair.CurrencyPair) (ticker.TickerPrice, error) { - tickerNew, err := ticker.GetTicker(g.GetName(), p) - if err == nil { - return tickerNew, nil - } - +func (g *Gemini) UpdateTicker(p pair.CurrencyPair) (ticker.TickerPrice, error) { var tickerPrice ticker.TickerPrice tick, err := g.GetTicker(p.Pair().String()) if err != nil { @@ -89,6 +83,14 @@ func (g *Gemini) GetTickerPrice(p pair.CurrencyPair) (ticker.TickerPrice, error) return tickerPrice, nil } +func (g *Gemini) GetTickerPrice(p pair.CurrencyPair) (ticker.TickerPrice, error) { + tickerNew, err := ticker.GetTicker(g.GetName(), p) + if err != nil { + return g.UpdateTicker(p) + } + return tickerNew, nil +} + func (g *Gemini) GetOrderbookEx(p pair.CurrencyPair) (orderbook.OrderbookBase, error) { ob, err := orderbook.GetOrderbook(g.GetName(), p) if err == nil { diff --git a/exchanges/huobi/huobi_wrapper.go b/exchanges/huobi/huobi_wrapper.go index 9324b984..6cfad9c4 100644 --- a/exchanges/huobi/huobi_wrapper.go +++ b/exchanges/huobi/huobi_wrapper.go @@ -33,7 +33,7 @@ func (h *HUOBI) Run() { for x := range pairs { curr := pairs[x] go func() { - ticker, err := h.GetTickerPrice(curr) + ticker, err := h.UpdateTicker(curr) if err != nil { log.Println(err) return @@ -50,12 +50,7 @@ func (h *HUOBI) Run() { } } -func (h *HUOBI) GetTickerPrice(p pair.CurrencyPair) (ticker.TickerPrice, error) { - tickerNew, err := ticker.GetTicker(h.GetName(), p) - if err == nil { - return tickerNew, nil - } - +func (h *HUOBI) UpdateTicker(p pair.CurrencyPair) (ticker.TickerPrice, error) { var tickerPrice ticker.TickerPrice tick, err := h.GetTicker(p.GetFirstCurrency().Lower().String()) if err != nil { @@ -72,6 +67,14 @@ func (h *HUOBI) GetTickerPrice(p pair.CurrencyPair) (ticker.TickerPrice, error) return tickerPrice, nil } +func (h *HUOBI) GetTickerPrice(p pair.CurrencyPair) (ticker.TickerPrice, error) { + tickerNew, err := ticker.GetTicker(h.GetName(), p) + if err != nil { + return h.UpdateTicker(p) + } + return tickerNew, nil +} + func (h *HUOBI) GetOrderbookEx(p pair.CurrencyPair) (orderbook.OrderbookBase, error) { ob, err := orderbook.GetOrderbook(h.GetName(), p) if err == nil { diff --git a/exchanges/itbit/itbit_wrapper.go b/exchanges/itbit/itbit_wrapper.go index d444c024..078a4e9b 100644 --- a/exchanges/itbit/itbit_wrapper.go +++ b/exchanges/itbit/itbit_wrapper.go @@ -26,7 +26,7 @@ func (i *ItBit) Run() { for x := range pairs { currency := pairs[x] go func() { - ticker, err := i.GetTickerPrice(currency) + ticker, err := i.UpdateTicker(currency) if err != nil { log.Println(err) return @@ -39,12 +39,7 @@ func (i *ItBit) Run() { } } -func (i *ItBit) GetTickerPrice(p pair.CurrencyPair) (ticker.TickerPrice, error) { - tickerNew, err := ticker.GetTicker(i.GetName(), p) - if err == nil { - return tickerNew, nil - } - +func (i *ItBit) UpdateTicker(p pair.CurrencyPair) (ticker.TickerPrice, error) { var tickerPrice ticker.TickerPrice tick, err := i.GetTicker(p.Pair().String()) if err != nil { @@ -62,6 +57,14 @@ func (i *ItBit) GetTickerPrice(p pair.CurrencyPair) (ticker.TickerPrice, error) return tickerPrice, nil } +func (i *ItBit) GetTickerPrice(p pair.CurrencyPair) (ticker.TickerPrice, error) { + tickerNew, err := ticker.GetTicker(i.GetName(), p) + if err != nil { + return i.UpdateTicker(p) + } + return tickerNew, nil +} + func (i *ItBit) GetOrderbookEx(p pair.CurrencyPair) (orderbook.OrderbookBase, error) { ob, err := orderbook.GetOrderbook(i.GetName(), p) if err == nil { diff --git a/exchanges/kraken/kraken_wrapper.go b/exchanges/kraken/kraken_wrapper.go index 356f7380..869ef5b3 100644 --- a/exchanges/kraken/kraken_wrapper.go +++ b/exchanges/kraken/kraken_wrapper.go @@ -57,6 +57,10 @@ func (k *Kraken) Run() { } } +func (k *Kraken) UpdateTicker(p pair.CurrencyPair) (ticker.TickerPrice, error) { + return ticker.TickerPrice{}, nil +} + //This will return the TickerPrice struct when tickers are completed here.. func (k *Kraken) GetTickerPrice(p pair.CurrencyPair) (ticker.TickerPrice, error) { var tickerPrice ticker.TickerPrice diff --git a/exchanges/lakebtc/lakebtc_wrapper.go b/exchanges/lakebtc/lakebtc_wrapper.go index 8bf35b45..1b6ca633 100644 --- a/exchanges/lakebtc/lakebtc_wrapper.go +++ b/exchanges/lakebtc/lakebtc_wrapper.go @@ -26,7 +26,7 @@ func (l *LakeBTC) Run() { pairs := l.GetEnabledCurrencies() for x := range pairs { currency := pairs[x] - ticker, err := l.GetTickerPrice(currency) + ticker, err := l.UpdateTicker(currency) if err != nil { log.Println(err) continue @@ -38,12 +38,7 @@ func (l *LakeBTC) Run() { } } -func (l *LakeBTC) GetTickerPrice(p pair.CurrencyPair) (ticker.TickerPrice, error) { - tickerNew, err := ticker.GetTicker(l.GetName(), p) - if err == nil { - return tickerNew, nil - } - +func (l *LakeBTC) UpdateTicker(p pair.CurrencyPair) (ticker.TickerPrice, error) { tick, err := l.GetTicker() if err != nil { return ticker.TickerPrice{}, err @@ -66,6 +61,14 @@ func (l *LakeBTC) GetTickerPrice(p pair.CurrencyPair) (ticker.TickerPrice, error return tickerPrice, nil } +func (l *LakeBTC) GetTickerPrice(p pair.CurrencyPair) (ticker.TickerPrice, error) { + tickerNew, err := ticker.GetTicker(l.GetName(), p) + if err != nil { + return l.UpdateTicker(p) + } + return tickerNew, nil +} + func (l *LakeBTC) GetOrderbookEx(p pair.CurrencyPair) (orderbook.OrderbookBase, error) { ob, err := orderbook.GetOrderbook(l.GetName(), p) if err == nil { diff --git a/exchanges/liqui/liqui_wrapper.go b/exchanges/liqui/liqui_wrapper.go index 6ad4a709..9f4b39d4 100644 --- a/exchanges/liqui/liqui_wrapper.go +++ b/exchanges/liqui/liqui_wrapper.go @@ -61,6 +61,10 @@ func (l *Liqui) Run() { } } +func (l *Liqui) UpdateTicker(p pair.CurrencyPair) (ticker.TickerPrice, error) { + return ticker.TickerPrice{}, nil +} + func (l *Liqui) GetTickerPrice(p pair.CurrencyPair) (ticker.TickerPrice, error) { var tickerPrice ticker.TickerPrice tick, ok := l.Ticker[exchange.FormatExchangeCurrency(l.Name, p).String()] diff --git a/exchanges/localbitcoins/localbitcoins_wrapper.go b/exchanges/localbitcoins/localbitcoins_wrapper.go index 9d891da1..e12de734 100644 --- a/exchanges/localbitcoins/localbitcoins_wrapper.go +++ b/exchanges/localbitcoins/localbitcoins_wrapper.go @@ -39,6 +39,10 @@ func (l *LocalBitcoins) Run() { } } +func (l *LocalBitcoins) UpdateTicker(p pair.CurrencyPair) (ticker.TickerPrice, error) { + return ticker.TickerPrice{}, nil +} + func (l *LocalBitcoins) GetTickerPrice(p pair.CurrencyPair) (ticker.TickerPrice, error) { tickerNew, err := ticker.GetTicker(l.GetName(), p) if err == nil { diff --git a/exchanges/okcoin/okcoin_wrapper.go b/exchanges/okcoin/okcoin_wrapper.go index 6677276f..6c91e764 100644 --- a/exchanges/okcoin/okcoin_wrapper.go +++ b/exchanges/okcoin/okcoin_wrapper.go @@ -46,7 +46,7 @@ func (o *OKCoin) Run() { }() } go func() { - ticker, err := o.GetTickerPrice(curr) + ticker, err := o.UpdateTicker(curr) if err != nil { log.Println(err) return @@ -56,7 +56,7 @@ func (o *OKCoin) Run() { }() } else { go func() { - ticker, err := o.GetTickerPrice(curr) + ticker, err := o.UpdateTicker(curr) if err != nil { log.Println(err) return @@ -74,12 +74,7 @@ func (o *OKCoin) Run() { } } -func (o *OKCoin) GetTickerPrice(currency pair.CurrencyPair) (ticker.TickerPrice, error) { - tickerNew, err := ticker.GetTicker(o.GetName(), currency) - if err == nil { - return tickerNew, nil - } - +func (o *OKCoin) UpdateTicker(currency pair.CurrencyPair) (ticker.TickerPrice, error) { var tickerPrice ticker.TickerPrice tick, err := o.GetTicker(exchange.FormatExchangeCurrency(o.Name, currency).String()) if err != nil { @@ -96,6 +91,14 @@ func (o *OKCoin) GetTickerPrice(currency pair.CurrencyPair) (ticker.TickerPrice, return tickerPrice, nil } +func (o *OKCoin) GetTickerPrice(currency pair.CurrencyPair) (ticker.TickerPrice, error) { + tickerNew, err := ticker.GetTicker(o.GetName(), currency) + if err != nil { + return o.UpdateTicker(currency) + } + return tickerNew, nil +} + func (o *OKCoin) GetOrderbookEx(currency pair.CurrencyPair) (orderbook.OrderbookBase, error) { ob, err := orderbook.GetOrderbook(o.GetName(), currency) if err == nil { diff --git a/exchanges/poloniex/poloniex_wrapper.go b/exchanges/poloniex/poloniex_wrapper.go index bccc8597..538c2270 100644 --- a/exchanges/poloniex/poloniex_wrapper.go +++ b/exchanges/poloniex/poloniex_wrapper.go @@ -32,7 +32,7 @@ func (p *Poloniex) Run() { for x := range pairs { currency := pairs[x] go func() { - ticker, err := p.GetTickerPrice(currency) + ticker, err := p.UpdateTicker(currency) if err != nil { log.Println(err) return @@ -45,13 +45,8 @@ func (p *Poloniex) Run() { } } -func (p *Poloniex) GetTickerPrice(currencyPair pair.CurrencyPair) (ticker.TickerPrice, error) { +func (p *Poloniex) UpdateTicker(currencyPair pair.CurrencyPair) (ticker.TickerPrice, error) { currency := currencyPair.Pair().String() - tickerNew, err := ticker.GetTicker(p.GetName(), currencyPair) - if err == nil { - return tickerNew, nil - } - var tickerPrice ticker.TickerPrice tick, err := p.GetTicker() if err != nil { @@ -69,6 +64,14 @@ func (p *Poloniex) GetTickerPrice(currencyPair pair.CurrencyPair) (ticker.Ticker return tickerPrice, nil } +func (p *Poloniex) GetTickerPrice(currencyPair pair.CurrencyPair) (ticker.TickerPrice, error) { + tickerNew, err := ticker.GetTicker(p.GetName(), currencyPair) + if err != nil { + return p.UpdateTicker(currencyPair) + } + return tickerNew, nil +} + func (p *Poloniex) GetOrderbookEx(currencyPair pair.CurrencyPair) (orderbook.OrderbookBase, error) { currency := currencyPair.Pair().String() ob, err := orderbook.GetOrderbook(p.GetName(), currencyPair) diff --git a/main.go b/main.go index 592755c6..5a20e936 100644 --- a/main.go +++ b/main.go @@ -187,6 +187,11 @@ func main() { SeedExchangeAccountInfo(GetAllEnabledExchangeAccountInfo().Data) go portfolio.StartPortfolioWatcher() + log.Println("Starting websocket handler") + go WebsocketHandler() + + go TickerUpdaterRoutine() + if bot.config.Webserver.Enabled { err := bot.config.CheckWebserverConfigValues() if err != nil { diff --git a/restful_router.go b/restful_router.go index d6092671..467dd05f 100644 --- a/restful_router.go +++ b/restful_router.go @@ -17,6 +17,7 @@ func NewRouter(exchanges []exchange.IBotExchange) *mux.Router { allRoutes = append(allRoutes, PortfolioRoutes...) allRoutes = append(allRoutes, WalletRoutes...) allRoutes = append(allRoutes, IndexRoute...) + allRoutes = append(allRoutes, WebsocketRoutes...) for _, route := range allRoutes { var handler http.Handler handler = route.HandlerFunc diff --git a/routines.go b/routines.go new file mode 100644 index 00000000..e4584fef --- /dev/null +++ b/routines.go @@ -0,0 +1,37 @@ +package main + +import ( + "log" + "time" + + "github.com/thrasher-/gocryptotrader/currency/pair" +) + +func TickerUpdaterRoutine() { + log.Println("Starting ticker updater routine") + for { + for x := range bot.exchanges { + if bot.exchanges[x].IsEnabled() { + exchangeName := bot.exchanges[x].GetName() + enabledCurrencies := bot.exchanges[x].GetEnabledCurrencies() + + for _, y := range enabledCurrencies { + currency := pair.NewCurrencyPair(y[0:3], y[3:]) + result, err := bot.exchanges[x].UpdateTicker(currency) + if err != nil { + log.Printf("failed to get %s currency", currency.Pair().String()) + continue + } + + evt := WebsocketEvent{ + Data: result, + Event: "ticker_update", + Exchange: exchangeName, + } + BroadcastWebsocketMessage(evt) + } + } + } + time.Sleep(time.Second * 10) + } +} diff --git a/ticker_routes.go b/ticker_routes.go index 3d7e1ded..7da2a1a7 100644 --- a/ticker_routes.go +++ b/ticker_routes.go @@ -10,31 +10,35 @@ import ( "github.com/thrasher-/gocryptotrader/exchanges/ticker" ) -func jsonTickerResponse(w http.ResponseWriter, r *http.Request) { - vars := mux.Vars(r) - currency := vars["currency"] - exchangeName := vars["exchangeName"] - var response ticker.TickerPrice +func GetSpecificTicker(currency, exchangeName string) (ticker.TickerPrice, error) { + var specificTicker ticker.TickerPrice var err error for i := 0; i < len(bot.exchanges); i++ { if bot.exchanges[i] != nil { if bot.exchanges[i].IsEnabled() && bot.exchanges[i].GetName() == exchangeName { - response, err = bot.exchanges[i].GetTickerPrice( + specificTicker, err = bot.exchanges[i].GetTickerPrice( pair.NewCurrencyPairFromString(currency), ) - if err != nil { - log.Println(err) - continue - } + break } } } + return specificTicker, err +} +func jsonTickerResponse(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + currency := vars["currency"] + exchange := vars["exchangeName"] + response, err := GetSpecificTicker(currency, exchange) + if err != nil { + log.Printf("Failed to fetch ticker for %s currency: %s\n", exchange, + currency) + return + } w.Header().Set("Content-Type", "application/json; charset=UTF-8") w.WriteHeader(http.StatusOK) - encoder := json.NewEncoder(w) - - if err = encoder.Encode(response); err != nil { + if err := json.NewEncoder(w).Encode(response); err != nil { panic(err) } } @@ -51,8 +55,8 @@ type EnabledExchangeCurrencies struct { ExchangeValues []ticker.TickerPrice `json:"exchangeValues"` } -func getAllActiveTickersResponse(w http.ResponseWriter, r *http.Request) { - var response AllEnabledExchangeCurrencies +func GetAllActiveTickers() []EnabledExchangeCurrencies { + var tickerData []EnabledExchangeCurrencies for _, individualBot := range bot.exchanges { if individualBot != nil && individualBot.IsEnabled() { @@ -74,9 +78,16 @@ func getAllActiveTickersResponse(w http.ResponseWriter, r *http.Request) { individualExchange.ExchangeValues, tickerPrice, ) } - response.Data = append(response.Data, individualExchange) + tickerData = append(tickerData, individualExchange) } } + return tickerData +} + +func getAllActiveTickersResponse(w http.ResponseWriter, r *http.Request) { + var response AllEnabledExchangeCurrencies + response.Data = GetAllActiveTickers() + w.Header().Set("Content-Type", "application/json; charset=UTF-8") w.WriteHeader(http.StatusOK) if err := json.NewEncoder(w).Encode(response); err != nil { diff --git a/tools/websocket_client/main.go b/tools/websocket_client/main.go new file mode 100644 index 00000000..509ada13 --- /dev/null +++ b/tools/websocket_client/main.go @@ -0,0 +1,221 @@ +package main + +import ( + "log" + "net/http" + "time" + + "github.com/gorilla/websocket" + "github.com/thrasher-/gocryptotrader/common" +) + +var ( + WSConn *websocket.Conn +) + +type WebsocketEvent struct { + Event string `json:"event"` + Data interface{} `json:"data"` + Exchange string `json:"exchange,omitempty"` +} + +type WebsocketAuth struct { + Username string `json:"username"` + Password string `json:"password"` +} + +type WebsocketEventResponse struct { + Event string `json:"event"` + Data interface{} `json:"data"` + Error string `json:"error"` +} + +type WebsocketTickerRequest struct { + Exchange string `json:"exchangeName"` + Currency string `json:"currency"` +} + +func SendWebsocketAuth(username, password string) error { + pwHash := common.HexEncodeToString(common.GetSHA256([]byte(password))) + req := WebsocketEvent{ + Event: "auth", + Data: WebsocketAuth{ + Username: username, + Password: pwHash, + }, + } + + return SendWebsocketMsg(req) +} + +func SendWebsocketMsg(data interface{}) error { + return WSConn.WriteJSON(data) +} + +func GetWebsocketTicker(currency string) error { + wsevt := WebsocketEvent{ + Event: "ticker", + Data: currency, + } + + return SendWebsocketMsg(wsevt) +} + +func main() { + var Dialer websocket.Dialer + var err error + + WSConn, _, err = Dialer.Dial("ws://localhost:9050/ws", http.Header{}) + + if err != nil { + log.Println("Unable to connect to websocket server") + return + } + + log.Println("Connected to websocket!") + log.Println("Authenticating..") + SendWebsocketAuth("username", "password") + + var wsResp WebsocketEventResponse + err = WSConn.ReadJSON(&wsResp) + if err != nil { + log.Println(err) + return + } + + if wsResp.Error != "" { + log.Fatal(wsResp.Error) + } + + log.Println("Authenticated successfully") + log.Println("Getting config..") + + req := WebsocketEvent{ + Event: "GetConfig", + } + + err = WSConn.WriteJSON(req) + if err != nil { + log.Println(err) + return + } + + err = WSConn.ReadJSON(&wsResp) + if err != nil { + log.Println(err) + return + } + + if wsResp.Error != "" { + log.Fatal(wsResp.Error) + } + + log.Printf("Fetched config.") + + req = WebsocketEvent{ + Event: "SaveConfig", + Data: wsResp.Data, + } + + log.Println("Saving config..") + err = WSConn.WriteJSON(req) + if err != nil { + log.Fatal(err) + } + + err = WSConn.ReadJSON(&wsResp) + if err != nil { + log.Println(err) + return + } + + if wsResp.Error != "" { + log.Fatal(wsResp.Error) + } + + log.Println("Saved config!") + log.Println("Getting account info..") + + req = WebsocketEvent{ + Event: "GetAccountInfo", + } + + err = WSConn.WriteJSON(req) + if err != nil { + log.Println(err) + return + } + + err = WSConn.ReadJSON(&wsResp) + if err != nil { + log.Println(err) + return + } + + if wsResp.Error != "" { + log.Fatal(wsResp.Error) + } + + log.Println("Getting tickers..") + + req = WebsocketEvent{ + Event: "GetTickers", + } + + err = WSConn.WriteJSON(req) + if err != nil { + log.Println(err) + return + } + + err = WSConn.ReadJSON(&wsResp) + if err != nil { + log.Println(err) + return + } + + if wsResp.Error != "" { + log.Fatal(wsResp.Error) + } + + log.Println("Getting specific ticker..") + + var tickReq WebsocketTickerRequest + tickReq.Currency = "LTCUSD" + tickReq.Exchange = "Bitfinex" + + req = WebsocketEvent{ + Event: "GetTicker", + Data: tickReq, + } + + err = WSConn.WriteJSON(req) + if err != nil { + log.Println(err) + return + } + + err = WSConn.ReadJSON(&wsResp) + if err != nil { + log.Println(err) + return + } + + if wsResp.Error != "" { + log.Fatal(wsResp.Error) + } + + log.Println(wsResp) + + for { + msgType, resp, err := WSConn.ReadMessage() + if err != nil { + log.Fatal(err) + } + + log.Println(msgType) + log.Println(string(resp)) + } + time.Sleep(time.Second * 10) + WSConn.Close() +} diff --git a/websocket.go b/websocket.go new file mode 100644 index 00000000..ccdb4499 --- /dev/null +++ b/websocket.go @@ -0,0 +1,270 @@ +package main + +import ( + "errors" + "log" + "net/http" + "time" + + "github.com/gorilla/websocket" + "github.com/thrasher-/gocryptotrader/common" + "github.com/thrasher-/gocryptotrader/config" +) + +const ( + WebsocketResponseSuccess = "OK" +) + +var WebsocketRoutes = Routes{ + Route{ + "ws", + "GET", + "/ws", + WebsocketClientHandler, + }, +} + +type WebsocketClient struct { + ID int + Conn *websocket.Conn + LastRecv time.Time + Authenticated bool +} + +type WebsocketEvent struct { + Exchange string `json:"exchange,omitempty"` + Event string + Data interface{} +} + +type WebsocketEventResponse struct { + Event string `json:"event"` + Data interface{} `json:"data"` + Error string `json:"error"` +} + +type WebsocketTickerRequest struct { + Exchange string `json:"exchangeName"` + Currency string `json:"currency"` +} + +var WebsocketClientHub []WebsocketClient + +func WebsocketClientHandler(w http.ResponseWriter, r *http.Request) { + upgrader := websocket.Upgrader{ + WriteBufferSize: 1024, + ReadBufferSize: 1024, + } + + newClient := WebsocketClient{ + ID: len(WebsocketClientHub), + } + + conn, err := upgrader.Upgrade(w, r, nil) + if err != nil { + log.Println(err) + return + } + + newClient.Conn = conn + WebsocketClientHub = append(WebsocketClientHub, newClient) + log.Println("New websocket client connected.") +} + +func DisconnectWebsocketClient(id int, err error) { + for i := range WebsocketClientHub { + if WebsocketClientHub[i].ID == id { + WebsocketClientHub[i].Conn.Close() + WebsocketClientHub = append(WebsocketClientHub[:i], WebsocketClientHub[i+1:]...) + log.Printf("Disconnected Websocket client, error: %s", err) + return + } + } +} + +func SendWebsocketMessage(id int, data interface{}) error { + for _, x := range WebsocketClientHub { + if x.ID == id { + return x.Conn.WriteJSON(data) + } + } + return nil +} + +func BroadcastWebsocketMessage(evt WebsocketEvent) error { + log.Println(evt) + for _, x := range WebsocketClientHub { + x.Conn.WriteJSON(evt) + } + return nil +} + +type WebsocketAuth struct { + Username string `json:"username"` + Password string `json:"password"` +} + +func WebsocketHandler() { + for { + for x := range WebsocketClientHub { + msgType, msg, err := WebsocketClientHub[x].Conn.ReadMessage() + if err != nil { + DisconnectWebsocketClient(x, err) + continue + } + + if msgType != websocket.TextMessage { + DisconnectWebsocketClient(x, err) + continue + } + + var evt WebsocketEvent + err = common.JSONDecode(msg, &evt) + if err != nil { + log.Println(err) + continue + } + + if evt.Event == "" { + DisconnectWebsocketClient(x, errors.New("Websocket client sent data we did not understand")) + continue + } + + dataJSON, err := common.JSONEncode(evt.Data) + if err != nil { + log.Println(err) + continue + } + + if !WebsocketClientHub[x].Authenticated && evt.Event != "auth" { + wsResp := WebsocketEventResponse{ + Event: "auth", + Error: "you must authenticate first", + } + SendWebsocketMessage(x, wsResp) + DisconnectWebsocketClient(x, errors.New("Websocket client did not auth")) + continue + } else if !WebsocketClientHub[x].Authenticated && evt.Event == "auth" { + var auth WebsocketAuth + err = common.JSONDecode(dataJSON, &auth) + if err != nil { + log.Println(err) + continue + } + hashPW := common.HexEncodeToString(common.GetSHA256([]byte("password"))) + if auth.Username == "username" && auth.Password == hashPW { + WebsocketClientHub[x].Authenticated = true + wsResp := WebsocketEventResponse{ + Event: "auth", + Data: WebsocketResponseSuccess, + } + SendWebsocketMessage(x, wsResp) + log.Println("Websocket client authenticated successfully") + continue + } else { + wsResp := WebsocketEventResponse{ + Event: "auth", + Error: "invalid username/password", + } + SendWebsocketMessage(x, wsResp) + DisconnectWebsocketClient(x, errors.New("Websocket client sent wrong username/password")) + continue + } + } + switch evt.Event { + case "GetConfig": + wsResp := WebsocketEventResponse{ + Event: "GetConfig", + Data: bot.config, + } + SendWebsocketMessage(x, wsResp) + continue + case "SaveConfig": + wsResp := WebsocketEventResponse{ + Event: "SaveConfig", + } + var cfg config.Config + err := common.JSONDecode(dataJSON, &cfg) + if err != nil { + wsResp.Error = err.Error() + SendWebsocketMessage(x, wsResp) + log.Println(err) + continue + } + + //Save change the settings + for x := range bot.config.Exchanges { + for i := 0; i < len(cfg.Exchanges); i++ { + if cfg.Exchanges[i].Name == bot.config.Exchanges[x].Name { + bot.config.Exchanges[x].Enabled = cfg.Exchanges[i].Enabled + bot.config.Exchanges[x].APIKey = cfg.Exchanges[i].APIKey + bot.config.Exchanges[x].APISecret = cfg.Exchanges[i].APISecret + bot.config.Exchanges[x].EnabledPairs = cfg.Exchanges[i].EnabledPairs + } + } + } + + //Reload the configuration + err = bot.config.SaveConfig(bot.configFile) + if err != nil { + wsResp.Error = err.Error() + SendWebsocketMessage(x, wsResp) + continue + } + err = bot.config.LoadConfig(bot.configFile) + if err != nil { + wsResp.Error = err.Error() + SendWebsocketMessage(x, wsResp) + continue + } + setupBotExchanges() + wsResp.Data = WebsocketResponseSuccess + SendWebsocketMessage(x, wsResp) + continue + case "GetAccountInfo": + accountInfo := GetAllEnabledExchangeAccountInfo() + wsResp := WebsocketEventResponse{ + Event: "GetAccountInfo", + Data: accountInfo, + } + SendWebsocketMessage(x, wsResp) + continue + case "GetTicker": + wsResp := WebsocketEventResponse{ + Event: "GetTicker", + } + var tickerReq WebsocketTickerRequest + err := common.JSONDecode(dataJSON, &tickerReq) + if err != nil { + wsResp.Error = err.Error() + SendWebsocketMessage(x, wsResp) + log.Println(err) + continue + } + + data, err := GetSpecificTicker(tickerReq.Currency, + tickerReq.Exchange) + + if err != nil { + wsResp.Error = err.Error() + SendWebsocketMessage(x, wsResp) + log.Println(err) + continue + } + wsResp.Data = data + SendWebsocketMessage(x, wsResp) + continue + + case "GetTickers": + wsResp := WebsocketEventResponse{ + Event: "GetTickers", + } + tickers := GetAllActiveTickers() + wsResp.Data = tickers + SendWebsocketMessage(x, wsResp) + continue + } + } + time.Sleep(time.Millisecond) + } +}