mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-05-13 23:16:45 +00:00
Merge branch 'webserver-test' of https://github.com/thrasher-/gocryptotrader
This commit is contained in:
4
.gitignore
vendored
4
.gitignore
vendored
@@ -1 +1,3 @@
|
||||
config.json
|
||||
config.json
|
||||
node_modules
|
||||
lib
|
||||
|
||||
@@ -203,6 +203,21 @@ func (a *Alphapoint) GetTicker(symbol string) (AlphapointTicker, error) {
|
||||
return response, nil
|
||||
}
|
||||
|
||||
func (a *Alphapoint) GetTickerPrice(currency string) TickerPrice {
|
||||
var tickerPrice TickerPrice
|
||||
ticker, err := a.GetTicker(currency)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return TickerPrice{}
|
||||
}
|
||||
tickerPrice.Ask = ticker.Ask
|
||||
tickerPrice.Bid = ticker.Bid
|
||||
|
||||
return tickerPrice
|
||||
}
|
||||
|
||||
|
||||
|
||||
func (a *Alphapoint) GetTrades(symbol string, startIndex, count int) (AlphapointTrades, error) {
|
||||
request := make(map[string]interface{})
|
||||
request["ins"] = symbol
|
||||
|
||||
18
anxhttp.go
18
anxhttp.go
@@ -188,6 +188,24 @@ func (a *ANX) GetTicker(currency string) ANXTicker {
|
||||
return ticker
|
||||
}
|
||||
|
||||
func (a *ANX) GetTickerPrice(currency string) TickerPrice {
|
||||
var tickerPrice TickerPrice
|
||||
ticker := a.GetTicker(currency)
|
||||
tickerPrice.Ask = ticker.Data.Buy.Value
|
||||
tickerPrice.Bid = ticker.Data.Sell.Value
|
||||
tickerPrice.CryptoCurrency = currency
|
||||
tickerPrice.Low = ticker.Data.Low.Value
|
||||
tickerPrice.Last = ticker.Data.Last.Value
|
||||
tickerPrice.Volume = ticker.Data.Vol.Value
|
||||
tickerPrice.High = ticker.Data.High.Value
|
||||
|
||||
return tickerPrice
|
||||
}
|
||||
|
||||
func (a *ANX) GetEnabledCurrencies() []string {
|
||||
return a.EnabledPairs
|
||||
}
|
||||
|
||||
func (a *ANX) GetAPIKey(username, password, otp, deviceID string) (string, string) {
|
||||
request := make(map[string]interface{})
|
||||
request["nonce"] = strconv.FormatInt(time.Now().UnixNano(), 10)[0:13]
|
||||
|
||||
@@ -3,12 +3,13 @@ package main
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/gorilla/websocket"
|
||||
"log"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -211,6 +212,10 @@ func (b *Bitfinex) Setup(exch Exchanges) {
|
||||
}
|
||||
}
|
||||
|
||||
func (k *Bitfinex) GetEnabledCurrencies() []string {
|
||||
return k.EnabledPairs
|
||||
}
|
||||
|
||||
func (b *Bitfinex) Start() {
|
||||
go b.Run()
|
||||
}
|
||||
@@ -284,6 +289,24 @@ func (b *Bitfinex) GetTicker(symbol string, values url.Values) (BitfinexTicker,
|
||||
return response, nil
|
||||
}
|
||||
|
||||
func (b *Bitfinex) GetTickerPrice(currency string) TickerPrice {
|
||||
var tickerPrice TickerPrice
|
||||
ticker, err := b.GetTicker(currency, nil)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return tickerPrice
|
||||
}
|
||||
tickerPrice.Ask = ticker.Ask
|
||||
tickerPrice.Bid = ticker.Bid
|
||||
tickerPrice.CryptoCurrency = currency
|
||||
tickerPrice.Low = ticker.Low
|
||||
tickerPrice.Last = ticker.Last
|
||||
tickerPrice.Volume = ticker.Volume
|
||||
tickerPrice.High = ticker.High
|
||||
|
||||
return tickerPrice
|
||||
}
|
||||
|
||||
type BitfinexLendbookBidAsk struct {
|
||||
Rate float64 `json:"rate,string"`
|
||||
Amount float64 `json:"amount,string"`
|
||||
|
||||
@@ -169,6 +169,10 @@ func (b *Bitstamp) Setup(exch Exchanges) {
|
||||
}
|
||||
}
|
||||
|
||||
func (k *Bitstamp) GetEnabledCurrencies() []string {
|
||||
return k.EnabledPairs
|
||||
}
|
||||
|
||||
func (b *Bitstamp) SetEnabled(enabled bool) {
|
||||
b.Enabled = enabled
|
||||
}
|
||||
@@ -234,6 +238,24 @@ func (b *Bitstamp) GetTicker(hourly bool) (BitstampTicker, error) {
|
||||
return ticker, nil
|
||||
}
|
||||
|
||||
func (b *Bitstamp) GetTickerPrice(currency string) TickerPrice {
|
||||
var tickerPrice TickerPrice
|
||||
ticker, err := b.GetTicker(true)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return tickerPrice
|
||||
}
|
||||
tickerPrice.Ask = ticker.Ask
|
||||
tickerPrice.Bid = ticker.Bid
|
||||
tickerPrice.CryptoCurrency = currency
|
||||
tickerPrice.Low = ticker.Low
|
||||
tickerPrice.Last = ticker.Last
|
||||
tickerPrice.Volume = ticker.Volume
|
||||
tickerPrice.High = ticker.High
|
||||
|
||||
return tickerPrice
|
||||
}
|
||||
|
||||
func (b *Bitstamp) GetOrderbook() (BitstampOrderbook, error) {
|
||||
type response struct {
|
||||
Timestamp int64 `json:"timestamp,string"`
|
||||
|
||||
@@ -61,6 +61,10 @@ func (b *BrightonPeak) Setup(exch Exchanges) {
|
||||
}
|
||||
}
|
||||
|
||||
func (k *BrightonPeak) GetEnabledCurrencies() []string {
|
||||
return k.EnabledPairs
|
||||
}
|
||||
|
||||
func (b *BrightonPeak) Start() {
|
||||
go b.Run()
|
||||
}
|
||||
@@ -134,6 +138,24 @@ func (b *BrightonPeak) GetTicker(symbol string) (AlphapointTicker, error) {
|
||||
return b.API.GetTicker(symbol)
|
||||
}
|
||||
|
||||
func (b *BrightonPeak) GetTickerPrice(currency string) TickerPrice {
|
||||
var tickerPrice TickerPrice
|
||||
ticker, err := b.GetTicker(currency)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return tickerPrice
|
||||
}
|
||||
tickerPrice.Ask = ticker.Ask
|
||||
tickerPrice.Bid = ticker.Bid
|
||||
tickerPrice.CryptoCurrency = currency
|
||||
tickerPrice.Low = ticker.Low
|
||||
tickerPrice.Last = ticker.Last
|
||||
tickerPrice.Volume = ticker.Volume
|
||||
tickerPrice.High = ticker.High
|
||||
|
||||
return tickerPrice
|
||||
}
|
||||
|
||||
func (b *BrightonPeak) GetTrades(symbol string, startIndex, count int) (AlphapointTrades, error) {
|
||||
return b.API.GetTrades(symbol, startIndex, count)
|
||||
}
|
||||
|
||||
18
btcchttp.go
18
btcchttp.go
@@ -198,6 +198,10 @@ func (b *BTCC) Setup(exch Exchanges) {
|
||||
}
|
||||
}
|
||||
|
||||
func (k *BTCC) GetEnabledCurrencies() []string {
|
||||
return k.EnabledPairs
|
||||
}
|
||||
|
||||
//Start is run if exchange is enabled, after Setup
|
||||
func (b *BTCC) Start() {
|
||||
go b.Run()
|
||||
@@ -272,6 +276,20 @@ func (b *BTCC) GetTicker(symbol string) BTCCTicker {
|
||||
return resp.Ticker
|
||||
}
|
||||
|
||||
func (b *BTCC) GetTickerPrice(currency string) TickerPrice {
|
||||
var tickerPrice TickerPrice
|
||||
ticker := b.GetTicker(currency)
|
||||
tickerPrice.Ask = ticker.Sell
|
||||
tickerPrice.Bid = ticker.Buy
|
||||
tickerPrice.CryptoCurrency = currency
|
||||
tickerPrice.Low = ticker.Low
|
||||
tickerPrice.Last = ticker.Last
|
||||
tickerPrice.Volume = ticker.Vol
|
||||
tickerPrice.High = ticker.High
|
||||
|
||||
return tickerPrice
|
||||
}
|
||||
|
||||
func (b *BTCC) GetTradesLast24h(symbol string) bool {
|
||||
req := fmt.Sprintf("%sdata/trades?market=%s", BTCC_API_URL, symbol)
|
||||
err := SendHTTPGetRequest(req, true, nil)
|
||||
|
||||
19
btcehttp.go
19
btcehttp.go
@@ -116,6 +116,10 @@ func (b *BTCE) Setup(exch Exchanges) {
|
||||
}
|
||||
}
|
||||
|
||||
func (k *BTCE) GetEnabledCurrencies() []string {
|
||||
return k.EnabledPairs
|
||||
}
|
||||
|
||||
func (b *BTCE) Start() {
|
||||
go b.Run()
|
||||
}
|
||||
@@ -185,6 +189,21 @@ func (b *BTCE) GetTicker(symbol string) (map[string]BTCeTicker, error) {
|
||||
return response.Data, nil
|
||||
}
|
||||
|
||||
/// This getticker is different, so I'll let someone else implement....
|
||||
/// Or I will, just later...
|
||||
func (b *BTCE) GetTickerPrice(currency string) TickerPrice {
|
||||
var tickerPrice TickerPrice
|
||||
/*ticker, err:= b.GetTicker(currency)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return tickerPrice
|
||||
}
|
||||
tickerPrice.Ask = ticker.Buy
|
||||
tickerPrice.Bid = ticker.Sell
|
||||
*/
|
||||
return tickerPrice
|
||||
}
|
||||
|
||||
func (b *BTCE) GetDepth(symbol string) {
|
||||
type Response struct {
|
||||
Data map[string]BTCEOrderbook
|
||||
|
||||
@@ -125,6 +125,10 @@ func (b *BTCMarkets) Setup(exch Exchanges) {
|
||||
}
|
||||
}
|
||||
|
||||
func (k *BTCMarkets) GetEnabledCurrencies() []string {
|
||||
return k.EnabledPairs
|
||||
}
|
||||
|
||||
func (b *BTCMarkets) Start() {
|
||||
go b.Run()
|
||||
}
|
||||
@@ -188,6 +192,21 @@ func (b *BTCMarkets) GetTicker(symbol string) (BTCMarketsTicker, error) {
|
||||
return ticker, nil
|
||||
}
|
||||
|
||||
func (b *BTCMarkets) GetTickerPrice(currency string) TickerPrice {
|
||||
var tickerPrice TickerPrice
|
||||
ticker, err := b.GetTicker(currency)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return tickerPrice
|
||||
}
|
||||
tickerPrice.Ask = ticker.BestAsk
|
||||
tickerPrice.Bid = ticker.BestBID
|
||||
tickerPrice.CryptoCurrency = currency
|
||||
tickerPrice.Last = ticker.LastPrice
|
||||
|
||||
return tickerPrice
|
||||
}
|
||||
|
||||
func (b *BTCMarkets) GetOrderbook(symbol string) (BTCMarketsOrderbook, error) {
|
||||
orderbook := BTCMarketsOrderbook{}
|
||||
path := fmt.Sprintf("/market/%s/AUD/orderbook", symbol)
|
||||
|
||||
@@ -159,6 +159,10 @@ func (c *Coinbase) Setup(exch Exchanges) {
|
||||
}
|
||||
}
|
||||
|
||||
func (k *Coinbase) GetEnabledCurrencies() []string {
|
||||
return k.EnabledPairs
|
||||
}
|
||||
|
||||
func (c *Coinbase) Start() {
|
||||
go c.Run()
|
||||
}
|
||||
@@ -359,6 +363,20 @@ func (c *Coinbase) GetTicker(symbol string) (CoinbaseTicker, error) {
|
||||
return ticker, nil
|
||||
}
|
||||
|
||||
func (c *Coinbase) GetTickerPrice(currency string) TickerPrice {
|
||||
var tickerPrice TickerPrice
|
||||
ticker, err := c.GetTicker(currency)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return TickerPrice{}
|
||||
}
|
||||
tickerPrice.Ask = ticker.Price
|
||||
tickerPrice.CryptoCurrency = currency
|
||||
tickerPrice.Volume = ticker.Size
|
||||
|
||||
return tickerPrice
|
||||
}
|
||||
|
||||
func (c *Coinbase) GetTrades(symbol string) ([]CoinbaseTrade, error) {
|
||||
trades := []CoinbaseTrade{}
|
||||
path := fmt.Sprintf("%s/%s/%s", COINBASE_API_URL+COINBASE_PRODUCTS, symbol, COINBASE_TRADES)
|
||||
|
||||
@@ -137,6 +137,10 @@ func (g *Gemini) Setup(exch Exchanges) {
|
||||
}
|
||||
}
|
||||
|
||||
func (k *Gemini) GetEnabledCurrencies() []string {
|
||||
return k.EnabledPairs
|
||||
}
|
||||
|
||||
func (g *Gemini) Start() {
|
||||
go g.Run()
|
||||
}
|
||||
@@ -186,6 +190,13 @@ func (g *Gemini) Run() {
|
||||
}
|
||||
}
|
||||
|
||||
/// Once GetTicker is created, then add in GetTickerPrice code plz - Scott
|
||||
func (g *Gemini) GetTickerPrice(currency string) TickerPrice {
|
||||
var tickerPrice TickerPrice
|
||||
|
||||
return tickerPrice
|
||||
}
|
||||
|
||||
func (g *Gemini) GetSymbols() ([]string, error) {
|
||||
symbols := []string{}
|
||||
path := fmt.Sprintf("%s/v%s/%s", GEMINI_API_URL, GEMINI_API_VERSION, GEMINI_SYMBOLS)
|
||||
|
||||
18
huobihttp.go
18
huobihttp.go
@@ -79,6 +79,10 @@ func (h *HUOBI) Setup(exch Exchanges) {
|
||||
}
|
||||
}
|
||||
|
||||
func (k *HUOBI) GetEnabledCurrencies() []string {
|
||||
return k.EnabledPairs
|
||||
}
|
||||
|
||||
func (h *HUOBI) Start() {
|
||||
go h.Run()
|
||||
}
|
||||
@@ -132,6 +136,20 @@ func (h *HUOBI) GetTicker(symbol string) HuobiTicker {
|
||||
return resp.Ticker
|
||||
}
|
||||
|
||||
func (h *HUOBI) GetTickerPrice(currency string) TickerPrice {
|
||||
var tickerPrice TickerPrice
|
||||
ticker := h.GetTicker(currency)
|
||||
tickerPrice.Ask = ticker.Sell
|
||||
tickerPrice.Bid = ticker.Buy
|
||||
tickerPrice.CryptoCurrency = currency
|
||||
tickerPrice.Low = ticker.Low
|
||||
tickerPrice.Last = ticker.Last
|
||||
tickerPrice.Volume = ticker.Vol
|
||||
tickerPrice.High = ticker.High
|
||||
|
||||
return tickerPrice
|
||||
}
|
||||
|
||||
func (h *HUOBI) GetOrderBook(symbol string) bool {
|
||||
path := fmt.Sprintf("http://market.huobi.com/staticmarket/depth_%s_json.js", symbol)
|
||||
err := SendHTTPGetRequest(path, true, nil)
|
||||
|
||||
@@ -6,4 +6,6 @@ type IBotExchange interface {
|
||||
SetDefaults()
|
||||
GetName() string
|
||||
IsEnabled() bool
|
||||
GetTickerPrice(currency string) TickerPrice
|
||||
GetEnabledCurrencies() []string
|
||||
}
|
||||
|
||||
14
itbithttp.go
14
itbithttp.go
@@ -86,6 +86,10 @@ func (i *ItBit) Setup(exch Exchanges) {
|
||||
}
|
||||
}
|
||||
|
||||
func (k *ItBit) GetEnabledCurrencies() []string {
|
||||
return k.EnabledPairs
|
||||
}
|
||||
|
||||
func (i *ItBit) Start() {
|
||||
go i.Run()
|
||||
}
|
||||
@@ -134,6 +138,16 @@ func (i *ItBit) GetTicker(currency string) ItBitTicker {
|
||||
return itbitTicker
|
||||
}
|
||||
|
||||
func (i *ItBit) GetTickerPrice(currency string) TickerPrice {
|
||||
var tickerPrice TickerPrice
|
||||
ticker := i.GetTicker(currency)
|
||||
|
||||
tickerPrice.Ask = ticker.Ask
|
||||
tickerPrice.Bid = ticker.Bid
|
||||
|
||||
return tickerPrice
|
||||
}
|
||||
|
||||
type ItbitOrderbookEntry struct {
|
||||
Quantitiy float64 `json:"quantity,string"`
|
||||
Price float64 `json:"price,string"`
|
||||
|
||||
19
kraken.go
19
kraken.go
@@ -90,6 +90,10 @@ func (k *Kraken) Setup(exch Exchanges) {
|
||||
}
|
||||
}
|
||||
|
||||
func (k *Kraken) GetEnabledCurrencies() []string {
|
||||
return k.EnabledPairs
|
||||
}
|
||||
|
||||
func (k *Kraken) Start() {
|
||||
go k.Run()
|
||||
}
|
||||
@@ -229,6 +233,21 @@ func (k *Kraken) GetTicker(symbol string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
//This will return the TickerPrice struct when tickers are completed here..
|
||||
func (k *Kraken) GetTickerPrice(currency string) TickerPrice {
|
||||
var tickerPrice TickerPrice
|
||||
/*
|
||||
ticker, err := i.GetTicker(currency)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return tickerPrice
|
||||
}
|
||||
tickerPrice.Ask = ticker.Ask
|
||||
tickerPrice.Bid = ticker.Bid
|
||||
*/
|
||||
return tickerPrice
|
||||
}
|
||||
|
||||
func (k *Kraken) GetOHLC(symbol string) error {
|
||||
values := url.Values{}
|
||||
values.Set("pair", symbol)
|
||||
|
||||
@@ -95,6 +95,10 @@ func (l *LakeBTC) Setup(exch Exchanges) {
|
||||
}
|
||||
}
|
||||
|
||||
func (k *LakeBTC) GetEnabledCurrencies() []string {
|
||||
return k.EnabledPairs
|
||||
}
|
||||
|
||||
func (l *LakeBTC) Start() {
|
||||
go l.Run()
|
||||
}
|
||||
@@ -148,6 +152,23 @@ func (l *LakeBTC) GetTicker() LakeBTCTickerResponse {
|
||||
return response
|
||||
}
|
||||
|
||||
func (l *LakeBTC) GetTickerPrice(currency string) TickerPrice {
|
||||
var tickerPrice TickerPrice
|
||||
ticker := l.GetTicker()
|
||||
|
||||
if currency == "USD" {
|
||||
tickerPrice.Ask = ticker.USD.Ask
|
||||
tickerPrice.Bid = ticker.USD.Bid
|
||||
} else if currency == "CNY" {
|
||||
tickerPrice.Ask = ticker.CNY.Ask
|
||||
tickerPrice.Bid = ticker.CNY.Bid
|
||||
}
|
||||
|
||||
tickerPrice.CryptoCurrency = currency
|
||||
|
||||
return tickerPrice
|
||||
}
|
||||
|
||||
func (l *LakeBTC) GetOrderBook(currency string) bool {
|
||||
req := LAKEBTC_ORDERBOOK
|
||||
if currency == "CNY" {
|
||||
|
||||
@@ -74,6 +74,10 @@ func (l *LocalBitcoins) Setup(exch Exchanges) {
|
||||
}
|
||||
}
|
||||
|
||||
func (k *LocalBitcoins) GetEnabledCurrencies() []string {
|
||||
return k.EnabledPairs
|
||||
}
|
||||
|
||||
func (l *LocalBitcoins) Start() {
|
||||
go l.Run()
|
||||
}
|
||||
@@ -136,6 +140,19 @@ func (l *LocalBitcoins) GetTicker() (map[string]LocalBitcoinsTicker, error) {
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (l *LocalBitcoins) GetTickerPrice(currency string) TickerPrice {
|
||||
var tickerPrice TickerPrice
|
||||
ticker, err := l.GetTicker()
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return tickerPrice
|
||||
}
|
||||
tickerPrice.Ask = ticker[currency].Rates.Last
|
||||
tickerPrice.CryptoCurrency = currency
|
||||
|
||||
return tickerPrice
|
||||
}
|
||||
|
||||
type LocalBitcoinsTrade struct {
|
||||
TID int64 `json:"tid"`
|
||||
Date int64 `json:"date"`
|
||||
|
||||
77
main.go
77
main.go
@@ -3,6 +3,7 @@ package main
|
||||
import (
|
||||
"errors"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"runtime"
|
||||
@@ -40,8 +41,9 @@ type Bot struct {
|
||||
var bot Bot
|
||||
|
||||
func SetupBotConfiguration(s IBotExchange, exch Exchanges) {
|
||||
s.Setup(exch)
|
||||
s.SetDefaults()
|
||||
if s.GetName() == exch.Name {
|
||||
s.Setup(exch)
|
||||
if s.IsEnabled() {
|
||||
log.Printf("%s: Exchange support: %s (Authenticated API support: %s - Verbose mode: %s).\n", exch.Name, IsEnabled(exch.Enabled), IsEnabled(exch.AuthenticatedAPISupport), IsEnabled(exch.Verbose))
|
||||
s.Start()
|
||||
@@ -80,30 +82,10 @@ func main() {
|
||||
} else {
|
||||
log.Printf("SMS support enabled. Number of SMS contacts %d.\n", GetEnabledSMSContacts())
|
||||
}
|
||||
}
|
||||
if !bot.config.SMS.Enabled {
|
||||
} else {
|
||||
log.Println("SMS support disabled.")
|
||||
}
|
||||
|
||||
if bot.config.Webserver.Enabled {
|
||||
err := CheckWebserverValues()
|
||||
if err != nil {
|
||||
log.Println(err) // non fatal event
|
||||
bot.config.Webserver.Enabled = false
|
||||
} else {
|
||||
log.Println("HTTP Webserver support enabled.")
|
||||
err = StartWebserver()
|
||||
if err != nil {
|
||||
log.Println("Unable to start Webserver: ", err)
|
||||
} else {
|
||||
log.Printf("HTTP server enabled and running at http://%s:%d\n", GetWebserverHost(), GetWebserverPort())
|
||||
}
|
||||
}
|
||||
}
|
||||
if !bot.config.Webserver.Enabled {
|
||||
log.Println("HTTP Webserver support disabled.")
|
||||
}
|
||||
|
||||
log.Printf("Available Exchanges: %d. Enabled Exchanges: %d.\n", len(bot.config.Exchanges), GetEnabledExchanges())
|
||||
log.Println("Bot Exchange support:")
|
||||
|
||||
@@ -111,25 +93,24 @@ func main() {
|
||||
bot.exchange.okcoinChina.APIUrl = OKCOIN_API_URL_CHINA
|
||||
|
||||
bot.exchanges = []IBotExchange{
|
||||
&bot.exchange.anx,
|
||||
&bot.exchange.kraken,
|
||||
&bot.exchange.btcc,
|
||||
&bot.exchange.bitstamp,
|
||||
&bot.exchange.brightonpeak,
|
||||
&bot.exchange.bitfinex,
|
||||
&bot.exchange.btce,
|
||||
&bot.exchange.btcmarkets,
|
||||
&bot.exchange.coinbase,
|
||||
&bot.exchange.gemini,
|
||||
&bot.exchange.okcoinChina,
|
||||
&bot.exchange.okcoinIntl,
|
||||
&bot.exchange.itbit,
|
||||
&bot.exchange.lakebtc,
|
||||
&bot.exchange.localbitcoins,
|
||||
&bot.exchange.poloniex,
|
||||
&bot.exchange.huobi,
|
||||
new(ANX),
|
||||
new(Kraken),
|
||||
new(BTCC),
|
||||
new(Bitstamp),
|
||||
new(BrightonPeak),
|
||||
new(Bitfinex),
|
||||
new(BTCE),
|
||||
new(BTCMarkets),
|
||||
new(Coinbase),
|
||||
new(Gemini),
|
||||
new(OKCoin),
|
||||
new(OKCoin),
|
||||
new(ItBit),
|
||||
new(LakeBTC),
|
||||
new(LocalBitcoins),
|
||||
new(Poloniex),
|
||||
new(HUOBI),
|
||||
}
|
||||
|
||||
for i := 0; i < len(bot.exchanges); i++ {
|
||||
if bot.exchanges[i] != nil {
|
||||
bot.exchanges[i].SetDefaults()
|
||||
@@ -150,6 +131,22 @@ func main() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if bot.config.Webserver.Enabled {
|
||||
err := CheckWebserverValues()
|
||||
if err != nil {
|
||||
log.Println(err) // non fatal event
|
||||
//bot.config.Webserver.Enabled = false
|
||||
} else {
|
||||
log.Println("HTTP Webserver support enabled.")
|
||||
router := NewRouter(bot.exchanges)
|
||||
log.Fatal(http.ListenAndServe(bot.config.Webserver.ListenAddress, router))
|
||||
}
|
||||
}
|
||||
if !bot.config.Webserver.Enabled {
|
||||
log.Println("HTTP Webserver support disabled.")
|
||||
}
|
||||
|
||||
<-bot.shutdown
|
||||
Shutdown()
|
||||
}
|
||||
|
||||
@@ -2,12 +2,13 @@ package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"github.com/gorilla/websocket"
|
||||
"log"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -229,6 +230,10 @@ func (o *OKCoin) Setup(exch Exchanges) {
|
||||
}
|
||||
}
|
||||
|
||||
func (k *OKCoin) GetEnabledCurrencies() []string {
|
||||
return k.EnabledPairs
|
||||
}
|
||||
|
||||
func (o *OKCoin) Start() {
|
||||
go o.Run()
|
||||
}
|
||||
@@ -322,6 +327,24 @@ func (o *OKCoin) GetTicker(symbol string) (OKCoinTicker, error) {
|
||||
return resp.Ticker, nil
|
||||
}
|
||||
|
||||
func (o *OKCoin) GetTickerPrice(currency string) TickerPrice {
|
||||
var tickerPrice TickerPrice
|
||||
ticker, err := o.GetTicker(currency)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return tickerPrice
|
||||
}
|
||||
tickerPrice.Ask = ticker.Sell
|
||||
tickerPrice.Bid = ticker.Buy
|
||||
tickerPrice.CryptoCurrency = currency
|
||||
tickerPrice.Low = ticker.Low
|
||||
tickerPrice.Last = ticker.Last
|
||||
tickerPrice.Volume = ticker.Vol
|
||||
tickerPrice.High = ticker.High
|
||||
|
||||
return tickerPrice
|
||||
}
|
||||
|
||||
func (o *OKCoin) GetOrderBook(symbol string, size int64, merge bool) (OKCoinOrderbook, error) {
|
||||
resp := OKCoinOrderbook{}
|
||||
vals := url.Values{}
|
||||
|
||||
@@ -105,6 +105,10 @@ func (p *Poloniex) Setup(exch Exchanges) {
|
||||
}
|
||||
}
|
||||
|
||||
func (k *Poloniex) GetEnabledCurrencies() []string {
|
||||
return k.EnabledPairs
|
||||
}
|
||||
|
||||
func (p *Poloniex) Start() {
|
||||
go p.Run()
|
||||
}
|
||||
@@ -161,6 +165,24 @@ func (p *Poloniex) GetTicker() (map[string]PoloniexTicker, error) {
|
||||
return resp.Data, nil
|
||||
}
|
||||
|
||||
func (p *Poloniex) GetTickerPrice(currency string) TickerPrice {
|
||||
var tickerPrice TickerPrice
|
||||
ticker, err := p.GetTicker()
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return tickerPrice
|
||||
}
|
||||
tickerPrice.CryptoCurrency = currency
|
||||
tickerPrice.Ask = ticker[currency].Last
|
||||
tickerPrice.Bid = ticker[currency].HighestBid
|
||||
tickerPrice.High = ticker[currency].HighestBid
|
||||
tickerPrice.Last = ticker[currency].Last
|
||||
tickerPrice.Low = ticker[currency].LowestAsk
|
||||
tickerPrice.Volume = ticker[currency].BaseVolume
|
||||
|
||||
return tickerPrice
|
||||
}
|
||||
|
||||
func (p *Poloniex) GetVolume() (interface{}, error) {
|
||||
var resp interface{}
|
||||
path := fmt.Sprintf("%s/public?command=return24hVolume", POLONIEX_API_URL)
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"gopkg.in/jcelliott/turnpike.v2"
|
||||
"log"
|
||||
"strconv"
|
||||
|
||||
"gopkg.in/jcelliott/turnpike.v2"
|
||||
)
|
||||
|
||||
const (
|
||||
|
||||
11
restfulHandlers.go
Normal file
11
restfulHandlers.go
Normal file
@@ -0,0 +1,11 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func Index(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Fprintln(w, bot.exchanges[0].GetName())
|
||||
|
||||
}
|
||||
23
restfulLogger.go
Normal file
23
restfulLogger.go
Normal file
@@ -0,0 +1,23 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
func Logger(inner http.Handler, name string) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
start := time.Now()
|
||||
|
||||
inner.ServeHTTP(w, r)
|
||||
|
||||
log.Printf(
|
||||
"%s\t%s\t%s\t%s",
|
||||
r.Method,
|
||||
r.RequestURI,
|
||||
name,
|
||||
time.Since(start),
|
||||
)
|
||||
})
|
||||
}
|
||||
25
restfulRouter.go
Normal file
25
restfulRouter.go
Normal file
@@ -0,0 +1,25 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
|
||||
func NewRouter(exchanges []IBotExchange) *mux.Router {
|
||||
router := mux.NewRouter().StrictSlash(true)
|
||||
allRoutes := append(routes, exchangeRoutes...)
|
||||
for _, route := range allRoutes {
|
||||
var handler http.Handler
|
||||
handler = route.HandlerFunc
|
||||
handler = Logger(handler, route.Name)
|
||||
|
||||
router.
|
||||
Methods(route.Method).
|
||||
Path(route.Pattern).
|
||||
Name(route.Name).
|
||||
Handler(handler)
|
||||
|
||||
}
|
||||
return router
|
||||
}
|
||||
16
restfulRoutes.go
Normal file
16
restfulRoutes.go
Normal file
@@ -0,0 +1,16 @@
|
||||
package main
|
||||
|
||||
import "net/http"
|
||||
|
||||
type Route struct {
|
||||
Name string
|
||||
Method string
|
||||
Pattern string
|
||||
HandlerFunc http.HandlerFunc
|
||||
}
|
||||
|
||||
type Routes []Route
|
||||
|
||||
var routes = Routes{
|
||||
|
||||
}
|
||||
16
ticker.go
16
ticker.go
@@ -5,14 +5,14 @@ import (
|
||||
)
|
||||
|
||||
type TickerPrice struct {
|
||||
CryptoCurrency string
|
||||
FiatCurrency string
|
||||
Last float64
|
||||
High float64
|
||||
Low float64
|
||||
Bid float64
|
||||
Ask float64
|
||||
Volume float64
|
||||
CryptoCurrency string `json:"CryptoCurrency"`
|
||||
FiatCurrency string `json:"FiatCurrency"`
|
||||
Last float64 `json:"Last"`
|
||||
High float64 `json:"High"`
|
||||
Low float64 `json:"Low"`
|
||||
Bid float64 `json:"Bid"`
|
||||
Ask float64 `json:"Ask"`
|
||||
Volume float64 `json:"Volume"`
|
||||
}
|
||||
|
||||
type Ticker struct {
|
||||
|
||||
84
tickerRoutes.go
Normal file
84
tickerRoutes.go
Normal file
@@ -0,0 +1,84 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"log"
|
||||
"net/http"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
|
||||
func jsonTickerResponse(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
currency := vars["currency"]
|
||||
exchangeName := vars["exchangeName"]
|
||||
var response TickerPrice
|
||||
for i := 0; i < len(bot.exchanges); i++ {
|
||||
if bot.exchanges[i] != nil {
|
||||
if bot.exchanges[i].IsEnabled() && bot.exchanges[i].GetName() == exchangeName {
|
||||
response = bot.exchanges[i].GetTickerPrice(currency)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
type AllEnabledExchangeCurrencies struct {
|
||||
Data []EnabledExchangeCurrencies `json:"data"`
|
||||
}
|
||||
|
||||
type EnabledExchangeCurrencies struct {
|
||||
ExchangeName string `json:"exchangeName"`
|
||||
ExchangeValues []TickerPrice `json:"exchangeValues"`
|
||||
}
|
||||
|
||||
func getAllActiveTickersResponse(w http.ResponseWriter, r *http.Request) {
|
||||
var response AllEnabledExchangeCurrencies
|
||||
log.Println(bot.exchanges[15])
|
||||
|
||||
for _, individualBot := range bot.exchanges {
|
||||
if individualBot != nil && individualBot.IsEnabled() {
|
||||
var individualExchange EnabledExchangeCurrencies
|
||||
individualExchange.ExchangeName = individualBot.GetName()
|
||||
log.Println("Getting enabled currencies for '" + individualBot.GetName() + "'")
|
||||
currencies := individualBot.GetEnabledCurrencies()
|
||||
log.Println(currencies)
|
||||
for _, currency := range currencies {
|
||||
tickerPrice := individualBot.GetTickerPrice(currency)
|
||||
log.Println(tickerPrice)
|
||||
|
||||
individualExchange.ExchangeValues = append(individualExchange.ExchangeValues, tickerPrice)
|
||||
}
|
||||
response.Data = append(response.Data, individualExchange)
|
||||
}
|
||||
}
|
||||
|
||||
log.Println(response)
|
||||
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
if err := json.NewEncoder(w).Encode(response); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
var exchangeRoutes = Routes{
|
||||
Route{
|
||||
"AllActiveExchangesAndCurrencies",
|
||||
"GET",
|
||||
"/exchanges/enabled/latest/all",
|
||||
getAllActiveTickersResponse,
|
||||
},
|
||||
Route{
|
||||
"IndividualExchangeAndCurrency",
|
||||
"GET",
|
||||
"/exchanges/{exchangeName}/latest/{currency}",
|
||||
jsonTickerResponse,
|
||||
},
|
||||
}
|
||||
3
web/.bowerrc
Normal file
3
web/.bowerrc
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"directory": "app/bower_components"
|
||||
}
|
||||
7
web/.gitignore
vendored
Normal file
7
web/.gitignore
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
logs/*
|
||||
!.gitkeep
|
||||
node_modules/
|
||||
bower_components/
|
||||
tmp
|
||||
.DS_Store
|
||||
.idea
|
||||
24
web/.jshintrc
Normal file
24
web/.jshintrc
Normal file
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"strict": "global",
|
||||
"globals": {
|
||||
// Angular
|
||||
"angular": false,
|
||||
|
||||
// Angular mocks
|
||||
"module": false,
|
||||
"inject": false,
|
||||
|
||||
// Jasmine
|
||||
"jasmine": false,
|
||||
"describe": false,
|
||||
"beforeEach": false,
|
||||
"afterEach": false,
|
||||
"it": false,
|
||||
"expect": false,
|
||||
|
||||
// Protractor
|
||||
"browser": false,
|
||||
"element": false,
|
||||
"by": false
|
||||
}
|
||||
}
|
||||
14
web/.travis.yml
Normal file
14
web/.travis.yml
Normal file
@@ -0,0 +1,14 @@
|
||||
language: node_js
|
||||
node_js:
|
||||
- '4.4'
|
||||
|
||||
before_script:
|
||||
- export DISPLAY=:99.0
|
||||
- sh -e /etc/init.d/xvfb start
|
||||
- npm start > /dev/null &
|
||||
- npm run update-webdriver
|
||||
- sleep 1 # give server time to start
|
||||
|
||||
script:
|
||||
- node_modules/.bin/karma start karma.conf.js --no-auto-watch --single-run --reporters=dots --browsers=Firefox
|
||||
- node_modules/.bin/protractor e2e-tests/protractor.conf.js --browser=firefox
|
||||
22
web/LICENSE
Normal file
22
web/LICENSE
Normal file
@@ -0,0 +1,22 @@
|
||||
The MIT License
|
||||
|
||||
Copyright (c) 2010-2016 Google, Inc. http://angularjs.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
24
web/README.md
Normal file
24
web/README.md
Normal file
@@ -0,0 +1,24 @@
|
||||
### Prerequisites
|
||||
|
||||
You need git to clone the angular-seed repository. You can get git from
|
||||
[http://git-scm.com/](http://git-scm.com/).
|
||||
|
||||
We also use a number of node.js tools to initialize and test angular-seed. You must have node.js and
|
||||
its package manager (npm) installed. You can get them from [http://nodejs.org/](http://nodejs.org/).
|
||||
### Install Dependencies
|
||||
|
||||
```
|
||||
npm install
|
||||
```
|
||||
|
||||
|
||||
### Run the Application
|
||||
|
||||
The simplest way to start this server is:
|
||||
|
||||
```
|
||||
npm start
|
||||
```
|
||||
|
||||
Now browse to the app at `http://localhost/`.
|
||||
|
||||
30
web/app/app.css
Normal file
30
web/app/app.css
Normal file
@@ -0,0 +1,30 @@
|
||||
/* app css stylesheet */
|
||||
|
||||
.menu {
|
||||
list-style: none;
|
||||
border-bottom: 0.1em solid black;
|
||||
margin-bottom: 2em;
|
||||
padding: 0 0 0.5em;
|
||||
}
|
||||
|
||||
.menu:before {
|
||||
content: "[";
|
||||
}
|
||||
|
||||
.menu:after {
|
||||
content: "]";
|
||||
}
|
||||
|
||||
.menu > li {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.menu > li:before {
|
||||
content: "|";
|
||||
padding-right: 0.3em;
|
||||
}
|
||||
|
||||
.menu > li:nth-child(1):before {
|
||||
content: "";
|
||||
padding: 0;
|
||||
}
|
||||
14
web/app/app.js
Normal file
14
web/app/app.js
Normal file
@@ -0,0 +1,14 @@
|
||||
'use strict';
|
||||
|
||||
// Declare app level module which depends on views, and components
|
||||
angular.module('myApp', [
|
||||
'ngRoute',
|
||||
'myApp.home',
|
||||
'myApp.about',
|
||||
'myApp.version'
|
||||
]).
|
||||
config(['$locationProvider', '$routeProvider', function($locationProvider, $routeProvider) {
|
||||
$locationProvider.hashPrefix('!');
|
||||
|
||||
$routeProvider.otherwise({redirectTo: '/'});
|
||||
}]);
|
||||
9
web/app/components/version/interpolate-filter.js
Normal file
9
web/app/components/version/interpolate-filter.js
Normal file
@@ -0,0 +1,9 @@
|
||||
'use strict';
|
||||
|
||||
angular.module('myApp.version.interpolate-filter', [])
|
||||
|
||||
.filter('interpolate', ['version', function(version) {
|
||||
return function(text) {
|
||||
return String(text).replace(/\%VERSION\%/mg, version);
|
||||
};
|
||||
}]);
|
||||
15
web/app/components/version/interpolate-filter_test.js
Normal file
15
web/app/components/version/interpolate-filter_test.js
Normal file
@@ -0,0 +1,15 @@
|
||||
'use strict';
|
||||
|
||||
describe('myApp.version module', function() {
|
||||
beforeEach(module('myApp.version'));
|
||||
|
||||
describe('interpolate filter', function() {
|
||||
beforeEach(module(function($provide) {
|
||||
$provide.value('version', 'TEST_VER');
|
||||
}));
|
||||
|
||||
it('should replace VERSION', inject(function(interpolateFilter) {
|
||||
expect(interpolateFilter('before %VERSION% after')).toEqual('before TEST_VER after');
|
||||
}));
|
||||
});
|
||||
});
|
||||
9
web/app/components/version/version-directive.js
Normal file
9
web/app/components/version/version-directive.js
Normal file
@@ -0,0 +1,9 @@
|
||||
'use strict';
|
||||
|
||||
angular.module('myApp.version.version-directive', [])
|
||||
|
||||
.directive('appVersion', ['version', function(version) {
|
||||
return function(scope, elm, attrs) {
|
||||
elm.text(version);
|
||||
};
|
||||
}]);
|
||||
17
web/app/components/version/version-directive_test.js
Normal file
17
web/app/components/version/version-directive_test.js
Normal file
@@ -0,0 +1,17 @@
|
||||
'use strict';
|
||||
|
||||
describe('myApp.version module', function() {
|
||||
beforeEach(module('myApp.version'));
|
||||
|
||||
describe('app-version directive', function() {
|
||||
it('should print current version', function() {
|
||||
module(function($provide) {
|
||||
$provide.value('version', 'TEST_VER');
|
||||
});
|
||||
inject(function($compile, $rootScope) {
|
||||
var element = $compile('<span app-version></span>')($rootScope);
|
||||
expect(element.text()).toEqual('TEST_VER');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
8
web/app/components/version/version.js
Normal file
8
web/app/components/version/version.js
Normal file
@@ -0,0 +1,8 @@
|
||||
'use strict';
|
||||
|
||||
angular.module('myApp.version', [
|
||||
'myApp.version.interpolate-filter',
|
||||
'myApp.version.version-directive'
|
||||
])
|
||||
|
||||
.value('version', '0.1');
|
||||
11
web/app/components/version/version_test.js
Normal file
11
web/app/components/version/version_test.js
Normal file
@@ -0,0 +1,11 @@
|
||||
'use strict';
|
||||
|
||||
describe('myApp.version module', function() {
|
||||
beforeEach(module('myApp.version'));
|
||||
|
||||
describe('version service', function() {
|
||||
it('should return current version', inject(function(version) {
|
||||
expect(version).toEqual('0.1');
|
||||
}));
|
||||
});
|
||||
});
|
||||
58
web/app/index-async.html
Normal file
58
web/app/index-async.html
Normal file
@@ -0,0 +1,58 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<link rel="stylesheet" href="bower_components/html5-boilerplate/css/normalize.css">
|
||||
<link rel="stylesheet" href="bower_components/html5-boilerplate/css/main.css">
|
||||
<style>
|
||||
[ng-cloak] {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
<script src="bower_components/html5-boilerplate/js/vendor/modernizr-2.6.2.min.js"></script>
|
||||
<script>
|
||||
// include angular loader, which allows the files to load in any order
|
||||
//@@NG_LOADER_START@@
|
||||
// You need to run `npm run update-index-async` to inject the angular async code here
|
||||
//@@NG_LOADER_END@@
|
||||
|
||||
// include a third-party async loader library
|
||||
/*!
|
||||
* $script.js v1.3
|
||||
* https://github.com/ded/script.js
|
||||
* Copyright: @ded & @fat - Dustin Diaz, Jacob Thornton 2011
|
||||
* Follow our software http://twitter.com/dedfat
|
||||
* License: MIT
|
||||
*/
|
||||
!function(a,b,c){function t(a,c){var e=b.createElement("script"),f=j;e.onload=e.onerror=e[o]=function(){e[m]&&!/^c|loade/.test(e[m])||f||(e.onload=e[o]=null,f=1,c())},e.async=1,e.src=a,d.insertBefore(e,d.firstChild)}function q(a,b){p(a,function(a){return!b(a)})}var d=b.getElementsByTagName("head")[0],e={},f={},g={},h={},i="string",j=!1,k="push",l="DOMContentLoaded",m="readyState",n="addEventListener",o="onreadystatechange",p=function(a,b){for(var c=0,d=a.length;c<d;++c)if(!b(a[c]))return j;return 1};!b[m]&&b[n]&&(b[n](l,function r(){b.removeEventListener(l,r,j),b[m]="complete"},j),b[m]="loading");var s=function(a,b,d){function o(){if(!--m){e[l]=1,j&&j();for(var a in g)p(a.split("|"),n)&&!q(g[a],n)&&(g[a]=[])}}function n(a){return a.call?a():e[a]}a=a[k]?a:[a];var i=b&&b.call,j=i?b:d,l=i?a.join(""):b,m=a.length;c(function(){q(a,function(a){h[a]?(l&&(f[l]=1),o()):(h[a]=1,l&&(f[l]=1),t(s.path?s.path+a+".js":a,o))})},0);return s};s.get=t,s.ready=function(a,b,c){a=a[k]?a:[a];var d=[];!q(a,function(a){e[a]||d[k](a)})&&p(a,function(a){return e[a]})?b():!function(a){g[a]=g[a]||[],g[a][k](b),c&&c(d)}(a.join("|"));return s};var u=a.$script;s.noConflict=function(){a.$script=u;return this},typeof module!="undefined"&&module.exports?module.exports=s:a.$script=s}(this,document,setTimeout)
|
||||
|
||||
// load all of the dependencies asynchronously.
|
||||
$script([
|
||||
'bower_components/angular/angular.js',
|
||||
'bower_components/angular-route/angular-route.js',
|
||||
'app.js',
|
||||
'view1/view1.js',
|
||||
'view2/view2.js',
|
||||
'components/version/version.js',
|
||||
'components/version/version-directive.js',
|
||||
'components/version/interpolate-filter.js'
|
||||
], function() {
|
||||
// when all is done, execute bootstrap angular application
|
||||
angular.bootstrap(document, ['myApp']);
|
||||
});
|
||||
</script>
|
||||
<title>My AngularJS App</title>
|
||||
<link rel="stylesheet" href="app.css">
|
||||
</head>
|
||||
<body ng-cloak>
|
||||
<ul class="menu">
|
||||
<li><a href="#!/view1">view1</a></li>
|
||||
<li><a href="#!/view2">view2</a></li>
|
||||
</ul>
|
||||
|
||||
<div ng-view></div>
|
||||
|
||||
<div>Angular seed app: v<span app-version></span></div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
63
web/app/index.html
Normal file
63
web/app/index.html
Normal file
@@ -0,0 +1,63 @@
|
||||
<!DOCTYPE html>
|
||||
<!--[if lt IE 7]> <html lang="en" ng-app="myApp" class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
|
||||
<!--[if IE 7]> <html lang="en" ng-app="myApp" class="no-js lt-ie9 lt-ie8"> <![endif]-->
|
||||
<!--[if IE 8]> <html lang="en" ng-app="myApp" class="no-js lt-ie9"> <![endif]-->
|
||||
<!--[if gt IE 8]><!--> <html lang="en" ng-app="myApp" class="no-js"> <!--<![endif]-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<title>GoCrpto Trader</title>
|
||||
<meta name="description" content="">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="stylesheet" href="/bower_components/html5-boilerplate/dist/css/normalize.css">
|
||||
<link rel="stylesheet" href="/bower_components/html5-boilerplate/dist/css/main.css">
|
||||
<link rel="stylesheet" href="/app.css">
|
||||
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css">
|
||||
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
|
||||
|
||||
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/js/bootstrap.min.js"></script>
|
||||
<script src="bower_components/html5-boilerplate/dist/js/vendor/modernizr-2.8.3.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<nav class="navbar navbar-default" role="navigation">
|
||||
<div class="container-fluid">
|
||||
|
||||
<div class="navbar-header">
|
||||
<a class="navbar-brand" href="/">
|
||||
GoCrypto Trader
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<ul class="nav navbar-nav">
|
||||
<li><a href="#!/">Dashboard</a></li>
|
||||
<li><a href="#!/about">About</a></li>
|
||||
</ul>
|
||||
<ul class="nav navbar-nav pull-right">
|
||||
<li class=""><a href="#!/settings">Settings</a></li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
|
||||
<!--[if lt IE 7]>
|
||||
<p class="browsehappy">You are using an <strong>outdated</strong> browser. Please <a href="http://browsehappy.com/">upgrade your browser</a> to improve your experience.</p>
|
||||
<![endif]-->
|
||||
|
||||
<div ng-view></div>
|
||||
|
||||
|
||||
<p class="text-center text-muted">Copyright 2016 GoCrypto Trader</p>
|
||||
<!-- In production use:
|
||||
<script src="//ajax.googleapis.com/ajax/libs/angularjs/x.x.x/angular.min.js"></script>
|
||||
-->
|
||||
<script src="/bower_components/angular/angular.js"></script>
|
||||
<script src="/bower_components/angular-route/angular-route.js"></script>
|
||||
<script src="/app.js"></script>
|
||||
<script src="/views/home/home.js"></script>
|
||||
<script src="/views/about/about.js"></script>
|
||||
<script src="/components/version/version.js"></script>
|
||||
<script src="/components/version/version-directive.js"></script>
|
||||
<script src="/components/version/interpolate-filter.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
179
web/app/views/about/about.html
Normal file
179
web/app/views/about/about.html
Normal file
@@ -0,0 +1,179 @@
|
||||
<div class="row">
|
||||
<div class="col-sm-8">
|
||||
|
||||
<div class="jumbotron">
|
||||
<div class="readme boxed-group clearfix announce instapaper_body md" id="readme">
|
||||
<h3>
|
||||
<svg width="16" viewBox="0 0 16 16" version="1.1" height="16" class="octicon octicon-book" aria-hidden="true"><path d="M3 5h4v1H3V5zm0 3h4V7H3v1zm0 2h4V9H3v1zm11-5h-4v1h4V5zm0 2h-4v1h4V7zm0 2h-4v1h4V9zm2-6v9c0 .55-.45 1-1 1H9.5l-1 1-1-1H2c-.55 0-1-.45-1-1V3c0-.55.45-1 1-1h5.5l1 1 1-1H15c.55 0 1 .45 1 1zm-8 .5L7.5 3H2v9h6V3.5zm7-.5H9.5l-.5.5V12h6V3z"/></svg>
|
||||
README.md
|
||||
</h3>
|
||||
|
||||
<article itemprop="text" class="markdown-body entry-content"><h2><a aria-hidden="true" href="#cryptocurrency-trading-bot-written-in-golang" class="anchor" id="user-content-cryptocurrency-trading-bot-written-in-golang"><svg width="16" viewBox="0 0 16 16" version="1.1" height="16" class="octicon octicon-link" aria-hidden="true"><path d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"/></svg></a>Cryptocurrency trading bot written in Golang</h2>
|
||||
|
||||
<p><a href="https://travis-ci.org/thrasher-/gocryptotrader"><img style="max-width:100%;" data-canonical-src="https://travis-ci.org/thrasher-/gocryptotrader.svg?branch=master" alt="Build Status" src="https://camo.githubusercontent.com/1e8eb47c187ffb439ae782f27635f82f93d08e1c/68747470733a2f2f7472617669732d63692e6f72672f74687261736865722d2f676f63727970746f7472616465722e7376673f6272616e63683d6d6173746572"></a>
|
||||
<a href="https://codecov.io/github/thrasher-/gocryptotrader?branch=master"><img style="max-width:100%;" data-canonical-src="https://codecov.io/github/thrasher-/gocryptotrader/coverage.svg?branch=master" alt="Test Coverage" src="https://camo.githubusercontent.com/c33fdbdc74ecbcef915afc325478cdf4a9317f01/68747470733a2f2f636f6465636f762e696f2f6769746875622f74687261736865722d2f676f63727970746f7472616465722f636f7665726167652e7376673f6272616e63683d6d6173746572"></a></p>
|
||||
|
||||
<p>A cryptocurrency trading bot supporting multiple exchanges written in Golang. </p>
|
||||
|
||||
<p><strong>Please note that this bot is under development and is not ready for production!</strong></p>
|
||||
|
||||
<h2><a aria-hidden="true" href="#exchange-support-table" class="anchor" id="user-content-exchange-support-table"><svg width="16" viewBox="0 0 16 16" version="1.1" height="16" class="octicon octicon-link" aria-hidden="true"><path d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"/></svg></a>Exchange Support Table</h2>
|
||||
|
||||
<table><thead>
|
||||
<tr>
|
||||
<th>Exchange</th>
|
||||
<th>REST API</th>
|
||||
<th>Streaming API</th>
|
||||
<th>FIX API</th>
|
||||
</tr>
|
||||
</thead><tbody>
|
||||
<tr>
|
||||
<td>Alphapoint</td>
|
||||
<td>Yes</td>
|
||||
<td>Yes</td>
|
||||
<td>NA</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>ANXPRO</td>
|
||||
<td>Yes</td>
|
||||
<td>No</td>
|
||||
<td>NA</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Bitfinex</td>
|
||||
<td>Yes</td>
|
||||
<td>Yes</td>
|
||||
<td>NA</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Bitstamp</td>
|
||||
<td>Yes</td>
|
||||
<td>Yes</td>
|
||||
<td>NA</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>BTCC</td>
|
||||
<td>Yes</td>
|
||||
<td>Yes</td>
|
||||
<td>No</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>BTCE</td>
|
||||
<td>Yes</td>
|
||||
<td>NA</td>
|
||||
<td>NA</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>BTCMarkets</td>
|
||||
<td>Yes</td>
|
||||
<td>NA</td>
|
||||
<td>NA</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Coinbase</td>
|
||||
<td>Yes</td>
|
||||
<td>Yes</td>
|
||||
<td>No</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Gemini</td>
|
||||
<td>Yes</td>
|
||||
<td>NA</td>
|
||||
<td>NA</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Huobi</td>
|
||||
<td>Yes</td>
|
||||
<td>Yes</td>
|
||||
<td>No</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>ItBit</td>
|
||||
<td>Yes</td>
|
||||
<td>NA</td>
|
||||
<td>NA</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Kraken</td>
|
||||
<td>Yes</td>
|
||||
<td>NA</td>
|
||||
<td>NA</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>LakeBTC</td>
|
||||
<td>Yes</td>
|
||||
<td>Yes</td>
|
||||
<td>NA</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>LocalBitcoins</td>
|
||||
<td>Yes</td>
|
||||
<td>NA</td>
|
||||
<td>NA</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>OKCoin (both)</td>
|
||||
<td>Yes</td>
|
||||
<td>Yes</td>
|
||||
<td>No</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Poloniex</td>
|
||||
<td>Yes</td>
|
||||
<td>Yes</td>
|
||||
<td>NA</td>
|
||||
</tr>
|
||||
</tbody></table>
|
||||
|
||||
<p>** NA means not applicable as the Exchange does not support the feature.</p>
|
||||
|
||||
<h2><a aria-hidden="true" href="#current-features" class="anchor" id="user-content-current-features"><svg width="16" viewBox="0 0 16 16" version="1.1" height="16" class="octicon octicon-link" aria-hidden="true"><path d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"/></svg></a>Current Features</h2>
|
||||
|
||||
<ul>
|
||||
<li>Support for all Exchange fiat and digital currencies, with the ability to individually toggle them on/off.</li>
|
||||
<li>REST API support for all exchanges.</li>
|
||||
<li>Websocket support for applicable exchanges.</li>
|
||||
<li>Ability to turn off/on certain exchanges.</li>
|
||||
<li>Ability to adjust manual polling timer for exchanges.</li>
|
||||
<li>SMS notification support via SMS Gateway.</li>
|
||||
<li>Basic event trigger system.</li>
|
||||
</ul>
|
||||
|
||||
<h2><a aria-hidden="true" href="#planned-features" class="anchor" id="user-content-planned-features"><svg width="16" viewBox="0 0 16 16" version="1.1" height="16" class="octicon octicon-link" aria-hidden="true"><path d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"/></svg></a>Planned Features</h2>
|
||||
|
||||
<ul>
|
||||
<li>WebGUI.</li>
|
||||
<li>FIX support.</li>
|
||||
<li>Expanding event trigger system.</li>
|
||||
<li>TALib.</li>
|
||||
<li>Trade history summary generation for tax purposes.</li>
|
||||
</ul>
|
||||
|
||||
<p>Please feel free to submit any pull requests or suggest any desired features to be added.</p>
|
||||
|
||||
<h2><a aria-hidden="true" href="#compiling-instructions" class="anchor" id="user-content-compiling-instructions"><svg width="16" viewBox="0 0 16 16" version="1.1" height="16" class="octicon octicon-link" aria-hidden="true"><path d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"/></svg></a>Compiling instructions</h2>
|
||||
|
||||
<p>Download Go from <a href="https://golang.org/dl/">https://golang.org/dl/</a><br>
|
||||
Using a terminal, type go get github.com/thrasher-/gocryptotrader<br>
|
||||
Change directory to the package directory, then type go install.<br>
|
||||
Copy config_example.json to config.json.<br>
|
||||
Make any neccessary changes to the config file.<br>
|
||||
Run the application! </p>
|
||||
|
||||
<h2><a aria-hidden="true" href="#binaries" class="anchor" id="user-content-binaries"><svg width="16" viewBox="0 0 16 16" version="1.1" height="16" class="octicon octicon-link" aria-hidden="true"><path d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"/></svg></a>Binaries</h2>
|
||||
|
||||
<p>Binaries will be published once the codebase reaches a stable condition.</p>
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="col-sm-4">
|
||||
|
||||
<div class="well">
|
||||
<h3>Look I'm A Sidebar!</h3>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
14
web/app/views/about/about.js
Normal file
14
web/app/views/about/about.js
Normal file
@@ -0,0 +1,14 @@
|
||||
'use strict';
|
||||
|
||||
angular.module('myApp.about', ['ngRoute'])
|
||||
|
||||
.config(['$routeProvider', function($routeProvider) {
|
||||
$routeProvider.when('/about', {
|
||||
templateUrl: '/views/about/about.html',
|
||||
controller: 'AboutController'
|
||||
});
|
||||
}])
|
||||
|
||||
.controller('AboutController', [function() {
|
||||
|
||||
}]);
|
||||
16
web/app/views/about/about_test.js
Normal file
16
web/app/views/about/about_test.js
Normal file
@@ -0,0 +1,16 @@
|
||||
'use strict';
|
||||
|
||||
describe('myApp.view2 module', function() {
|
||||
|
||||
beforeEach(module('myApp.view2'));
|
||||
|
||||
describe('view2 controller', function(){
|
||||
|
||||
it('should ....', inject(function($controller) {
|
||||
//spec body
|
||||
var view2Ctrl = $controller('View2Ctrl');
|
||||
expect(view2Ctrl).toBeDefined();
|
||||
}));
|
||||
|
||||
});
|
||||
});
|
||||
28
web/app/views/home/home.html
Normal file
28
web/app/views/home/home.html
Normal file
@@ -0,0 +1,28 @@
|
||||
<h2>Dashboard</h2>
|
||||
<h3>All enabled currencies</h3>
|
||||
<div ng-repeat="exchange in exchanges">
|
||||
<h4>{{exchange.exchangeName}}</h4>
|
||||
<table class="table table-striped">
|
||||
<tr>
|
||||
<th>Currency</th>
|
||||
<th>Last</th>
|
||||
<th>High</th>
|
||||
<th>Low</th>
|
||||
<th>Volume</th>
|
||||
<th>Bid</th>
|
||||
<th>Ask</th>
|
||||
</tr>
|
||||
<tr ng-repeat="value in exchange.exchangeValues">
|
||||
<td>{{value.CryptoCurrency}}</td>
|
||||
<td>{{value.Last}}</td>
|
||||
<td>{{value.High}}</td>
|
||||
<td>{{value.Low}}</td>
|
||||
<td>{{value.Volume}}</td>
|
||||
<td>{{value.Bid}}</td>
|
||||
<td>{{value.Ask}}</td>
|
||||
</tr>
|
||||
</table>
|
||||
<div ng-repeat="value in exchange.exchangeValues">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
28
web/app/views/home/home.js
Normal file
28
web/app/views/home/home.js
Normal file
@@ -0,0 +1,28 @@
|
||||
'use strict';
|
||||
|
||||
angular.module('myApp.home', ['ngRoute'])
|
||||
|
||||
.config(['$routeProvider', function($routeProvider) {
|
||||
$routeProvider.when('/', {
|
||||
templateUrl: '/views/home/home.html',
|
||||
controller: 'HomeController'
|
||||
});
|
||||
}])
|
||||
|
||||
.controller('HomeController', function ($scope, $http) {
|
||||
$scope.getDashboardData = function() {
|
||||
$http({
|
||||
method: 'GET',
|
||||
url: '/data/all-enabled-currencies'
|
||||
}).
|
||||
success(function (data, status, headers, config) {
|
||||
$scope.exchanges = data.data;
|
||||
}).
|
||||
error(function (data, status, headers, config) {
|
||||
console.log('error');
|
||||
});
|
||||
};
|
||||
|
||||
$scope.getDashboardData();
|
||||
|
||||
});
|
||||
16
web/app/views/home/home_test.js
Normal file
16
web/app/views/home/home_test.js
Normal file
@@ -0,0 +1,16 @@
|
||||
'use strict';
|
||||
|
||||
describe('myApp.view1 module', function() {
|
||||
|
||||
beforeEach(module('myApp.view1'));
|
||||
|
||||
describe('view1 controller', function(){
|
||||
|
||||
it('should ....', inject(function($controller) {
|
||||
//spec body
|
||||
var view1Ctrl = $controller('View1Ctrl');
|
||||
expect(view1Ctrl).toBeDefined();
|
||||
}));
|
||||
|
||||
});
|
||||
});
|
||||
15
web/bower.json
Normal file
15
web/bower.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"name": "angular-seed",
|
||||
"description": "A starter project for AngularJS",
|
||||
"version": "0.0.0",
|
||||
"homepage": "https://github.com/angular/angular-seed",
|
||||
"license": "MIT",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"angular": "~1.5.0",
|
||||
"angular-route": "~1.5.0",
|
||||
"angular-loader": "~1.5.0",
|
||||
"angular-mocks": "~1.5.0",
|
||||
"html5-boilerplate": "^5.3.0"
|
||||
}
|
||||
}
|
||||
22
web/e2e-tests/protractor.conf.js
Normal file
22
web/e2e-tests/protractor.conf.js
Normal file
@@ -0,0 +1,22 @@
|
||||
//jshint strict: false
|
||||
exports.config = {
|
||||
|
||||
allScriptsTimeout: 11000,
|
||||
|
||||
specs: [
|
||||
'*.js'
|
||||
],
|
||||
|
||||
capabilities: {
|
||||
'browserName': 'chrome'
|
||||
},
|
||||
|
||||
baseUrl: 'http://localhost:8000/',
|
||||
|
||||
framework: 'jasmine',
|
||||
|
||||
jasmineNodeOpts: {
|
||||
defaultTimeoutInterval: 30000
|
||||
}
|
||||
|
||||
};
|
||||
42
web/e2e-tests/scenarios.js
Normal file
42
web/e2e-tests/scenarios.js
Normal file
@@ -0,0 +1,42 @@
|
||||
'use strict';
|
||||
|
||||
/* https://github.com/angular/protractor/blob/master/docs/toc.md */
|
||||
|
||||
describe('my app', function() {
|
||||
|
||||
|
||||
it('should automatically redirect to /view1 when location hash/fragment is empty', function() {
|
||||
browser.get('index.html');
|
||||
expect(browser.getLocationAbsUrl()).toMatch("/view1");
|
||||
});
|
||||
|
||||
|
||||
describe('view1', function() {
|
||||
|
||||
beforeEach(function() {
|
||||
browser.get('index.html#!/view1');
|
||||
});
|
||||
|
||||
|
||||
it('should render view1 when user navigates to /view1', function() {
|
||||
expect(element.all(by.css('[ng-view] p')).first().getText()).
|
||||
toMatch(/partial for view 1/);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
describe('view2', function() {
|
||||
|
||||
beforeEach(function() {
|
||||
browser.get('index.html#!/view2');
|
||||
});
|
||||
|
||||
|
||||
it('should render view2 when user navigates to /view2', function() {
|
||||
expect(element.all(by.css('[ng-view] p')).first().getText()).
|
||||
toMatch(/partial for view 2/);
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
@@ -1,4 +0,0 @@
|
||||
{{define "footer"}}
|
||||
</body>
|
||||
</html>
|
||||
{{end}}
|
||||
@@ -1,15 +0,0 @@
|
||||
{{define "header"}}
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>{{.title}}</title>
|
||||
<!-- latest compiled and minified jquery -- >
|
||||
<script src="https://code.jquery.com/jquery-2.2.2.min.js" integrity="sha256-36cp2Co+/62rEAAYHLmRCPIych47CvdM+uTBJwSzWjI=" crossorigin="anonymous"></script>
|
||||
<!-- Latest compiled and minified CSS -->
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous">
|
||||
<!-- Latest compiled and minified JavaScript -->
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js" integrity="sha384-0mSbJDEHialfmuBBQP6A4Qrprq5OVfW37PRR3j5ELqxss1yVqOtnepnHVP9aJ7xS" crossorigin="anonymous"></script>
|
||||
</head>
|
||||
<body>
|
||||
{{end}}
|
||||
@@ -1,5 +0,0 @@
|
||||
{{template "header" .}}
|
||||
|
||||
<p>Index</p>
|
||||
|
||||
{{template "footer" .}}
|
||||
34
web/karma.conf.js
Normal file
34
web/karma.conf.js
Normal file
@@ -0,0 +1,34 @@
|
||||
//jshint strict: false
|
||||
module.exports = function(config) {
|
||||
config.set({
|
||||
|
||||
basePath: './app',
|
||||
|
||||
files: [
|
||||
'bower_components/angular/angular.js',
|
||||
'bower_components/angular-route/angular-route.js',
|
||||
'bower_components/angular-mocks/angular-mocks.js',
|
||||
'components/**/*.js',
|
||||
'view*/**/*.js'
|
||||
],
|
||||
|
||||
autoWatch: true,
|
||||
|
||||
frameworks: ['jasmine'],
|
||||
|
||||
browsers: ['Chrome'],
|
||||
|
||||
plugins: [
|
||||
'karma-chrome-launcher',
|
||||
'karma-firefox-launcher',
|
||||
'karma-jasmine',
|
||||
'karma-junit-reporter'
|
||||
],
|
||||
|
||||
junitReporter: {
|
||||
outputFile: 'test_out/unit.xml',
|
||||
suite: 'unit'
|
||||
}
|
||||
|
||||
});
|
||||
};
|
||||
38
web/package.json
Normal file
38
web/package.json
Normal file
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"name": "angular-seed",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"description": "A starter project for AngularJS",
|
||||
"repository": "https://github.com/angular/angular-seed",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"bower": "^1.7.7",
|
||||
"http-server": "^0.9.0",
|
||||
"jasmine-core": "^2.4.1",
|
||||
"karma": "^0.13.22",
|
||||
"karma-chrome-launcher": "^0.2.3",
|
||||
"karma-firefox-launcher": "^0.1.7",
|
||||
"karma-jasmine": "^0.3.8",
|
||||
"karma-junit-reporter": "^0.4.1",
|
||||
"protractor": "^3.2.2",
|
||||
"express" : "latest"
|
||||
},
|
||||
"scripts": {
|
||||
"postinstall": "bower install",
|
||||
|
||||
"prestart": "npm install",
|
||||
"start": "node server.js",
|
||||
|
||||
"pretest": "npm install",
|
||||
"test": "karma start karma.conf.js",
|
||||
"test-single-run": "karma start karma.conf.js --single-run",
|
||||
|
||||
"preupdate-webdriver": "npm install",
|
||||
"update-webdriver": "webdriver-manager update",
|
||||
|
||||
"preprotractor": "npm run update-webdriver",
|
||||
"protractor": "protractor e2e-tests/protractor.conf.js",
|
||||
|
||||
"update-index-async": "node -e \"var fs=require('fs'),indexFile='app/index-async.html',loaderFile='app/bower_components/angular-loader/angular-loader.min.js',loaderText=fs.readFileSync(loaderFile,'utf-8').split(/sourceMappingURL=angular-loader.min.js.map/).join('sourceMappingURL=bower_components/angular-loader/angular-loader.min.js.map'),indexText=fs.readFileSync(indexFile,'utf-8').split(/\\/\\/@@NG_LOADER_START@@[\\s\\S]*\\/\\/@@NG_LOADER_END@@/).join('//@@NG_LOADER_START@@\\n'+loaderText+' //@@NG_LOADER_END@@');fs.writeFileSync(indexFile,indexText);\""
|
||||
}
|
||||
}
|
||||
27
web/server.js
Normal file
27
web/server.js
Normal file
@@ -0,0 +1,27 @@
|
||||
var express = require('express')
|
||||
, app = express();
|
||||
var request = require('request');
|
||||
var path = __dirname + '/app/';
|
||||
|
||||
app.use("/bower_components", express.static(path + '/bower_components'));
|
||||
|
||||
app.get("/",function(req,res){
|
||||
res.sendFile(path + "index.html");
|
||||
});
|
||||
|
||||
app.use("/", express.static(path + '/'));
|
||||
|
||||
app.get('/data/all-enabled-currencies', function (req, res) {
|
||||
request({
|
||||
url :'http://localhost:9050/exchanges/enabled/latest/all'
|
||||
},function(err, resp, body){
|
||||
res.send(body);
|
||||
})
|
||||
|
||||
});
|
||||
|
||||
|
||||
|
||||
app.listen(80, function(){
|
||||
console.log('CORS-enabled web server listening on port 80');
|
||||
});
|
||||
54
webserver.go
54
webserver.go
@@ -1,54 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"html/template"
|
||||
"log"
|
||||
"net/http"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func GetWebserverHost() string {
|
||||
host := SplitStrings(bot.config.Webserver.ListenAddress, ":")[0]
|
||||
if host == "" {
|
||||
return "localhost"
|
||||
}
|
||||
return host
|
||||
}
|
||||
|
||||
func GetWebserverPort() int {
|
||||
portStr := SplitStrings(bot.config.Webserver.ListenAddress, ":")[1]
|
||||
port, _ := strconv.Atoi(portStr)
|
||||
return port
|
||||
}
|
||||
|
||||
func StartWebserver() error {
|
||||
http.HandleFunc("/", index)
|
||||
var err error
|
||||
go func() {
|
||||
err = http.ListenAndServe(bot.config.Webserver.ListenAddress, nil)
|
||||
}()
|
||||
return err
|
||||
}
|
||||
|
||||
func ServerHTTPError(w http.ResponseWriter, err error) {
|
||||
log.Println(err)
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
w.Header().Set("Content-Type", "text/plain; charset=utf-8")
|
||||
}
|
||||
|
||||
func index(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||
|
||||
tmpl, err := template.ParseFiles("web/index.html", "web/header.html", "web/footer.html")
|
||||
if err != nil {
|
||||
ServerHTTPError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
tmplValues := map[string]interface{}{"title": "Home"}
|
||||
tmpl.Execute(w, tmplValues)
|
||||
if err != nil {
|
||||
ServerHTTPError(w, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user