mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-05-13 23:16:45 +00:00
Link up websocket handler to routes after refactor and various improvements
This commit is contained in:
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
12
main.go
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
12
websocket.go
12
websocket.go
@@ -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{
|
||||
|
||||
Reference in New Issue
Block a user