Merge branch 'master' into engine

This commit is contained in:
Adrian Gallagher
2019-06-21 18:10:55 +10:00
87 changed files with 5669 additions and 992 deletions

View File

@@ -2,12 +2,16 @@ package zb
import (
"fmt"
"net/http"
"testing"
"time"
"github.com/gorilla/websocket"
"github.com/thrasher-/gocryptotrader/common"
"github.com/thrasher-/gocryptotrader/config"
"github.com/thrasher-/gocryptotrader/currency"
exchange "github.com/thrasher-/gocryptotrader/exchanges"
"github.com/thrasher-/gocryptotrader/exchanges/sharedtestvalues"
)
// Please supply you own test keys here for due diligence testing.
@@ -18,6 +22,7 @@ const (
)
var z ZB
var wsSetupRan bool
func TestSetDefaults(t *testing.T) {
z.SetDefaults()
@@ -31,12 +36,35 @@ func TestSetup(t *testing.T) {
t.Error("Test Failed - ZB Setup() init error")
}
zbConfig.API.AuthenticatedSupport = true
zbConfig.API.AuthenticatedWebsocketSupport = true
zbConfig.API.Credentials.Key = apiKey
zbConfig.API.Credentials.Secret = apiSecret
z.Setup(zbConfig)
}
func setupWsAuth(t *testing.T) {
if wsSetupRan {
return
}
z.SetDefaults()
TestSetup(t)
if !z.Websocket.IsEnabled() && !z.API.AuthenticatedWebsocketSupport || !areTestAPIKeysSet() || !canManipulateRealOrders {
t.Skip(exchange.WebsocketNotEnabled)
}
var err error
var dialer websocket.Dialer
z.WebsocketConn, _, err = dialer.Dial(z.Websocket.GetWebsocketURL(),
http.Header{})
if err != nil {
t.Fatal(err)
}
z.Websocket.DataHandler = make(chan interface{}, 11)
z.Websocket.TrafficAlert = make(chan struct{}, 11)
go z.WsHandleData()
wsSetupRan = true
}
func TestSpotNewOrder(t *testing.T) {
t.Parallel()
@@ -462,3 +490,233 @@ func TestGetDepositAddress(t *testing.T) {
}
}
}
// TestZBInvalidJSON ZB sends poorly formed JSON. this tests the JSON fixer
// Then JSON decode it to test if successful
func TestZBInvalidJSON(t *testing.T) {
json := `{"success":true,"code":1000,"channel":"getSubUserList","message":"[{"isOpenApi":false,"memo":"Memo","userName":"hello@imgoodthanksandyou.com@good","userId":1337,"isFreez":false}]","no":"0"}`
fixedJSON := z.wsFixInvalidJSON([]byte(json))
var response WsGetSubUserListResponse
err := common.JSONDecode(fixedJSON, &response)
if err != nil {
t.Log(err)
}
if response.Message[0].UserID != 1337 {
t.Error("Expected extracted JSON USERID to equal 1337")
}
json = `{"success":true,"code":1000,"channel":"createSubUserKey","message":"{"apiKey":"thisisnotareallykeyyousillybilly","apiSecret":"lol"}","no":"14728151154382111746154"}`
fixedJSON = z.wsFixInvalidJSON([]byte(json))
var response2 WsRequestResponse
err = common.JSONDecode(fixedJSON, &response2)
if err != nil {
t.Log(err)
}
}
// TestWsTransferFunds ws test
func TestWsTransferFunds(t *testing.T) {
setupWsAuth(t)
err := z.wsDoTransferFunds(currency.BTC,
0.0001,
"username1",
"username2",
)
if err != nil {
t.Error(err)
}
timer := time.NewTimer(sharedtestvalues.WebsocketResponseDefaultTimeout)
select {
case resp := <-z.Websocket.DataHandler:
if resp.(WsRequestResponse).Code == 1002 || resp.(WsRequestResponse).Code == 1003 {
t.Error("Hash not calculated correctly")
}
case <-timer.C:
t.Error("Have not received a response")
}
timer.Stop()
}
// TestWsCreateSuUserKey ws test
func TestWsCreateSuUserKey(t *testing.T) {
setupWsAuth(t)
z.wsGetSubUserList()
timer := time.NewTimer(sharedtestvalues.WebsocketResponseDefaultTimeout)
var userID int64
select {
case resp := <-z.Websocket.DataHandler:
if len(resp.(WsGetSubUserListResponse).Message) == 0 {
t.Fatal("Expected a userID. Ensure you have made a subuserID before running this test")
}
userID = resp.(WsGetSubUserListResponse).Message[0].UserID
case <-timer.C:
t.Fatal("Have not received a response")
}
timer.Stop()
err := z.wsCreateSubUserKey(true, true, true, true, "subu", fmt.Sprintf("%v", userID))
if err != nil {
t.Error(err)
}
timer = time.NewTimer(sharedtestvalues.WebsocketResponseDefaultTimeout)
select {
case resp := <-z.Websocket.DataHandler:
if resp.(WsRequestResponse).Code == 1002 || resp.(WsRequestResponse).Code == 1003 {
t.Error("Hash not calculated correctly")
}
case <-timer.C:
t.Error("Have not received a response")
}
timer.Stop()
}
// TestGetSubUserList ws test
func TestGetSubUserList(t *testing.T) {
setupWsAuth(t)
err := z.wsGetSubUserList()
if err != nil {
t.Fatal(err)
}
timer := time.NewTimer(sharedtestvalues.WebsocketResponseDefaultTimeout)
select {
case resp := <-z.Websocket.DataHandler:
if resp.(WsGetSubUserListResponse).Code == 1002 || resp.(WsGetSubUserListResponse).Code == 1003 {
t.Error("Hash not calculated correctly")
}
case <-timer.C:
t.Error("Have not received a response")
}
timer.Stop()
}
// TestAddSubUser ws test
func TestAddSubUser(t *testing.T) {
setupWsAuth(t)
err := z.wsAddSubUser("abcde", "123456789101112aA!")
if err != nil {
t.Fatal(err)
}
timer := time.NewTimer(sharedtestvalues.WebsocketResponseDefaultTimeout)
select {
case resp := <-z.Websocket.DataHandler:
if resp.(WsRequestResponse).Code == 1002 || resp.(WsRequestResponse).Code == 1003 {
t.Error("Hash not calculated correctly")
}
case <-timer.C:
t.Error("Have not received a response")
}
timer.Stop()
}
// TestWsSubmitOrder ws test
func TestWsSubmitOrder(t *testing.T) {
setupWsAuth(t)
err := z.wsSubmitOrder(currency.NewPairWithDelimiter(currency.LTC.String(), currency.BTC.String(), "").Lower(), 1, 1, 1)
if err != nil {
t.Fatal(err)
}
timer := time.NewTimer(sharedtestvalues.WebsocketResponseDefaultTimeout)
select {
case resp := <-z.Websocket.DataHandler:
if resp.(WsSubmitOrderResponse).Code == 1002 || resp.(WsSubmitOrderResponse).Code == 1003 {
t.Error("Hash not calculated correctly")
}
case <-timer.C:
t.Error("Have not received a response")
}
timer.Stop()
}
// TestWsCancelOrder ws test
func TestWsCancelOrder(t *testing.T) {
setupWsAuth(t)
err := z.wsCancelOrder(currency.NewPairWithDelimiter(currency.LTC.String(), currency.BTC.String(), "").Lower(), 1234)
if err != nil {
t.Fatal(err)
}
timer := time.NewTimer(sharedtestvalues.WebsocketResponseDefaultTimeout)
select {
case resp := <-z.Websocket.DataHandler:
if resp.(WsCancelOrderResponse).Code == 1002 || resp.(WsCancelOrderResponse).Code == 1003 {
t.Error("Hash not calculated correctly")
}
case <-timer.C:
t.Error("Have not received a response")
}
timer.Stop()
}
// TestWsGetAccountInfo ws test
func TestWsGetAccountInfo(t *testing.T) {
setupWsAuth(t)
err := z.wsGetAccountInfoRequest()
if err != nil {
t.Fatal(err)
}
timer := time.NewTimer(sharedtestvalues.WebsocketResponseDefaultTimeout)
select {
case resp := <-z.Websocket.DataHandler:
if resp.(WsGetAccountInfoResponse).Code == 1002 || resp.(WsGetAccountInfoResponse).Code == 1003 {
t.Error("Hash not calculated correctly")
}
case <-timer.C:
t.Error("Have not received a response")
}
timer.Stop()
}
// TestWsGetOrder ws test
func TestWsGetOrder(t *testing.T) {
setupWsAuth(t)
err := z.wsGetOrder(currency.NewPairWithDelimiter(currency.LTC.String(), currency.BTC.String(), "").Lower(), 1234)
if err != nil {
t.Fatal(err)
}
timer := time.NewTimer(sharedtestvalues.WebsocketResponseDefaultTimeout)
select {
case resp := <-z.Websocket.DataHandler:
if resp.(WsGetOrderResponse).Code == 1002 || resp.(WsGetOrderResponse).Code == 1003 {
t.Error("Hash not calculated correctly")
}
case <-timer.C:
t.Error("Have not received a response")
}
timer.Stop()
}
// TestWsGetOrders ws test
func TestWsGetOrders(t *testing.T) {
setupWsAuth(t)
err := z.wsGetOrders(currency.NewPairWithDelimiter(currency.LTC.String(), currency.BTC.String(), "").Lower(), 1, 1)
if err != nil {
t.Fatal(err)
}
timer := time.NewTimer(sharedtestvalues.WebsocketResponseDefaultTimeout)
select {
case resp := <-z.Websocket.DataHandler:
if resp.(WsGetOrdersResponse).Code == 1002 || resp.(WsGetOrdersResponse).Code == 1003 {
t.Error("Hash not calculated correctly")
}
case <-timer.C:
t.Error("Have not received a response")
}
timer.Stop()
}
// TestWsGetOrdersIgnoreTradeType ws test
func TestWsGetOrdersIgnoreTradeType(t *testing.T) {
setupWsAuth(t)
err := z.wsGetOrdersIgnoreTradeType(currency.NewPairWithDelimiter(currency.LTC.String(), currency.BTC.String(), "").Lower(), 1, 1)
if err != nil {
t.Fatal(err)
}
timer := time.NewTimer(sharedtestvalues.WebsocketResponseDefaultTimeout)
select {
case resp := <-z.Websocket.DataHandler:
if resp.(WsGetOrdersResponse).Code == 1002 || resp.(WsGetOrdersResponse).Code == 1003 {
t.Error("Hash not calculated correctly")
}
case <-timer.C:
t.Error("Have not received a response")
}
timer.Stop()
}

View File

@@ -5,11 +5,13 @@ import (
"fmt"
"net/http"
"net/url"
"regexp"
"strings"
"time"
"github.com/gorilla/websocket"
"github.com/thrasher-/gocryptotrader/common"
"github.com/thrasher-/gocryptotrader/common/crypto"
"github.com/thrasher-/gocryptotrader/currency"
exchange "github.com/thrasher-/gocryptotrader/exchanges"
"github.com/thrasher-/gocryptotrader/exchanges/asset"
@@ -18,7 +20,8 @@ import (
)
const (
zbWebsocketAPI = "wss://api.zb.cn:9999/websocket"
zbWebsocketAPI = "wss://api.zb.cn:9999/websocket"
zWebsocketAddChannel = "addChannel"
)
// WsConnect initiates a websocket connection
@@ -82,9 +85,9 @@ func (z *ZB) WsHandleData() {
time.Sleep(time.Second)
continue
}
fixedJSON := z.wsFixInvalidJSON(resp.Raw)
var result Generic
err = common.JSONDecode(resp.Raw, &result)
err = common.JSONDecode(fixedJSON, &result)
if err != nil {
z.Websocket.DataHandler <- err
continue
@@ -108,7 +111,7 @@ func (z *ZB) WsHandleData() {
var ticker WsTicker
err := common.JSONDecode(resp.Raw, &ticker)
err := common.JSONDecode(fixedJSON, &ticker)
if err != nil {
z.Websocket.DataHandler <- err
continue
@@ -126,7 +129,7 @@ func (z *ZB) WsHandleData() {
case strings.Contains(result.Channel, "depth"):
var depth WsDepth
err := common.JSONDecode(resp.Raw, &depth)
err := common.JSONDecode(fixedJSON, &depth)
if err != nil {
z.Websocket.DataHandler <- err
continue
@@ -175,13 +178,16 @@ func (z *ZB) WsHandleData() {
case strings.Contains(result.Channel, "trades"):
var trades WsTrades
err := common.JSONDecode(resp.Raw, &trades)
err := common.JSONDecode(fixedJSON, &trades)
if err != nil {
z.Websocket.DataHandler <- err
continue
}
// Most up to date trade
if len(trades.Data) == 0 {
continue
}
t := trades.Data[len(trades.Data)-1]
channelInfo := strings.Split(result.Channel, "_")
@@ -197,7 +203,86 @@ func (z *ZB) WsHandleData() {
Amount: t.Amount,
Side: t.TradeType,
}
case strings.EqualFold(result.Channel, "addSubUser"):
var response WsRequestResponse
err := common.JSONDecode(fixedJSON, &response)
if err != nil {
z.Websocket.DataHandler <- err
continue
}
z.Websocket.DataHandler <- response
case strings.EqualFold(result.Channel, "getSubUserList"):
var response WsGetSubUserListResponse
err := common.JSONDecode(fixedJSON, &response)
if err != nil {
z.Websocket.DataHandler <- err
continue
}
z.Websocket.DataHandler <- response
case strings.EqualFold(result.Channel, "doTransferFunds"):
var response WsRequestResponse
err := common.JSONDecode(fixedJSON, &response)
if err != nil {
z.Websocket.DataHandler <- err
continue
}
z.Websocket.DataHandler <- response
case strings.EqualFold(result.Channel, "createSubUserKey"):
var response WsRequestResponse
err := common.JSONDecode(fixedJSON, &response)
if err != nil {
z.Websocket.DataHandler <- err
continue
}
z.Websocket.DataHandler <- response
case strings.Contains(result.Channel, "_order"):
var response WsSubmitOrderResponse
err := common.JSONDecode(fixedJSON, &response)
if err != nil {
z.Websocket.DataHandler <- err
continue
}
z.Websocket.DataHandler <- response
case strings.Contains(result.Channel, "_cancelorder"):
var response WsCancelOrderResponse
err := common.JSONDecode(fixedJSON, &response)
if err != nil {
z.Websocket.DataHandler <- err
continue
}
z.Websocket.DataHandler <- response
case strings.Contains(result.Channel, "_getorders"):
var response WsGetOrdersResponse
err := common.JSONDecode(fixedJSON, &response)
if err != nil {
z.Websocket.DataHandler <- err
continue
}
z.Websocket.DataHandler <- response
case strings.Contains(result.Channel, "_getorder"):
var response WsGetOrderResponse
err := common.JSONDecode(fixedJSON, &response)
if err != nil {
z.Websocket.DataHandler <- err
continue
}
z.Websocket.DataHandler <- response
case strings.Contains(result.Channel, "_getordersignoretradetype"):
var response WsGetOrdersIgnoreTradeTypeResponse
err := common.JSONDecode(fixedJSON, &response)
if err != nil {
z.Websocket.DataHandler <- err
continue
}
z.Websocket.DataHandler <- response
case strings.EqualFold(result.Channel, "getAccountInfo"):
var response WsGetAccountInfoResponse
err := common.JSONDecode(fixedJSON, &response)
if err != nil {
z.Websocket.DataHandler <- err
continue
}
z.Websocket.DataHandler <- response
default:
z.Websocket.DataHandler <- errors.New("zb_websocket.go error - unhandled websocket response")
continue
@@ -242,7 +327,7 @@ var wsErrCodes = map[int64]string{
// GenerateDefaultSubscriptions Adds default subscriptions to websocket to be handled by ManageSubscriptions()
func (z *ZB) GenerateDefaultSubscriptions() {
subscriptions := []exchange.WebsocketChannelSubscription{}
var subscriptions []exchange.WebsocketChannelSubscription
// Tickerdata is its own channel
subscriptions = append(subscriptions, exchange.WebsocketChannelSubscription{
Channel: "markets",
@@ -264,7 +349,7 @@ func (z *ZB) GenerateDefaultSubscriptions() {
// Subscribe sends a websocket message to receive data from the channel
func (z *ZB) Subscribe(channelToSubscribe exchange.WebsocketChannelSubscription) error {
subscriptionRequest := Subscription{
Event: "addChannel",
Event: zWebsocketAddChannel,
Channel: channelToSubscribe.Channel,
}
return z.wsSend(subscriptionRequest)
@@ -279,7 +364,198 @@ func (z *ZB) wsSend(data interface{}) error {
return err
}
if z.Verbose {
log.Debugf("%v sending message to websocket %v", z.Name, data)
log.Debugf("%v sending message to websocket %v", z.Name, string(json))
}
return z.WebsocketConn.WriteMessage(websocket.TextMessage, json)
}
func (z *ZB) wsAddSubUser(username, password string) error {
if !z.GetAuthenticatedAPISupport(exchange.WebsocketAuthentication) {
return fmt.Errorf("%v AuthenticatedWebsocketAPISupport not enabled", z.Name)
}
request := WsAddSubUserRequest{
Memo: "Memo",
Password: password,
SubUserName: username,
}
request.Channel = "addSubUser"
request.Event = zWebsocketAddChannel
request.Accesskey = z.API.Credentials.Key
request.Sign = z.wsGenerateSignature(request)
return z.wsSend(request)
}
func (z *ZB) wsGetSubUserList() error {
if !z.GetAuthenticatedAPISupport(exchange.WebsocketAuthentication) {
return fmt.Errorf("%v AuthenticatedWebsocketAPISupport not enabled", z.Name)
}
request := WsAuthenticatedRequest{}
request.Channel = "getSubUserList"
request.Event = zWebsocketAddChannel
request.Accesskey = z.API.Credentials.Key
request.Sign = z.wsGenerateSignature(request)
return z.wsSend(request)
}
func (z *ZB) wsDoTransferFunds(pair currency.Code, amount float64, fromUserName, toUserName string) error {
if !z.GetAuthenticatedAPISupport(exchange.WebsocketAuthentication) {
return fmt.Errorf("%v AuthenticatedWebsocketAPISupport not enabled", z.Name)
}
request := WsDoTransferFundsRequest{
Amount: amount,
Currency: pair,
FromUserName: fromUserName,
ToUserName: toUserName,
No: fmt.Sprintf("%v", time.Now().Unix()),
}
request.Channel = "doTransferFunds"
request.Event = zWebsocketAddChannel
request.Accesskey = z.API.Credentials.Key
request.Sign = z.wsGenerateSignature(request)
return z.wsSend(request)
}
func (z *ZB) wsCreateSubUserKey(assetPerm, entrustPerm, leverPerm, moneyPerm bool, keyName, toUserID string) error {
if !z.GetAuthenticatedAPISupport(exchange.WebsocketAuthentication) {
return fmt.Errorf("%v AuthenticatedWebsocketAPISupport not enabled", z.Name)
}
request := WsCreateSubUserKeyRequest{
AssetPerm: assetPerm,
EntrustPerm: entrustPerm,
KeyName: keyName,
LeverPerm: leverPerm,
MoneyPerm: moneyPerm,
No: fmt.Sprintf("%v", time.Now().Unix()),
ToUserID: toUserID,
}
request.Channel = "createSubUserKey"
request.Event = zWebsocketAddChannel
request.Accesskey = z.API.Credentials.Key
request.Sign = z.wsGenerateSignature(request)
return z.wsSend(request)
}
func (z *ZB) wsGenerateSignature(request interface{}) string {
jsonResponse, err := common.JSONEncode(request)
if err != nil {
log.Error(err)
}
hmac := crypto.GetHMAC(crypto.HashMD5,
jsonResponse,
[]byte(crypto.Sha1ToHex(z.API.Credentials.Secret)))
return fmt.Sprintf("%x", hmac)
}
func (z *ZB) wsFixInvalidJSON(json []byte) []byte {
invalidZbJSONRegex := `(\"\[|\"\{)(.*)(\]\"|\}\")`
regexChecker := regexp.MustCompile(invalidZbJSONRegex)
matchingResults := regexChecker.Find(json)
if matchingResults == nil {
return json
}
// Remove first quote character
capturedInvalidZBJSON := strings.Replace(string(matchingResults), "\"", "", 1)
// Remove last quote character
fixedJSON := capturedInvalidZBJSON[:len(capturedInvalidZBJSON)-1]
return []byte(strings.Replace(string(json), string(matchingResults), fixedJSON, 1))
}
func (z *ZB) wsSubmitOrder(pair currency.Pair, amount, price float64, tradeType int64) error {
if !z.GetAuthenticatedAPISupport(exchange.WebsocketAuthentication) {
return fmt.Errorf("%v AuthenticatedWebsocketAPISupport not enabled", z.Name)
}
request := WsSubmitOrderRequest{
Amount: amount,
Price: price,
TradeType: tradeType,
No: fmt.Sprintf("%v", time.Now().Unix()),
}
request.Channel = fmt.Sprintf("%v_order", pair.String())
request.Event = zWebsocketAddChannel
request.Accesskey = z.API.Credentials.Key
request.Sign = z.wsGenerateSignature(request)
return z.wsSend(request)
}
func (z *ZB) wsCancelOrder(pair currency.Pair, orderID int64) error {
if !z.GetAuthenticatedAPISupport(exchange.WebsocketAuthentication) {
return fmt.Errorf("%v AuthenticatedWebsocketAPISupport not enabled", z.Name)
}
request := WsCancelOrderRequest{
ID: orderID,
}
request.Channel = fmt.Sprintf("%v_cancelorder", pair.String())
request.Event = zWebsocketAddChannel
request.Accesskey = z.API.Credentials.Key
request.Sign = z.wsGenerateSignature(request)
return z.wsSend(request)
}
func (z *ZB) wsGetOrder(pair currency.Pair, orderID int64) error {
if !z.GetAuthenticatedAPISupport(exchange.WebsocketAuthentication) {
return fmt.Errorf("%v AuthenticatedWebsocketAPISupport not enabled", z.Name)
}
request := WsGetOrderRequest{
ID: orderID,
}
request.Channel = fmt.Sprintf("%v_getorder", pair.String())
request.Event = zWebsocketAddChannel
request.Accesskey = z.API.Credentials.Key
request.Sign = z.wsGenerateSignature(request)
return z.wsSend(request)
}
func (z *ZB) wsGetOrders(pair currency.Pair, pageIndex, tradeType int64) error {
if !z.GetAuthenticatedAPISupport(exchange.WebsocketAuthentication) {
return fmt.Errorf("%v AuthenticatedWebsocketAPISupport not enabled", z.Name)
}
request := WsGetOrdersRequest{
PageIndex: pageIndex,
TradeType: tradeType,
}
request.Channel = fmt.Sprintf("%v_getorders", pair.String())
request.Event = zWebsocketAddChannel
request.Accesskey = z.API.Credentials.Key
request.Sign = z.wsGenerateSignature(request)
return z.wsSend(request)
}
func (z *ZB) wsGetOrdersIgnoreTradeType(pair currency.Pair, pageIndex, pageSize int64) error {
if !z.GetAuthenticatedAPISupport(exchange.WebsocketAuthentication) {
return fmt.Errorf("%v AuthenticatedWebsocketAPISupport not enabled", z.Name)
}
request := WsGetOrdersIgnoreTradeTypeRequest{
PageIndex: pageIndex,
PageSize: pageSize,
}
request.Channel = fmt.Sprintf("%v_getordersignoretradetype", pair.String())
request.Event = zWebsocketAddChannel
request.Accesskey = z.API.Credentials.Key
request.Sign = z.wsGenerateSignature(request)
return z.wsSend(request)
}
func (z *ZB) wsGetAccountInfoRequest() error {
if !z.GetAuthenticatedAPISupport(exchange.WebsocketAuthentication) {
return fmt.Errorf("%v AuthenticatedWebsocketAPISupport not enabled", z.Name)
}
request := WsAuthenticatedRequest{
Channel: "getaccountinfo",
Event: zWebsocketAddChannel,
Accesskey: z.API.Credentials.Key,
No: fmt.Sprintf("%v", time.Now().Unix()),
}
request.Sign = z.wsGenerateSignature(request)
return z.wsSend(request)
}

View File

@@ -1,6 +1,10 @@
package zb
import "encoding/json"
import (
"encoding/json"
"github.com/thrasher-/gocryptotrader/currency"
)
// Subscription defines an initial subscription type to be sent
type Subscription struct {
@@ -13,7 +17,7 @@ type Generic struct {
Code int64 `json:"code"`
Success bool `json:"success"`
Channel string `json:"channel"`
Message string `json:"message"`
Message interface{} `json:"message"`
No string `json:"no"`
Data json.RawMessage `json:"data"`
}
@@ -55,3 +59,221 @@ type WsTrades struct {
TradeType string `json:"trade_type"`
} `json:"data"`
}
// WsAuthenticatedRequest base request type
type WsAuthenticatedRequest struct {
Accesskey string `json:"accesskey"`
Channel string `json:"channel"`
Event string `json:"event"`
No string `json:"no,omitempty"`
Sign string `json:"sign,omitempty"`
}
// WsAddSubUserRequest data to add sub users
type WsAddSubUserRequest struct {
Accesskey string `json:"accesskey"`
Channel string `json:"channel"`
Event string `json:"event"`
Sign string `json:"sign,omitempty"`
Memo string `json:"memo"`
Password string `json:"password"`
SubUserName string `json:"subUserName"`
}
// WsCreateSubUserKeyRequest data to add sub user keys
type WsCreateSubUserKeyRequest struct {
Accesskey string `json:"accesskey"`
AssetPerm bool `json:"assetPerm,string"`
Channel string `json:"channel"`
EntrustPerm bool `json:"entrustPerm,string"`
Event string `json:"event"`
KeyName string `json:"keyName"`
LeverPerm bool `json:"leverPerm,string"`
MoneyPerm bool `json:"moneyPerm,string"`
No string `json:"no"`
Sign string `json:"sign,omitempty"`
ToUserID string `json:"toUserId"`
}
// WsDoTransferFundsRequest data to transfer funds
type WsDoTransferFundsRequest struct {
Accesskey string `json:"accesskey"`
Amount float64 `json:"amount,string"`
Channel string `json:"channel"`
Currency currency.Code `json:"currency"`
Event string `json:"event"`
FromUserName string `json:"fromUserName"`
No string `json:"no"`
Sign string `json:"sign,omitempty"`
ToUserName string `json:"toUserName"`
}
// WsGetSubUserListResponse data response from GetSubUserList
type WsGetSubUserListResponse struct {
Success bool `json:"success"`
Code int64 `json:"code"`
Channel string `json:"channel"`
Message []WsGetSubUserListResponseData `json:"message"`
No string `json:"no"`
}
// WsGetSubUserListResponseData user data
type WsGetSubUserListResponseData struct {
IsOpenAPI bool `json:"isOpenApi,omitempty"`
Memo string `json:"memo,omitempty"`
UserName string `json:"userName,omitempty"`
UserID int64 `json:"userId,omitempty"`
IsFreez bool `json:"isFreez,omitempty"`
}
// WsRequestResponse generic response data
type WsRequestResponse struct {
Success bool `json:"success"`
Code int64 `json:"code"`
Channel string `json:"channel"`
Message interface{} `json:"message"`
No string `json:"no"`
}
// WsSubmitOrderRequest creates an order via ws
type WsSubmitOrderRequest struct {
Accesskey string `json:"accesskey"`
Amount float64 `json:"amount,string"`
Channel string `json:"channel"`
Event string `json:"event"`
No string `json:"no,omitempty"`
Price float64 `json:"price,string"`
Sign string `json:"sign,omitempty"`
TradeType int64 `json:"tradeType,string"`
}
// WsSubmitOrderResponse data about submitted order
type WsSubmitOrderResponse struct {
Message string `json:"message"`
No string `json:"no"`
Data struct {
EntrustID int64 `json:"intrustID"`
} `json:"data"`
Code int64 `json:"code"`
Channel string `json:"channel"`
Success bool `json:"success"`
}
// WsCancelOrderRequest order cancel request
type WsCancelOrderRequest struct {
Accesskey string `json:"accesskey"`
Channel string `json:"channel"`
Event string `json:"event"`
ID int64 `json:"id"`
Sign string `json:"sign,omitempty"`
}
// WsCancelOrderResponse order cancel response
type WsCancelOrderResponse struct {
Message string `json:"message"`
No string `json:"no"`
Code int64 `json:"code"`
Channel string `json:"channel"`
Success bool `json:"success"`
}
// WsGetOrderRequest Get specific order details
type WsGetOrderRequest struct {
Accesskey string `json:"accesskey"`
Channel string `json:"channel"`
Event string `json:"event"`
ID int64 `json:"id"`
Sign string `json:"sign,omitempty"`
}
// WsGetOrderResponse contains order data
type WsGetOrderResponse struct {
Message string `json:"message"`
No string `json:"no"`
Code int64 `json:"code"`
Channel string `json:"channel"`
Success bool `json:"success"`
Data WsGetOrderResponseData `json:"data"`
}
// WsGetOrderResponseData Detailed order data
type WsGetOrderResponseData struct {
Currency string `json:"currency"`
Fees float64 `json:"fees"`
ID string `json:"id"`
Price float64 `json:"price"`
Status int64 `json:"status"`
TotalAmount float64 `json:"total_amount"`
TradeAmount float64 `json:"trade_amount"`
TradePrice float64 `json:"trade_price"`
TradeDate int64 `json:"trade_date"`
TradeMoney float64 `json:"trade_money"`
Type int64 `json:"type"`
}
// WsGetOrdersRequest get more orders, with no orderID filtering
type WsGetOrdersRequest struct {
Accesskey string `json:"accesskey"`
Channel string `json:"channel"`
Event string `json:"event"`
PageIndex int64 `json:"pageIndex"`
TradeType int64 `json:"tradeType"`
Sign string `json:"sign,omitempty"`
}
// WsGetOrdersResponse contains orders data
type WsGetOrdersResponse struct {
Message string `json:"message"`
No string `json:"no"`
Code int64 `json:"code"`
Channel string `json:"channel"`
Success bool `json:"success"`
Data []WsGetOrderResponseData `json:"data"`
}
// WsGetOrdersIgnoreTradeTypeRequest ws request
type WsGetOrdersIgnoreTradeTypeRequest struct {
Accesskey string `json:"accesskey"`
Channel string `json:"channel"`
Event string `json:"event"`
ID int64 `json:"id"`
PageIndex int64 `json:"pageIndex"`
PageSize int64 `json:"pageSize"`
Sign string `json:"sign,omitempty"`
}
// WsGetOrdersIgnoreTradeTypeResponse contains orders data
type WsGetOrdersIgnoreTradeTypeResponse struct {
Message string `json:"message"`
No string `json:"no"`
Code int64 `json:"code"`
Channel string `json:"channel"`
Success bool `json:"success"`
Data []WsGetOrderResponseData `json:"data"`
}
// WsGetAccountInfoResponse contains account data
type WsGetAccountInfoResponse struct {
Message string `json:"message"`
No string `json:"no"`
Data struct {
Coins []struct {
Freez float64 `json:"freez,string"`
EnName string `json:"enName"`
UnitDecimal int `json:"unitDecimal"`
CnName string `json:"cnName"`
UnitTag string `json:"unitTag"`
Available float64 `json:"available,string"`
Key string `json:"key"`
} `json:"coins"`
Base struct {
Username string `json:"username"`
TradePasswordEnabled bool `json:"trade_password_enabled"`
AuthGoogleEnabled bool `json:"auth_google_enabled"`
AuthMobileEnabled bool `json:"auth_mobile_enabled"`
} `json:"base"`
} `json:"data"`
Code int `json:"code"`
Channel string `json:"channel"`
Success bool `json:"success"`
}

View File

@@ -541,3 +541,13 @@ func (z *ZB) SubscribeToWebsocketChannels(channels []exchange.WebsocketChannelSu
func (z *ZB) UnsubscribeToWebsocketChannels(channels []exchange.WebsocketChannelSubscription) error {
return common.ErrFunctionNotSupported
}
// GetSubscriptions returns a copied list of subscriptions
func (z *ZB) GetSubscriptions() ([]exchange.WebsocketChannelSubscription, error) {
return z.Websocket.GetSubscriptions(), nil
}
// AuthenticateWebsocket sends an authentication message to the websocket
func (z *ZB) AuthenticateWebsocket() error {
return common.ErrFunctionNotSupported
}