package main import ( "crypto/sha256" "encoding/hex" "errors" "fmt" "log" "net" "net/http" "strconv" gws "github.com/gorilla/websocket" "github.com/thrasher-corp/gocryptotrader/common" "github.com/thrasher-corp/gocryptotrader/config" "github.com/thrasher-corp/gocryptotrader/encoding/json" "github.com/thrasher-corp/gocryptotrader/exchanges/asset" ) // Vars for the websocket client var ( WSConn *gws.Conn ) // WebsocketEvent is the struct used for websocket events type WebsocketEvent struct { Exchange string `json:"exchange,omitempty"` AssetType string `json:"assetType,omitempty"` Event string Data any } // 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 any `json:"data"` Error string `json:"error"` } // WebsocketOrderbookTickerRequest is a struct used for ticker and orderbook // requests type WebsocketOrderbookTickerRequest struct { Exchange string `json:"exchangeName"` Currency string `json:"currency"` AssetType asset.Item `json:"assetType"` } // SendWebsocketEvent sends a websocket event message func SendWebsocketEvent(event string, reqData any, result *WebsocketEventResponse) error { req := WebsocketEvent{ Event: event, } if reqData != nil { req.Data = reqData } 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.File, true) if err != nil { log.Fatalf("Failed to load config file: %s", err) } listenAddr := cfg.RemoteControl.WebsocketRPC.ListenAddress wsHost := fmt.Sprintf("ws://%s/ws", net.JoinHostPort(common.ExtractHostOrDefault(listenAddr), strconv.Itoa(common.ExtractPortOrDefault(listenAddr)))) log.Printf("Connecting to websocket host: %s", wsHost) var dialer gws.Dialer var resp *http.Response WSConn, resp, err = dialer.Dial(wsHost, http.Header{}) if err != nil { log.Println("Unable to connect to websocket server") return } resp.Body.Close() log.Println("Connected to websocket!") log.Println("Authenticating..") shasum := sha256.Sum256([]byte(cfg.RemoteControl.Password)) reqData := WebsocketAuth{ Username: cfg.RemoteControl.Username, Password: hex.EncodeToString(shasum[:]), } var wsResp WebsocketEventResponse err = SendWebsocketEvent("auth", reqData, &wsResp) if err != nil { log.Fatal(err) } log.Println("Authenticated successfully") log.Println("Getting config..") err = SendWebsocketEvent("GetConfig", nil, &wsResp) if err != nil { log.Fatal(err) } log.Printf("Fetched config.") dataJSON, err := json.Marshal(&wsResp.Data) if err != nil { log.Fatal(err) } var resultCfg config.Config err = json.Unmarshal(dataJSON, &resultCfg) if err != nil { log.Fatal(err) } log.Println("Saving config..") origBotName := resultCfg.Name resultCfg.Name = "TEST" err = SendWebsocketEvent("SaveConfig", resultCfg, &wsResp) if err != nil { log.Fatal(err) } 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..") err = SendWebsocketEvent("GetAccountInfo", nil, &wsResp) if err != nil { log.Fatal(err) } log.Println("Got account info!") log.Println("Getting tickers..") err = SendWebsocketEvent("GetTickers", nil, &wsResp) if err != nil { log.Fatal(err) } log.Println("Got tickers!") log.Println("Getting specific ticker..") dataReq := WebsocketOrderbookTickerRequest{ Exchange: "Bitfinex", Currency: "BTCUSD", AssetType: asset.Spot, } err = SendWebsocketEvent("GetTicker", dataReq, &wsResp) if err != nil { log.Fatal(err) } log.Println("Got ticker!") log.Println("Getting orderbooks..") err = SendWebsocketEvent("GetOrderbooks", nil, &wsResp) if err != nil { log.Fatal(err) } log.Println("Got orderbooks!") log.Println("Getting specific orderbook..") err = SendWebsocketEvent("GetOrderbook", dataReq, &wsResp) if err != nil { log.Fatal(err) } log.Println("Got orderbook!") for { var wsEvent WebsocketEvent err = WSConn.ReadJSON(&wsEvent) if err != nil { break } log.Printf("Recv'd: %s", wsEvent.Event) } WSConn.Close() }