diff --git a/anxhttp.go b/anxhttp.go index 73021984..840e52cc 100644 --- a/anxhttp.go +++ b/anxhttp.go @@ -85,8 +85,8 @@ type ANXTicker struct { Last ANXTickerComponent `json:"last"` Buy ANXTickerComponent `json:"buy"` Sell ANXTickerComponent `json:"sell"` - Now float64 `json:"now"` - UpdateTime float64 `json:"dataUpdateTime"` + Now string `json:"now"` + UpdateTime string `json:"dataUpdateTime"` } `json:"data"` } diff --git a/btcchttp.go b/btcchttp.go index 2a07d085..860e28d6 100644 --- a/btcchttp.go +++ b/btcchttp.go @@ -241,10 +241,12 @@ func (b *BTCC) Run() { for b.Enabled { for _, x := range b.EnabledPairs { + currency := x go func() { - currency := x + log.Println(currency) ticker, err := b.GetTickerPrice(StringToLower(currency)) if err != nil { + log.Println(err) return } log.Printf("BTCC %s: Last %f High %f Low %f Volume %f\n", currency, ticker.Last, ticker.High, ticker.Low, ticker.Volume) diff --git a/common.go b/common.go index 47c255c6..e7fbc4be 100644 --- a/common.go +++ b/common.go @@ -253,6 +253,7 @@ func SendHTTPGetRequest(url string, jsonDecode bool, result interface{}) (err er err := JSONDecode(contents, &result) if err != nil { + log.Println(url) return err } } else { diff --git a/config_example.dat b/config_example.dat index d2bf8d1b..efd88e30 100644 --- a/config_example.dat +++ b/config_example.dat @@ -209,13 +209,13 @@ "APIKey": "Key", "APISecret": "Secret", "ClientID": "", - "AvailablePairs": "XBTEUR,XBTUSD,XBTCAD,XBTGBP,XBTJPY,LTCEUR,LTCUSD,LTCCAD,ETHXBT,ETHEUR,ETHUSD,ETHCAD,ETHGBP,ETHJPY,XBTLTC,XBTNMC,XBTXDG,XBTXLM,XBTXRP", - "EnabledPairs": "XBTEUR,XBTUSD,XBTCAD,XBTGBP,XBTJPY,LTCEUR,LTCUSD,LTCCAD,ETHXBT,ETHEUR,ETHUSD,ETHCAD,ETHGBP,ETHJPY,XBTLTC,XBTNMC,XBTXDG,XBTXLM,XBTXRP", + "AvailablePairs": "ETCUSD,ICNETH,REPXBT,ZECXBT,ETHXBT,ETHXBT.d,ETHGBP,LTCXBT,XBTGBP.d,XDGXBT,XMRUSD,ZECUSD,ETCETH,ETHJPY,XBTCAD.d,XBTJPY.d,XBTUSD.d,XLMXBT,XLMEUR,XLMUSD,XMREUR,ETCXBT,ETHCAD.d,ETHEUR.d,ETHJPY.d,XBTEUR.d,ETHEUR,ETHGBP.d,ICNXBT,LTCEUR,REPEUR,XBTGBP,XBTJPY,ETHUSD,ETHUSD.d,LTCUSD,REPETH,XBTUSD,XMRXBT,ETCEUR,ETHCAD,REPUSD,XBTCAD,XBTEUR,XRPXBT,ZECEUR", + "EnabledPairs": "ETCUSD,XBTUSD,ETHUSD", "BaseCurrencies": "EUR,USD,CAD,GBP,JPY" }, { "Name": "LakeBTC", - "Enabled": false, + "Enabled": true, "Verbose": false, "Websocket": false, "RESTPollingDelay": 10, @@ -223,9 +223,9 @@ "APIKey": "Key", "APISecret": "Secret", "ClientID": "", - "AvailablePairs": "BTCUSD,BTCCNY", - "EnabledPairs": "BTCUSD,BTCCNY", - "BaseCurrencies": "USD,CNY,SEK" + "AvailablePairs": "BTCUSD,BTCEUR,USDHKD,AUDUSD,BTCGBP,BTCNZD,USDJPY,BTCSGD,BTCNGN,EURUSD,USDSGD,NZDUSD,USDNGN,USDCHF,BTCJPY,BTCAUD,BTCCAD,BTCCHF,GBPUSD,USDCAD", + "EnabledPairs": "BTCUSD,BTCAUD", + "BaseCurrencies": "USD,EUR,HKD,AUD,GBP,NZD,JPY,SGD,NGN,CHF,CAD" }, { "Name": "LocalBitcoins", diff --git a/itbithttp.go b/itbithttp.go index 1b0da489..33a5f7d6 100644 --- a/itbithttp.go +++ b/itbithttp.go @@ -157,6 +157,7 @@ func (i *ItBit) GetTickerPrice(currency string) (TickerPrice, error) { tickerPrice.Bid = ticker.Bid tickerPrice.FirstCurrency = currency[0:3] tickerPrice.SecondCurrency = currency[3:] + tickerPrice.Last = ticker.LastPrice tickerPrice.High = ticker.High24h tickerPrice.Low = ticker.Low24h tickerPrice.Volume = ticker.Volume24h diff --git a/kraken.go b/kraken.go index e1f7f048..1a167870 100644 --- a/kraken.go +++ b/kraken.go @@ -117,6 +117,27 @@ func (k *Kraken) Run() { log.Printf("%s %d currencies enabled: %s.\n", k.GetName(), len(k.EnabledPairs), k.EnabledPairs) } + assetPairs, err := k.GetAssetPairs() + if err != nil { + log.Printf("%s Failed to get available symbols.\n", k.GetName()) + } else { + var exchangeProducts []string + for _, v := range assetPairs { + exchangeProducts = append(exchangeProducts, v.Altname) + } + diff := StringSliceDifference(k.AvailablePairs, exchangeProducts) + if len(diff) > 0 { + exch, err := GetExchangeConfig(k.Name) + if err != nil { + log.Println(err) + } else { + log.Printf("%s Updating available pairs. Difference: %s.\n", k.Name, diff) + exch.AvailablePairs = JoinStrings(exchangeProducts, ",") + UpdateExchangeConfig(exch) + } + } + } + for k.Enabled { err := k.GetTicker(JoinStrings(k.EnabledPairs, ",")) if err != nil { @@ -158,17 +179,40 @@ func (k *Kraken) GetAssets() error { return nil } -func (k *Kraken) GetAssetPairs() error { - var result interface{} - path := fmt.Sprintf("%s/%s/public/%s", KRAKEN_API_URL, KRAKEN_API_VERSION, KRAKEN_ASSET_PAIRS) - err := SendHTTPGetRequest(path, true, &result) +type KrakenAssetPairs struct { + Altname string `json:"altname"` + AclassBase string `json:"aclass_base"` + Base string `json:"base"` + AclassQuote string `json:"aclass_quote"` + Quote string `json:"quote"` + Lot string `json:"lot"` + PairDecimals int `json:"pair_decimals"` + LotDecimals int `json:"lot_decimals"` + LotMultiplier int `json:"lot_multiplier"` + LeverageBuy []int `json:"leverage_buy"` + LeverageSell []int `json:"leverage_sell"` + Fees [][]float64 `json:"fees"` + FeesMaker [][]float64 `json:"fees_maker"` + FeeVolumeCurrency string `json:"fee_volume_currency"` + MarginCall int `json:"margin_call"` + MarginStop int `json:"margin_stop"` +} - if err != nil { - return err +func (k *Kraken) GetAssetPairs() (map[string]KrakenAssetPairs, error) { + type Response struct { + Result map[string]KrakenAssetPairs `json:"result"` + Error []interface{} `json:"error"` } - log.Println(result) - return nil + response := Response{} + path := fmt.Sprintf("%s/%s/public/%s", KRAKEN_API_URL, KRAKEN_API_VERSION, KRAKEN_ASSET_PAIRS) + err := SendHTTPGetRequest(path, true, &response) + + if err != nil { + return nil, err + } + + return response.Result, nil } type KrakenTicker struct { diff --git a/lakebtchttp.go b/lakebtchttp.go index 18732a12..7d4c2091 100644 --- a/lakebtchttp.go +++ b/lakebtchttp.go @@ -10,8 +10,8 @@ import ( ) const ( - LAKEBTC_API_URL = "https://www.LakeBTC.com/api_v1/" - LAKEBTC_API_VERSION = "1" + LAKEBTC_API_URL = "https://api.lakebtc.com/api_v2/" + LAKEBTC_API_VERSION = "2" LAKEBTC_TICKER = "ticker" LAKEBTC_ORDERBOOK = "bcorderbook" LAKEBTC_ORDERBOOK_CNY = "bcorderbook_cny" @@ -52,11 +52,6 @@ type LakeBTCOrderbook struct { Asks [][]float64 `json:"bids"` } -type LakeBTCTickerResponse struct { - USD LakeBTCTicker - CNY LakeBTCTicker -} - func (l *LakeBTC) SetDefaults() { l.Name = "LakeBTC" l.Enabled = false @@ -128,36 +123,63 @@ func (l *LakeBTC) Run() { } for l.Enabled { - ticker, err := l.GetTickerPrice("BTCUSD") - if err != nil { - log.Println(err) - return - } - ticker, err = l.GetTickerPrice("BTCCNY") - if err != nil { - log.Println(err) - return - } for _, x := range l.EnabledPairs { - if x == "BTCUSD" { - log.Printf("LakeBTC BTC USD: Last %f High %f Low %f Volume %f\n", ticker.Last, ticker.High, ticker.Low, ticker.Volume) - AddExchangeInfo(l.GetName(), x[0:3], x[3:], ticker.Last, ticker.Volume) - } else if x == "BTCCNY" { - log.Printf("LakeBTC BTC CNY: Last %f High %f Low %f Volume %f\n", ticker.Last, ticker.High, ticker.Low, ticker.Volume) - AddExchangeInfo(l.GetName(), x[0:3], x[3:], ticker.Last, ticker.Volume) + ticker, err := l.GetTickerPrice(x) + if err != nil { + log.Println(err) + continue } + log.Printf("LakeBTC BTC %s: Last %f High %f Low %f Volume %f\n", x[3:], ticker.Last, ticker.High, ticker.Low, ticker.Volume) + AddExchangeInfo(l.GetName(), x[0:3], x[3:], ticker.Last, ticker.Volume) } time.Sleep(time.Second * l.RESTPollingDelay) } } -func (l *LakeBTC) GetTicker() (LakeBTCTickerResponse, error) { - response := LakeBTCTickerResponse{} +/* Silly hack due to API returning null instead of strings */ +type LakeBTCTickerResponse struct { + Last interface{} + Bid interface{} + Ask interface{} + High interface{} + Low interface{} + Volume interface{} +} + +func (l *LakeBTC) GetTicker() (map[string]LakeBTCTicker, error) { + response := make(map[string]LakeBTCTickerResponse) err := SendHTTPGetRequest(LAKEBTC_API_URL+LAKEBTC_TICKER, true, &response) if err != nil { - return response, err + return nil, err } - return response, nil + result := make(map[string]LakeBTCTicker) + + var addresses []string + for k, v := range response { + var ticker LakeBTCTicker + key := StringToUpper(k) + if v.Ask != nil { + ticker.Ask, _ = strconv.ParseFloat(v.Ask.(string), 64) + } + if v.Bid != nil { + ticker.Bid, _ = strconv.ParseFloat(v.Bid.(string), 64) + } + if v.High != nil { + ticker.High, _ = strconv.ParseFloat(v.High.(string), 64) + } + if v.Last != nil { + ticker.Last, _ = strconv.ParseFloat(v.Last.(string), 64) + } + if v.Low != nil { + ticker.Low, _ = strconv.ParseFloat(v.Low.(string), 64) + } + if v.Volume != nil { + ticker.Volume, _ = strconv.ParseFloat(v.Volume.(string), 64) + } + result[key] = ticker + addresses = append(addresses, key) + } + return result, nil } func (l *LakeBTC) GetTickerPrice(currency string) (TickerPrice, error) { @@ -166,28 +188,23 @@ func (l *LakeBTC) GetTickerPrice(currency string) (TickerPrice, error) { return tickerNew, nil } - var tickerPrice TickerPrice ticker, err := l.GetTicker() if err != nil { - return tickerPrice, err + return TickerPrice{}, err } - if currency == "USD" { - tickerPrice.Ask = ticker.USD.Ask - tickerPrice.Bid = ticker.USD.Bid - tickerPrice.Volume = ticker.USD.Volume - tickerPrice.High = ticker.USD.High - tickerPrice.Low = ticker.USD.Low - tickerPrice.Last = ticker.USD.Last - } else if currency == "CNY" { - tickerPrice.Ask = ticker.CNY.Ask - tickerPrice.Bid = ticker.CNY.Bid - tickerPrice.Volume = ticker.CNY.Volume - tickerPrice.High = ticker.CNY.High - tickerPrice.Low = ticker.CNY.Low - tickerPrice.Last = ticker.CNY.Last + result, ok := ticker[currency] + if !ok { + return TickerPrice{}, err } + var tickerPrice TickerPrice + tickerPrice.Ask = result.Ask + tickerPrice.Bid = result.Bid + tickerPrice.Volume = result.Volume + tickerPrice.High = result.High + tickerPrice.Low = result.Low + tickerPrice.Last = result.Last tickerPrice.FirstCurrency = currency[0:3] tickerPrice.SecondCurrency = currency[3:] ProcessTicker(l.GetName(), tickerPrice.FirstCurrency, tickerPrice.SecondCurrency, tickerPrice) diff --git a/lakebtcwebsocket.go b/lakebtcwebsocket.go index cd0f3a1d..c91fd45b 100644 --- a/lakebtcwebsocket.go +++ b/lakebtcwebsocket.go @@ -7,6 +7,10 @@ import ( "net/http" ) +type LakeBTCWebsocketTickerResponse struct { + Blah float64 +} + const ( LAKEBTC_WEBSOCKET_URL = "wss://www.LakeBTC.com/websocket" ) diff --git a/localbitcoinshttp.go b/localbitcoinshttp.go index 01cea9df..feeac26d 100644 --- a/localbitcoinshttp.go +++ b/localbitcoinshttp.go @@ -97,18 +97,18 @@ func (l *LocalBitcoins) Run() { } for l.Enabled { - ticker, err := l.GetTickerPrice("BTCUSD") - - if err != nil { - log.Println(err) - goto sleep - } for _, x := range l.EnabledPairs { currency := x[3:] + ticker, err := l.GetTickerPrice("BTC" + currency) + + if err != nil { + log.Println(err) + return + } + log.Printf("LocalBitcoins BTC %s: Last %f Volume %f\n", currency, ticker.Last, ticker.Volume) AddExchangeInfo(l.GetName(), x[0:3], x[3:], ticker.Last, ticker.Volume) } - sleep: time.Sleep(time.Second * l.RESTPollingDelay) } } @@ -119,9 +119,9 @@ func (l *LocalBitcoins) SetAPIKeys(apiKey, apiSecret string) { } type LocalBitcoinsTicker struct { - Avg12h float64 `json:"avg_12h"` - Avg1h float64 `json:"avg_1h"` - Avg24h float64 `json:"avg_24h"` + Avg12h float64 `json:"avg_12h,string"` + Avg1h float64 `json:"avg_1h,string"` + Avg24h float64 `json:"avg_24h,string"` Rates struct { Last float64 `json:"last,string"` } `json:"rates"` @@ -145,16 +145,19 @@ func (l *LocalBitcoins) GetTickerPrice(currency string) (TickerPrice, error) { return tickerNew, nil } - var tickerPrice TickerPrice ticker, err := l.GetTicker() if err != nil { - return tickerPrice, err + return TickerPrice{}, err + } + + var tickerPrice TickerPrice + for key, value := range ticker { + tickerPrice.Last = value.Rates.Last + tickerPrice.FirstCurrency = currency[0:3] + tickerPrice.SecondCurrency = key + tickerPrice.Volume = value.VolumeBTC + ProcessTicker(l.GetName(), tickerPrice.FirstCurrency, tickerPrice.SecondCurrency, tickerPrice) } - tickerPrice.Ask = ticker[currency].Rates.Last - tickerPrice.FirstCurrency = currency[0:3] - tickerPrice.SecondCurrency = currency[3:] - tickerPrice.Volume = ticker[currency].VolumeBTC - ProcessTicker(l.GetName(), tickerPrice.FirstCurrency, tickerPrice.SecondCurrency, tickerPrice) return tickerPrice, nil }