mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-05-20 23:16:49 +00:00
websocket: Remove GenerateMessageID (#2008)
* Exchanges: Remove example BespokeGenerateMessageID * Okx: Replace conn.RequestIDGenerator with MesssageID Continued overall direction to remove the closed-loop of e => conn => e roundtrip for message ids * Exchanges: Add MessageSequence This method removes the either/or nature of message id generation. We don't tie the message ids to connections, or to anything. Consumers just call whichever they want, or even combine them as they want. Anything more complicated will need a separate installation anyway * GateIO: Split usage of MessageID and MessageSequence * Binance: Switch to UUID message IDs * Kraken: Switch to e.MessageSequence * Kucoin: Switch to MessageID * HitBTC: Switch to UUIDv7 for ws message ID * Bybit: Switch to UUIDv7 for ws message ID * Bitfinex: Switch to UUIDv7 and MessageSequence Tested CID - It accepts 53 bits only for an int, so MessageSequence makes sense. Can't use MessageID * Websocket: Remove now unused MessageID function Moved all MessageID usage into funcs and onto base methods, to remove the closed loop of message IDs * Docs: Update guidance for message signatures
This commit is contained in:
@@ -1998,7 +1998,7 @@ func TestSubscribe(t *testing.T) {
|
||||
var req WsPayload
|
||||
require.NoError(tb, json.Unmarshal(msg, &req), "Unmarshal must not error")
|
||||
require.ElementsMatch(tb, req.Params, exp, "Params must have correct channels")
|
||||
return w.WriteMessage(gws.TextMessage, fmt.Appendf(nil, `{"result":null,"id":%d}`, req.ID))
|
||||
return w.WriteMessage(gws.TextMessage, fmt.Appendf(nil, `{"result":null,"id":"%s"}`, req.ID))
|
||||
}
|
||||
e = testexch.MockWsInstance[Exchange](t, mockws.CurryWsMockUpgrader(t, mock))
|
||||
} else {
|
||||
@@ -2020,7 +2020,7 @@ func TestSubscribeBadResp(t *testing.T) {
|
||||
var req WsPayload
|
||||
err := json.Unmarshal(msg, &req)
|
||||
require.NoError(tb, err, "Unmarshal must not error")
|
||||
return w.WriteMessage(gws.TextMessage, fmt.Appendf(nil, `{"result":{"error":"carrots"},"id":%d}`, req.ID))
|
||||
return w.WriteMessage(gws.TextMessage, fmt.Appendf(nil, `{"result":{"error":"carrots"},"id":"%s"}`, req.ID))
|
||||
}
|
||||
b := testexch.MockWsInstance[Exchange](t, mockws.CurryWsMockUpgrader(t, mock))
|
||||
err := b.Subscribe(channels)
|
||||
|
||||
@@ -837,7 +837,7 @@ type WsListStatusData struct {
|
||||
type WsPayload struct {
|
||||
Method string `json:"method"`
|
||||
Params []string `json:"params"`
|
||||
ID int64 `json:"id"`
|
||||
ID string `json:"id"`
|
||||
}
|
||||
|
||||
// CrossMarginInterestData stores cross margin data for borrowing
|
||||
|
||||
@@ -166,7 +166,7 @@ func (e *Exchange) wsReadData() {
|
||||
}
|
||||
|
||||
func (e *Exchange) wsHandleData(respRaw []byte) error {
|
||||
if id, err := jsonparser.GetInt(respRaw, "id"); err == nil {
|
||||
if id, err := jsonparser.GetString(respRaw, "id"); err == nil {
|
||||
if e.Websocket.Match.IncomingWithData(id, respRaw) {
|
||||
return nil
|
||||
}
|
||||
@@ -570,7 +570,7 @@ func (e *Exchange) manageSubs(ctx context.Context, op string, subs subscription.
|
||||
}
|
||||
|
||||
req := WsPayload{
|
||||
ID: e.Websocket.Conn.GenerateMessageID(false),
|
||||
ID: e.MessageID(),
|
||||
Method: op,
|
||||
Params: subs.QualifiedChannels(),
|
||||
}
|
||||
|
||||
@@ -1716,7 +1716,7 @@ func (e *Exchange) subscribeToChan(ctx context.Context, subs subscription.List)
|
||||
|
||||
// subId is a single round-trip identifier that provides linking sub requests to chanIDs
|
||||
// Although docs only mention subId for wsBookChannel, it works for all chans
|
||||
subID := strconv.FormatInt(e.Websocket.Conn.GenerateMessageID(false), 10)
|
||||
subID := e.MessageID()
|
||||
req["subId"] = subID
|
||||
|
||||
// Add a temporary Key so we can find this Sub when we get the resp without delay or context switch
|
||||
@@ -1829,7 +1829,7 @@ func (e *Exchange) WsSendAuth(ctx context.Context) error {
|
||||
|
||||
// WsNewOrder authenticated new order request
|
||||
func (e *Exchange) WsNewOrder(ctx context.Context, data *WsNewOrderRequest) (string, error) {
|
||||
data.CustomID = e.Websocket.AuthConn.GenerateMessageID(false)
|
||||
data.CustomID = e.MessageSequence()
|
||||
req := makeRequestInterface(wsOrderNew, data)
|
||||
resp, err := e.Websocket.AuthConn.SendMessageReturnResponse(ctx, request.Unset, data.CustomID, req)
|
||||
if err != nil {
|
||||
|
||||
@@ -29,8 +29,7 @@ import (
|
||||
type Exchange struct {
|
||||
exchange.Base
|
||||
|
||||
messageIDSeq common.Counter
|
||||
account accountTypeHolder
|
||||
account accountTypeHolder
|
||||
}
|
||||
|
||||
const (
|
||||
|
||||
@@ -2936,7 +2936,6 @@ type FixtureConnection struct {
|
||||
websocket.Connection
|
||||
}
|
||||
|
||||
func (d *FixtureConnection) GenerateMessageID(bool) int64 { return 1337 }
|
||||
func (d *FixtureConnection) SetupPingHandler(request.EndpointLimit, websocket.PingHandler) {}
|
||||
func (d *FixtureConnection) Dial(context.Context, *gws.Dialer, http.Header) error { return d.dialError }
|
||||
|
||||
|
||||
@@ -102,7 +102,7 @@ func (e *Exchange) WsConnect(ctx context.Context, conn websocket.Connection) err
|
||||
// WebsocketAuthenticatePrivateConnection sends an authentication message to the private websocket for inbound account
|
||||
// data
|
||||
func (e *Exchange) WebsocketAuthenticatePrivateConnection(ctx context.Context, conn websocket.Connection) error {
|
||||
req, err := e.GetAuthenticationPayload(ctx, strconv.FormatInt(conn.GenerateMessageID(false), 10))
|
||||
req, err := e.GetAuthenticationPayload(ctx, e.MessageID())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -170,7 +170,7 @@ func (e *Exchange) GetAuthenticationPayload(ctx context.Context, requestID strin
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (e *Exchange) handleSubscriptions(conn websocket.Connection, operation string, subs subscription.List) (args []SubscriptionArgument, err error) {
|
||||
func (e *Exchange) handleSubscriptions(_ websocket.Connection, operation string, subs subscription.List) (args []SubscriptionArgument, err error) {
|
||||
subs, err = subs.ExpandTemplates(e)
|
||||
if err != nil {
|
||||
return
|
||||
@@ -181,7 +181,7 @@ func (e *Exchange) handleSubscriptions(conn websocket.Connection, operation stri
|
||||
args = append(args, SubscriptionArgument{
|
||||
auth: b[0].Authenticated,
|
||||
Operation: operation,
|
||||
RequestID: strconv.FormatInt(conn.GenerateMessageID(false), 10),
|
||||
RequestID: e.MessageID(),
|
||||
Arguments: b.QualifiedChannels(),
|
||||
associatedSubs: b,
|
||||
})
|
||||
@@ -719,7 +719,7 @@ func hasPotentialDelimiter(a asset.Item) bool {
|
||||
|
||||
// TODO: Remove this function when template expansion is across all assets
|
||||
func (e *Exchange) submitDirectSubscription(ctx context.Context, conn websocket.Connection, a asset.Item, operation string, channelsToSubscribe subscription.List) error {
|
||||
payloads, err := e.directSubscriptionPayload(conn, a, operation, channelsToSubscribe)
|
||||
payloads, err := e.directSubscriptionPayload(a, operation, channelsToSubscribe)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -757,17 +757,17 @@ func (e *Exchange) submitDirectSubscription(ctx context.Context, conn websocket.
|
||||
}
|
||||
|
||||
// TODO: Remove this function when template expansion is across all assets
|
||||
func (e *Exchange) directSubscriptionPayload(conn websocket.Connection, assetType asset.Item, operation string, channelsToSubscribe subscription.List) ([]SubscriptionArgument, error) {
|
||||
func (e *Exchange) directSubscriptionPayload(assetType asset.Item, operation string, channelsToSubscribe subscription.List) ([]SubscriptionArgument, error) {
|
||||
var args []SubscriptionArgument
|
||||
arg := SubscriptionArgument{
|
||||
Operation: operation,
|
||||
RequestID: strconv.FormatInt(conn.GenerateMessageID(false), 10),
|
||||
RequestID: e.MessageID(),
|
||||
Arguments: []string{},
|
||||
}
|
||||
authArg := SubscriptionArgument{
|
||||
auth: true,
|
||||
Operation: operation,
|
||||
RequestID: strconv.FormatInt(conn.GenerateMessageID(false), 10),
|
||||
RequestID: e.MessageID(),
|
||||
Arguments: []string{},
|
||||
}
|
||||
|
||||
@@ -812,7 +812,7 @@ func (e *Exchange) directSubscriptionPayload(conn websocket.Connection, assetTyp
|
||||
args = append(args, arg)
|
||||
arg = SubscriptionArgument{
|
||||
Operation: operation,
|
||||
RequestID: strconv.FormatInt(conn.GenerateMessageID(false), 10),
|
||||
RequestID: e.MessageID(),
|
||||
Arguments: []string{},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,9 +75,6 @@ func (e *Exchange) sendWebsocketTradeRequest(ctx context.Context, op, orderLinkI
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tn := time.Now()
|
||||
requestID := strconv.FormatInt(outbound.GenerateMessageID(false), 10)
|
||||
|
||||
// Set up a listener to wait for the response to come back from the inbound connection. The request is sent through
|
||||
// the outbound trade connection, the response can come back through the inbound private connection before the
|
||||
// outbound connection sends its acknowledgement.
|
||||
@@ -86,9 +83,10 @@ func (e *Exchange) sendWebsocketTradeRequest(ctx context.Context, op, orderLinkI
|
||||
return nil, err
|
||||
}
|
||||
|
||||
requestID := e.MessageID()
|
||||
outResp, err := outbound.SendMessageReturnResponse(ctx, limit, requestID, WebsocketGeneralPayload{
|
||||
RequestID: requestID,
|
||||
Header: map[string]string{"X-BAPI-TIMESTAMP": strconv.FormatInt(tn.UnixMilli(), 10)},
|
||||
Header: map[string]string{"X-BAPI-TIMESTAMP": strconv.FormatInt(time.Now().UnixMilli(), 10)},
|
||||
Operation: op,
|
||||
Arguments: []any{payload},
|
||||
})
|
||||
|
||||
@@ -255,7 +255,6 @@ func (e *Exchange) Setup(exch *config.Exchange) error {
|
||||
Handler: func(_ context.Context, conn websocket.Connection, resp []byte) error {
|
||||
return e.wsHandleData(conn, asset.Spot, resp)
|
||||
},
|
||||
RequestIDGenerator: e.messageIDSeq.IncrementAndGet,
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -277,7 +276,6 @@ func (e *Exchange) Setup(exch *config.Exchange) error {
|
||||
Handler: func(_ context.Context, conn websocket.Connection, resp []byte) error {
|
||||
return e.wsHandleData(conn, asset.Options, resp)
|
||||
},
|
||||
RequestIDGenerator: e.messageIDSeq.IncrementAndGet,
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -305,8 +303,7 @@ func (e *Exchange) Setup(exch *config.Exchange) error {
|
||||
Handler: func(_ context.Context, conn websocket.Connection, resp []byte) error {
|
||||
return e.wsHandleData(conn, asset.USDTMarginedFutures, resp)
|
||||
},
|
||||
RequestIDGenerator: e.messageIDSeq.IncrementAndGet,
|
||||
MessageFilter: asset.USDTMarginedFutures, // Unused but it allows us to differentiate between the two linear futures types.
|
||||
MessageFilter: asset.USDTMarginedFutures, // Unused but it allows us to differentiate between the two linear futures types.
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -334,8 +331,7 @@ func (e *Exchange) Setup(exch *config.Exchange) error {
|
||||
Handler: func(_ context.Context, conn websocket.Connection, resp []byte) error {
|
||||
return e.wsHandleData(conn, asset.USDCMarginedFutures, resp)
|
||||
},
|
||||
RequestIDGenerator: e.messageIDSeq.IncrementAndGet,
|
||||
MessageFilter: asset.USDCMarginedFutures, // Unused but it allows us to differentiate between the two linear futures types.
|
||||
MessageFilter: asset.USDCMarginedFutures, // Unused but it allows us to differentiate between the two linear futures types.
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -357,7 +353,6 @@ func (e *Exchange) Setup(exch *config.Exchange) error {
|
||||
Handler: func(_ context.Context, conn websocket.Connection, resp []byte) error {
|
||||
return e.wsHandleData(conn, asset.CoinMarginedFutures, resp)
|
||||
},
|
||||
RequestIDGenerator: e.messageIDSeq.IncrementAndGet,
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -376,7 +371,6 @@ func (e *Exchange) Setup(exch *config.Exchange) error {
|
||||
Handler: func(_ context.Context, conn websocket.Connection, resp []byte) error {
|
||||
return e.wsHandleTradeData(conn, resp)
|
||||
},
|
||||
RequestIDGenerator: e.messageIDSeq.IncrementAndGet,
|
||||
Authenticate: e.WebsocketAuthenticateTradeConnection,
|
||||
MessageFilter: OutboundTradeConnection,
|
||||
SubscriptionsNotRequired: true,
|
||||
@@ -400,7 +394,6 @@ func (e *Exchange) Setup(exch *config.Exchange) error {
|
||||
Subscriber: e.authSubscribe,
|
||||
Unsubscriber: e.authUnsubscribe,
|
||||
Handler: e.wsHandleAuthenticatedData,
|
||||
RequestIDGenerator: e.messageIDSeq.IncrementAndGet,
|
||||
Authenticate: e.WebsocketAuthenticatePrivateConnection,
|
||||
MessageFilter: InboundPrivateConnection,
|
||||
})
|
||||
|
||||
@@ -1960,3 +1960,9 @@ func (*Base) WebsocketCancelOrder(context.Context, *order.Cancel) error {
|
||||
func (b *Base) MessageID() string {
|
||||
return uuid.Must(uuid.NewV7()).String()
|
||||
}
|
||||
|
||||
// MessageSequence returns a sequential message sequence number from common.Counter
|
||||
// It is not universally unique but should be unique and sequential within each *Base instance
|
||||
func (b *Base) MessageSequence() int64 {
|
||||
return b.messageSequence.IncrementAndGet()
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"github.com/thrasher-corp/gocryptotrader/config"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchange/websocket"
|
||||
@@ -257,6 +258,7 @@ type Base struct {
|
||||
|
||||
AssetWebsocketSupport
|
||||
*currencystate.States
|
||||
messageSequence common.Counter
|
||||
}
|
||||
|
||||
// url lookup consts
|
||||
|
||||
@@ -2768,7 +2768,6 @@ func TestGetSettlementCurrency(t *testing.T) {
|
||||
|
||||
type FixtureConnection struct{ websocket.Connection }
|
||||
|
||||
func (d *FixtureConnection) GenerateMessageID(bool) int64 { return 1337 }
|
||||
func (d *FixtureConnection) SendMessageReturnResponse(context.Context, request.EndpointLimit, any, any) ([]byte, error) {
|
||||
return []byte(`{"time":1726121320,"time_ms":1726121320745,"id":1,"conn_id":"f903779a148987ca","trace_id":"d8ee37cd14347e4ed298d44e69aedaa7","channel":"spot.tickers","event":"subscribe","payload":["BRETT_USDT"],"result":{"status":"success"},"requestId":"d8ee37cd14347e4ed298d44e69aedaa7"}`), nil
|
||||
}
|
||||
@@ -2778,12 +2777,12 @@ func TestHandleSubscriptions(t *testing.T) {
|
||||
|
||||
subs := subscription.List{{Channel: subscription.OrderbookChannel}}
|
||||
|
||||
err := e.handleSubscription(t.Context(), &FixtureConnection{}, subscribeEvent, subs, func(context.Context, websocket.Connection, string, subscription.List) ([]WsInput, error) {
|
||||
err := e.handleSubscription(t.Context(), &FixtureConnection{}, subscribeEvent, subs, func(context.Context, string, subscription.List) ([]WsInput, error) {
|
||||
return []WsInput{{}}, nil
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
err = e.handleSubscription(t.Context(), &FixtureConnection{}, unsubscribeEvent, subs, func(context.Context, websocket.Connection, string, subscription.List) ([]WsInput, error) {
|
||||
err = e.handleSubscription(t.Context(), &FixtureConnection{}, unsubscribeEvent, subs, func(context.Context, string, subscription.List) ([]WsInput, error) {
|
||||
return []WsInput{{}}, nil
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -124,7 +124,7 @@ func (e *Exchange) websocketLogin(ctx context.Context, conn websocket.Connection
|
||||
signature := hex.EncodeToString(mac.Sum(nil))
|
||||
|
||||
payload := WebsocketPayload{
|
||||
RequestID: strconv.FormatInt(conn.GenerateMessageID(false), 10),
|
||||
RequestID: e.MessageID(),
|
||||
APIKey: creds.Key,
|
||||
Signature: signature,
|
||||
Timestamp: strconv.FormatInt(tn, 10),
|
||||
@@ -640,7 +640,7 @@ func (e *Exchange) manageSubs(ctx context.Context, event string, conn websocket.
|
||||
|
||||
for _, s := range subs {
|
||||
if err := func() error {
|
||||
msg, err := e.manageSubReq(ctx, event, conn, s)
|
||||
msg, err := e.manageSubReq(ctx, event, s)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -667,9 +667,9 @@ func (e *Exchange) manageSubs(ctx context.Context, event string, conn websocket.
|
||||
}
|
||||
|
||||
// manageSubReq constructs the subscription management message for a subscription
|
||||
func (e *Exchange) manageSubReq(ctx context.Context, event string, conn websocket.Connection, s *subscription.Subscription) (*WsInput, error) {
|
||||
func (e *Exchange) manageSubReq(ctx context.Context, event string, s *subscription.Subscription) (*WsInput, error) {
|
||||
req := &WsInput{
|
||||
ID: conn.GenerateMessageID(false),
|
||||
ID: e.MessageSequence(),
|
||||
Event: event,
|
||||
Channel: channelName(s),
|
||||
Time: time.Now().Unix(),
|
||||
@@ -886,11 +886,11 @@ const subTplText = `
|
||||
`
|
||||
|
||||
// GeneratePayload returns the payload for a websocket message
|
||||
type GeneratePayload func(ctx context.Context, conn websocket.Connection, event string, channelsToSubscribe subscription.List) ([]WsInput, error)
|
||||
type GeneratePayload func(ctx context.Context, event string, channelsToSubscribe subscription.List) ([]WsInput, error)
|
||||
|
||||
// handleSubscription sends a websocket message to receive data from the channel
|
||||
func (e *Exchange) handleSubscription(ctx context.Context, conn websocket.Connection, event string, channelsToSubscribe subscription.List, generatePayload GeneratePayload) error {
|
||||
payloads, err := generatePayload(ctx, conn, event, channelsToSubscribe)
|
||||
payloads, err := generatePayload(ctx, event, channelsToSubscribe)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -941,7 +941,7 @@ func (e *Exchange) SendWebsocketRequest(ctx context.Context, epl request.Endpoin
|
||||
Channel: channel,
|
||||
Event: "api",
|
||||
Payload: WebsocketPayload{
|
||||
RequestID: strconv.FormatInt(conn.GenerateMessageID(false), 10),
|
||||
RequestID: e.MessageID(),
|
||||
RequestParam: paramPayload,
|
||||
Timestamp: strconv.FormatInt(tn, 10),
|
||||
},
|
||||
|
||||
@@ -111,7 +111,7 @@ func (e *Exchange) DeliveryFuturesUnsubscribe(ctx context.Context, conn websocke
|
||||
return e.handleSubscription(ctx, conn, unsubscribeEvent, channelsToUnsubscribe, e.generateDeliveryFuturesPayload)
|
||||
}
|
||||
|
||||
func (e *Exchange) generateDeliveryFuturesPayload(ctx context.Context, conn websocket.Connection, event string, channelsToSubscribe subscription.List) ([]WsInput, error) {
|
||||
func (e *Exchange) generateDeliveryFuturesPayload(ctx context.Context, event string, channelsToSubscribe subscription.List) ([]WsInput, error) {
|
||||
if len(channelsToSubscribe) == 0 {
|
||||
return nil, errors.New("cannot generate payload, no channels supplied")
|
||||
}
|
||||
@@ -194,7 +194,7 @@ func (e *Exchange) generateDeliveryFuturesPayload(ctx context.Context, conn webs
|
||||
}
|
||||
}
|
||||
outbound = append(outbound, WsInput{
|
||||
ID: conn.GenerateMessageID(false),
|
||||
ID: e.MessageSequence(),
|
||||
Event: event,
|
||||
Channel: channelsToSubscribe[i].Channel,
|
||||
Payload: params,
|
||||
|
||||
@@ -194,7 +194,7 @@ func (e *Exchange) WsHandleFuturesData(ctx context.Context, conn websocket.Conne
|
||||
}
|
||||
}
|
||||
|
||||
func (e *Exchange) generateFuturesPayload(ctx context.Context, conn websocket.Connection, event string, channelsToSubscribe subscription.List) ([]WsInput, error) {
|
||||
func (e *Exchange) generateFuturesPayload(ctx context.Context, event string, channelsToSubscribe subscription.List) ([]WsInput, error) {
|
||||
if len(channelsToSubscribe) == 0 {
|
||||
return nil, errors.New("cannot generate payload, no channels supplied")
|
||||
}
|
||||
@@ -280,7 +280,7 @@ func (e *Exchange) generateFuturesPayload(ctx context.Context, conn websocket.Co
|
||||
}
|
||||
}
|
||||
outbound = append(outbound, WsInput{
|
||||
ID: conn.GenerateMessageID(false),
|
||||
ID: e.MessageSequence(),
|
||||
Event: event,
|
||||
Channel: channelsToSubscribe[i].Channel,
|
||||
Payload: params,
|
||||
|
||||
@@ -160,7 +160,7 @@ getEnabledPairs:
|
||||
return subscriptions, nil
|
||||
}
|
||||
|
||||
func (e *Exchange) generateOptionsPayload(ctx context.Context, conn websocket.Connection, event string, channelsToSubscribe subscription.List) ([]WsInput, error) {
|
||||
func (e *Exchange) generateOptionsPayload(ctx context.Context, event string, channelsToSubscribe subscription.List) ([]WsInput, error) {
|
||||
if len(channelsToSubscribe) == 0 {
|
||||
return nil, errors.New("cannot generate payload, no channels supplied")
|
||||
}
|
||||
@@ -262,7 +262,7 @@ func (e *Exchange) generateOptionsPayload(ctx context.Context, conn websocket.Co
|
||||
params...)
|
||||
}
|
||||
payloads[i] = WsInput{
|
||||
ID: conn.GenerateMessageID(false),
|
||||
ID: e.MessageSequence(),
|
||||
Event: event,
|
||||
Channel: channelsToSubscribe[i].Channel,
|
||||
Payload: params,
|
||||
|
||||
@@ -219,7 +219,6 @@ func (e *Exchange) Setup(exch *config.Exchange) error {
|
||||
Connector: e.WsConnectSpot,
|
||||
Authenticate: e.authenticateSpot,
|
||||
MessageFilter: asset.Spot,
|
||||
RequestIDGenerator: e.messageIDSeq.IncrementAndGet,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -237,10 +236,9 @@ func (e *Exchange) Setup(exch *config.Exchange) error {
|
||||
GenerateSubscriptions: func() (subscription.List, error) {
|
||||
return e.GenerateFuturesDefaultSubscriptions(asset.USDTMarginedFutures)
|
||||
},
|
||||
Connector: e.WsFuturesConnect,
|
||||
Authenticate: e.authenticateFutures,
|
||||
MessageFilter: asset.USDTMarginedFutures,
|
||||
RequestIDGenerator: e.messageIDSeq.IncrementAndGet,
|
||||
Connector: e.WsFuturesConnect,
|
||||
Authenticate: e.authenticateFutures,
|
||||
MessageFilter: asset.USDTMarginedFutures,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -259,9 +257,8 @@ func (e *Exchange) Setup(exch *config.Exchange) error {
|
||||
GenerateSubscriptions: func() (subscription.List, error) {
|
||||
return e.GenerateFuturesDefaultSubscriptions(asset.CoinMarginedFutures)
|
||||
},
|
||||
Connector: e.WsFuturesConnect,
|
||||
MessageFilter: asset.CoinMarginedFutures,
|
||||
RequestIDGenerator: e.messageIDSeq.IncrementAndGet,
|
||||
Connector: e.WsFuturesConnect,
|
||||
MessageFilter: asset.CoinMarginedFutures,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -281,7 +278,6 @@ func (e *Exchange) Setup(exch *config.Exchange) error {
|
||||
GenerateSubscriptions: e.GenerateDeliveryFuturesDefaultSubscriptions,
|
||||
Connector: e.WsDeliveryFuturesConnect,
|
||||
MessageFilter: asset.DeliveryFutures,
|
||||
RequestIDGenerator: e.messageIDSeq.IncrementAndGet,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -298,7 +294,6 @@ func (e *Exchange) Setup(exch *config.Exchange) error {
|
||||
GenerateSubscriptions: e.GenerateOptionsDefaultSubscriptions,
|
||||
Connector: e.WsOptionsConnect,
|
||||
MessageFilter: asset.Options,
|
||||
RequestIDGenerator: e.messageIDSeq.IncrementAndGet,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -568,7 +568,7 @@ func TestWsGetCurrenciesJSON(t *testing.T) {
|
||||
"delisted": false,
|
||||
"payoutFee": "0.001"
|
||||
},
|
||||
"id": 123
|
||||
"id": "c4ce77f5-1c50-435a-b623-4961191ca129"
|
||||
}`)
|
||||
err := e.wsHandleData(pressXToJSON)
|
||||
if err != nil {
|
||||
@@ -589,7 +589,7 @@ func TestWsGetSymbolsJSON(t *testing.T) {
|
||||
"provideLiquidityRate": "-0.0001",
|
||||
"feeCurrency": "BTC"
|
||||
},
|
||||
"id": 123
|
||||
"id": "1c847290-b366-412b-b8f5-dc630ed5b147"
|
||||
}`)
|
||||
err := e.wsHandleData(pressXToJSON)
|
||||
if err != nil {
|
||||
@@ -744,7 +744,7 @@ func TestWsSubmitOrderJSON(t *testing.T) {
|
||||
"updatedAt": "2017-10-20T12:29:43.166Z",
|
||||
"reportType": "new"
|
||||
},
|
||||
"id": 123
|
||||
"id": "99f55c70-1166-49a7-87e9-3b54a00ad893"
|
||||
}`)
|
||||
err := e.wsHandleData(pressXToJSON)
|
||||
if err != nil {
|
||||
@@ -771,7 +771,7 @@ func TestWsCancelOrderJSON(t *testing.T) {
|
||||
"updatedAt": "2017-10-20T12:31:26.174Z",
|
||||
"reportType": "canceled"
|
||||
},
|
||||
"id": 123
|
||||
"id": "2ce46937-2770-4453-ac99-ee87939bf5bb"
|
||||
}`)
|
||||
err := e.wsHandleData(pressXToJSON)
|
||||
if err != nil {
|
||||
@@ -799,7 +799,7 @@ func TestWsCancelReplaceJSON(t *testing.T) {
|
||||
"reportType": "replaced",
|
||||
"originalRequestClientOrderId": "9cbe79cb6f864b71a811402a48d4b5b1"
|
||||
},
|
||||
"id": 123
|
||||
"id": "91e925d3-3b95-4e29-8ae7-938fd5006709"
|
||||
}`)
|
||||
err := e.wsHandleData(pressXToJSON)
|
||||
if err != nil {
|
||||
@@ -827,7 +827,7 @@ func TestWsGetTradesRequestResponse(t *testing.T) {
|
||||
"reserved": "0.00200000"
|
||||
}
|
||||
],
|
||||
"id": 123
|
||||
"id": "4b1f1391-215e-4d12-972c-5cea9d50edf4"
|
||||
}`)
|
||||
err := e.wsHandleData(pressXToJSON)
|
||||
if err != nil {
|
||||
@@ -857,7 +857,7 @@ func TestWsGetActiveOrdersRequestJSON(t *testing.T) {
|
||||
"originalRequestClientOrderId": "9cbe79cb6f864b71a811402a48d4b5b1"
|
||||
}
|
||||
],
|
||||
"id": 123
|
||||
"id": "9e67b440-2eec-445a-be3a-e81f962c8391"
|
||||
}`)
|
||||
err := e.wsHandleData(pressXToJSON)
|
||||
if err != nil {
|
||||
|
||||
@@ -283,7 +283,7 @@ type capture struct {
|
||||
Method string `json:"method,omitempty"`
|
||||
Result any `json:"result"`
|
||||
Error ResponseError `json:"error"`
|
||||
ID int64 `json:"id,omitempty"`
|
||||
ID string `json:"id,omitempty"`
|
||||
}
|
||||
|
||||
// ResponseError contains error codes from JSON responses
|
||||
@@ -297,7 +297,7 @@ type WsRequest struct {
|
||||
JSONRPCVersion string `json:"jsonrpc,omitempty"`
|
||||
Method string `json:"method"`
|
||||
Params *WsParams `json:"params,omitempty"`
|
||||
ID int64 `json:"id,omitempty"`
|
||||
ID string `json:"id,omitempty"`
|
||||
}
|
||||
|
||||
// WsParams are websocket params for a request
|
||||
@@ -359,7 +359,7 @@ type WsTrade struct {
|
||||
type WsLoginRequest struct {
|
||||
Method string `json:"method"`
|
||||
Params WsLoginData `json:"params"`
|
||||
ID int64 `json:"id,omitempty"`
|
||||
ID string `json:"id,omitempty"`
|
||||
}
|
||||
|
||||
// WsLoginData sets credentials for WsLoginRequest
|
||||
@@ -378,17 +378,17 @@ type wsActiveOrdersResponse struct {
|
||||
|
||||
type wsReportResponse struct {
|
||||
OrderData wsOrderData `json:"params"`
|
||||
ID int64 `json:"id"`
|
||||
ID string `json:"id"`
|
||||
}
|
||||
|
||||
type wsOrderResponse struct {
|
||||
OrderData wsOrderData `json:"result"`
|
||||
ID int64 `json:"id"`
|
||||
ID string `json:"id"`
|
||||
}
|
||||
|
||||
type wsActiveOrderRequestResponse struct {
|
||||
OrderData []wsOrderData `json:"result"`
|
||||
ID int64 `json:"id"`
|
||||
ID string `json:"id"`
|
||||
}
|
||||
|
||||
// wsOrderData Active order data for WsActiveOrdersResponse
|
||||
@@ -446,12 +446,12 @@ type WsReportResponseData struct {
|
||||
type WsSubmitOrderRequest struct {
|
||||
Method string `json:"method"`
|
||||
Params WsSubmitOrderRequestData `json:"params"`
|
||||
ID int64 `json:"id"`
|
||||
ID string `json:"id"`
|
||||
}
|
||||
|
||||
// WsSubmitOrderRequestData WS request data
|
||||
type WsSubmitOrderRequestData struct {
|
||||
ClientOrderID int64 `json:"clientOrderId,string,omitempty"`
|
||||
ClientOrderID string `json:"clientOrderId,omitempty"`
|
||||
Symbol string `json:"symbol"`
|
||||
Side string `json:"side"`
|
||||
Price float64 `json:"price,string"`
|
||||
@@ -461,7 +461,7 @@ type WsSubmitOrderRequestData struct {
|
||||
// WsSubmitOrderSuccessResponse WS response
|
||||
type WsSubmitOrderSuccessResponse struct {
|
||||
Result WsSubmitOrderSuccessResponseData `json:"result"`
|
||||
ID int64 `json:"id"`
|
||||
ID string `json:"id"`
|
||||
Error ResponseError `json:"error"`
|
||||
}
|
||||
|
||||
@@ -499,7 +499,7 @@ type WsSubmitOrderErrorResponseData struct {
|
||||
// WsCancelOrderResponse WS response
|
||||
type WsCancelOrderResponse struct {
|
||||
Result WsCancelOrderResponseData `json:"result"`
|
||||
ID int64 `json:"id"`
|
||||
ID string `json:"id"`
|
||||
Error ResponseError `json:"error"`
|
||||
}
|
||||
|
||||
@@ -524,7 +524,7 @@ type WsCancelOrderResponseData struct {
|
||||
// WsReplaceOrderResponse WS response
|
||||
type WsReplaceOrderResponse struct {
|
||||
Result WsReplaceOrderResponseData `json:"result"`
|
||||
ID int64 `json:"id"`
|
||||
ID string `json:"id"`
|
||||
Error ResponseError `json:"error"`
|
||||
}
|
||||
|
||||
@@ -550,7 +550,7 @@ type WsReplaceOrderResponseData struct {
|
||||
// WsGetActiveOrdersResponse WS response
|
||||
type WsGetActiveOrdersResponse struct {
|
||||
Result []WsGetActiveOrdersResponseData `json:"result"`
|
||||
ID int64 `json:"id"`
|
||||
ID string `json:"id"`
|
||||
Error ResponseError `json:"error"`
|
||||
}
|
||||
|
||||
@@ -576,7 +576,7 @@ type WsGetActiveOrdersResponseData struct {
|
||||
// WsGetTradingBalanceResponse WS response
|
||||
type WsGetTradingBalanceResponse struct {
|
||||
Result []WsGetTradingBalanceResponseData `json:"result"`
|
||||
ID int64 `json:"id"`
|
||||
ID string `json:"id"`
|
||||
Error ResponseError `json:"error"`
|
||||
}
|
||||
|
||||
@@ -591,7 +591,7 @@ type WsGetTradingBalanceResponseData struct {
|
||||
type WsCancelOrderRequest struct {
|
||||
Method string `json:"method"`
|
||||
Params WsCancelOrderRequestData `json:"params"`
|
||||
ID int64 `json:"id"`
|
||||
ID string `json:"id"`
|
||||
}
|
||||
|
||||
// WsCancelOrderRequestData WS request data
|
||||
@@ -603,7 +603,7 @@ type WsCancelOrderRequestData struct {
|
||||
type WsReplaceOrderRequest struct {
|
||||
Method string `json:"method"`
|
||||
Params WsReplaceOrderRequestData `json:"params"`
|
||||
ID int64 `json:"id,omitempty"`
|
||||
ID string `json:"id,omitempty"`
|
||||
}
|
||||
|
||||
// WsReplaceOrderRequestData WS request data
|
||||
@@ -618,7 +618,7 @@ type WsReplaceOrderRequestData struct {
|
||||
type WsGetCurrenciesRequest struct {
|
||||
Method string `json:"method"`
|
||||
Params WsGetCurrenciesRequestParameters `json:"params"`
|
||||
ID int64 `json:"id"`
|
||||
ID string `json:"id"`
|
||||
}
|
||||
|
||||
// WsGetCurrenciesRequestParameters parameters
|
||||
@@ -629,7 +629,7 @@ type WsGetCurrenciesRequestParameters struct {
|
||||
// WsGetCurrenciesResponse currency response
|
||||
type WsGetCurrenciesResponse struct {
|
||||
Result WsGetCurrenciesResponseData `json:"result"`
|
||||
ID int64 `json:"id"`
|
||||
ID string `json:"id"`
|
||||
Error ResponseError `json:"error"`
|
||||
}
|
||||
|
||||
@@ -652,7 +652,7 @@ type WsGetCurrenciesResponseData struct {
|
||||
type WsGetSymbolsRequest struct {
|
||||
Method string `json:"method"`
|
||||
Params WsGetSymbolsRequestParameters `json:"params"`
|
||||
ID int64 `json:"id"`
|
||||
ID string `json:"id"`
|
||||
}
|
||||
|
||||
// WsGetSymbolsRequestParameters request parameters
|
||||
@@ -663,7 +663,7 @@ type WsGetSymbolsRequestParameters struct {
|
||||
// WsGetSymbolsResponse symbol response
|
||||
type WsGetSymbolsResponse struct {
|
||||
Result WsGetSymbolsResponseData `json:"result"`
|
||||
ID int64 `json:"id"`
|
||||
ID string `json:"id"`
|
||||
Error ResponseError `json:"error"`
|
||||
}
|
||||
|
||||
@@ -683,7 +683,7 @@ type WsGetSymbolsResponseData struct {
|
||||
type WsGetTradesRequest struct {
|
||||
Method string `json:"method"`
|
||||
Params WsGetTradesRequestParameters `json:"params"`
|
||||
ID int64 `json:"id"`
|
||||
ID string `json:"id"`
|
||||
}
|
||||
|
||||
// WsGetTradesRequestParameters trade request params
|
||||
@@ -698,7 +698,7 @@ type WsGetTradesRequestParameters struct {
|
||||
type WsGetTradesResponse struct {
|
||||
Jsonrpc string `json:"jsonrpc"`
|
||||
Result WsGetTradesResponseData `json:"result"`
|
||||
ID int64 `json:"id"`
|
||||
ID string `json:"id"`
|
||||
Error ResponseError `json:"error"`
|
||||
}
|
||||
|
||||
|
||||
@@ -102,7 +102,7 @@ func (e *Exchange) wsGetTableName(respRaw []byte) (string, error) {
|
||||
if init.Error.Code == errAuthFailed {
|
||||
e.Websocket.SetCanUseAuthenticatedEndpoints(false)
|
||||
}
|
||||
if init.ID > 0 {
|
||||
if init.ID != "" {
|
||||
if e.Websocket.Match.IncomingWithData(init.ID, respRaw) {
|
||||
return "", nil
|
||||
}
|
||||
@@ -519,7 +519,7 @@ func (e *Exchange) manageSubs(ctx context.Context, op string, subs subscription.
|
||||
for _, s := range subs {
|
||||
r := WsRequest{
|
||||
JSONRPCVersion: rpcVersion,
|
||||
ID: e.Websocket.Conn.GenerateMessageID(false),
|
||||
ID: e.MessageID(),
|
||||
}
|
||||
if err := json.Unmarshal([]byte(s.QualifiedChannel), &r); err != nil {
|
||||
errs = common.AppendError(errs, err)
|
||||
@@ -565,7 +565,7 @@ func (e *Exchange) wsLogin(ctx context.Context) error {
|
||||
Nonce: n,
|
||||
Signature: hex.EncodeToString(hmac),
|
||||
},
|
||||
ID: e.Websocket.Conn.GenerateMessageID(false),
|
||||
ID: e.MessageID(),
|
||||
}
|
||||
|
||||
err = e.Websocket.Conn.SendJSONMessage(ctx, request.Unset, req)
|
||||
@@ -583,7 +583,7 @@ func (e *Exchange) wsPlaceOrder(ctx context.Context, pair currency.Pair, side st
|
||||
return nil, fmt.Errorf("%v not authenticated, cannot place order", e.Name)
|
||||
}
|
||||
|
||||
id := e.Websocket.Conn.GenerateMessageID(false)
|
||||
id := e.MessageID()
|
||||
fPair, err := e.FormatExchangeCurrency(pair, asset.Spot)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -625,7 +625,7 @@ func (e *Exchange) wsCancelOrder(ctx context.Context, clientOrderID string) (*Ws
|
||||
Params: WsCancelOrderRequestData{
|
||||
ClientOrderID: clientOrderID,
|
||||
},
|
||||
ID: e.Websocket.Conn.GenerateMessageID(false),
|
||||
ID: e.MessageID(),
|
||||
}
|
||||
resp, err := e.Websocket.Conn.SendMessageReturnResponse(ctx, request.Unset, req.ID, req)
|
||||
if err != nil {
|
||||
@@ -655,7 +655,7 @@ func (e *Exchange) wsReplaceOrder(ctx context.Context, clientOrderID string, qua
|
||||
Quantity: quantity,
|
||||
Price: price,
|
||||
},
|
||||
ID: e.Websocket.Conn.GenerateMessageID(false),
|
||||
ID: e.MessageID(),
|
||||
}
|
||||
resp, err := e.Websocket.Conn.SendMessageReturnResponse(ctx, request.Unset, req.ID, req)
|
||||
if err != nil {
|
||||
@@ -680,7 +680,7 @@ func (e *Exchange) wsGetActiveOrders(ctx context.Context) (*wsActiveOrdersRespon
|
||||
req := WsReplaceOrderRequest{
|
||||
Method: "getOrders",
|
||||
Params: WsReplaceOrderRequestData{},
|
||||
ID: e.Websocket.Conn.GenerateMessageID(false),
|
||||
ID: e.MessageID(),
|
||||
}
|
||||
resp, err := e.Websocket.Conn.SendMessageReturnResponse(ctx, request.Unset, req.ID, req)
|
||||
if err != nil {
|
||||
@@ -705,7 +705,7 @@ func (e *Exchange) wsGetTradingBalance(ctx context.Context) (*WsGetTradingBalanc
|
||||
req := WsReplaceOrderRequest{
|
||||
Method: "getTradingBalance",
|
||||
Params: WsReplaceOrderRequestData{},
|
||||
ID: e.Websocket.Conn.GenerateMessageID(false),
|
||||
ID: e.MessageID(),
|
||||
}
|
||||
resp, err := e.Websocket.Conn.SendMessageReturnResponse(ctx, request.Unset, req.ID, req)
|
||||
if err != nil {
|
||||
@@ -729,7 +729,7 @@ func (e *Exchange) wsGetCurrencies(ctx context.Context, currencyItem currency.Co
|
||||
Params: WsGetCurrenciesRequestParameters{
|
||||
Currency: currencyItem,
|
||||
},
|
||||
ID: e.Websocket.Conn.GenerateMessageID(false),
|
||||
ID: e.MessageID(),
|
||||
}
|
||||
resp, err := e.Websocket.Conn.SendMessageReturnResponse(ctx, request.Unset, req.ID, req)
|
||||
if err != nil {
|
||||
@@ -758,7 +758,7 @@ func (e *Exchange) wsGetSymbols(ctx context.Context, c currency.Pair) (*WsGetSym
|
||||
Params: WsGetSymbolsRequestParameters{
|
||||
Symbol: fPair.String(),
|
||||
},
|
||||
ID: e.Websocket.Conn.GenerateMessageID(false),
|
||||
ID: e.MessageID(),
|
||||
}
|
||||
resp, err := e.Websocket.Conn.SendMessageReturnResponse(ctx, request.Unset, req.ID, req)
|
||||
if err != nil {
|
||||
@@ -790,7 +790,7 @@ func (e *Exchange) wsGetTrades(ctx context.Context, c currency.Pair, limit int64
|
||||
Sort: sort,
|
||||
By: by,
|
||||
},
|
||||
ID: e.Websocket.Conn.GenerateMessageID(false),
|
||||
ID: e.MessageID(),
|
||||
}
|
||||
resp, err := e.Websocket.Conn.SendMessageReturnResponse(ctx, request.Unset, req.ID, req)
|
||||
if err != nil {
|
||||
|
||||
@@ -443,7 +443,7 @@ func (e *Exchange) SubmitOrder(ctx context.Context, o *order.Submit) (*order.Sub
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
orderID = strconv.FormatInt(response.ID, 10)
|
||||
orderID = response.ID
|
||||
if response.Result.CumQuantity == o.Amount {
|
||||
status = order.Filled
|
||||
}
|
||||
|
||||
@@ -813,7 +813,7 @@ func (e *Exchange) manageSubs(ctx context.Context, op string, subs subscription.
|
||||
reqFmt := currency.PairFormat{Uppercase: true, Delimiter: "/"}
|
||||
r := &WebsocketSubRequest{
|
||||
Event: op,
|
||||
RequestID: e.Websocket.Conn.GenerateMessageID(false),
|
||||
RequestID: e.MessageSequence(),
|
||||
Subscription: WebsocketSubscriptionData{
|
||||
Name: s.QualifiedChannel,
|
||||
Depth: s.Levels,
|
||||
@@ -1040,7 +1040,7 @@ func (e *Exchange) wsAddOrder(ctx context.Context, req *WsAddOrderRequest) (stri
|
||||
if req == nil {
|
||||
return "", common.ErrNilPointer
|
||||
}
|
||||
req.RequestID = e.Websocket.AuthConn.GenerateMessageID(false)
|
||||
req.RequestID = e.MessageSequence()
|
||||
req.Event = krakenWsAddOrder
|
||||
req.Token = e.websocketAuthToken()
|
||||
jsonResp, err := e.Websocket.AuthConn.SendMessageReturnResponse(ctx, request.Unset, req.RequestID, req)
|
||||
@@ -1079,7 +1079,7 @@ func (e *Exchange) wsCancelOrders(ctx context.Context, orderIDs []string) error
|
||||
|
||||
// wsCancelOrder cancels an open order
|
||||
func (e *Exchange) wsCancelOrder(ctx context.Context, orderID string) error {
|
||||
id := e.Websocket.AuthConn.GenerateMessageID(false)
|
||||
id := e.MessageSequence()
|
||||
req := WsCancelOrderRequest{
|
||||
Event: krakenWsCancelOrder,
|
||||
Token: e.websocketAuthToken(),
|
||||
@@ -1110,14 +1110,13 @@ func (e *Exchange) wsCancelOrder(ctx context.Context, orderID string) error {
|
||||
// wsCancelAllOrders cancels all opened orders
|
||||
// Returns number (count param) of affected orders or 0 if no open orders found
|
||||
func (e *Exchange) wsCancelAllOrders(ctx context.Context) (*WsCancelOrderResponse, error) {
|
||||
id := e.Websocket.AuthConn.GenerateMessageID(false)
|
||||
req := WsCancelOrderRequest{
|
||||
Event: krakenWsCancelAll,
|
||||
Token: e.websocketAuthToken(),
|
||||
RequestID: id,
|
||||
RequestID: e.MessageSequence(),
|
||||
}
|
||||
|
||||
jsonResp, err := e.Websocket.AuthConn.SendMessageReturnResponse(ctx, request.Unset, id, req)
|
||||
jsonResp, err := e.Websocket.AuthConn.SendMessageReturnResponse(ctx, request.Unset, req.RequestID, req)
|
||||
if err != nil {
|
||||
return &WsCancelOrderResponse{}, err
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"slices"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"text/template"
|
||||
@@ -227,7 +226,7 @@ func (e *Exchange) wsHandleData(ctx context.Context, respData []byte) error {
|
||||
return nil
|
||||
}
|
||||
if resp.ID != "" {
|
||||
return e.Websocket.Match.RequireMatchWithData("msgID:"+resp.ID, respData)
|
||||
return e.Websocket.Match.RequireMatchWithData(resp.ID, respData)
|
||||
}
|
||||
topicInfo := strings.Split(resp.Topic, ":")
|
||||
switch topicInfo[0] {
|
||||
@@ -1023,15 +1022,14 @@ func (e *Exchange) Unsubscribe(subscriptions subscription.List) error {
|
||||
func (e *Exchange) manageSubscriptions(ctx context.Context, subs subscription.List, operation string) error {
|
||||
var errs error
|
||||
for _, s := range subs {
|
||||
msgID := strconv.FormatInt(e.Websocket.Conn.GenerateMessageID(false), 10)
|
||||
req := WsSubscriptionInput{
|
||||
ID: msgID,
|
||||
ID: e.MessageID(),
|
||||
Type: operation,
|
||||
Topic: s.QualifiedChannel,
|
||||
PrivateChannel: s.Authenticated,
|
||||
Response: true,
|
||||
}
|
||||
if respRaw, err := e.Websocket.Conn.SendMessageReturnResponse(ctx, request.Unset, "msgID:"+msgID, req); err != nil {
|
||||
if respRaw, err := e.Websocket.Conn.SendMessageReturnResponse(ctx, request.Unset, req.ID, req); err != nil {
|
||||
errs = common.AppendError(errs, err)
|
||||
} else {
|
||||
rType, err := jsonparser.GetUnsafeString(respRaw, "type")
|
||||
|
||||
@@ -33,7 +33,6 @@ import (
|
||||
type Exchange struct {
|
||||
exchange.Base
|
||||
|
||||
messageIDSeq common.Counter
|
||||
instrumentsInfoMapLock sync.Mutex
|
||||
instrumentsInfoMap map[string][]Instrument
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gofrs/uuid"
|
||||
"github.com/shopspring/decimal"
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"github.com/thrasher-corp/gocryptotrader/common/key"
|
||||
@@ -224,7 +225,6 @@ func (e *Exchange) Setup(exch *config.Exchange) error {
|
||||
ResponseCheckTimeout: exch.WebsocketResponseCheckTimeout,
|
||||
ResponseMaxLimit: websocketResponseMaxLimit,
|
||||
RateLimit: request.NewRateLimitWithWeight(time.Second, 2, 1),
|
||||
RequestIDGenerator: e.messageIDSeq.IncrementAndGet,
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -235,7 +235,6 @@ func (e *Exchange) Setup(exch *config.Exchange) error {
|
||||
ResponseMaxLimit: websocketResponseMaxLimit,
|
||||
Authenticated: true,
|
||||
RateLimit: request.NewRateLimitWithWeight(time.Second, 2, 1),
|
||||
RequestIDGenerator: e.messageIDSeq.IncrementAndGet,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -3038,3 +3037,8 @@ func (e *Exchange) GetCurrencyTradeURL(ctx context.Context, a asset.Item, cp cur
|
||||
return "", fmt.Errorf("%w %q", asset.ErrNotSupported, a)
|
||||
}
|
||||
}
|
||||
|
||||
// MessageID returns a universally unique ID using UUID V7, with hyphens removed to fit the maximum 32-character field for okx
|
||||
func (e *Exchange) MessageID() string {
|
||||
return strings.Replace(uuid.Must(uuid.NewV7()).String(), "-", "", 4)
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strconv"
|
||||
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"github.com/thrasher-corp/gocryptotrader/encoding/json"
|
||||
@@ -28,10 +27,8 @@ func (e *Exchange) WSPlaceOrder(ctx context.Context, arg *PlaceOrderRequestParam
|
||||
return nil, err
|
||||
}
|
||||
|
||||
id := strconv.FormatInt(e.Websocket.AuthConn.GenerateMessageID(false), 10)
|
||||
|
||||
var resp []*OrderData
|
||||
if err := e.SendAuthenticatedWebsocketRequest(ctx, placeOrderEPL, id, "order", []PlaceOrderRequestParam{*arg}, &resp); err != nil {
|
||||
if err := e.SendAuthenticatedWebsocketRequest(ctx, placeOrderEPL, e.MessageID(), "order", []PlaceOrderRequestParam{*arg}, &resp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return singleItem(resp)
|
||||
@@ -49,10 +46,8 @@ func (e *Exchange) WSPlaceMultipleOrders(ctx context.Context, args []PlaceOrderR
|
||||
}
|
||||
}
|
||||
|
||||
id := strconv.FormatInt(e.Websocket.AuthConn.GenerateMessageID(false), 10)
|
||||
|
||||
var resp []*OrderData
|
||||
return resp, e.SendAuthenticatedWebsocketRequest(ctx, placeMultipleOrdersEPL, id, "batch-orders", args, &resp)
|
||||
return resp, e.SendAuthenticatedWebsocketRequest(ctx, placeMultipleOrdersEPL, e.MessageID(), "batch-orders", args, &resp)
|
||||
}
|
||||
|
||||
// WSCancelOrder cancels an order
|
||||
@@ -67,10 +62,8 @@ func (e *Exchange) WSCancelOrder(ctx context.Context, arg *CancelOrderRequestPar
|
||||
return nil, order.ErrOrderIDNotSet
|
||||
}
|
||||
|
||||
id := strconv.FormatInt(e.Websocket.AuthConn.GenerateMessageID(false), 10)
|
||||
|
||||
var resp []*OrderData
|
||||
if err := e.SendAuthenticatedWebsocketRequest(ctx, cancelOrderEPL, id, "cancel-order", []CancelOrderRequestParam{*arg}, &resp); err != nil {
|
||||
if err := e.SendAuthenticatedWebsocketRequest(ctx, cancelOrderEPL, e.MessageID(), "cancel-order", []CancelOrderRequestParam{*arg}, &resp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -92,10 +85,8 @@ func (e *Exchange) WSCancelMultipleOrders(ctx context.Context, args []CancelOrde
|
||||
}
|
||||
}
|
||||
|
||||
id := strconv.FormatInt(e.Websocket.AuthConn.GenerateMessageID(false), 10)
|
||||
|
||||
var resp []*OrderData
|
||||
return resp, e.SendAuthenticatedWebsocketRequest(ctx, cancelMultipleOrdersEPL, id, "batch-cancel-orders", args, &resp)
|
||||
return resp, e.SendAuthenticatedWebsocketRequest(ctx, cancelMultipleOrdersEPL, e.MessageID(), "batch-cancel-orders", args, &resp)
|
||||
}
|
||||
|
||||
// WSAmendOrder amends an order
|
||||
@@ -113,10 +104,8 @@ func (e *Exchange) WSAmendOrder(ctx context.Context, arg *AmendOrderRequestParam
|
||||
return nil, errInvalidNewSizeOrPriceInformation
|
||||
}
|
||||
|
||||
id := strconv.FormatInt(e.Websocket.AuthConn.GenerateMessageID(false), 10)
|
||||
|
||||
var resp []*OrderData
|
||||
if err := e.SendAuthenticatedWebsocketRequest(ctx, amendOrderEPL, id, "amend-order", []AmendOrderRequestParams{*arg}, &resp); err != nil {
|
||||
if err := e.SendAuthenticatedWebsocketRequest(ctx, amendOrderEPL, e.MessageID(), "amend-order", []AmendOrderRequestParams{*arg}, &resp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return singleItem(resp)
|
||||
@@ -140,10 +129,8 @@ func (e *Exchange) WSAmendMultipleOrders(ctx context.Context, args []AmendOrderR
|
||||
}
|
||||
}
|
||||
|
||||
id := strconv.FormatInt(e.Websocket.AuthConn.GenerateMessageID(false), 10)
|
||||
|
||||
var resp []*OrderData
|
||||
return resp, e.SendAuthenticatedWebsocketRequest(ctx, amendMultipleOrdersEPL, id, "batch-amend-orders", args, &resp)
|
||||
return resp, e.SendAuthenticatedWebsocketRequest(ctx, amendMultipleOrdersEPL, e.MessageID(), "batch-amend-orders", args, &resp)
|
||||
}
|
||||
|
||||
// WSMassCancelOrders cancels all MMP pending orders of an instrument family. Only applicable to Option in Portfolio Margin mode, and MMP privilege is required.
|
||||
@@ -161,12 +148,10 @@ func (e *Exchange) WSMassCancelOrders(ctx context.Context, args []CancelMassReqP
|
||||
}
|
||||
}
|
||||
|
||||
id := strconv.FormatInt(e.Websocket.AuthConn.GenerateMessageID(false), 10)
|
||||
|
||||
var resps []*struct {
|
||||
Result bool `json:"result"`
|
||||
}
|
||||
if err := e.SendAuthenticatedWebsocketRequest(ctx, amendOrderEPL, id, "mass-cancel", args, &resps); err != nil {
|
||||
if err := e.SendAuthenticatedWebsocketRequest(ctx, amendOrderEPL, e.MessageID(), "mass-cancel", args, &resps); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -188,10 +173,8 @@ func (e *Exchange) WSPlaceSpreadOrder(ctx context.Context, arg *SpreadOrderParam
|
||||
return nil, err
|
||||
}
|
||||
|
||||
id := strconv.FormatInt(e.Websocket.AuthConn.GenerateMessageID(false), 10)
|
||||
|
||||
var resp []*SpreadOrderResponse
|
||||
if err := e.SendAuthenticatedWebsocketRequest(ctx, placeSpreadOrderEPL, id, "sprd-order", []SpreadOrderParam{*arg}, &resp); err != nil {
|
||||
if err := e.SendAuthenticatedWebsocketRequest(ctx, placeSpreadOrderEPL, e.MessageID(), "sprd-order", []SpreadOrderParam{*arg}, &resp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -210,10 +193,8 @@ func (e *Exchange) WSAmendSpreadOrder(ctx context.Context, arg *AmendSpreadOrder
|
||||
return nil, errSizeOrPriceIsRequired
|
||||
}
|
||||
|
||||
id := strconv.FormatInt(e.Websocket.AuthConn.GenerateMessageID(false), 10)
|
||||
|
||||
var resp []*SpreadOrderResponse
|
||||
if err := e.SendAuthenticatedWebsocketRequest(ctx, amendSpreadOrderEPL, id, "sprd-amend-order", []AmendSpreadOrderParam{*arg}, &resp); err != nil {
|
||||
if err := e.SendAuthenticatedWebsocketRequest(ctx, amendSpreadOrderEPL, e.MessageID(), "sprd-amend-order", []AmendSpreadOrderParam{*arg}, &resp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -234,10 +215,8 @@ func (e *Exchange) WSCancelSpreadOrder(ctx context.Context, orderID, clientOrder
|
||||
arg["clOrdId"] = clientOrderID
|
||||
}
|
||||
|
||||
id := strconv.FormatInt(e.Websocket.AuthConn.GenerateMessageID(false), 10)
|
||||
|
||||
var resp []*SpreadOrderResponse
|
||||
if err := e.SendAuthenticatedWebsocketRequest(ctx, cancelSpreadOrderEPL, id, "sprd-cancel-order", []map[string]string{arg}, &resp); err != nil {
|
||||
if err := e.SendAuthenticatedWebsocketRequest(ctx, cancelSpreadOrderEPL, e.MessageID(), "sprd-cancel-order", []map[string]string{arg}, &resp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -251,10 +230,8 @@ func (e *Exchange) WSCancelAllSpreadOrders(ctx context.Context, spreadID string)
|
||||
arg["sprdId"] = spreadID
|
||||
}
|
||||
|
||||
id := strconv.FormatInt(e.Websocket.AuthConn.GenerateMessageID(false), 10)
|
||||
|
||||
var resps []*ResponseResult
|
||||
if err := e.SendAuthenticatedWebsocketRequest(ctx, cancelAllSpreadOrderEPL, id, "sprd-mass-cancel", []map[string]string{arg}, &resps); err != nil {
|
||||
if err := e.SendAuthenticatedWebsocketRequest(ctx, cancelAllSpreadOrderEPL, e.MessageID(), "sprd-mass-cancel", []map[string]string{arg}, &resps); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"github.com/gofrs/uuid"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
@@ -281,3 +282,20 @@ func TestSingleItem(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, got)
|
||||
}
|
||||
|
||||
func TestMessageID(t *testing.T) {
|
||||
t.Parallel()
|
||||
id := new(Exchange).MessageID()
|
||||
require.Len(t, id, 32, "Must return the correct length of message id")
|
||||
u, err := uuid.FromString(id)
|
||||
require.NoError(t, err, "MessageID must return a valid UUID")
|
||||
assert.Equal(t, byte(0x7), u.Version(), "MessageID should return a V7 uuid")
|
||||
}
|
||||
|
||||
// BenchmarkMessageID-8 4736883 259.9 ns/op 96 B/op 4 allocs/op
|
||||
func BenchmarkMessageID(b *testing.B) {
|
||||
e := new(Exchange)
|
||||
for b.Loop() {
|
||||
_ = e.MessageID()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user