Link up websocket handler to routes after refactor and various improvements

This commit is contained in:
Adrian Gallagher
2017-09-11 09:07:41 +10:00
parent 0682dcec88
commit 6e9bda83a1
9 changed files with 148 additions and 169 deletions

View File

@@ -54,6 +54,16 @@ func Add(exchange string, p pair.CurrencyPair, assetType string, price, volume f
return
}
if p.FirstCurrency == "XBT" {
newPair := pair.NewCurrencyPair("BTC", p.SecondCurrency.String())
Append(exchange, newPair, assetType, price, volume)
}
if p.SecondCurrency == "USDT" {
newPair := pair.NewCurrencyPair(p.FirstCurrency.String(), "USD")
Append(exchange, newPair, assetType, price, volume)
}
Append(exchange, p, assetType, price, volume)
}

View File

@@ -114,6 +114,20 @@ func TestAdd(t *testing.T) {
if len(Items) != 1 {
t.Error("Test Failed - stats Add did not add exchange info.")
}
p.FirstCurrency = "XBT"
Add("ANX", p, "SPOT", 1201, 43)
if Items[1].Pair.Pair() != "XBTUSD" {
t.Fatal("Test failed. stats Add did not add exchange info.")
}
p = pair.NewCurrencyPair("ETH", "USDT")
Add("ANX", p, "SPOT", 300, 1000)
if Items[2].Pair.Pair() != "ETHUSD" {
t.Fatal("Test failed. stats Add did not add exchange info.")
}
}
func TestAppend(t *testing.T) {

View File

@@ -4,11 +4,10 @@ import (
"errors"
"fmt"
"github.com/thrasher-/gocryptotrader/exchanges/stats"
"github.com/thrasher-/gocryptotrader/currency/pair"
exchange "github.com/thrasher-/gocryptotrader/exchanges"
"github.com/thrasher-/gocryptotrader/exchanges/orderbook"
"github.com/thrasher-/gocryptotrader/exchanges/stats"
"github.com/thrasher-/gocryptotrader/exchanges/ticker"
)

12
main.go
View File

@@ -299,9 +299,15 @@ func SeedExchangeAccountInfo(data []exchange.AccountInfo) {
currencyName)
port.RemoveExchangeAddress(exchangeName, currencyName)
} else {
log.Printf("Portfolio: Updating %s %s entry with balance %f.\n",
exchangeName, currencyName, total)
port.UpdateExchangeAddressBalance(exchangeName, currencyName, total)
balance, ok := port.GetAddressBalance(exchangeName, currencyName, portfolio.PortfolioAddressExchange)
if !ok {
continue
}
if balance != total {
log.Printf("Portfolio: Updating %s %s entry with balance %f.\n",
exchangeName, currencyName, total)
port.UpdateExchangeAddressBalance(exchangeName, currencyName, total)
}
}
}
}

View File

@@ -108,10 +108,12 @@ func GetCryptoIDAddress(address string, coinType string) (float64, error) {
}
// GetAddressBalance acceses the portfolio base and returns the balance by passed
// in address
func (p *Base) GetAddressBalance(address string) (float64, bool) {
// in address, coin type and description
func (p *Base) GetAddressBalance(address, coinType, description string) (float64, bool) {
for x := range p.Addresses {
if p.Addresses[x].Address == address {
if p.Addresses[x].Address == address &&
p.Addresses[x].Description == description &&
p.Addresses[x].CoinType == coinType {
return p.Addresses[x].Balance, true
}
}

View File

@@ -49,12 +49,12 @@ func TestGetAddressBalance(t *testing.T) {
portfolio := Base{}
portfolio.AddAddress(ltcAddress, ltc, description, balance)
addBalance, _ := portfolio.GetAddressBalance("LdP8Qox1VAhCzLJNqrr74YovaWYyNBUWvL")
addBalance, _ := portfolio.GetAddressBalance("LdP8Qox1VAhCzLJNqrr74YovaWYyNBUWvL", ltc, description)
if addBalance != balance {
t.Error("Test Failed - Portfolio GetAddressBalance() Error: Incorrect value")
}
addBalance, found := portfolio.GetAddressBalance("WigWham")
addBalance, found := portfolio.GetAddressBalance("WigWham", ltc, description)
if addBalance != 0 {
t.Error("Test Failed - Portfolio GetAddressBalance() Error: Incorrect value")
}

View File

@@ -46,6 +46,12 @@ func NewRouter(exchanges []exchange.IBotExchange) *mux.Router {
router := mux.NewRouter().StrictSlash(true)
routes = Routes{
Route{
"",
"GET",
"/",
getIndex,
},
Route{
"GetAllSettings",
"GET",
@@ -94,6 +100,12 @@ func NewRouter(exchanges []exchange.IBotExchange) *mux.Router {
"/exchanges/{exchangeName}/orderbook/latest/{currency}",
RESTGetOrderbook,
},
Route{
"ws",
"GET",
"/ws",
WebsocketClientHandler,
},
}
for _, route := range routes {
@@ -114,13 +126,3 @@ func getIndex(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, "<html>GoCryptoTrader RESTful interface. For the web GUI, please visit the <a href=https://github.com/thrasher-/gocryptotrader/blob/master/web/README.md>web GUI readme.</a></html>")
w.WriteHeader(http.StatusOK)
}
// IndexRoute maps the index route to the getIndex function
var IndexRoute = Routes{
Route{
"",
"GET",
"/",
getIndex,
},
}

View File

@@ -1,116 +1,114 @@
package main
import (
"errors"
"fmt"
"log"
"net/http"
"time"
"github.com/gorilla/websocket"
"github.com/thrasher-/gocryptotrader/common"
"github.com/thrasher-/gocryptotrader/config"
)
// Vars for the websocket client
var (
WSConn *websocket.Conn
)
// WebsocketEvent is the struct used for websocket events
type WebsocketEvent struct {
Event string `json:"event"`
Data interface{} `json:"data"`
Exchange string `json:"exchange,omitempty"`
Exchange string `json:"exchange,omitempty"`
AssetType string `json:"assetType,omitempty"`
Event string
Data interface{}
}
// WebsocketAuth is the struct used for a websocket auth request
type WebsocketAuth struct {
Username string `json:"username"`
Password string `json:"password"`
}
// WebsocketEventResponse is the struct used for websocket event responses
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"`
// WebsocketOrderbookTickerRequest is a struct used for ticker and orderbook
// requests
type WebsocketOrderbookTickerRequest struct {
Exchange string `json:"exchangeName"`
Currency string `json:"currency"`
AssetType string `json:"assetType"`
}
func SendWebsocketAuth(username, password string) error {
pwHash := common.HexEncodeToString(common.GetSHA256([]byte(password)))
// SendWebsocketEvent sends a websocket event message
func SendWebsocketEvent(event string, reqData interface{}, result *WebsocketEventResponse) error {
req := WebsocketEvent{
Event: "auth",
Data: WebsocketAuth{
Username: username,
Password: pwHash,
},
Event: event,
}
return SendWebsocketMsg(req)
}
func SendWebsocketMsg(data interface{}) error {
return WSConn.WriteJSON(data)
}
func GetWebsocketTicker(currency string) error {
wsevt := WebsocketEvent{
Event: "ticker",
Data: currency,
if reqData != nil {
req.Data = reqData
}
return SendWebsocketMsg(wsevt)
err := WSConn.WriteJSON(req)
if err != nil {
return err
}
err = WSConn.ReadJSON(&result)
if err != nil {
return err
}
if result.Error != "" {
return errors.New(result.Error)
}
return nil
}
func main() {
cfg := config.GetConfig()
err := cfg.LoadConfig(config.ConfigFile)
if err != nil {
log.Fatalf("Failed to load config file: %s", err)
}
listenAddr := cfg.Webserver.ListenAddress
wsHost := fmt.Sprintf("ws://%s:%d/ws", common.ExtractHost(listenAddr),
common.ExtractPort(listenAddr))
log.Printf("Connecting to websocket host: %s", wsHost)
var Dialer websocket.Dialer
var err error
WSConn, _, err = Dialer.Dial("ws://localhost:9050/ws", http.Header{})
WSConn, _, err = Dialer.Dial(wsHost, http.Header{})
if err != nil {
log.Println("Unable to connect to websocket server")
return
}
log.Println("Connected to websocket!")
log.Println("Authenticating..")
SendWebsocketAuth("blah", "blah")
var wsResp WebsocketEventResponse
err = WSConn.ReadJSON(&wsResp)
reqData := WebsocketAuth{
Username: cfg.Webserver.AdminUsername,
Password: common.HexEncodeToString(common.GetSHA256([]byte(cfg.Webserver.AdminPassword))),
}
err = SendWebsocketEvent("auth", reqData, &wsResp)
if err != nil {
log.Println(err)
return
log.Fatal(err)
}
if wsResp.Error != "" {
log.Fatal(wsResp.Error)
}
log.Println("Authenticated successfully")
log.Println("Getting config..")
req := WebsocketEvent{
Event: "GetConfig",
}
err = WSConn.WriteJSON(req)
err = SendWebsocketEvent("GetConfig", nil, &wsResp)
if err != nil {
log.Println(err)
return
log.Fatal(err)
}
err = WSConn.ReadJSON(&wsResp)
if err != nil {
log.Println(err)
return
}
if wsResp.Error != "" {
log.Fatal(wsResp.Error)
}
log.Printf("Fetched config.")
dataJSON, err := common.JSONEncode(&wsResp.Data)
@@ -124,112 +122,70 @@ func main() {
log.Fatal(err)
}
resultCfg.Name = "TEST"
req = WebsocketEvent{
Event: "SaveConfig",
Data: resultCfg,
}
log.Println("Saving config..")
err = WSConn.WriteJSON(req)
origBotName := resultCfg.Name
resultCfg.Name = "TEST"
err = SendWebsocketEvent("SaveConfig", resultCfg, &wsResp)
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!")
resultCfg.Name = origBotName
err = SendWebsocketEvent("SaveConfig", resultCfg, &wsResp)
if err != nil {
log.Fatal(err)
}
log.Println("Saved config (restored original bot name)!")
log.Println("Getting account info..")
req = WebsocketEvent{
Event: "GetAccountInfo",
}
err = WSConn.WriteJSON(req)
err = SendWebsocketEvent("GetAccountInfo", nil, &wsResp)
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.Fatal(err)
}
log.Println("Got account info!")
log.Println("Getting tickers..")
req = WebsocketEvent{
Event: "GetTickers",
}
err = WSConn.WriteJSON(req)
err = SendWebsocketEvent("GetTickers", nil, &wsResp)
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.Fatal(err)
}
log.Println("Got tickers!")
log.Println("Getting specific ticker..")
var tickReq WebsocketTickerRequest
tickReq.Currency = "LTCUSD"
tickReq.Exchange = "Bitfinex"
req = WebsocketEvent{
Event: "GetTicker",
Data: tickReq,
dataReq := WebsocketOrderbookTickerRequest{
Exchange: "Bitfinex",
Currency: "BTCUSD",
AssetType: "SPOT",
}
err = WSConn.WriteJSON(req)
err = SendWebsocketEvent("GetTicker", dataReq, &wsResp)
if err != nil {
log.Println(err)
return
log.Fatal(err)
}
log.Println("Got ticker!")
err = WSConn.ReadJSON(&wsResp)
log.Println("Getting orderbooks..")
err = SendWebsocketEvent("GetOrderbooks", nil, &wsResp)
if err != nil {
log.Println(err)
return
log.Fatal(err)
}
log.Println("Got orderbooks!")
if wsResp.Error != "" {
log.Fatal(wsResp.Error)
log.Println("Getting specific orderbook..")
err = SendWebsocketEvent("GetOrderbook", dataReq, &wsResp)
if err != nil {
log.Fatal(err)
}
log.Println(wsResp)
log.Println("Got orderbook!")
for {
msgType, resp, err := WSConn.ReadMessage()
var wsEvent WebsocketEventResponse
err = WSConn.ReadJSON(&wsEvent)
if err != nil {
log.Fatal(err)
break
}
log.Println(msgType)
log.Println(string(resp))
log.Printf("Recv'd: %s", wsEvent.Event)
}
time.Sleep(time.Second * 10)
WSConn.Close()
}

View File

@@ -17,16 +17,6 @@ const (
WebsocketResponseSuccess = "OK"
)
// WebsocketRoutes adds ws route to the HTTP server
var WebsocketRoutes = Routes{
Route{
"ws",
"GET",
"/ws",
WebsocketClientHandler,
},
}
// WebsocketClient stores information related to the websocket client
type WebsocketClient struct {
ID int
@@ -304,7 +294,7 @@ func WebsocketHandler() {
log.Println(err)
continue
}
hashPW := common.HexEncodeToString(common.GetSHA256([]byte(bot.config.Webserver.AdminUsername)))
hashPW := common.HexEncodeToString(common.GetSHA256([]byte(bot.config.Webserver.AdminPassword)))
if auth.Username == bot.config.Webserver.AdminUsername && auth.Password == hashPW {
WebsocketClientHub[x].Authenticated = true
wsResp := WebsocketEventResponse{