From 3e80f1b9e5b74dd563d95d7e410603be4d630daf Mon Sep 17 00:00:00 2001 From: Ryan O'Hara-Reid Date: Tue, 17 Jun 2025 13:43:00 +1000 Subject: [PATCH] websocket/exchanges: populate context before multi connection upgrade (#1933) * websocket/exchanges: populate context before multi connection upgrade * fix test * linter: fix * gk: dial * gk: nits rm param names --------- Co-authored-by: Ryan O'Hara-Reid --- exchange/websocket/connection.go | 10 +- exchange/websocket/manager_test.go | 20 +- exchanges/alphapoint/alphapoint.go | 6 +- exchanges/binance/binance_live_test.go | 5 +- exchanges/binance/binance_mock_test.go | 5 +- exchanges/binance/binance_test.go | 4 +- exchanges/binance/binance_websocket.go | 35 +- exchanges/binanceus/binanceus_test.go | 5 +- exchanges/binanceus/binanceus_websocket.go | 37 +- exchanges/bitfinex/bitfinex_test.go | 68 +-- exchanges/bitfinex/bitfinex_websocket.go | 65 ++- exchanges/bitfinex/bitfinex_wrapper.go | 8 +- exchanges/bithumb/bithumb_websocket.go | 12 +- exchanges/bithumb/bithumb_websocket_test.go | 2 +- exchanges/bithumb/bithumb_ws_orderbook.go | 28 +- exchanges/bitmex/bitmex_test.go | 2 +- exchanges/bitmex/bitmex_websocket.go | 18 +- exchanges/bitstamp/bitstamp_test.go | 14 +- exchanges/bitstamp/bitstamp_websocket.go | 29 +- exchanges/btcmarkets/btcmarkets_test.go | 24 +- exchanges/btcmarkets/btcmarkets_websocket.go | 25 +- exchanges/btse/btse_test.go | 12 +- exchanges/btse/btse_websocket.go | 19 +- exchanges/bybit/bybit_inverse_websocket.go | 15 +- exchanges/bybit/bybit_linear_websocket.go | 17 +- exchanges/bybit/bybit_options_websocket.go | 15 +- exchanges/bybit/bybit_test.go | 9 +- exchanges/bybit/bybit_websocket.go | 37 +- exchanges/coinbasepro/coinbasepro_test.go | 32 +- .../coinbasepro/coinbasepro_websocket.go | 25 +- exchanges/coinut/coinut_test.go | 18 +- exchanges/coinut/coinut_websocket.go | 53 +- exchanges/coinut/coinut_wrapper.go | 42 +- exchanges/deribit/deribit.go | 2 +- exchanges/deribit/deribit_test.go | 538 +++++++++--------- exchanges/deribit/deribit_types.go | 2 +- exchanges/deribit/deribit_websocket.go | 37 +- exchanges/deribit/deribit_wrapper.go | 59 +- exchanges/deribit/deribit_ws_endpoints.go | 517 ++++++++--------- exchanges/exchange.go | 4 +- exchanges/exchange_test.go | 2 +- exchanges/gateio/gateio_test.go | 3 +- exchanges/gateio/gateio_websocket.go | 2 +- .../gateio_websocket_delivery_futures.go | 5 +- exchanges/gateio/gateio_websocket_futures.go | 2 +- exchanges/gateio/gateio_websocket_option.go | 7 +- exchanges/gemini/gemini_websocket.go | 17 +- exchanges/hitbtc/hitbtc_test.go | 21 +- exchanges/hitbtc/hitbtc_websocket.go | 49 +- exchanges/hitbtc/hitbtc_wrapper.go | 2 +- exchanges/huobi/huobi_websocket.go | 39 +- exchanges/huobi/huobi_wrapper.go | 4 +- exchanges/kraken/kraken_test.go | 14 +- exchanges/kraken/kraken_websocket.go | 43 +- exchanges/kraken/kraken_wrapper.go | 16 +- exchanges/kucoin/kucoin_test.go | 11 +- exchanges/kucoin/kucoin_websocket.go | 67 +-- exchanges/okx/okx_business_websocket.go | 22 +- exchanges/okx/okx_test.go | 4 +- exchanges/okx/okx_websocket.go | 39 +- exchanges/okx/okx_wrapper.go | 6 +- exchanges/poloniex/poloniex_test.go | 4 +- exchanges/poloniex/poloniex_websocket.go | 23 +- internal/testing/exchange/exchange.go | 7 +- 64 files changed, 1160 insertions(+), 1124 deletions(-) diff --git a/exchange/websocket/connection.go b/exchange/websocket/connection.go index d560b5c8..529e20e1 100644 --- a/exchange/websocket/connection.go +++ b/exchange/websocket/connection.go @@ -34,8 +34,7 @@ var ( // Connection defines the interface for websocket connections type Connection interface { - Dial(*gws.Dialer, http.Header) error - DialContext(context.Context, *gws.Dialer, http.Header) error + Dial(context.Context, *gws.Dialer, http.Header) error ReadMessage() Response SetupPingHandler(request.EndpointLimit, PingHandler) // GenerateMessageID generates a message ID for the individual connection. If a bespoke function is set @@ -131,12 +130,7 @@ type connection struct { } // Dial sets proxy urls and then connects to the websocket -func (c *connection) Dial(dialer *gws.Dialer, headers http.Header) error { - return c.DialContext(context.Background(), dialer, headers) -} - -// DialContext sets proxy urls and then connects to the websocket -func (c *connection) DialContext(ctx context.Context, dialer *gws.Dialer, headers http.Header) error { +func (c *connection) Dial(ctx context.Context, dialer *gws.Dialer, headers http.Header) error { if c.ProxyURL != "" { proxy, err := url.Parse(c.ProxyURL) if err != nil { diff --git a/exchange/websocket/manager_test.go b/exchange/websocket/manager_test.go index ebf71fa1..68dc5e8f 100644 --- a/exchange/websocket/manager_test.go +++ b/exchange/websocket/manager_test.go @@ -275,7 +275,7 @@ func TestConnectionMessageErrors(t *testing.T) { require.ErrorIs(t, err, errDastardlyReason) ws.connectionManager[0].setup.Connector = func(ctx context.Context, conn Connection) error { - return conn.DialContext(ctx, gws.DefaultDialer, nil) + return conn.Dial(ctx, gws.DefaultDialer, nil) } err = ws.Connect() require.ErrorIs(t, err, errDastardlyReason) @@ -469,7 +469,7 @@ func TestDial(t *testing.T) { t.Log("Proxy testing not enabled, skipping") continue } - err := testCases[i].WC.Dial(&gws.Dialer{}, http.Header{}) + err := testCases[i].WC.Dial(t.Context(), &gws.Dialer{}, http.Header{}) if err != nil { if testCases[i].Error != nil && strings.Contains(err.Error(), testCases[i].Error.Error()) { return @@ -521,7 +521,7 @@ func TestSendMessage(t *testing.T) { t.Log("Proxy testing not enabled, skipping") continue } - err := testCases[x].WC.Dial(&gws.Dialer{}, http.Header{}) + err := testCases[x].WC.Dial(t.Context(), &gws.Dialer{}, http.Header{}) if err != nil { if testCases[x].Error != nil && strings.Contains(err.Error(), testCases[x].Error.Error()) { return @@ -551,7 +551,7 @@ func TestSendMessageReturnResponse(t *testing.T) { t.Skip("Proxy testing not enabled, skipping") } - err := wc.Dial(&gws.Dialer{}, http.Header{}) + err := wc.Dial(t.Context(), &gws.Dialer{}, http.Header{}) if err != nil { t.Fatal(err) } @@ -676,7 +676,7 @@ func TestSetupPingHandler(t *testing.T) { t.Skip("Proxy testing not enabled, skipping") } wc.shutdown = make(chan struct{}) - err := wc.Dial(&gws.Dialer{}, http.Header{}) + err := wc.Dial(t.Context(), &gws.Dialer{}, http.Header{}) if err != nil { t.Fatal(err) } @@ -692,7 +692,7 @@ func TestSetupPingHandler(t *testing.T) { t.Error(err) } - err = wc.Dial(&gws.Dialer{}, http.Header{}) + err = wc.Dial(t.Context(), &gws.Dialer{}, http.Header{}) if err != nil { t.Fatal(err) } @@ -953,7 +953,7 @@ func TestFlushChannels(t *testing.T) { amazingCandidate := &ConnectionSetup{ URL: "ws" + mock.URL[len("http"):] + "/ws", Connector: func(ctx context.Context, conn Connection) error { - return conn.DialContext(ctx, gws.DefaultDialer, nil) + return conn.Dial(ctx, gws.DefaultDialer, nil) }, GenerateSubscriptions: newgen.generateSubs, Subscriber: func(context.Context, Connection, subscription.List) error { return nil }, @@ -1090,7 +1090,7 @@ func TestConnectionShutdown(t *testing.T) { err := wc.Shutdown() assert.NoError(t, err, "Shutdown should not error") - err = wc.Dial(&gws.Dialer{}, nil) + err = wc.Dial(t.Context(), &gws.Dialer{}, nil) assert.ErrorContains(t, err, "malformed ws or wss URL", "Dial should error correctly") mock := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { mockws.WsMockUpgrader(t, w, r, mockws.EchoHandler) })) @@ -1098,7 +1098,7 @@ func TestConnectionShutdown(t *testing.T) { wc.URL = "ws" + mock.URL[len("http"):] + "/ws" - err = wc.Dial(&gws.Dialer{}, nil) + err = wc.Dial(t.Context(), &gws.Dialer{}, nil) require.NoError(t, err, "Dial must not error") err = wc.Shutdown() @@ -1126,7 +1126,7 @@ func TestLatency(t *testing.T) { t.Skip("Proxy testing not enabled, skipping") } - err := wc.Dial(&gws.Dialer{}, http.Header{}) + err := wc.Dial(t.Context(), &gws.Dialer{}, http.Header{}) require.NoError(t, err) go readMessages(t, wc) diff --git a/exchanges/alphapoint/alphapoint.go b/exchanges/alphapoint/alphapoint.go index 48822bfc..3b88b8d9 100644 --- a/exchanges/alphapoint/alphapoint.go +++ b/exchanges/alphapoint/alphapoint.go @@ -542,7 +542,7 @@ func (a *Alphapoint) GetOrderFee(ctx context.Context, symbol, side string, quant } // SendHTTPRequest sends an unauthenticated HTTP request -func (a *Alphapoint) SendHTTPRequest(_ context.Context, ep exchange.URL, method, path string, data map[string]any, result any) error { +func (a *Alphapoint) SendHTTPRequest(ctx context.Context, ep exchange.URL, method, path string, data map[string]any, result any) error { endpoint, err := a.API.Endpoints.GetURL(ep) if err != nil { return err @@ -566,7 +566,7 @@ func (a *Alphapoint) SendHTTPRequest(_ context.Context, ep exchange.URL, method, HTTPRecording: a.HTTPRecording, } - return a.SendPayload(context.Background(), request.Unset, func() (*request.Item, error) { + return a.SendPayload(ctx, request.Unset, func() (*request.Item, error) { item.Body = bytes.NewBuffer(PayloadJSON) return item, nil }, request.UnauthenticatedRequest) @@ -617,7 +617,7 @@ func (a *Alphapoint) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchan HTTPRecording: a.HTTPRecording, } - return a.SendPayload(context.Background(), request.Unset, func() (*request.Item, error) { + return a.SendPayload(ctx, request.Unset, func() (*request.Item, error) { item.Body = bytes.NewBuffer(PayloadJSON) return item, nil }, request.AuthenticatedRequest) diff --git a/exchanges/binance/binance_live_test.go b/exchanges/binance/binance_live_test.go index a2831504..4b567e20 100644 --- a/exchanges/binance/binance_live_test.go +++ b/exchanges/binance/binance_live_test.go @@ -41,10 +41,11 @@ func TestMain(m *testing.M) { } } - b.setupOrderbookManager() + ctx := context.Background() + b.setupOrderbookManager(ctx) b.Websocket.DataHandler = sharedtestvalues.GetWebsocketInterfaceChannelOverride() log.Printf(sharedtestvalues.LiveTesting, b.Name) - if err := b.UpdateTradablePairs(context.Background(), true); err != nil { + if err := b.UpdateTradablePairs(ctx, true); err != nil { log.Fatal("Binance setup error", err) } diff --git a/exchanges/binance/binance_mock_test.go b/exchanges/binance/binance_mock_test.go index 6d074e27..a04c131e 100644 --- a/exchanges/binance/binance_mock_test.go +++ b/exchanges/binance/binance_mock_test.go @@ -29,8 +29,9 @@ func TestMain(m *testing.M) { log.Fatal(err) } - b.setupOrderbookManager() - if err := b.UpdateTradablePairs(context.Background(), true); err != nil { + ctx := context.Background() + b.setupOrderbookManager(ctx) + if err := b.UpdateTradablePairs(ctx, true); err != nil { log.Fatal(err) } diff --git a/exchanges/binance/binance_test.go b/exchanges/binance/binance_test.go index 52f80dfd..515c1e97 100644 --- a/exchanges/binance/binance_test.go +++ b/exchanges/binance/binance_test.go @@ -2092,7 +2092,7 @@ func TestWsDepthUpdate(t *testing.T) { t.Parallel() b := new(Binance) //nolint:govet // Intentional shadow to avoid future copy/paste mistakes require.NoError(t, testexch.Setup(b), "Test instance Setup must not error") - b.setupOrderbookManager() + b.setupOrderbookManager(t.Context()) seedLastUpdateID := int64(161) book := OrderBook{ Asks: []OrderbookItem{ @@ -2454,7 +2454,7 @@ func TestProcessOrderbookUpdate(t *testing.T) { t.Parallel() b := new(Binance) //nolint:govet // Intentional shadow to avoid future copy/paste mistakes require.NoError(t, testexch.Setup(b), "Test instance Setup must not error") - b.setupOrderbookManager() + b.setupOrderbookManager(t.Context()) p := currency.NewBTCUSDT() var depth WebsocketDepthStream err := json.Unmarshal(websocketDepthUpdate, &depth) diff --git a/exchanges/binance/binance_websocket.go b/exchanges/binance/binance_websocket.go index aff05ea9..1137eb37 100644 --- a/exchanges/binance/binance_websocket.go +++ b/exchanges/binance/binance_websocket.go @@ -51,6 +51,7 @@ var ( // WsConnect initiates a websocket connection func (b *Binance) WsConnect() error { + ctx := context.TODO() if !b.Websocket.IsEnabled() || !b.IsEnabled() { return websocket.ErrWebsocketNotEnabled } @@ -60,7 +61,7 @@ func (b *Binance) WsConnect() error { dialer.Proxy = http.ProxyFromEnvironment var err error if b.Websocket.CanUseAuthenticatedEndpoints() { - listenKey, err = b.GetWsAuthStreamKey(context.TODO()) + listenKey, err = b.GetWsAuthStreamKey(ctx) if err != nil { b.Websocket.SetCanUseAuthenticatedEndpoints(false) log.Errorf(log.ExchangeSys, @@ -78,7 +79,7 @@ func (b *Binance) WsConnect() error { } } - err = b.Websocket.Conn.Dial(&dialer, http.Header{}) + err = b.Websocket.Conn.Dial(ctx, &dialer, http.Header{}) if err != nil { return fmt.Errorf("%v - Unable to connect to Websocket. Error: %s", b.Name, @@ -86,7 +87,7 @@ func (b *Binance) WsConnect() error { } if b.Websocket.CanUseAuthenticatedEndpoints() { - go b.KeepAuthKeyAlive() + go b.KeepAuthKeyAlive(ctx) } b.Websocket.Conn.SetupPingHandler(request.Unset, websocket.PingHandler{ @@ -98,11 +99,11 @@ func (b *Binance) WsConnect() error { b.Websocket.Wg.Add(1) go b.wsReadData() - b.setupOrderbookManager() + b.setupOrderbookManager(ctx) return nil } -func (b *Binance) setupOrderbookManager() { +func (b *Binance) setupOrderbookManager(ctx context.Context) { if b.obm == nil { b.obm = &orderbookManager{ state: make(map[currency.Code]map[currency.Code]map[asset.Item]*update), @@ -123,13 +124,13 @@ func (b *Binance) setupOrderbookManager() { for range maxWSOrderbookWorkers { // 10 workers for synchronising book - b.SynchroniseWebsocketOrderbook() + b.SynchroniseWebsocketOrderbook(ctx) } } // KeepAuthKeyAlive will continuously send messages to // keep the WS auth key active -func (b *Binance) KeepAuthKeyAlive() { +func (b *Binance) KeepAuthKeyAlive(ctx context.Context) { b.Websocket.Wg.Add(1) defer b.Websocket.Wg.Done() ticks := time.NewTicker(time.Minute * 30) @@ -139,7 +140,7 @@ func (b *Binance) KeepAuthKeyAlive() { ticks.Stop() return case <-ticks.C: - err := b.MaintainWsAuthStreamKey(context.TODO()) + err := b.MaintainWsAuthStreamKey(ctx) if err != nil { b.Websocket.DataHandler <- err log.Warnf(log.ExchangeSys, "%s - Unable to renew auth websocket token, may experience shutdown", b.Name) @@ -558,16 +559,18 @@ func formatChannelInterval(s *subscription.Subscription) string { // Subscribe subscribes to a set of channels func (b *Binance) Subscribe(channels subscription.List) error { - return b.ParallelChanOp(channels, func(l subscription.List) error { return b.manageSubs(wsSubscribeMethod, l) }, 50) + ctx := context.TODO() + return b.ParallelChanOp(ctx, channels, func(ctx context.Context, l subscription.List) error { return b.manageSubs(ctx, wsSubscribeMethod, l) }, 50) } // Unsubscribe unsubscribes from a set of channels func (b *Binance) Unsubscribe(channels subscription.List) error { - return b.ParallelChanOp(channels, func(l subscription.List) error { return b.manageSubs(wsUnsubscribeMethod, l) }, 50) + ctx := context.TODO() + return b.ParallelChanOp(ctx, channels, func(ctx context.Context, l subscription.List) error { return b.manageSubs(ctx, wsUnsubscribeMethod, l) }, 50) } // manageSubs subscribes or unsubscribes from a list of subscriptions -func (b *Binance) manageSubs(op string, subs subscription.List) error { +func (b *Binance) manageSubs(ctx context.Context, op string, subs subscription.List) error { if op == wsSubscribeMethod { if err := b.Websocket.AddSubscriptions(b.Websocket.Conn, subs...); err != nil { // Note: AddSubscription will set state to subscribing return err @@ -584,7 +587,7 @@ func (b *Binance) manageSubs(op string, subs subscription.List) error { Params: subs.QualifiedChannels(), } - respRaw, err := b.Websocket.Conn.SendMessageReturnResponse(context.TODO(), request.Unset, req.ID, req) + respRaw, err := b.Websocket.Conn.SendMessageReturnResponse(ctx, request.Unset, req.ID, req) if err == nil { if v, d, _, rErr := jsonparser.Get(respRaw, "result"); rErr != nil { err = rErr @@ -699,7 +702,7 @@ func (o *orderbookManager) setNeedsFetchingBook(pair currency.Pair) error { // SynchroniseWebsocketOrderbook synchronises full orderbook for currency pair // asset -func (b *Binance) SynchroniseWebsocketOrderbook() { +func (b *Binance) SynchroniseWebsocketOrderbook(ctx context.Context) { b.Websocket.Wg.Add(1) go func() { defer b.Websocket.Wg.Done() @@ -714,7 +717,7 @@ func (b *Binance) SynchroniseWebsocketOrderbook() { } } case j := <-b.obm.jobs: - err := b.processJob(j.Pair) + err := b.processJob(ctx, j.Pair) if err != nil { log.Errorf(log.WebsocketMgr, "%s processing websocket orderbook error %v", @@ -726,8 +729,8 @@ func (b *Binance) SynchroniseWebsocketOrderbook() { } // processJob fetches and processes orderbook updates -func (b *Binance) processJob(p currency.Pair) error { - err := b.SeedLocalCache(context.TODO(), p) +func (b *Binance) processJob(ctx context.Context, p currency.Pair) error { + err := b.SeedLocalCache(ctx, p) if err != nil { return fmt.Errorf("%s %s seeding local cache for orderbook error: %v", p, asset.Spot, err) diff --git a/exchanges/binanceus/binanceus_test.go b/exchanges/binanceus/binanceus_test.go index 8c4f4108..62d6b5f7 100644 --- a/exchanges/binanceus/binanceus_test.go +++ b/exchanges/binanceus/binanceus_test.go @@ -1,6 +1,7 @@ package binanceus import ( + "context" "log" "os" reflects "reflect" @@ -60,7 +61,7 @@ func TestMain(m *testing.M) { if err != nil { log.Fatal("Binanceus TestMain()", err) } - bi.setupOrderbookManager() + bi.setupOrderbookManager(context.Background()) os.Exit(m.Run()) } @@ -1342,7 +1343,7 @@ func TestWebsocketStreamTradeUpdate(t *testing.T) { func TestWebsocketOrderBookDepthDiffStream(t *testing.T) { binanceusOrderBookLock.Lock() defer binanceusOrderBookLock.Unlock() - bi.setupOrderbookManager() + bi.setupOrderbookManager(t.Context()) seedLastUpdateID := int64(161) book := OrderBook{ Asks: []OrderbookItem{ diff --git a/exchanges/binanceus/binanceus_websocket.go b/exchanges/binanceus/binanceus_websocket.go index 9ba53dab..f3967e0b 100644 --- a/exchanges/binanceus/binanceus_websocket.go +++ b/exchanges/binanceus/binanceus_websocket.go @@ -45,6 +45,7 @@ var ( // WsConnect initiates a websocket connection func (bi *Binanceus) WsConnect() error { + ctx := context.TODO() if !bi.Websocket.IsEnabled() || !bi.IsEnabled() { return websocket.ErrWebsocketNotEnabled } @@ -53,7 +54,7 @@ func (bi *Binanceus) WsConnect() error { dialer.Proxy = http.ProxyFromEnvironment var err error if bi.Websocket.CanUseAuthenticatedEndpoints() { - listenKey, err = bi.GetWsAuthStreamKey(context.TODO()) + listenKey, err = bi.GetWsAuthStreamKey(ctx) if err != nil { bi.Websocket.SetCanUseAuthenticatedEndpoints(false) log.Errorf(log.ExchangeSys, @@ -70,7 +71,7 @@ func (bi *Binanceus) WsConnect() error { } } } - err = bi.Websocket.Conn.Dial(&dialer, http.Header{}) + err = bi.Websocket.Conn.Dial(ctx, &dialer, http.Header{}) if err != nil { return fmt.Errorf("%v - Unable to connect to Websocket. Error: %s", bi.Name, @@ -79,7 +80,7 @@ func (bi *Binanceus) WsConnect() error { if bi.Websocket.CanUseAuthenticatedEndpoints() { bi.Websocket.Wg.Add(1) - go bi.KeepAuthKeyAlive() + go bi.KeepAuthKeyAlive(ctx) } bi.Websocket.Conn.SetupPingHandler(request.Unset, websocket.PingHandler{ @@ -91,17 +92,17 @@ func (bi *Binanceus) WsConnect() error { bi.Websocket.Wg.Add(1) go bi.wsReadData() - bi.setupOrderbookManager() + bi.setupOrderbookManager(ctx) return nil } // KeepAuthKeyAlive will continuously send messages to // keep the WS auth key active -func (bi *Binanceus) KeepAuthKeyAlive() { +func (bi *Binanceus) KeepAuthKeyAlive(ctx context.Context) { defer bi.Websocket.Wg.Done() // ClosUserDataStream closes the User data stream and remove the listen key when closing the websocket. defer func() { - er := bi.CloseUserDataStream(context.Background()) + er := bi.CloseUserDataStream(ctx) if er != nil { log.Errorf(log.WebsocketMgr, "%s closing user data stream error %v", bi.Name, er) @@ -115,7 +116,7 @@ func (bi *Binanceus) KeepAuthKeyAlive() { ticks.Stop() return case <-ticks.C: - err := bi.MaintainWsAuthStreamKey(context.TODO()) + err := bi.MaintainWsAuthStreamKey(ctx) if err != nil { bi.Websocket.DataHandler <- err log.Warnf(log.ExchangeSys, "%s - Unable to renew auth websocket token, may experience shutdown", bi.Name) @@ -557,13 +558,14 @@ subs: // Subscribe subscribes to a set of channels func (bi *Binanceus) Subscribe(channelsToSubscribe subscription.List) error { + ctx := context.TODO() payload := WebsocketPayload{ Method: "SUBSCRIBE", } for i := range channelsToSubscribe { payload.Params = append(payload.Params, channelsToSubscribe[i].Channel) if i%50 == 0 && i != 0 { - err := bi.Websocket.Conn.SendJSONMessage(context.TODO(), request.Unset, payload) + err := bi.Websocket.Conn.SendJSONMessage(ctx, request.Unset, payload) if err != nil { return err } @@ -571,7 +573,7 @@ func (bi *Binanceus) Subscribe(channelsToSubscribe subscription.List) error { } } if len(payload.Params) > 0 { - err := bi.Websocket.Conn.SendJSONMessage(context.TODO(), request.Unset, payload) + err := bi.Websocket.Conn.SendJSONMessage(ctx, request.Unset, payload) if err != nil { return err } @@ -581,13 +583,14 @@ func (bi *Binanceus) Subscribe(channelsToSubscribe subscription.List) error { // Unsubscribe unsubscribes from a set of channels func (bi *Binanceus) Unsubscribe(channelsToUnsubscribe subscription.List) error { + ctx := context.TODO() payload := WebsocketPayload{ Method: "UNSUBSCRIBE", } for i := range channelsToUnsubscribe { payload.Params = append(payload.Params, channelsToUnsubscribe[i].Channel) if i%50 == 0 && i != 0 { - err := bi.Websocket.Conn.SendJSONMessage(context.TODO(), request.Unset, payload) + err := bi.Websocket.Conn.SendJSONMessage(ctx, request.Unset, payload) if err != nil { return err } @@ -595,7 +598,7 @@ func (bi *Binanceus) Unsubscribe(channelsToUnsubscribe subscription.List) error } } if len(payload.Params) > 0 { - err := bi.Websocket.Conn.SendJSONMessage(context.TODO(), request.Unset, payload) + err := bi.Websocket.Conn.SendJSONMessage(ctx, request.Unset, payload) if err != nil { return err } @@ -603,7 +606,7 @@ func (bi *Binanceus) Unsubscribe(channelsToUnsubscribe subscription.List) error return bi.Websocket.RemoveSubscriptions(bi.Websocket.Conn, channelsToUnsubscribe...) } -func (bi *Binanceus) setupOrderbookManager() { +func (bi *Binanceus) setupOrderbookManager(ctx context.Context) { if bi.obm == nil { bi.obm = &orderbookManager{ state: make(map[currency.Code]map[currency.Code]map[asset.Item]*update), @@ -623,12 +626,12 @@ func (bi *Binanceus) setupOrderbookManager() { } for range maxWSOrderbookWorkers { // 10 workers for synchronising book - bi.SynchroniseWebsocketOrderbook() + bi.SynchroniseWebsocketOrderbook(ctx) } } // SynchroniseWebsocketOrderbook synchronises full orderbook for currency pair asset -func (bi *Binanceus) SynchroniseWebsocketOrderbook() { +func (bi *Binanceus) SynchroniseWebsocketOrderbook(ctx context.Context) { bi.Websocket.Wg.Add(1) go func() { defer bi.Websocket.Wg.Done() @@ -643,7 +646,7 @@ func (bi *Binanceus) SynchroniseWebsocketOrderbook() { } } case j := <-bi.obm.jobs: - err := bi.processJob(j.Pair) + err := bi.processJob(ctx, j.Pair) if err != nil { log.Errorf(log.WebsocketMgr, "%s processing websocket orderbook error %v", @@ -767,8 +770,8 @@ func (o *orderbookManager) stopFetchingBook(pair currency.Pair) error { } // processJob fetches and processes orderbook updates -func (bi *Binanceus) processJob(p currency.Pair) error { - err := bi.SeedLocalCache(context.TODO(), p) +func (bi *Binanceus) processJob(ctx context.Context, p currency.Pair) error { + err := bi.SeedLocalCache(ctx, p) if err != nil { return fmt.Errorf("%s %s seeding local cache for orderbook error: %v", p, asset.Spot, err) diff --git a/exchanges/bitfinex/bitfinex_test.go b/exchanges/bitfinex/bitfinex_test.go index 023ebed1..345e04f2 100644 --- a/exchanges/bitfinex/bitfinex_test.go +++ b/exchanges/bitfinex/bitfinex_test.go @@ -1259,7 +1259,7 @@ func TestSubToMap(t *testing.T) { func TestWSNewOrder(t *testing.T) { sharedtestvalues.SkipTestIfCredentialsUnset(t, b, canManipulateRealOrders) testexch.SetupWs(t, b) - _, err := b.WsNewOrder(&WsNewOrderRequest{ + _, err := b.WsNewOrder(t.Context(), &WsNewOrderRequest{ GroupID: 1, Type: "EXCHANGE LIMIT", Symbol: "tXRPUSD", @@ -1272,14 +1272,14 @@ func TestWSNewOrder(t *testing.T) { func TestWSCancelOrder(t *testing.T) { sharedtestvalues.SkipTestIfCredentialsUnset(t, b, canManipulateRealOrders) testexch.SetupWs(t, b) - err := b.WsCancelOrder(1234) + err := b.WsCancelOrder(t.Context(), 1234) assert.NoError(t, err) } func TestWSModifyOrder(t *testing.T) { sharedtestvalues.SkipTestIfCredentialsUnset(t, b, canManipulateRealOrders) testexch.SetupWs(t, b) - err := b.WsModifyOrder(&WsUpdateOrderRequest{ + err := b.WsModifyOrder(t.Context(), &WsUpdateOrderRequest{ OrderID: 1234, Price: -111, Amount: 111, @@ -1290,21 +1290,21 @@ func TestWSModifyOrder(t *testing.T) { func TestWSCancelAllOrders(t *testing.T) { sharedtestvalues.SkipTestIfCredentialsUnset(t, b, canManipulateRealOrders) testexch.SetupWs(t, b) - err := b.WsCancelAllOrders() + err := b.WsCancelAllOrders(t.Context()) assert.NoError(t, err) } func TestWSCancelMultiOrders(t *testing.T) { sharedtestvalues.SkipTestIfCredentialsUnset(t, b, canManipulateRealOrders) testexch.SetupWs(t, b) - err := b.WsCancelMultiOrders([]int64{1, 2, 3, 4}) + err := b.WsCancelMultiOrders(t.Context(), []int64{1, 2, 3, 4}) assert.NoError(t, err) } func TestWSNewOffer(t *testing.T) { sharedtestvalues.SkipTestIfCredentialsUnset(t, b, canManipulateRealOrders) testexch.SetupWs(t, b) - err := b.WsNewOffer(&WsNewOfferRequest{ + err := b.WsNewOffer(t.Context(), &WsNewOfferRequest{ Type: order.Limit.String(), Symbol: "fBTC", Amount: -10, @@ -1317,14 +1317,14 @@ func TestWSNewOffer(t *testing.T) { func TestWSCancelOffer(t *testing.T) { sharedtestvalues.SkipTestIfCredentialsUnset(t, b, canManipulateRealOrders) testexch.SetupWs(t, b) - err := b.WsCancelOffer(1234) + err := b.WsCancelOffer(t.Context(), 1234) assert.NoError(t, err) } func TestWSSubscribedResponse(t *testing.T) { ch, err := b.Websocket.Match.Set("subscribe:waiter1", 1) assert.NoError(t, err, "Setting a matcher should not error") - err = b.wsHandleData([]byte(`{"event":"subscribed","channel":"ticker","chanId":224555,"subId":"waiter1","symbol":"tBTCUSD","pair":"BTCUSD"}`)) + err = b.wsHandleData(t.Context(), []byte(`{"event":"subscribed","channel":"ticker","chanId":224555,"subId":"waiter1","symbol":"tBTCUSD","pair":"BTCUSD"}`)) if assert.Error(t, err, "Should error if sub is not registered yet") { assert.ErrorIs(t, err, websocket.ErrSubscriptionFailure, "Should error SubFailure if sub isn't registered yet") assert.ErrorIs(t, err, subscription.ErrNotFound, "Should error SubNotFound if sub isn't registered yet") @@ -1333,7 +1333,7 @@ func TestWSSubscribedResponse(t *testing.T) { err = b.Websocket.AddSubscriptions(b.Websocket.Conn, &subscription.Subscription{Key: "waiter1"}) require.NoError(t, err, "AddSubscriptions must not error") - err = b.wsHandleData([]byte(`{"event":"subscribed","channel":"ticker","chanId":224555,"subId":"waiter1","symbol":"tBTCUSD","pair":"BTCUSD"}`)) + err = b.wsHandleData(t.Context(), []byte(`{"event":"subscribed","channel":"ticker","chanId":224555,"subId":"waiter1","symbol":"tBTCUSD","pair":"BTCUSD"}`)) assert.NoError(t, err, "wsHandleData should not error") if assert.NotEmpty(t, ch, "Matcher should have received a sub notification") { msg := <-ch @@ -1347,17 +1347,17 @@ func TestWSOrderBook(t *testing.T) { err := b.Websocket.AddSubscriptions(b.Websocket.Conn, &subscription.Subscription{Key: 23405, Asset: asset.Spot, Pairs: currency.Pairs{btcusdPair}, Channel: subscription.OrderbookChannel}) require.NoError(t, err, "AddSubscriptions must not error") pressXToJSON := `[23405,[[38334303613,9348.8,0.53],[38334308111,9348.8,5.98979404],[38331335157,9344.1,1.28965787],[38334302803,9343.8,0.08230094],[38334279092,9343,0.8],[38334307036,9342.938663676,0.8],[38332749107,9342.9,0.2],[38332277330,9342.8,0.85],[38329406786,9342,0.1432012],[38332841570,9341.947288638,0.3],[38332163238,9341.7,0.3],[38334303384,9341.6,0.324],[38332464840,9341.4,0.5],[38331935870,9341.2,0.5],[38334312082,9340.9,0.02126899],[38334261292,9340.8,0.26763],[38334138680,9340.625455254,0.12],[38333896802,9339.8,0.85],[38331627527,9338.9,1.57863959],[38334186713,9338.9,0.26769],[38334305819,9338.8,2.999],[38334211180,9338.75285796,3.999],[38334310699,9337.8,0.10679883],[38334307414,9337.5,1],[38334179822,9337.1,0.26773],[38334306600,9336.659955102,1.79],[38334299667,9336.6,1.1],[38334306452,9336.6,0.13979771],[38325672859,9336.3,1.25],[38334311646,9336.2,1],[38334258509,9336.1,0.37],[38334310592,9336,1.79],[38334310378,9335.6,1.43],[38334132444,9335.2,0.26777],[38331367325,9335,0.07],[38334310703,9335,0.10680562],[38334298209,9334.7,0.08757301],[38334304857,9334.456899462,0.291],[38334309940,9334.088390727,0.0725],[38334310377,9333.7,1.2868],[38334297615,9333.607784,0.1108],[38334095188,9333.3,0.26785],[38334228913,9332.7,0.40861186],[38334300526,9332.363996604,0.3884],[38334310701,9332.2,0.10680562],[38334303548,9332.005382871,0.07],[38334311798,9331.8,0.41285228],[38334301012,9331.7,1.7952],[38334089877,9331.4,0.2679],[38321942150,9331.2,0.2],[38334310670,9330,1.069],[38334063096,9329.6,0.26796],[38334310700,9329.4,0.10680562],[38334310404,9329.3,1],[38334281630,9329.1,6.57150597],[38334036864,9327.7,0.26801],[38334310702,9326.6,0.10680562],[38334311799,9326.1,0.50220625],[38334164163,9326,0.219638],[38334309722,9326,1.5],[38333051682,9325.8,0.26807],[38334302027,9325.7,0.75],[38334203435,9325.366592,0.32397696],[38321967613,9325,0.05],[38334298787,9324.9,0.3],[38334301719,9324.8,3.6227592],[38331316716,9324.763454646,0.71442],[38334310698,9323.8,0.10680562],[38334035499,9323.7,0.23431017],[38334223472,9322.670551788,0.42150603],[38334163459,9322.560399006,0.143967],[38321825171,9320.8,2],[38334075805,9320.467496148,0.30772633],[38334075800,9319.916732238,0.61457592],[38333682302,9319.7,0.0011],[38331323088,9319.116771762,0.12913],[38333677480,9319,0.0199],[38334277797,9318.6,0.89],[38325235155,9318.041088,1.20249],[38334310910,9317.82382938,1.79],[38334311811,9317.2,0.61079138],[38334311812,9317.2,0.71937652],[38333298214,9317.1,50],[38334306359,9317,1.79],[38325531545,9316.382823951,0.21263],[38333727253,9316.3,0.02316372],[38333298213,9316.1,45],[38333836479,9316,2.135],[38324520465,9315.9,2.7681],[38334307411,9315.5,1],[38330313617,9315.3,0.84455],[38334077770,9315.294024,0.01248397],[38334286663,9315.294024,1],[38325533762,9315.290315394,2.40498],[38334310018,9315.2,3],[38333682617,9314.6,0.0011],[38334304794,9314.6,0.76364676],[38334304798,9314.3,0.69242113],[38332915733,9313.8,0.0199],[38334084411,9312.8,1],[38334311893,9350.1,-1.015],[38334302734,9350.3,-0.26737],[38334300732,9350.8,-5.2],[38333957619,9351,-0.90677089],[38334300521,9351,-1.6457],[38334301600,9351.012829557,-0.0523],[38334308878,9351.7,-2.5],[38334299570,9351.921544,-0.1015],[38334279367,9352.1,-0.26732],[38334299569,9352.411802928,-0.4036],[38334202773,9353.4,-0.02139404],[38333918472,9353.7,-1.96412776],[38334278782,9354,-0.26731],[38334278606,9355,-1.2785],[38334302105,9355.439221251,-0.79191542],[38313897370,9355.569409242,-0.43363],[38334292995,9355.584296,-0.0979],[38334216989,9355.8,-0.03686414],[38333894025,9355.9,-0.26721],[38334293798,9355.936691952,-0.4311],[38331159479,9356,-0.4204022],[38333918888,9356.1,-1.10885563],[38334298205,9356.4,-0.20124428],[38328427481,9356.5,-0.1],[38333343289,9356.6,-0.41034213],[38334297205,9356.6,-0.08835018],[38334277927,9356.741101161,-0.0737],[38334311645,9356.8,-0.5],[38334309002,9356.9,-5],[38334309736,9357,-0.10680107],[38334306448,9357.4,-0.18645275],[38333693302,9357.7,-0.2672],[38332815159,9357.8,-0.0011],[38331239824,9358.2,-0.02],[38334271608,9358.3,-2.999],[38334311971,9358.4,-0.55],[38333919260,9358.5,-1.9972841],[38334265365,9358.5,-1.7841],[38334277960,9359,-3],[38334274601,9359.020969848,-3],[38326848839,9359.1,-0.84],[38334291080,9359.247048,-0.16199869],[38326848844,9359.4,-1.84],[38333680200,9359.6,-0.26713],[38331326606,9359.8,-0.84454],[38334309738,9359.8,-0.10680107],[38331314707,9359.9,-0.2],[38333919803,9360.9,-1.41177599],[38323651149,9361.33417827,-0.71442],[38333656906,9361.5,-0.26705],[38334035500,9361.5,-0.40861586],[38334091886,9362.4,-6.85940815],[38334269617,9362.5,-4],[38323629409,9362.545858872,-2.40497],[38334309737,9362.7,-0.10680107],[38334312380,9362.7,-3],[38325280830,9362.8,-1.75123],[38326622800,9362.8,-1.05145],[38333175230,9363,-0.0011],[38326848745,9363.2,-0.79],[38334308960,9363.206775564,-0.12],[38333920234,9363.3,-1.25318113],[38326848843,9363.4,-1.29],[38331239823,9363.4,-0.02],[38333209613,9363.4,-0.26719],[38334299964,9364,-0.05583123],[38323470224,9364.161816648,-0.12912],[38334284711,9365,-0.21346019],[38334299594,9365,-2.6757062],[38323211816,9365.073132585,-0.21262],[38334312456,9365.1,-0.11167861],[38333209612,9365.2,-0.26719],[38327770474,9365.3,-0.0073],[38334298788,9365.3,-0.3],[38334075803,9365.409831204,-0.30772637],[38334309740,9365.5,-0.10680107],[38326608767,9365.7,-2.76809],[38333920657,9365.7,-1.25848083],[38329594226,9366.6,-0.02587],[38334311813,9366.7,-4.72290945],[38316386301,9367.39258128,-2.37581],[38334302026,9367.4,-4.5],[38334228915,9367.9,-0.81725458],[38333921381,9368.1,-1.72213641],[38333175678,9368.2,-0.0011],[38334301150,9368.2,-2.654604],[38334297208,9368.3,-0.78036466],[38334309739,9368.3,-0.10680107],[38331227515,9368.7,-0.02],[38331184470,9369,-0.003975],[38334203436,9369.319616,-0.32397695],[38334269964,9369.7,-0.5],[38328386732,9370,-4.11759935],[38332719555,9370,-0.025],[38333921935,9370.5,-1.2224398],[38334258511,9370.5,-0.35],[38326848842,9370.8,-0.34],[38333985038,9370.9,-0.8551502],[38334283018,9370.9,-1],[38326848744,9371,-1.34]],5]` - err = b.wsHandleData([]byte(pressXToJSON)) + err = b.wsHandleData(t.Context(), []byte(pressXToJSON)) if err != nil { t.Error(err) } pressXToJSON = `[23405,[7617,52.98726298,7617.1,53.601795929999994,-550.9,-0.0674,7617,8318.92961981,8257.8,7500],6]` - err = b.wsHandleData([]byte(pressXToJSON)) + err = b.wsHandleData(t.Context(), []byte(pressXToJSON)) if err != nil { t.Error(err) } pressXToJSON = `[23405,[7617,52.98726298,7617.1,53.601795929999994,-550.9,-0.0674,7617,8318.92961981,8257.8,7500]]` - assert.NotPanics(t, func() { err = b.wsHandleData([]byte(pressXToJSON)) }, "handleWSBookUpdate should not panic when seqNo is not configured to be sent") + assert.NotPanics(t, func() { err = b.wsHandleData(t.Context(), []byte(pressXToJSON)) }, "handleWSBookUpdate should not panic when seqNo is not configured to be sent") assert.ErrorIs(t, err, errNoSeqNo, "handleWSBookUpdate should send correct error") } @@ -1402,7 +1402,7 @@ func TestWSTickerResponse(t *testing.T) { err := b.Websocket.AddSubscriptions(b.Websocket.Conn, &subscription.Subscription{Asset: asset.Spot, Pairs: currency.Pairs{btcusdPair}, Channel: subscription.TickerChannel, Key: 11534}) require.NoError(t, err, "AddSubscriptions must not error") pressXToJSON := `[11534,[61.304,2228.36155358,61.305,1323.2442970500003,0.395,0.0065,61.371,50973.3020771,62.5,57.421]]` - err = b.wsHandleData([]byte(pressXToJSON)) + err = b.wsHandleData(t.Context(), []byte(pressXToJSON)) if err != nil { t.Error(err) } @@ -1413,7 +1413,7 @@ func TestWSTickerResponse(t *testing.T) { err = b.Websocket.AddSubscriptions(b.Websocket.Conn, &subscription.Subscription{Asset: asset.Spot, Pairs: currency.Pairs{pair}, Channel: subscription.TickerChannel, Key: 123412}) require.NoError(t, err, "AddSubscriptions must not error") pressXToJSON = `[123412,[61.304,2228.36155358,61.305,1323.2442970500003,0.395,0.0065,61.371,50973.3020771,62.5,57.421]]` - err = b.wsHandleData([]byte(pressXToJSON)) + err = b.wsHandleData(t.Context(), []byte(pressXToJSON)) if err != nil { t.Error(err) } @@ -1424,7 +1424,7 @@ func TestWSTickerResponse(t *testing.T) { err = b.Websocket.AddSubscriptions(b.Websocket.Conn, &subscription.Subscription{Asset: asset.Spot, Pairs: currency.Pairs{pair}, Channel: subscription.TickerChannel, Key: 123413}) require.NoError(t, err, "AddSubscriptions must not error") pressXToJSON = `[123413,[61.304,2228.36155358,61.305,1323.2442970500003,0.395,0.0065,61.371,50973.3020771,62.5,57.421]]` - err = b.wsHandleData([]byte(pressXToJSON)) + err = b.wsHandleData(t.Context(), []byte(pressXToJSON)) if err != nil { t.Error(err) } @@ -1435,7 +1435,7 @@ func TestWSTickerResponse(t *testing.T) { err = b.Websocket.AddSubscriptions(b.Websocket.Conn, &subscription.Subscription{Asset: asset.Spot, Pairs: currency.Pairs{pair}, Channel: subscription.TickerChannel, Key: 123414}) require.NoError(t, err, "AddSubscriptions must not error") pressXToJSON = `[123414,[61.304,2228.36155358,61.305,1323.2442970500003,0.395,0.0065,61.371,50973.3020771,62.5,57.421]]` - err = b.wsHandleData([]byte(pressXToJSON)) + err = b.wsHandleData(t.Context(), []byte(pressXToJSON)) if err != nil { t.Error(err) } @@ -1445,12 +1445,12 @@ func TestWSCandleResponse(t *testing.T) { err := b.Websocket.AddSubscriptions(b.Websocket.Conn, &subscription.Subscription{Asset: asset.Spot, Pairs: currency.Pairs{btcusdPair}, Channel: subscription.CandlesChannel, Key: 343351}) require.NoError(t, err, "AddSubscriptions must not error") pressXToJSON := `[343351,[[1574698260000,7379.785503,7383.8,7388.3,7379.785503,1.68829482]]]` - err = b.wsHandleData([]byte(pressXToJSON)) + err = b.wsHandleData(t.Context(), []byte(pressXToJSON)) if err != nil { t.Error(err) } pressXToJSON = `[343351,[1574698200000,7399.9,7379.7,7399.9,7371.8,41.63633658]]` - err = b.wsHandleData([]byte(pressXToJSON)) + err = b.wsHandleData(t.Context(), []byte(pressXToJSON)) if err != nil { t.Error(err) } @@ -1458,12 +1458,12 @@ func TestWSCandleResponse(t *testing.T) { func TestWSOrderSnapshot(t *testing.T) { pressXToJSON := `[0,"os",[[34930659963,null,1574955083558,"tETHUSD",1574955083558,1574955083573,0.201104,0.201104,"EXCHANGE LIMIT",null,null,null,0,"ACTIVE",null,null,120,0,0,0,null,null,null,0,0,null,null,null,"BFX",null,null,null]]]` - err := b.wsHandleData([]byte(pressXToJSON)) + err := b.wsHandleData(t.Context(), []byte(pressXToJSON)) if err != nil { t.Error(err) } pressXToJSON = `[0,"oc",[34930659963,null,1574955083558,"tETHUSD",1574955083558,1574955354487,0.201104,0.201104,"EXCHANGE LIMIT",null,null,null,0,"CANCELED",null,null,120,0,0,0,null,null,null,0,0,null,null,null,"BFX",null,null,null]]` - err = b.wsHandleData([]byte(pressXToJSON)) + err = b.wsHandleData(t.Context(), []byte(pressXToJSON)) if err != nil { t.Error(err) } @@ -1471,13 +1471,13 @@ func TestWSOrderSnapshot(t *testing.T) { func TestWSNotifications(t *testing.T) { pressXToJSON := `[0,"n",[1575282446099,"fon-req",null,null,[41238905,null,null,null,-1000,null,null,null,null,null,null,null,null,null,0.002,2,null,null,null,null,null],null,"SUCCESS","Submitting funding bid of 1000.0 USD at 0.2000 for 2 days."]]` - err := b.wsHandleData([]byte(pressXToJSON)) + err := b.wsHandleData(t.Context(), []byte(pressXToJSON)) if err != nil { t.Error(err) } pressXToJSON = `[0,"n",[1575287438.515,"on-req",null,null,[1185815098,null,1575287436979,"tETHUSD",1575287438515,1575287438515,-2.5,-2.5,"LIMIT",null,null,null,0,"ACTIVE",null,null,230,0,0,0,null,null,null,0,null,null,null,null,"API>BFX",null,null,null],null,"SUCCESS","Submitting limit sell order for -2.5 ETH."]]` - err = b.wsHandleData([]byte(pressXToJSON)) + err = b.wsHandleData(t.Context(), []byte(pressXToJSON)) if err != nil { t.Error(err) } @@ -1485,76 +1485,76 @@ func TestWSNotifications(t *testing.T) { func TestWSFundingOfferSnapshotAndUpdate(t *testing.T) { pressXToJSON := `[0,"fos",[[41237920,"fETH",1573912039000,1573912039000,0.5,0.5,"LIMIT",null,null,0,"ACTIVE",null,null,null,0.0024,2,0,0,null,0,null]]]` - if err := b.wsHandleData([]byte(pressXToJSON)); err != nil { + if err := b.wsHandleData(t.Context(), []byte(pressXToJSON)); err != nil { t.Error(err) } pressXToJSON = `[0,"fon",[41238747,"fUST",1575026670000,1575026670000,5000,5000,"LIMIT",null,null,0,"ACTIVE",null,null,null,0.006000000000000001,30,0,0,null,0,null]]` - if err := b.wsHandleData([]byte(pressXToJSON)); err != nil { + if err := b.wsHandleData(t.Context(), []byte(pressXToJSON)); err != nil { t.Error(err) } } func TestWSFundingCreditSnapshotAndUpdate(t *testing.T) { pressXToJSON := `[0,"fcs",[[26223578,"fUST",1,1575052261000,1575296187000,350,0,"ACTIVE",null,null,null,0,30,1575052261000,1575293487000,0,0,null,0,null,0,"tBTCUST"],[26223711,"fUSD",-1,1575291961000,1575296187000,180,0,"ACTIVE",null,null,null,0.002,7,1575282446000,1575295587000,0,0,null,0,null,0,"tETHUSD"]]]` - if err := b.wsHandleData([]byte(pressXToJSON)); err != nil { + if err := b.wsHandleData(t.Context(), []byte(pressXToJSON)); err != nil { t.Error(err) } pressXToJSON = `[0,"fcu",[26223578,"fUST",1,1575052261000,1575296787000,350,0,"ACTIVE",null,null,null,0,30,1575052261000,1575293487000,0,0,null,0,null,0,"tBTCUST"]]` - if err := b.wsHandleData([]byte(pressXToJSON)); err != nil { + if err := b.wsHandleData(t.Context(), []byte(pressXToJSON)); err != nil { t.Error(err) } } func TestWSFundingLoanSnapshotAndUpdate(t *testing.T) { pressXToJSON := `[0,"fls",[[2995442,"fUSD",-1,1575291961000,1575295850000,820,0,"ACTIVE",null,null,null,0.002,7,1575282446000,1575295850000,0,0,null,0,null,0]]]` - if err := b.wsHandleData([]byte(pressXToJSON)); err != nil { + if err := b.wsHandleData(t.Context(), []byte(pressXToJSON)); err != nil { t.Error(err) } pressXToJSON = `[0,"fln",[2995444,"fUSD",-1,1575298742000,1575298742000,1000,0,"ACTIVE",null,null,null,0.002,7,1575298742000,1575298742000,0,0,null,0,null,0]]` - if err := b.wsHandleData([]byte(pressXToJSON)); err != nil { + if err := b.wsHandleData(t.Context(), []byte(pressXToJSON)); err != nil { t.Error(err) } } func TestWSWalletSnapshot(t *testing.T) { pressXToJSON := `[0,"ws",[["exchange","SAN",19.76,0,null,null,null]]]` - if err := b.wsHandleData([]byte(pressXToJSON)); err != nil { + if err := b.wsHandleData(t.Context(), []byte(pressXToJSON)); err != nil { t.Error(err) } } func TestWSBalanceUpdate(t *testing.T) { const pressXToJSON = `[0,"bu",[4131.85,4131.85]]` - if err := b.wsHandleData([]byte(pressXToJSON)); err != nil { + if err := b.wsHandleData(t.Context(), []byte(pressXToJSON)); err != nil { t.Error(err) } } func TestWSMarginInfoUpdate(t *testing.T) { const pressXToJSON = `[0,"miu",["base",[-13.014640000000007,0,49331.70267297,49318.68803297,27]]]` - if err := b.wsHandleData([]byte(pressXToJSON)); err != nil { + if err := b.wsHandleData(t.Context(), []byte(pressXToJSON)); err != nil { t.Error(err) } } func TestWSFundingInfoUpdate(t *testing.T) { const pressXToJSON = `[0,"fiu",["sym","tETHUSD",[149361.09689202666,149639.26293509,830.0182168075556,895.0658432466332]]]` - if err := b.wsHandleData([]byte(pressXToJSON)); err != nil { + if err := b.wsHandleData(t.Context(), []byte(pressXToJSON)); err != nil { t.Error(err) } } func TestWSFundingTrade(t *testing.T) { pressXToJSON := `[0,"fte",[636854,"fUSD",1575282446000,41238905,-1000,0.002,7,null]]` - if err := b.wsHandleData([]byte(pressXToJSON)); err != nil { + if err := b.wsHandleData(t.Context(), []byte(pressXToJSON)); err != nil { t.Error(err) } pressXToJSON = `[0,"ftu",[636854,"fUSD",1575282446000,41238905,-1000,0.002,7,null]]` - if err := b.wsHandleData([]byte(pressXToJSON)); err != nil { + if err := b.wsHandleData(t.Context(), []byte(pressXToJSON)); err != nil { t.Error(err) } } diff --git a/exchanges/bitfinex/bitfinex_websocket.go b/exchanges/bitfinex/bitfinex_websocket.go index e046e2d7..d2b8f017 100644 --- a/exchanges/bitfinex/bitfinex_websocket.go +++ b/exchanges/bitfinex/bitfinex_websocket.go @@ -123,11 +123,12 @@ var subscriptionNames = map[string]string{ // WsConnect starts a new websocket connection func (b *Bitfinex) WsConnect() error { + ctx := context.TODO() if !b.Websocket.IsEnabled() || !b.IsEnabled() { return websocket.ErrWebsocketNotEnabled } var dialer gws.Dialer - err := b.Websocket.Conn.Dial(&dialer, http.Header{}) + err := b.Websocket.Conn.Dial(ctx, &dialer, http.Header{}) if err != nil { return fmt.Errorf("%v unable to connect to Websocket. Error: %s", b.Name, @@ -137,7 +138,7 @@ func (b *Bitfinex) WsConnect() error { b.Websocket.Wg.Add(1) go b.wsReadData(b.Websocket.Conn) if b.Websocket.CanUseAuthenticatedEndpoints() { - err = b.Websocket.AuthConn.Dial(&dialer, http.Header{}) + err = b.Websocket.AuthConn.Dial(ctx, &dialer, http.Header{}) if err != nil { log.Errorf(log.ExchangeSys, "%v unable to connect to authenticated Websocket. Error: %s", @@ -147,7 +148,7 @@ func (b *Bitfinex) WsConnect() error { } b.Websocket.Wg.Add(1) go b.wsReadData(b.Websocket.AuthConn) - err = b.WsSendAuth(context.TODO()) + err = b.WsSendAuth(ctx) if err != nil { log.Errorf(log.ExchangeSys, "%v - authentication failed: %v\n", @@ -158,8 +159,8 @@ func (b *Bitfinex) WsConnect() error { } b.Websocket.Wg.Add(1) - go b.WsDataHandler() - return b.ConfigureWS() + go b.WsDataHandler(ctx) + return b.ConfigureWS(ctx) } // wsReadData receives and passes on websocket messages for processing @@ -175,14 +176,14 @@ func (b *Bitfinex) wsReadData(ws websocket.Connection) { } // WsDataHandler handles data from wsReadData -func (b *Bitfinex) WsDataHandler() { +func (b *Bitfinex) WsDataHandler(ctx context.Context) { defer b.Websocket.Wg.Done() for { select { case <-b.Websocket.ShutdownC: select { case resp := <-comms: - err := b.wsHandleData(resp.Raw) + err := b.wsHandleData(ctx, resp.Raw) if err != nil { select { case b.Websocket.DataHandler <- err: @@ -197,7 +198,7 @@ func (b *Bitfinex) WsDataHandler() { if resp.Type != gws.TextMessage { continue } - err := b.wsHandleData(resp.Raw) + err := b.wsHandleData(ctx, resp.Raw) if err != nil { b.Websocket.DataHandler <- err } @@ -205,7 +206,7 @@ func (b *Bitfinex) WsDataHandler() { } } -func (b *Bitfinex) wsHandleData(respRaw []byte) error { +func (b *Bitfinex) wsHandleData(_ context.Context, respRaw []byte) error { var result any if err := json.Unmarshal(respRaw, &result); err != nil { return err @@ -1709,8 +1710,8 @@ func (b *Bitfinex) GetSubscriptionTemplate(_ *subscription.Subscription) (*templ } // ConfigureWS to send checksums and sequence numbers -func (b *Bitfinex) ConfigureWS() error { - return b.Websocket.Conn.SendJSONMessage(context.TODO(), request.Unset, map[string]any{ +func (b *Bitfinex) ConfigureWS(ctx context.Context) error { + return b.Websocket.Conn.SendJSONMessage(ctx, request.Unset, map[string]any{ "event": "conf", "flags": bitfinexChecksumFlag + bitfinexWsSequenceFlag, }) @@ -1718,25 +1719,27 @@ func (b *Bitfinex) ConfigureWS() error { // Subscribe sends a websocket message to receive data from channels func (b *Bitfinex) Subscribe(subs subscription.List) error { + ctx := context.TODO() var err error if subs, err = subs.ExpandTemplates(b); err != nil { return err } - return b.ParallelChanOp(subs, b.subscribeToChan, 1) + return b.ParallelChanOp(ctx, subs, b.subscribeToChan, 1) } // Unsubscribe sends a websocket message to stop receiving data from channels func (b *Bitfinex) Unsubscribe(subs subscription.List) error { + ctx := context.TODO() var err error if subs, err = subs.ExpandTemplates(b); err != nil { return err } - return b.ParallelChanOp(subs, b.unsubscribeFromChan, 1) + return b.ParallelChanOp(ctx, subs, b.unsubscribeFromChan, 1) } // subscribeToChan handles a single subscription and parses the result // on success it adds the subscription to the websocket -func (b *Bitfinex) subscribeToChan(subs subscription.List) error { +func (b *Bitfinex) subscribeToChan(ctx context.Context, subs subscription.List) error { if len(subs) != 1 { return subscription.ErrNotSinglePair } @@ -1766,7 +1769,7 @@ func (b *Bitfinex) subscribeToChan(subs subscription.List) error { _ = b.Websocket.RemoveSubscriptions(b.Websocket.Conn, s) }() - respRaw, err := b.Websocket.Conn.SendMessageReturnResponse(context.TODO(), request.Unset, "subscribe:"+subID, req) + respRaw, err := b.Websocket.Conn.SendMessageReturnResponse(ctx, request.Unset, "subscribe:"+subID, req) if err != nil { return fmt.Errorf("%w: Channel: %s Pair: %s", err, s.Channel, s.Pairs) } @@ -1781,7 +1784,7 @@ func (b *Bitfinex) subscribeToChan(subs subscription.List) error { } // unsubscribeFromChan sends a websocket message to stop receiving data from a channel -func (b *Bitfinex) unsubscribeFromChan(subs subscription.List) error { +func (b *Bitfinex) unsubscribeFromChan(ctx context.Context, subs subscription.List) error { if len(subs) != 1 { return errors.New("subscription batching limited to 1") } @@ -1796,7 +1799,7 @@ func (b *Bitfinex) unsubscribeFromChan(subs subscription.List) error { "chanId": chanID, } - respRaw, err := b.Websocket.Conn.SendMessageReturnResponse(context.TODO(), request.Unset, "unsubscribe:"+strconv.Itoa(chanID), req) + respRaw, err := b.Websocket.Conn.SendMessageReturnResponse(ctx, request.Unset, "unsubscribe:"+strconv.Itoa(chanID), req) if err != nil { return err } @@ -1863,10 +1866,10 @@ func (b *Bitfinex) WsSendAuth(ctx context.Context) error { } // WsNewOrder authenticated new order request -func (b *Bitfinex) WsNewOrder(data *WsNewOrderRequest) (string, error) { +func (b *Bitfinex) WsNewOrder(ctx context.Context, data *WsNewOrderRequest) (string, error) { data.CustomID = b.Websocket.AuthConn.GenerateMessageID(false) req := makeRequestInterface(wsOrderNew, data) - resp, err := b.Websocket.AuthConn.SendMessageReturnResponse(context.TODO(), request.Unset, data.CustomID, req) + resp, err := b.Websocket.AuthConn.SendMessageReturnResponse(ctx, request.Unset, data.CustomID, req) if err != nil { return "", err } @@ -1921,9 +1924,9 @@ func (b *Bitfinex) WsNewOrder(data *WsNewOrderRequest) (string, error) { } // WsModifyOrder authenticated modify order request -func (b *Bitfinex) WsModifyOrder(data *WsUpdateOrderRequest) error { +func (b *Bitfinex) WsModifyOrder(ctx context.Context, data *WsUpdateOrderRequest) error { req := makeRequestInterface(wsOrderUpdate, data) - resp, err := b.Websocket.AuthConn.SendMessageReturnResponse(context.TODO(), request.Unset, data.OrderID, req) + resp, err := b.Websocket.AuthConn.SendMessageReturnResponse(ctx, request.Unset, data.OrderID, req) if err != nil { return err } @@ -1963,21 +1966,21 @@ func (b *Bitfinex) WsModifyOrder(data *WsUpdateOrderRequest) error { } // WsCancelMultiOrders authenticated cancel multi order request -func (b *Bitfinex) WsCancelMultiOrders(orderIDs []int64) error { +func (b *Bitfinex) WsCancelMultiOrders(ctx context.Context, orderIDs []int64) error { cancel := WsCancelGroupOrdersRequest{ OrderID: orderIDs, } req := makeRequestInterface(wsCancelMultipleOrders, cancel) - return b.Websocket.AuthConn.SendJSONMessage(context.TODO(), request.Unset, req) + return b.Websocket.AuthConn.SendJSONMessage(ctx, request.Unset, req) } // WsCancelOrder authenticated cancel order request -func (b *Bitfinex) WsCancelOrder(orderID int64) error { +func (b *Bitfinex) WsCancelOrder(ctx context.Context, orderID int64) error { cancel := WsCancelOrderRequest{ OrderID: orderID, } req := makeRequestInterface(wsOrderCancel, cancel) - resp, err := b.Websocket.AuthConn.SendMessageReturnResponse(context.TODO(), request.Unset, orderID, req) + resp, err := b.Websocket.AuthConn.SendMessageReturnResponse(ctx, request.Unset, orderID, req) if err != nil { return err } @@ -2016,25 +2019,25 @@ func (b *Bitfinex) WsCancelOrder(orderID int64) error { } // WsCancelAllOrders authenticated cancel all orders request -func (b *Bitfinex) WsCancelAllOrders() error { +func (b *Bitfinex) WsCancelAllOrders(ctx context.Context) error { cancelAll := WsCancelAllOrdersRequest{All: 1} req := makeRequestInterface(wsCancelMultipleOrders, cancelAll) - return b.Websocket.AuthConn.SendJSONMessage(context.TODO(), request.Unset, req) + return b.Websocket.AuthConn.SendJSONMessage(ctx, request.Unset, req) } // WsNewOffer authenticated new offer request -func (b *Bitfinex) WsNewOffer(data *WsNewOfferRequest) error { +func (b *Bitfinex) WsNewOffer(ctx context.Context, data *WsNewOfferRequest) error { req := makeRequestInterface(wsFundingOfferNew, data) - return b.Websocket.AuthConn.SendJSONMessage(context.TODO(), request.Unset, req) + return b.Websocket.AuthConn.SendJSONMessage(ctx, request.Unset, req) } // WsCancelOffer authenticated cancel offer request -func (b *Bitfinex) WsCancelOffer(orderID int64) error { +func (b *Bitfinex) WsCancelOffer(ctx context.Context, orderID int64) error { cancel := WsCancelOrderRequest{ OrderID: orderID, } req := makeRequestInterface(wsFundingOfferCancel, cancel) - resp, err := b.Websocket.AuthConn.SendMessageReturnResponse(context.TODO(), request.Unset, orderID, req) + resp, err := b.Websocket.AuthConn.SendMessageReturnResponse(ctx, request.Unset, orderID, req) if err != nil { return err } diff --git a/exchanges/bitfinex/bitfinex_wrapper.go b/exchanges/bitfinex/bitfinex_wrapper.go index 62859d91..134c95ac 100644 --- a/exchanges/bitfinex/bitfinex_wrapper.go +++ b/exchanges/bitfinex/bitfinex_wrapper.go @@ -588,7 +588,7 @@ func (b *Bitfinex) SubmitOrder(ctx context.Context, o *order.Submit) (*order.Sub // All v2 apis use negatives for Short side req.Amount *= -1 } - orderID, err = b.WsNewOrder(req) + orderID, err = b.WsNewOrder(ctx, req) if err != nil { return nil, err } @@ -644,7 +644,7 @@ func (b *Bitfinex) ModifyOrder(ctx context.Context, action *order.Modify) (*orde if action.Side.IsShort() && action.Amount > 0 { wsRequest.Amount *= -1 } - err = b.WsModifyOrder(&wsRequest) + err = b.WsModifyOrder(ctx, &wsRequest) if err != nil { return nil, err } @@ -669,7 +669,7 @@ func (b *Bitfinex) CancelOrder(ctx context.Context, o *order.Cancel) error { return err } if b.Websocket.CanUseAuthenticatedWebsocketForWrapper() { - err = b.WsCancelOrder(orderIDInt) + err = b.WsCancelOrder(ctx, orderIDInt) } else { _, err = b.CancelExistingOrder(ctx, orderIDInt) } @@ -688,7 +688,7 @@ func (b *Bitfinex) CancelBatchOrders(_ context.Context, _ []order.Cancel) (*orde func (b *Bitfinex) CancelAllOrders(ctx context.Context, _ *order.Cancel) (order.CancelAllResponse, error) { var err error if b.Websocket.CanUseAuthenticatedWebsocketForWrapper() { - err = b.WsCancelAllOrders() + err = b.WsCancelAllOrders(ctx) } else { _, err = b.CancelAllExistingOrders(ctx) } diff --git a/exchanges/bithumb/bithumb_websocket.go b/exchanges/bithumb/bithumb_websocket.go index 65b19285..ec5834f2 100644 --- a/exchanges/bithumb/bithumb_websocket.go +++ b/exchanges/bithumb/bithumb_websocket.go @@ -36,6 +36,7 @@ var defaultSubscriptions = subscription.List{ // WsConnect initiates a websocket connection func (b *Bithumb) WsConnect() error { + ctx := context.TODO() if !b.Websocket.IsEnabled() || !b.IsEnabled() { return websocket.ErrWebsocketNotEnabled } @@ -44,17 +45,15 @@ func (b *Bithumb) WsConnect() error { dialer.HandshakeTimeout = b.Config.HTTPTimeout dialer.Proxy = http.ProxyFromEnvironment - err := b.Websocket.Conn.Dial(&dialer, http.Header{}) + err := b.Websocket.Conn.Dial(ctx, &dialer, http.Header{}) if err != nil { - return fmt.Errorf("%v - Unable to connect to Websocket. Error: %w", - b.Name, - err) + return fmt.Errorf("%v - Unable to connect to Websocket. Error: %w", b.Name, err) } b.Websocket.Wg.Add(1) go b.wsReadData() - b.setupOrderbookManager() + b.setupOrderbookManager(ctx) return nil } @@ -183,9 +182,10 @@ func (b *Bithumb) GetSubscriptionTemplate(_ *subscription.Subscription) (*templa // Subscribe subscribes to a set of channels func (b *Bithumb) Subscribe(subs subscription.List) error { + ctx := context.TODO() var errs error for _, s := range subs { - err := b.Websocket.Conn.SendJSONMessage(context.TODO(), request.Unset, json.RawMessage(s.QualifiedChannel)) + err := b.Websocket.Conn.SendJSONMessage(ctx, request.Unset, json.RawMessage(s.QualifiedChannel)) if err == nil { err = b.Websocket.AddSuccessfulSubscriptions(b.Websocket.Conn, s) } diff --git a/exchanges/bithumb/bithumb_websocket_test.go b/exchanges/bithumb/bithumb_websocket_test.go index e310d773..265bdda5 100644 --- a/exchanges/bithumb/bithumb_websocket_test.go +++ b/exchanges/bithumb/bithumb_websocket_test.go @@ -51,7 +51,7 @@ func TestWsHandleData(t *testing.T) { }, } - dummy.setupOrderbookManager() + dummy.setupOrderbookManager(t.Context()) dummy.API.Endpoints = b.NewEndpoints() welcomeMsg := []byte(`{"status":"0000","resmsg":"Connected Successfully"}`) diff --git a/exchanges/bithumb/bithumb_ws_orderbook.go b/exchanges/bithumb/bithumb_ws_orderbook.go index 7c49fa32..f23005ef 100644 --- a/exchanges/bithumb/bithumb_ws_orderbook.go +++ b/exchanges/bithumb/bithumb_ws_orderbook.go @@ -85,21 +85,13 @@ func (b *Bithumb) applyBufferUpdate(pair currency.Pair) error { recent, err := b.Websocket.Orderbook.GetOrderbook(pair, asset.Spot) if err != nil { - log.Errorf( - log.WebsocketMgr, - "%s error fetching recent orderbook when applying updates: %s\n", - b.Name, - err) + log.Errorf(log.WebsocketMgr, "%s error fetching recent orderbook when applying updates: %s\n", b.Name, err) } if recent != nil { err = b.obm.checkAndProcessOrderbookUpdate(b.processBooks, pair, recent) if err != nil { - log.Errorf( - log.WebsocketMgr, - "%s error processing update - initiating new orderbook sync via REST: %s\n", - b.Name, - err) + log.Errorf(log.WebsocketMgr, "%s error processing update - initiating new orderbook sync via REST: %s\n", b.Name, err) err = b.obm.setNeedsFetchingBook(pair) if err != nil { return err @@ -112,7 +104,7 @@ func (b *Bithumb) applyBufferUpdate(pair currency.Pair) error { // SynchroniseWebsocketOrderbook synchronises full orderbook for currency pair // asset -func (b *Bithumb) SynchroniseWebsocketOrderbook() { +func (b *Bithumb) SynchroniseWebsocketOrderbook(ctx context.Context) { b.Websocket.Wg.Add(1) go func() { defer b.Websocket.Wg.Done() @@ -127,11 +119,9 @@ func (b *Bithumb) SynchroniseWebsocketOrderbook() { } } case j := <-b.obm.jobs: - err := b.processJob(j.Pair) + err := b.processJob(ctx, j.Pair) if err != nil { - log.Errorf(log.WebsocketMgr, - "%s processing websocket orderbook error %v", - b.Name, err) + log.Errorf(log.WebsocketMgr, "%s processing websocket orderbook error %v", b.Name, err) } } } @@ -139,8 +129,8 @@ func (b *Bithumb) SynchroniseWebsocketOrderbook() { } // processJob fetches and processes orderbook updates -func (b *Bithumb) processJob(p currency.Pair) error { - err := b.SeedLocalCache(context.TODO(), p) +func (b *Bithumb) processJob(ctx context.Context, p currency.Pair) error { + err := b.SeedLocalCache(ctx, p) if err != nil { return fmt.Errorf("%s %s seeding local cache for orderbook error: %v", p, asset.Spot, err) @@ -178,7 +168,7 @@ func (b *Bithumb) flushAndCleanup(p currency.Pair) { } } -func (b *Bithumb) setupOrderbookManager() { +func (b *Bithumb) setupOrderbookManager(ctx context.Context) { if b.obm.state == nil { b.obm.state = make(map[currency.Code]map[currency.Code]map[asset.Item]*update) b.obm.jobs = make(chan job, maxWSOrderbookJobs) @@ -197,7 +187,7 @@ func (b *Bithumb) setupOrderbookManager() { for range maxWSOrderbookWorkers { // 10 workers for synchronising book - b.SynchroniseWebsocketOrderbook() + b.SynchroniseWebsocketOrderbook(ctx) } } diff --git a/exchanges/bitmex/bitmex_test.go b/exchanges/bitmex/bitmex_test.go index a81dfe31..f5e26052 100644 --- a/exchanges/bitmex/bitmex_test.go +++ b/exchanges/bitmex/bitmex_test.go @@ -662,7 +662,7 @@ func TestWsAuth(t *testing.T) { t.Skip(websocket.ErrWebsocketNotEnabled.Error()) } var dialer gws.Dialer - err := b.Websocket.Conn.Dial(&dialer, http.Header{}) + err := b.Websocket.Conn.Dial(t.Context(), &dialer, http.Header{}) require.NoError(t, err) go b.wsReadData() diff --git a/exchanges/bitmex/bitmex_websocket.go b/exchanges/bitmex/bitmex_websocket.go index 1a7d480b..24a3a0ea 100644 --- a/exchanges/bitmex/bitmex_websocket.go +++ b/exchanges/bitmex/bitmex_websocket.go @@ -88,8 +88,9 @@ func (b *Bitmex) WsConnect() error { return websocket.ErrWebsocketNotEnabled } + ctx := context.TODO() var dialer gws.Dialer - if err := b.Websocket.Conn.Dial(&dialer, http.Header{}); err != nil { + if err := b.Websocket.Conn.Dial(ctx, &dialer, http.Header{}); err != nil { return err } @@ -97,7 +98,6 @@ func (b *Bitmex) WsConnect() error { go b.wsReadData() if b.Websocket.CanUseAuthenticatedEndpoints() { - ctx := context.TODO() if err := b.websocketSendAuth(ctx); err != nil { b.Websocket.SetCanUseAuthenticatedEndpoints(false) log.Errorf(log.ExchangeSys, "%v - authentication failed: %v\n", b.Name, err) @@ -521,21 +521,23 @@ func (b *Bitmex) GetSubscriptionTemplate(_ *subscription.Subscription) (*templat // Subscribe subscribes to a websocket channel func (b *Bitmex) Subscribe(subs subscription.List) error { + ctx := context.TODO() return common.AppendError( - b.ParallelChanOp(subs.Public(), func(l subscription.List) error { return b.manageSubs(wsSubscribeOp, l) }, len(subs)), - b.ParallelChanOp(subs.Private(), func(l subscription.List) error { return b.manageSubs(wsSubscribeOp, l) }, len(subs)), + b.ParallelChanOp(ctx, subs.Public(), func(ctx context.Context, l subscription.List) error { return b.manageSubs(ctx, wsSubscribeOp, l) }, len(subs)), + b.ParallelChanOp(ctx, subs.Private(), func(ctx context.Context, l subscription.List) error { return b.manageSubs(ctx, wsSubscribeOp, l) }, len(subs)), ) } // Unsubscribe sends a websocket message to stop receiving data from the channel func (b *Bitmex) Unsubscribe(subs subscription.List) error { + ctx := context.TODO() return common.AppendError( - b.ParallelChanOp(subs.Public(), func(l subscription.List) error { return b.manageSubs(wsUnsubscribeOp, l) }, len(subs)), - b.ParallelChanOp(subs.Private(), func(l subscription.List) error { return b.manageSubs(wsUnsubscribeOp, l) }, len(subs)), + b.ParallelChanOp(ctx, subs.Public(), func(ctx context.Context, l subscription.List) error { return b.manageSubs(ctx, wsUnsubscribeOp, l) }, len(subs)), + b.ParallelChanOp(ctx, subs.Private(), func(ctx context.Context, l subscription.List) error { return b.manageSubs(ctx, wsUnsubscribeOp, l) }, len(subs)), ) } -func (b *Bitmex) manageSubs(op string, subs subscription.List) error { +func (b *Bitmex) manageSubs(ctx context.Context, op string, subs subscription.List) error { req := WebsocketRequest{ Command: op, } @@ -548,7 +550,7 @@ func (b *Bitmex) manageSubs(op string, subs subscription.List) error { if err != nil { return err } - resps, errs := b.Websocket.Conn.SendMessageReturnResponses(context.TODO(), request.Unset, string(reqJSON), req, len(subs)) + resps, errs := b.Websocket.Conn.SendMessageReturnResponses(ctx, request.Unset, string(reqJSON), req, len(subs)) for _, resp := range resps { if errMsg, _ := jsonparser.GetString(resp, "error"); errMsg != "" { errs = common.AppendError(errs, errors.New(errMsg)) diff --git a/exchanges/bitstamp/bitstamp_test.go b/exchanges/bitstamp/bitstamp_test.go index 4353a874..7e805907 100644 --- a/exchanges/bitstamp/bitstamp_test.go +++ b/exchanges/bitstamp/bitstamp_test.go @@ -738,7 +738,7 @@ func TestWsSubscription(t *testing.T) { "channel": "[channel_name]" } }`) - err := b.wsHandleData(pressXToJSON) + err := b.wsHandleData(t.Context(), pressXToJSON) require.NoError(t, err, "TestWsSubscription must not error") } @@ -749,29 +749,29 @@ func TestWsUnsubscribe(t *testing.T) { "channel": "[channel_name]" } }`) - err := b.wsHandleData(pressXToJSON) + err := b.wsHandleData(t.Context(), pressXToJSON) require.NoError(t, err, "WsUnsubscribe must not error") } func TestWsTrade(t *testing.T) { pressXToJSON := []byte(`{"data": {"microtimestamp": "1580336751488517", "amount": 0.00598803, "buy_order_id": 4621328909, "sell_order_id": 4621329035, "amount_str": "0.00598803", "price_str": "9334.73", "timestamp": "1580336751", "price": 9334.73, "type": 1, "id": 104007706}, "event": "trade", "channel": "live_trades_btcusd"}`) - err := b.wsHandleData(pressXToJSON) + err := b.wsHandleData(t.Context(), pressXToJSON) require.NoError(t, err, "TestWsTrade must not error") } func TestWsOrderbook(t *testing.T) { pressXToJSON := []byte(`{"data": {"timestamp": "1580336834", "microtimestamp": "1580336834607546", "bids": [["9328.28", "0.05925332"], ["9327.34", "0.43120000"], ["9327.29", "0.63470860"], ["9326.59", "0.41114619"], ["9326.38", "1.06910000"], ["9323.91", "2.67930000"], ["9322.69", "0.80000000"], ["9322.57", "0.03000000"], ["9322.31", "1.36010820"], ["9319.54", "0.03090000"], ["9318.97", "0.28000000"], ["9317.61", "0.02910000"], ["9316.39", "1.08000000"], ["9316.20", "2.00000000"], ["9315.48", "1.00000000"], ["9314.72", "0.11197459"], ["9314.47", "0.32207398"], ["9312.53", "0.03961501"], ["9312.29", "1.00000000"], ["9311.78", "0.03060000"], ["9311.69", "0.32217221"], ["9310.98", "3.29000000"], ["9310.18", "0.01304192"], ["9310.13", "0.02500000"], ["9309.04", "1.00000000"], ["9309.00", "0.05000000"], ["9308.96", "0.03030000"], ["9308.91", "0.32227154"], ["9307.52", "0.32191362"], ["9307.25", "2.44280000"], ["9305.92", "3.00000000"], ["9305.62", "2.37600000"], ["9305.60", "0.21815312"], ["9305.54", "2.80000000"], ["9305.13", "0.05000000"], ["9305.02", "2.90917302"], ["9303.68", "0.02316372"], ["9303.53", "12.55000000"], ["9303.00", "0.02191430"], ["9302.94", "2.38250000"], ["9302.37", "0.01000000"], ["9301.85", "2.50000000"], ["9300.89", "0.02000000"], ["9300.40", "4.10000000"], ["9300.00", "0.33936139"], ["9298.48", "1.45200000"], ["9297.80", "0.42380000"], ["9295.44", "4.54689328"], ["9295.43", "3.20000000"], ["9295.00", "0.28669566"], ["9291.66", "14.09931321"], ["9290.13", "2.87254900"], ["9290.00", "0.67530840"], ["9285.37", "0.38033002"], ["9285.15", "5.37993528"], ["9285.00", "0.09419278"], ["9283.71", "0.15679830"], ["9280.33", "12.55000000"], ["9280.13", "3.20310000"], ["9280.00", "1.36477909"], ["9276.01", "0.00707488"], ["9275.75", "0.56974291"], ["9275.00", "5.88000000"], ["9274.00", "0.00754205"], ["9271.68", "0.01400000"], ["9271.11", "15.37188500"], ["9270.00", "0.06674325"], ["9268.79", "24.54320000"], ["9257.18", "12.55000000"], ["9256.30", "0.17876365"], ["9255.71", "13.82642967"], ["9254.79", "0.96329407"], ["9250.00", "0.78214958"], ["9245.34", "4.90200000"], ["9245.13", "0.10000000"], ["9240.00", "0.44383459"], ["9238.84", "13.16615207"], ["9234.11", "0.43317656"], ["9234.10", "12.55000000"], ["9231.28", "11.79290000"], ["9230.09", "4.15059441"], ["9227.69", "0.00791097"], ["9225.00", "0.44768346"], ["9224.49", "0.85857203"], ["9223.50", "5.61001041"], ["9216.01", "0.03222653"], ["9216.00", "0.05000000"], ["9213.54", "0.71253866"], ["9212.50", "2.86768195"], ["9211.07", "12.55000000"], ["9210.00", "0.54288817"], ["9208.00", "1.00000000"], ["9206.06", "2.62587578"], ["9205.98", "15.40000000"], ["9205.52", "0.01710603"], ["9205.37", "0.03524953"], ["9205.11", "0.15000000"], ["9205.00", "0.01534763"], ["9204.76", "7.00600000"], ["9203.00", "0.01090000"]], "asks": [["9337.10", "0.03000000"], ["9340.85", "2.67820000"], ["9340.95", "0.02900000"], ["9341.17", "1.00000000"], ["9341.41", "2.13966390"], ["9341.61", "0.20000000"], ["9341.97", "0.11199911"], ["9341.98", "3.00000000"], ["9342.26", "0.32112762"], ["9343.87", "1.00000000"], ["9344.17", "3.57250000"], ["9345.04", "0.32103450"], ["9345.41", "4.90000000"], ["9345.69", "1.03000000"], ["9345.80", "0.03000000"], ["9346.00", "0.10200000"], ["9346.69", "0.02397394"], ["9347.41", "1.00000000"], ["9347.82", "0.32094177"], ["9348.23", "0.02880000"], ["9348.62", "11.96287551"], ["9349.31", "2.44270000"], ["9349.47", "0.96000000"], ["9349.86", "4.50000000"], ["9350.37", "0.03300000"], ["9350.57", "0.34682266"], ["9350.60", "0.32085527"], ["9351.45", "0.31147923"], ["9352.31", "0.28000000"], ["9352.86", "9.80000000"], ["9353.73", "0.02360739"], ["9354.00", "0.45000000"], ["9354.12", "0.03000000"], ["9354.29", "3.82446861"], ["9356.20", "0.64000000"], ["9356.90", "0.02316372"], ["9357.30", "2.50000000"], ["9357.70", "2.38240000"], ["9358.92", "6.00000000"], ["9359.97", "0.34898075"], ["9359.98", "2.30000000"], ["9362.56", "2.37600000"], ["9365.00", "0.64000000"], ["9365.16", "1.70030306"], ["9365.27", "3.03000000"], ["9369.99", "2.47102665"], ["9370.00", "3.15688574"], ["9370.21", "2.32720000"], ["9371.78", "13.20000000"], ["9371.89", "0.96293482"], ["9375.08", "4.74762500"], ["9384.34", "1.45200000"], ["9384.49", "16.42310000"], ["9385.66", "0.34382112"], ["9388.19", "0.00268265"], ["9392.20", "0.20980000"], ["9392.40", "0.10320000"], ["9393.00", "0.20980000"], ["9395.40", "0.40000000"], ["9398.86", "24.54310000"], ["9400.00", "0.05489988"], ["9400.33", "0.00495100"], ["9400.45", "0.00484700"], ["9402.92", "17.20000000"], ["9404.18", "10.00000000"], ["9418.89", "16.38000000"], ["9419.41", "3.06700000"], ["9420.40", "12.50000000"], ["9421.11", "0.10500000"], ["9434.47", "0.03215805"], ["9434.48", "0.28285714"], ["9434.49", "15.83000000"], ["9435.13", "0.15000000"], ["9438.93", "0.00368800"], ["9439.19", "0.69343985"], ["9442.86", "0.10000000"], ["9443.96", "12.50000000"], ["9444.00", "0.06004471"], ["9444.97", "0.01494896"], ["9447.00", "0.01234000"], ["9448.97", "0.14500000"], ["9449.00", "0.05000000"], ["9450.00", "11.13426018"], ["9451.87", "15.90000000"], ["9452.00", "0.20000000"], ["9454.25", "0.01100000"], ["9454.51", "0.02409062"], ["9455.05", "0.00600063"], ["9456.00", "0.27965118"], ["9456.10", "0.17000000"], ["9459.00", "0.00320000"], ["9459.98", "0.02460685"], ["9459.99", "8.11000000"], ["9460.00", "0.08500000"], ["9464.36", "0.56957951"], ["9464.54", "0.69158059"], ["9465.00", "21.00002015"], ["9467.57", "12.50000000"], ["9468.00", "0.08800000"], ["9469.09", "13.94000000"]]}, "event": "data", "channel": "order_book_btcusd"}`) - err := b.wsHandleData(pressXToJSON) + err := b.wsHandleData(t.Context(), pressXToJSON) require.NoError(t, err, "wsHandleData must not error") pressXToJSON = []byte(`{"data": {"timestamp": "1580336834", "microtimestamp": "1580336834607546", "bids": [["9328.28", "0.05925332"], ["9327.34", "0.43120000"], ["9327.29", "0.63470860"], ["9326.59", "0.41114619"], ["9326.38", "1.06910000"], ["9323.91", "2.67930000"], ["9322.69", "0.80000000"], ["9322.57", "0.03000000"], ["9322.31", "1.36010820"], ["9319.54", "0.03090000"], ["9318.97", "0.28000000"], ["9317.61", "0.02910000"], ["9316.39", "1.08000000"], ["9316.20", "2.00000000"], ["9315.48", "1.00000000"], ["9314.72", "0.11197459"], ["9314.47", "0.32207398"], ["9312.53", "0.03961501"], ["9312.29", "1.00000000"], ["9311.78", "0.03060000"], ["9311.69", "0.32217221"], ["9310.98", "3.29000000"], ["9310.18", "0.01304192"], ["9310.13", "0.02500000"], ["9309.04", "1.00000000"], ["9309.00", "0.05000000"], ["9308.96", "0.03030000"], ["9308.91", "0.32227154"], ["9307.52", "0.32191362"], ["9307.25", "2.44280000"], ["9305.92", "3.00000000"], ["9305.62", "2.37600000"], ["9305.60", "0.21815312"], ["9305.54", "2.80000000"], ["9305.13", "0.05000000"], ["9305.02", "2.90917302"], ["9303.68", "0.02316372"], ["9303.53", "12.55000000"], ["9303.00", "0.02191430"], ["9302.94", "2.38250000"], ["9302.37", "0.01000000"], ["9301.85", "2.50000000"], ["9300.89", "0.02000000"], ["9300.40", "4.10000000"], ["9300.00", "0.33936139"], ["9298.48", "1.45200000"], ["9297.80", "0.42380000"], ["9295.44", "4.54689328"], ["9295.43", "3.20000000"], ["9295.00", "0.28669566"], ["9291.66", "14.09931321"], ["9290.13", "2.87254900"], ["9290.00", "0.67530840"], ["9285.37", "0.38033002"], ["9285.15", "5.37993528"], ["9285.00", "0.09419278"], ["9283.71", "0.15679830"], ["9280.33", "12.55000000"], ["9280.13", "3.20310000"], ["9280.00", "1.36477909"], ["9276.01", "0.00707488"], ["9275.75", "0.56974291"], ["9275.00", "5.88000000"], ["9274.00", "0.00754205"], ["9271.68", "0.01400000"], ["9271.11", "15.37188500"], ["9270.00", "0.06674325"], ["9268.79", "24.54320000"], ["9257.18", "12.55000000"], ["9256.30", "0.17876365"], ["9255.71", "13.82642967"], ["9254.79", "0.96329407"], ["9250.00", "0.78214958"], ["9245.34", "4.90200000"], ["9245.13", "0.10000000"], ["9240.00", "0.44383459"], ["9238.84", "13.16615207"], ["9234.11", "0.43317656"], ["9234.10", "12.55000000"], ["9231.28", "11.79290000"], ["9230.09", "4.15059441"], ["9227.69", "0.00791097"], ["9225.00", "0.44768346"], ["9224.49", "0.85857203"], ["9223.50", "5.61001041"], ["9216.01", "0.03222653"], ["9216.00", "0.05000000"], ["9213.54", "0.71253866"], ["9212.50", "2.86768195"], ["9211.07", "12.55000000"], ["9210.00", "0.54288817"], ["9208.00", "1.00000000"], ["9206.06", "2.62587578"], ["9205.98", "15.40000000"], ["9205.52", "0.01710603"], ["9205.37", "0.03524953"], ["9205.11", "0.15000000"], ["9205.00", "0.01534763"], ["9204.76", "7.00600000"], ["9203.00", "0.01090000"]], "asks": [["9337.10", "0.03000000"], ["9340.85", "2.67820000"], ["9340.95", "0.02900000"], ["9341.17", "1.00000000"], ["9341.41", "2.13966390"], ["9341.61", "0.20000000"], ["9341.97", "0.11199911"], ["9341.98", "3.00000000"], ["9342.26", "0.32112762"], ["9343.87", "1.00000000"], ["9344.17", "3.57250000"], ["9345.04", "0.32103450"], ["9345.41", "4.90000000"], ["9345.69", "1.03000000"], ["9345.80", "0.03000000"], ["9346.00", "0.10200000"], ["9346.69", "0.02397394"], ["9347.41", "1.00000000"], ["9347.82", "0.32094177"], ["9348.23", "0.02880000"], ["9348.62", "11.96287551"], ["9349.31", "2.44270000"], ["9349.47", "0.96000000"], ["9349.86", "4.50000000"], ["9350.37", "0.03300000"], ["9350.57", "0.34682266"], ["9350.60", "0.32085527"], ["9351.45", "0.31147923"], ["9352.31", "0.28000000"], ["9352.86", "9.80000000"], ["9353.73", "0.02360739"], ["9354.00", "0.45000000"], ["9354.12", "0.03000000"], ["9354.29", "3.82446861"], ["9356.20", "0.64000000"], ["9356.90", "0.02316372"], ["9357.30", "2.50000000"], ["9357.70", "2.38240000"], ["9358.92", "6.00000000"], ["9359.97", "0.34898075"], ["9359.98", "2.30000000"], ["9362.56", "2.37600000"], ["9365.00", "0.64000000"], ["9365.16", "1.70030306"], ["9365.27", "3.03000000"], ["9369.99", "2.47102665"], ["9370.00", "3.15688574"], ["9370.21", "2.32720000"], ["9371.78", "13.20000000"], ["9371.89", "0.96293482"], ["9375.08", "4.74762500"], ["9384.34", "1.45200000"], ["9384.49", "16.42310000"], ["9385.66", "0.34382112"], ["9388.19", "0.00268265"], ["9392.20", "0.20980000"], ["9392.40", "0.10320000"], ["9393.00", "0.20980000"], ["9395.40", "0.40000000"], ["9398.86", "24.54310000"], ["9400.00", "0.05489988"], ["9400.33", "0.00495100"], ["9400.45", "0.00484700"], ["9402.92", "17.20000000"], ["9404.18", "10.00000000"], ["9418.89", "16.38000000"], ["9419.41", "3.06700000"], ["9420.40", "12.50000000"], ["9421.11", "0.10500000"], ["9434.47", "0.03215805"], ["9434.48", "0.28285714"], ["9434.49", "15.83000000"], ["9435.13", "0.15000000"], ["9438.93", "0.00368800"], ["9439.19", "0.69343985"], ["9442.86", "0.10000000"], ["9443.96", "12.50000000"], ["9444.00", "0.06004471"], ["9444.97", "0.01494896"], ["9447.00", "0.01234000"], ["9448.97", "0.14500000"], ["9449.00", "0.05000000"], ["9450.00", "11.13426018"], ["9451.87", "15.90000000"], ["9452.00", "0.20000000"], ["9454.25", "0.01100000"], ["9454.51", "0.02409062"], ["9455.05", "0.00600063"], ["9456.00", "0.27965118"], ["9456.10", "0.17000000"], ["9459.00", "0.00320000"], ["9459.98", "0.02460685"], ["9459.99", "8.11000000"], ["9460.00", "0.08500000"], ["9464.36", "0.56957951"], ["9464.54", "0.69158059"], ["9465.00", "21.00002015"], ["9467.57", "12.50000000"], ["9468.00", "0.08800000"], ["9469.09", "13.94000000"]]}, "event": "data", "channel": ""}`) - err = b.wsHandleData(pressXToJSON) + err = b.wsHandleData(t.Context(), pressXToJSON) require.ErrorIs(t, err, errChannelUnderscores, "wsHandleData must error parsing channel") } func TestWsOrderbook2(t *testing.T) { pressXToJSON := []byte(`{"data":{"timestamp":"1606965727","microtimestamp":"1606965727403931","bids":[["19133.97","0.01000000"],["19131.58","0.39200000"],["19131.18","0.69581810"],["19131.17","0.48139054"],["19129.72","0.48164130"],["19129.71","0.65400000"],["19128.80","1.04500000"],["19128.59","0.65400000"],["19128.12","0.00259236"],["19127.81","0.19784245"],["19126.66","1.04500000"],["19125.74","0.26020000"],["19124.68","0.22000000"],["19122.01","0.39777840"],["19122.00","1.04600000"],["19121.27","0.16741000"],["19121.10","1.56390000"],["19119.90","1.60000000"],["19119.58","0.15593238"],["19117.70","1.14600000"],["19115.36","2.61300000"],["19114.60","1.19570000"],["19113.88","0.07500000"],["19113.86","0.15668522"],["19113.70","1.00000000"],["19113.69","1.60000000"],["19112.27","0.00166667"],["19111.00","0.15464628"],["19108.80","0.70000000"],["19108.77","0.16300000"],["19108.38","1.10000000"],["19107.53","0.10000000"],["19106.83","0.21377991"],["19106.78","3.45938881"],["19104.24","1.30000000"],["19100.81","0.00166667"],["19100.21","0.49770000"],["19099.54","2.40971961"],["19099.53","0.51223189"],["19097.40","1.55000000"],["19095.55","2.61300000"],["19092.94","0.27402906"],["19092.20","1.60000000"],["19089.36","0.00166667"],["19086.32","1.62000000"],["19085.23","1.65670000"],["19080.88","1.40000000"],["19075.45","1.16000000"],["19071.24","1.20000000"],["19065.09","1.51000000"],["19059.38","1.57000000"],["19058.11","0.37393556"],["19052.98","0.01000000"],["19052.90","0.33000000"],["19049.55","6.89000000"],["19047.61","6.03623432"],["19030.16","16.60260000"],["19026.76","23.90800000"],["19024.78","2.16656212"],["19022.11","0.02628500"],["19020.37","6.03000000"],["19000.00","0.00132020"],["18993.52","2.22000000"],["18979.21","6.03240000"],["18970.20","0.01500000"],["18969.14","7.42000000"],["18956.46","6.03240000"],["18950.22","42.37500000"],["18950.00","0.00132019"],["18949.94","0.52650000"],["18946.00","0.00791700"],["18933.74","6.03240000"],["18932.21","8.21000000"],["18926.99","0.00150000"],["18926.98","0.02641500"],["18925.00","0.02000000"],["18909.99","0.00133000"],["18908.47","7.15000000"],["18905.99","0.00133000"],["18905.20","0.00190000"],["18901.00","0.10000000"],["18900.67","0.24430000"],["18900.00","7.56529933"],["18895.99","0.00178450"],["18890.00","0.10000000"],["18889.90","0.10580000"],["18888.00","0.00362564"],["18887.00","4.00000000"],["18881.62","0.20583403"],["18880.08","5.72198740"],["18880.05","8.33480000"],["18879.09","7.33000000"],["18875.99","0.00132450"],["18875.00","0.02000000"],["18873.47","0.25934200"],["18871.99","0.00132600"],["18870.93","0.36463225"],["18864.10","43.56800000"],["18853.11","0.00540000"],["18850.01","0.38925549"]],"asks":[["19141.75","0.39300000"],["19141.78","0.10204700"],["19143.05","1.99685100"],["19143.08","0.05777900"],["19143.09","1.60700800"],["19143.10","0.48282909"],["19143.36","0.11250000"],["19144.06","0.26040000"],["19145.97","0.65400000"],["19146.02","0.22000000"],["19146.56","0.45061841"],["19147.45","0.15877831"],["19148.92","0.70431840"],["19148.93","0.78400000"],["19150.32","0.78400000"],["19151.55","0.07500000"],["19152.64","3.11400000"],["19153.32","1.04600000"],["19153.84","0.15626630"],["19155.57","3.10000000"],["19156.40","0.13438213"],["19156.92","0.16300000"],["19157.54","1.38970000"],["19158.18","0.00166667"],["19158.41","0.15317000"],["19158.78","0.15888798"],["19160.14","0.10000000"],["19160.34","1.60000000"],["19160.70","1.21590000"],["19162.17","0.00352761"],["19162.67","1.04500000"],["19163.61","0.15000000"],["19163.80","1.18050000"],["19164.62","0.86919692"],["19165.36","0.15674424"],["19166.75","1.40000000"],["19167.47","2.61300000"],["19169.68","0.00166667"],["19171.08","0.15452025"],["19171.69","0.54308236"],["19172.12","0.49000000"],["19173.47","1.34000000"],["19174.49","1.07436448"],["19175.37","0.01200000"],["19178.25","1.50000000"],["19178.80","0.49770000"],["19181.18","0.00166667"],["19182.75","1.77297176"],["19182.76","2.61099999"],["19183.03","1.20000000"],["19185.17","6.00352761"],["19189.56","0.05797137"],["19189.72","1.17000000"],["19193.94","1.60000000"],["19197.15","0.26961100"],["19200.00","0.03107838"],["19200.06","1.29000000"],["19202.73","1.65670000"],["19206.06","1.30000000"],["19208.19","6.00352761"],["19209.00","0.00132021"],["19210.70","1.20000000"],["19213.77","0.02615500"],["19217.40","8.50000000"],["19217.57","1.29000000"],["19222.61","1.19000000"],["19230.00","0.00193480"],["19231.24","6.00000000"],["19237.91","6.89152278"],["19240.13","6.90000000"],["19242.16","0.00336000"],["19243.38","0.00299103"],["19244.48","14.79300000"],["19248.25","0.01300000"],["19250.00","1.95802492"],["19251.00","0.45000000"],["19254.20","0.00366102"],["19254.32","6.00000000"],["19259.00","0.00131022"],["19266.43","0.00917191"],["19267.63","0.05000000"],["19267.79","7.10000000"],["19268.72","16.60260000"],["19277.42","6.00000000"],["19286.64","0.00916230"],["19295.49","7.77000000"],["19300.00","0.19668172"],["19306.00","0.06000000"],["19307.00","3.00000000"],["19307.40","0.19000000"],["19309.00","0.00262046"],["19310.33","0.02602500"],["19319.33","0.00213688"],["19320.00","0.00171242"],["19321.02","48.47300000"],["19322.74","0.00250000"],["19324.00","0.36983571"],["19325.54","0.02314521"],["19325.73","7.22000000"],["19326.50","0.00915272"]]},"channel":"order_book_btcusd","event":"data"}`) - err := b.wsHandleData(pressXToJSON) + err := b.wsHandleData(t.Context(), pressXToJSON) require.NoError(t, err, "WsOrderbook2 must not error") } @@ -859,7 +859,7 @@ func TestWsRequestReconnect(t *testing.T) { "channel": "", "data": "" }`) - err := b.wsHandleData(pressXToJSON) + err := b.wsHandleData(t.Context(), pressXToJSON) require.NoError(t, err, "WsRequestReconnect must not error") } diff --git a/exchanges/bitstamp/bitstamp_websocket.go b/exchanges/bitstamp/bitstamp_websocket.go index caaea5fd..6ca74d08 100644 --- a/exchanges/bitstamp/bitstamp_websocket.go +++ b/exchanges/bitstamp/bitstamp_websocket.go @@ -59,8 +59,9 @@ func (b *Bitstamp) WsConnect() error { if !b.Websocket.IsEnabled() || !b.IsEnabled() { return websocket.ErrWebsocketNotEnabled } + ctx := context.TODO() var dialer gws.Dialer - err := b.Websocket.Conn.Dial(&dialer, http.Header{}) + err := b.Websocket.Conn.Dial(ctx, &dialer, http.Header{}) if err != nil { return err } @@ -72,19 +73,19 @@ func (b *Bitstamp) WsConnect() error { Message: hbMsg, Delay: hbInterval, }) - err = b.seedOrderBook(context.TODO()) + err = b.seedOrderBook(ctx) if err != nil { b.Websocket.DataHandler <- err } b.Websocket.Wg.Add(1) - go b.wsReadData() + go b.wsReadData(ctx) return nil } // wsReadData receives and passes on websocket messages for processing -func (b *Bitstamp) wsReadData() { +func (b *Bitstamp) wsReadData(ctx context.Context) { defer b.Websocket.Wg.Done() for { @@ -92,13 +93,13 @@ func (b *Bitstamp) wsReadData() { if resp.Raw == nil { return } - if err := b.wsHandleData(resp.Raw); err != nil { + if err := b.wsHandleData(ctx, resp.Raw); err != nil { b.Websocket.DataHandler <- err } } } -func (b *Bitstamp) wsHandleData(respRaw []byte) error { +func (b *Bitstamp) wsHandleData(_ context.Context, respRaw []byte) error { event, err := jsonparser.GetUnsafeString(respRaw, "event") if err != nil { return fmt.Errorf("%w `event`: %w", common.ErrParsingWSField, err) @@ -236,24 +237,26 @@ func (b *Bitstamp) GetSubscriptionTemplate(_ *subscription.Subscription) (*templ // Subscribe sends a websocket message to receive data from a list of channels func (b *Bitstamp) Subscribe(subs subscription.List) error { - return b.manageSubsWithCreds(subs, "sub") + ctx := context.TODO() + return b.manageSubsWithCreds(ctx, subs, "sub") } // Unsubscribe sends a websocket message to stop receiving data from a list of channels func (b *Bitstamp) Unsubscribe(subs subscription.List) error { - return b.manageSubsWithCreds(subs, "unsub") + ctx := context.TODO() + return b.manageSubsWithCreds(ctx, subs, "unsub") } -func (b *Bitstamp) manageSubsWithCreds(subs subscription.List, op string) error { +func (b *Bitstamp) manageSubsWithCreds(ctx context.Context, subs subscription.List, op string) error { var errs error var creds *WebsocketAuthResponse if authed := subs.Private(); len(authed) > 0 { - creds, errs = b.FetchWSAuth(context.TODO()) + creds, errs = b.FetchWSAuth(ctx) } - return common.AppendError(errs, b.ParallelChanOp(subs, func(s subscription.List) error { return b.manageSubs(s, op, creds) }, 1)) + return common.AppendError(errs, b.ParallelChanOp(ctx, subs, func(ctx context.Context, s subscription.List) error { return b.manageSubs(ctx, s, op, creds) }, 1)) } -func (b *Bitstamp) manageSubs(subs subscription.List, op string, creds *WebsocketAuthResponse) error { +func (b *Bitstamp) manageSubs(ctx context.Context, subs subscription.List, op string, creds *WebsocketAuthResponse) error { subs, errs := subs.ExpandTemplates(b) for _, s := range subs { req := websocketEventRequest{ @@ -269,7 +272,7 @@ func (b *Bitstamp) manageSubs(subs subscription.List, op string, creds *Websocke req.Data.Channel = "private-" + req.Data.Channel + "-" + strconv.Itoa(int(creds.UserID)) req.Data.Auth = creds.Token } - _, err := b.Websocket.Conn.SendMessageReturnResponse(context.TODO(), request.Unset, op+":"+req.Data.Channel, req) + _, err := b.Websocket.Conn.SendMessageReturnResponse(ctx, request.Unset, op+":"+req.Data.Channel, req) if err == nil { if op == "sub" { err = b.Websocket.AddSuccessfulSubscriptions(b.Websocket.Conn, s) diff --git a/exchanges/btcmarkets/btcmarkets_test.go b/exchanges/btcmarkets/btcmarkets_test.go index cf9ec391..08b9b992 100644 --- a/exchanges/btcmarkets/btcmarkets_test.go +++ b/exchanges/btcmarkets/btcmarkets_test.go @@ -487,7 +487,7 @@ func TestWsTicker(t *testing.T) { "volume24h": "299.12936654", "messageType": "tick" }`) - err := b.wsHandleData(pressXToJSON) + err := b.wsHandleData(t.Context(), pressXToJSON) if err != nil { t.Error(err) } @@ -554,7 +554,7 @@ func TestWsFundChange(t *testing.T) { "fee": "0", "messageType": "fundChange" }`) - err := b.wsHandleData(pressXToJSON) + err := b.wsHandleData(t.Context(), pressXToJSON) if err != nil { t.Error(err) } @@ -576,7 +576,7 @@ func TestWsOrderbookUpdate(t *testing.T) { [ "101", "6.32", 2 ] ], "messageType": "orderbookUpdate" }`) - err := b.wsHandleData(pressXToJSON) + err := b.wsHandleData(t.Context(), pressXToJSON) if err != nil { t.Error(err) } @@ -589,7 +589,7 @@ func TestWsOrderbookUpdate(t *testing.T) { "messageType": "orderbookUpdate", "checksum": "2513007604" }`) - err = b.wsHandleData(pressXToJSON) + err = b.wsHandleData(t.Context(), pressXToJSON) if err != nil { t.Error(err) } @@ -601,7 +601,7 @@ func TestWsHeartbeats(t *testing.T) { "code": 3, "message": "invalid channel names" }`) - err := b.wsHandleData(pressXToJSON) + err := b.wsHandleData(t.Context(), pressXToJSON) if err == nil { t.Error("expected error") } @@ -611,7 +611,7 @@ func TestWsHeartbeats(t *testing.T) { "code": 3, "message": "invalid marketIds" }`) - err = b.wsHandleData(pressXToJSON) + err = b.wsHandleData(t.Context(), pressXToJSON) if err == nil { t.Error("expected error") } @@ -621,7 +621,7 @@ func TestWsHeartbeats(t *testing.T) { "code": 1, "message": "authentication failed. invalid key" }`) - err = b.wsHandleData(pressXToJSON) + err = b.wsHandleData(t.Context(), pressXToJSON) if err == nil { t.Error("expected error") } @@ -640,7 +640,7 @@ func TestWsOrders(t *testing.T) { "timestamp": "2019-04-08T20:41:19.339Z", "messageType": "orderChange" }`) - err := b.wsHandleData(pressXToJSON) + err := b.wsHandleData(t.Context(), pressXToJSON) if err != nil { t.Error(err) } @@ -663,7 +663,7 @@ func TestWsOrders(t *testing.T) { "timestamp": "2019-04-08T20:50:39.658Z", "messageType": "orderChange" }`) - err = b.wsHandleData(pressXToJSON) + err = b.wsHandleData(t.Context(), pressXToJSON) if err != nil { t.Error(err) } @@ -680,7 +680,7 @@ func TestWsOrders(t *testing.T) { "timestamp": "2019-04-08T20:41:41.857Z", "messageType": "orderChange" }`) - err = b.wsHandleData(pressXToJSON) + err = b.wsHandleData(t.Context(), pressXToJSON) if err != nil { t.Error(err) } @@ -703,7 +703,7 @@ func TestWsOrders(t *testing.T) { "timestamp": "2019-04-08T20:41:41.857Z", "messageType": "orderChange" }`) - err = b.wsHandleData(pressXToJSON) + err = b.wsHandleData(t.Context(), pressXToJSON) if err != nil { t.Error(err) } @@ -720,7 +720,7 @@ func TestWsOrders(t *testing.T) { "timestamp": "2019-04-08T20:41:41.857Z", "messageType": "orderChange" }`) - err = b.wsHandleData(pressXToJSON) + err = b.wsHandleData(t.Context(), pressXToJSON) if err != nil { t.Error(err) } diff --git a/exchanges/btcmarkets/btcmarkets_websocket.go b/exchanges/btcmarkets/btcmarkets_websocket.go index 4e185a88..5d75c1bd 100644 --- a/exchanges/btcmarkets/btcmarkets_websocket.go +++ b/exchanges/btcmarkets/btcmarkets_websocket.go @@ -55,11 +55,12 @@ var subscriptionNames = map[string]string{ // WsConnect connects to a websocket feed func (b *BTCMarkets) WsConnect() error { + ctx := context.TODO() if !b.Websocket.IsEnabled() || !b.IsEnabled() { return websocket.ErrWebsocketNotEnabled } var dialer gws.Dialer - err := b.Websocket.Conn.Dial(&dialer, http.Header{}) + err := b.Websocket.Conn.Dial(ctx, &dialer, http.Header{}) if err != nil { return err } @@ -68,12 +69,12 @@ func (b *BTCMarkets) WsConnect() error { } b.Websocket.Wg.Add(1) - go b.wsReadData() + go b.wsReadData(ctx) return nil } // wsReadData receives and passes on websocket messages for processing -func (b *BTCMarkets) wsReadData() { +func (b *BTCMarkets) wsReadData(ctx context.Context) { defer b.Websocket.Wg.Done() for { @@ -81,7 +82,7 @@ func (b *BTCMarkets) wsReadData() { if resp.Raw == nil { return } - err := b.wsHandleData(resp.Raw) + err := b.wsHandleData(ctx, resp.Raw) if err != nil { b.Websocket.DataHandler <- err } @@ -104,7 +105,7 @@ func (w *WebsocketOrderbook) UnmarshalJSON(data []byte) error { return nil } -func (b *BTCMarkets) wsHandleData(respRaw []byte) error { +func (b *BTCMarkets) wsHandleData(ctx context.Context, respRaw []byte) error { var wsResponse WsMessageType err := json.Unmarshal(respRaw, &wsResponse) if err != nil { @@ -272,7 +273,7 @@ func (b *BTCMarkets) wsHandleData(respRaw []byte) error { } clientID := "" - if creds, err := b.GetCredentials(context.TODO()); err != nil { + if creds, err := b.GetCredentials(ctx); err != nil { b.Websocket.DataHandler <- order.ClassificationError{ Exchange: b.Name, OrderID: orderID, @@ -322,13 +323,14 @@ func (b *BTCMarkets) GetSubscriptionTemplate(_ *subscription.Subscription) (*tem // Subscribe sends a websocket message to receive data from the channel func (b *BTCMarkets) Subscribe(subs subscription.List) error { + ctx := context.TODO() baseReq := &WsSubscribe{ MessageType: subscribe, } var errs error if authed := subs.Private(); len(authed) > 0 { - if err := b.signWsReq(baseReq); err != nil { + if err := b.signWsReq(ctx, baseReq); err != nil { errs = err for _, s := range authed { errs = common.AppendError(errs, fmt.Errorf("%w: %s", request.ErrAuthRequestFailed, s)) @@ -351,7 +353,7 @@ func (b *BTCMarkets) Subscribe(subs subscription.List) error { r.Channels[i] = s.QualifiedChannel } - err := b.Websocket.Conn.SendJSONMessage(context.TODO(), request.Unset, r) + err := b.Websocket.Conn.SendJSONMessage(ctx, request.Unset, r) if err == nil { err = b.Websocket.AddSuccessfulSubscriptions(b.Websocket.Conn, batch...) } @@ -363,8 +365,8 @@ func (b *BTCMarkets) Subscribe(subs subscription.List) error { return errs } -func (b *BTCMarkets) signWsReq(r *WsSubscribe) error { - creds, err := b.GetCredentials(context.TODO()) +func (b *BTCMarkets) signWsReq(ctx context.Context, r *WsSubscribe) error { + creds, err := b.GetCredentials(ctx) if err != nil { return err } @@ -381,6 +383,7 @@ func (b *BTCMarkets) signWsReq(r *WsSubscribe) error { // Unsubscribe sends a websocket message to manage and remove a subscription. func (b *BTCMarkets) Unsubscribe(subs subscription.List) error { + ctx := context.TODO() var errs error for _, s := range subs { req := WsSubscribe{ @@ -390,7 +393,7 @@ func (b *BTCMarkets) Unsubscribe(subs subscription.List) error { MarketIDs: s.Pairs.Strings(), } - err := b.Websocket.Conn.SendJSONMessage(context.TODO(), request.Unset, req) + err := b.Websocket.Conn.SendJSONMessage(ctx, request.Unset, req) if err == nil { err = b.Websocket.RemoveSubscriptions(b.Websocket.Conn, s) } diff --git a/exchanges/btse/btse_test.go b/exchanges/btse/btse_test.go index 550cd30f..b712c576 100644 --- a/exchanges/btse/btse_test.go +++ b/exchanges/btse/btse_test.go @@ -477,7 +477,7 @@ func TestCancelAllExchangeOrders(t *testing.T) { func TestWsOrderbook(t *testing.T) { t.Parallel() pressXToJSON := []byte(`{"topic":"orderBookL2Api:BTC-USD_0","data":{"buyQuote":[{"price":"9272.0","size":"0.077"},{"price":"9271.0","size":"1.122"},{"price":"9270.0","size":"2.548"},{"price":"9267.5","size":"1.015"},{"price":"9265.5","size":"0.930"},{"price":"9265.0","size":"0.475"},{"price":"9264.5","size":"2.216"},{"price":"9264.0","size":"9.709"},{"price":"9263.5","size":"3.667"},{"price":"9263.0","size":"8.481"},{"price":"9262.5","size":"7.660"},{"price":"9262.0","size":"9.689"},{"price":"9261.5","size":"4.213"},{"price":"9261.0","size":"1.491"},{"price":"9260.5","size":"6.264"},{"price":"9260.0","size":"1.690"},{"price":"9259.5","size":"5.718"},{"price":"9259.0","size":"2.706"},{"price":"9258.5","size":"0.192"},{"price":"9258.0","size":"1.592"},{"price":"9257.5","size":"1.749"},{"price":"9257.0","size":"8.104"},{"price":"9256.0","size":"0.161"},{"price":"9252.0","size":"1.544"},{"price":"9249.5","size":"1.462"},{"price":"9247.5","size":"1.833"},{"price":"9247.0","size":"0.168"},{"price":"9245.5","size":"1.941"},{"price":"9244.0","size":"1.423"},{"price":"9243.5","size":"0.175"}],"currency":"USD","sellQuote":[{"price":"9303.5","size":"1.839"},{"price":"9303.0","size":"2.067"},{"price":"9302.0","size":"0.117"},{"price":"9298.5","size":"1.569"},{"price":"9297.0","size":"1.527"},{"price":"9295.0","size":"0.184"},{"price":"9294.0","size":"1.785"},{"price":"9289.0","size":"1.673"},{"price":"9287.5","size":"4.194"},{"price":"9287.0","size":"6.622"},{"price":"9286.5","size":"2.147"},{"price":"9286.0","size":"3.348"},{"price":"9285.5","size":"5.655"},{"price":"9285.0","size":"10.423"},{"price":"9284.5","size":"6.233"},{"price":"9284.0","size":"8.860"},{"price":"9283.5","size":"9.441"},{"price":"9283.0","size":"3.455"},{"price":"9282.5","size":"11.033"},{"price":"9282.0","size":"11.471"},{"price":"9281.5","size":"4.742"},{"price":"9281.0","size":"14.789"},{"price":"9280.5","size":"11.117"},{"price":"9280.0","size":"0.807"},{"price":"9279.5","size":"1.651"},{"price":"9279.0","size":"0.244"},{"price":"9278.5","size":"0.533"},{"price":"9277.0","size":"1.447"},{"price":"9273.0","size":"1.976"},{"price":"9272.5","size":"0.093"}]}}`) - err := b.wsHandleData(pressXToJSON) + err := b.wsHandleData(t.Context(), pressXToJSON) assert.NoError(t, err, "wsHandleData orderBookL2Api should not error") // TODO: Meaningful test of data parsing } @@ -531,7 +531,7 @@ func TestWsOrderNotification(t *testing.T) { status := []string{"ORDER_INSERTED", "ORDER_CANCELLED", "TRIGGER_INSERTED", "ORDER_FULL_TRANSACTED", "ORDER_PARTIALLY_TRANSACTED", "INSUFFICIENT_BALANCE", "TRIGGER_ACTIVATED", "MARKET_UNAVAILABLE"} for i := range status { pressXToJSON := []byte(`{"topic": "notificationApi","data": [{"symbol": "BTC-USD","orderID": "1234","orderMode": "MODE_BUY","orderType": "TYPE_LIMIT","price": "1","size": "1","status": "` + status[i] + `","timestamp": "1580349090693","type": "STOP","triggerPrice": "1"}]}`) - err := b.wsHandleData(pressXToJSON) + err := b.wsHandleData(t.Context(), pressXToJSON) assert.NoErrorf(t, err, "wsHandleData notificationApi should not error on %s", status[i]) // TODO: Meaningful test of data parsing } @@ -637,12 +637,12 @@ func TestOrderbookFilter(t *testing.T) { func TestWsLogin(t *testing.T) { t.Parallel() data := []byte(`{"event":"login","success":true}`) - err := b.wsHandleData(data) + err := b.wsHandleData(t.Context(), data) assert.NoError(t, err, "wsHandleData login should not error") assert.True(t, b.Websocket.CanUseAuthenticatedEndpoints(), "CanUseAuthenticatedEndpoints should be true after login") data = []byte(`{"event":"login","success":false}`) - err = b.wsHandleData(data) + err = b.wsHandleData(t.Context(), data) assert.NoError(t, err, "wsHandleData login should not error") assert.False(t, b.Websocket.CanUseAuthenticatedEndpoints(), "CanUseAuthenticatedEndpoints should be false failed login") } @@ -650,14 +650,14 @@ func TestWsLogin(t *testing.T) { func TestWsSubscription(t *testing.T) { t.Parallel() data := []byte(`{"event":"subscribe","channel":["orderBookL2Api:SFI-ETH_0","tradeHistory:SFI-ETH"]}`) - err := b.wsHandleData(data) + err := b.wsHandleData(t.Context(), data) assert.NoError(t, err, "wsHandleData subscribe should not error") } func TestWsUnexpectedData(t *testing.T) { t.Parallel() data := []byte(`{}`) - err := b.wsHandleData(data) + err := b.wsHandleData(t.Context(), data) assert.ErrorContains(t, err, websocket.UnhandledMessage, "wsHandleData should error on empty message") } diff --git a/exchanges/btse/btse_websocket.go b/exchanges/btse/btse_websocket.go index 96df0ab4..515673a6 100644 --- a/exchanges/btse/btse_websocket.go +++ b/exchanges/btse/btse_websocket.go @@ -41,11 +41,12 @@ var defaultSubscriptions = subscription.List{ // WsConnect connects the websocket client func (b *BTSE) WsConnect() error { + ctx := context.TODO() if !b.Websocket.IsEnabled() || !b.IsEnabled() { return websocket.ErrWebsocketNotEnabled } var dialer gws.Dialer - err := b.Websocket.Conn.Dial(&dialer, http.Header{}) + err := b.Websocket.Conn.Dial(ctx, &dialer, http.Header{}) if err != nil { return err } @@ -55,10 +56,10 @@ func (b *BTSE) WsConnect() error { }) b.Websocket.Wg.Add(1) - go b.wsReadData() + go b.wsReadData(ctx) if b.IsWebsocketAuthenticationSupported() { - err = b.WsAuthenticate(context.TODO()) + err = b.WsAuthenticate(ctx) if err != nil { b.Websocket.DataHandler <- err b.Websocket.SetCanUseAuthenticatedEndpoints(false) @@ -111,7 +112,7 @@ func stringToOrderStatus(status string) (order.Status, error) { } // wsReadData receives and passes on websocket messages for processing -func (b *BTSE) wsReadData() { +func (b *BTSE) wsReadData(ctx context.Context) { defer b.Websocket.Wg.Done() for { @@ -119,14 +120,14 @@ func (b *BTSE) wsReadData() { if resp.Raw == nil { return } - err := b.wsHandleData(resp.Raw) + err := b.wsHandleData(ctx, resp.Raw) if err != nil { b.Websocket.DataHandler <- err } } } -func (b *BTSE) wsHandleData(respRaw []byte) error { +func (b *BTSE) wsHandleData(_ context.Context, respRaw []byte) error { type Result map[string]any var result Result err := json.Unmarshal(respRaw, &result) @@ -385,11 +386,12 @@ func (b *BTSE) GetSubscriptionTemplate(_ *subscription.Subscription) (*template. // Subscribe sends a websocket message to receive data from a list of channels func (b *BTSE) Subscribe(subs subscription.List) error { + ctx := context.TODO() req := wsSub{Operation: "subscribe"} for _, s := range subs { req.Arguments = append(req.Arguments, s.QualifiedChannel) } - err := b.Websocket.Conn.SendJSONMessage(context.TODO(), request.Unset, req) + err := b.Websocket.Conn.SendJSONMessage(ctx, request.Unset, req) if err == nil { err = b.Websocket.AddSuccessfulSubscriptions(b.Websocket.Conn, subs...) } @@ -398,11 +400,12 @@ func (b *BTSE) Subscribe(subs subscription.List) error { // Unsubscribe sends a websocket message to stop receiving data from a list of channels func (b *BTSE) Unsubscribe(subs subscription.List) error { + ctx := context.TODO() req := wsSub{Operation: "unsubscribe"} for _, s := range subs { req.Arguments = append(req.Arguments, s.QualifiedChannel) } - err := b.Websocket.Conn.SendJSONMessage(context.TODO(), request.Unset, req) + err := b.Websocket.Conn.SendJSONMessage(ctx, request.Unset, req) if err == nil { err = b.Websocket.RemoveSubscriptions(b.Websocket.Conn, subs...) } diff --git a/exchanges/bybit/bybit_inverse_websocket.go b/exchanges/bybit/bybit_inverse_websocket.go index c3c9a785..19068ddb 100644 --- a/exchanges/bybit/bybit_inverse_websocket.go +++ b/exchanges/bybit/bybit_inverse_websocket.go @@ -14,12 +14,13 @@ import ( // WsInverseConnect connects to inverse websocket feed func (by *Bybit) WsInverseConnect() error { + ctx := context.TODO() if !by.Websocket.IsEnabled() || !by.IsEnabled() || !by.IsAssetWebsocketSupported(asset.CoinMarginedFutures) { return websocket.ErrWebsocketNotEnabled } by.Websocket.Conn.SetURL(inversePublic) var dialer gws.Dialer - err := by.Websocket.Conn.Dial(&dialer, http.Header{}) + err := by.Websocket.Conn.Dial(ctx, &dialer, http.Header{}) if err != nil { return err } @@ -30,7 +31,7 @@ func (by *Bybit) WsInverseConnect() error { }) by.Websocket.Wg.Add(1) - go by.wsReadData(asset.CoinMarginedFutures, by.Websocket.Conn) + go by.wsReadData(ctx, asset.CoinMarginedFutures, by.Websocket.Conn) return nil } @@ -57,15 +58,17 @@ func (by *Bybit) GenerateInverseDefaultSubscriptions() (subscription.List, error // InverseSubscribe sends a subscription message to linear public channels. func (by *Bybit) InverseSubscribe(channelSubscriptions subscription.List) error { - return by.handleInversePayloadSubscription("subscribe", channelSubscriptions) + ctx := context.TODO() + return by.handleInversePayloadSubscription(ctx, "subscribe", channelSubscriptions) } // InverseUnsubscribe sends an unsubscription messages through linear public channels. func (by *Bybit) InverseUnsubscribe(channelSubscriptions subscription.List) error { - return by.handleInversePayloadSubscription("unsubscribe", channelSubscriptions) + ctx := context.TODO() + return by.handleInversePayloadSubscription(ctx, "unsubscribe", channelSubscriptions) } -func (by *Bybit) handleInversePayloadSubscription(operation string, channelSubscriptions subscription.List) error { +func (by *Bybit) handleInversePayloadSubscription(ctx context.Context, operation string, channelSubscriptions subscription.List) error { payloads, err := by.handleSubscriptions(operation, channelSubscriptions) if err != nil { return err @@ -73,7 +76,7 @@ func (by *Bybit) handleInversePayloadSubscription(operation string, channelSubsc for a := range payloads { // The options connection does not send the subscription request id back with the subscription notification payload // therefore the code doesn't wait for the response to check whether the subscription is successful or not. - err = by.Websocket.Conn.SendJSONMessage(context.TODO(), request.Unset, payloads[a]) + err = by.Websocket.Conn.SendJSONMessage(ctx, request.Unset, payloads[a]) if err != nil { return err } diff --git a/exchanges/bybit/bybit_linear_websocket.go b/exchanges/bybit/bybit_linear_websocket.go index 473d1b62..c96a58e3 100644 --- a/exchanges/bybit/bybit_linear_websocket.go +++ b/exchanges/bybit/bybit_linear_websocket.go @@ -14,12 +14,13 @@ import ( // WsLinearConnect connects to linear a websocket feed func (by *Bybit) WsLinearConnect() error { + ctx := context.TODO() if !by.Websocket.IsEnabled() || !by.IsEnabled() || !by.IsAssetWebsocketSupported(asset.LinearContract) { return websocket.ErrWebsocketNotEnabled } by.Websocket.Conn.SetURL(linearPublic) var dialer gws.Dialer - err := by.Websocket.Conn.Dial(&dialer, http.Header{}) + err := by.Websocket.Conn.Dial(ctx, &dialer, http.Header{}) if err != nil { return err } @@ -30,9 +31,9 @@ func (by *Bybit) WsLinearConnect() error { }) by.Websocket.Wg.Add(1) - go by.wsReadData(asset.LinearContract, by.Websocket.Conn) + go by.wsReadData(ctx, asset.LinearContract, by.Websocket.Conn) if by.IsWebsocketAuthenticationSupported() { - err = by.WsAuth(context.TODO()) + err = by.WsAuth(ctx) if err != nil { by.Websocket.DataHandler <- err by.Websocket.SetCanUseAuthenticatedEndpoints(false) @@ -75,15 +76,17 @@ func (by *Bybit) GenerateLinearDefaultSubscriptions() (subscription.List, error) // LinearSubscribe sends a subscription message to linear public channels. func (by *Bybit) LinearSubscribe(channelSubscriptions subscription.List) error { - return by.handleLinearPayloadSubscription("subscribe", channelSubscriptions) + ctx := context.TODO() + return by.handleLinearPayloadSubscription(ctx, "subscribe", channelSubscriptions) } // LinearUnsubscribe sends an unsubscription messages through linear public channels. func (by *Bybit) LinearUnsubscribe(channelSubscriptions subscription.List) error { - return by.handleLinearPayloadSubscription("unsubscribe", channelSubscriptions) + ctx := context.TODO() + return by.handleLinearPayloadSubscription(ctx, "unsubscribe", channelSubscriptions) } -func (by *Bybit) handleLinearPayloadSubscription(operation string, channelSubscriptions subscription.List) error { +func (by *Bybit) handleLinearPayloadSubscription(ctx context.Context, operation string, channelSubscriptions subscription.List) error { payloads, err := by.handleSubscriptions(operation, channelSubscriptions) if err != nil { return err @@ -91,7 +94,7 @@ func (by *Bybit) handleLinearPayloadSubscription(operation string, channelSubscr for a := range payloads { // The options connection does not send the subscription request id back with the subscription notification payload // therefore the code doesn't wait for the response to check whether the subscription is successful or not. - err = by.Websocket.Conn.SendJSONMessage(context.TODO(), request.Unset, payloads[a]) + err = by.Websocket.Conn.SendJSONMessage(ctx, request.Unset, payloads[a]) if err != nil { return err } diff --git a/exchanges/bybit/bybit_options_websocket.go b/exchanges/bybit/bybit_options_websocket.go index 646ed088..3eff209c 100644 --- a/exchanges/bybit/bybit_options_websocket.go +++ b/exchanges/bybit/bybit_options_websocket.go @@ -16,12 +16,13 @@ import ( // WsOptionsConnect connects to options a websocket feed func (by *Bybit) WsOptionsConnect() error { + ctx := context.TODO() if !by.Websocket.IsEnabled() || !by.IsEnabled() || !by.IsAssetWebsocketSupported(asset.Options) { return websocket.ErrWebsocketNotEnabled } by.Websocket.Conn.SetURL(optionPublic) var dialer gws.Dialer - err := by.Websocket.Conn.Dial(&dialer, http.Header{}) + err := by.Websocket.Conn.Dial(ctx, &dialer, http.Header{}) if err != nil { return err } @@ -37,7 +38,7 @@ func (by *Bybit) WsOptionsConnect() error { }) by.Websocket.Wg.Add(1) - go by.wsReadData(asset.Options, by.Websocket.Conn) + go by.wsReadData(ctx, asset.Options, by.Websocket.Conn) return nil } @@ -64,15 +65,17 @@ func (by *Bybit) GenerateOptionsDefaultSubscriptions() (subscription.List, error // OptionSubscribe sends a subscription message to options public channels. func (by *Bybit) OptionSubscribe(channelSubscriptions subscription.List) error { - return by.handleOptionsPayloadSubscription("subscribe", channelSubscriptions) + ctx := context.TODO() + return by.handleOptionsPayloadSubscription(ctx, "subscribe", channelSubscriptions) } // OptionUnsubscribe sends an unsubscription messages through options public channels. func (by *Bybit) OptionUnsubscribe(channelSubscriptions subscription.List) error { - return by.handleOptionsPayloadSubscription("unsubscribe", channelSubscriptions) + ctx := context.TODO() + return by.handleOptionsPayloadSubscription(ctx, "unsubscribe", channelSubscriptions) } -func (by *Bybit) handleOptionsPayloadSubscription(operation string, channelSubscriptions subscription.List) error { +func (by *Bybit) handleOptionsPayloadSubscription(ctx context.Context, operation string, channelSubscriptions subscription.List) error { payloads, err := by.handleSubscriptions(operation, channelSubscriptions) if err != nil { return err @@ -80,7 +83,7 @@ func (by *Bybit) handleOptionsPayloadSubscription(operation string, channelSubsc for a := range payloads { // The options connection does not send the subscription request id back with the subscription notification payload // therefore the code doesn't wait for the response to check whether the subscription is successful or not. - err = by.Websocket.Conn.SendJSONMessage(context.TODO(), request.Unset, payloads[a]) + err = by.Websocket.Conn.SendJSONMessage(ctx, request.Unset, payloads[a]) if err != nil { return err } diff --git a/exchanges/bybit/bybit_test.go b/exchanges/bybit/bybit_test.go index f81ee85f..bf64e0fb 100644 --- a/exchanges/bybit/bybit_test.go +++ b/exchanges/bybit/bybit_test.go @@ -1,6 +1,7 @@ package bybit import ( + "context" "errors" "fmt" "maps" @@ -3054,7 +3055,7 @@ func TestPushData(t *testing.T) { slices.Sort(keys) for x := range keys { - err := b.wsHandleData(asset.Spot, []byte(pushDataMap[keys[x]])) + err := b.wsHandleData(t.Context(), asset.Spot, []byte(pushDataMap[keys[x]])) assert.NoError(t, err, "wsHandleData should not error") } } @@ -3067,9 +3068,9 @@ func TestWsTicker(t *testing.T) { asset.USDCMarginedFutures, asset.USDCMarginedFutures, asset.CoinMarginedFutures, asset.CoinMarginedFutures, } require.NoError(t, testexch.Setup(b), "Test instance Setup must not error") - testexch.FixtureToDataHandler(t, "testdata/wsTicker.json", func(r []byte) error { + testexch.FixtureToDataHandler(t, "testdata/wsTicker.json", func(_ context.Context, r []byte) error { defer slices.Delete(assetRouting, 0, 1) - return b.wsHandleData(assetRouting[0], r) + return b.wsHandleData(t.Context(), assetRouting[0], r) }) close(b.Websocket.DataHandler) expected := 8 @@ -3318,7 +3319,7 @@ func TestFetchTradablePairs(t *testing.T) { func TestDeltaUpdateOrderbook(t *testing.T) { t.Parallel() data := []byte(`{"topic":"orderbook.50.WEMIXUSDT","ts":1697573183768,"type":"snapshot","data":{"s":"WEMIXUSDT","b":[["0.9511","260.703"],["0.9677","0"]],"a":[],"u":3119516,"seq":14126848493},"cts":1728966699481}`) - err := b.wsHandleData(asset.Spot, data) + err := b.wsHandleData(t.Context(), asset.Spot, data) if err != nil { t.Fatal(err) } diff --git a/exchanges/bybit/bybit_websocket.go b/exchanges/bybit/bybit_websocket.go index 9f78d90d..98a4cfac 100644 --- a/exchanges/bybit/bybit_websocket.go +++ b/exchanges/bybit/bybit_websocket.go @@ -80,11 +80,12 @@ var subscriptionNames = map[string]string{ // WsConnect connects to a websocket feed func (by *Bybit) WsConnect() error { + ctx := context.TODO() if !by.Websocket.IsEnabled() || !by.IsEnabled() || !by.IsAssetWebsocketSupported(asset.Spot) { return websocket.ErrWebsocketNotEnabled } var dialer gws.Dialer - err := by.Websocket.Conn.Dial(&dialer, http.Header{}) + err := by.Websocket.Conn.Dial(ctx, &dialer, http.Header{}) if err != nil { return err } @@ -95,9 +96,9 @@ func (by *Bybit) WsConnect() error { }) by.Websocket.Wg.Add(1) - go by.wsReadData(asset.Spot, by.Websocket.Conn) + go by.wsReadData(ctx, asset.Spot, by.Websocket.Conn) if by.Websocket.CanUseAuthenticatedEndpoints() { - err = by.WsAuth(context.TODO()) + err = by.WsAuth(ctx) if err != nil { by.Websocket.DataHandler <- err by.Websocket.SetCanUseAuthenticatedEndpoints(false) @@ -114,7 +115,7 @@ func (by *Bybit) WsAuth(ctx context.Context) error { } var dialer gws.Dialer - if err := by.Websocket.AuthConn.Dial(&dialer, http.Header{}); err != nil { + if err := by.Websocket.AuthConn.Dial(ctx, &dialer, http.Header{}); err != nil { return err } @@ -125,7 +126,7 @@ func (by *Bybit) WsAuth(ctx context.Context) error { }) by.Websocket.Wg.Add(1) - go by.wsReadData(asset.Spot, by.Websocket.AuthConn) + go by.wsReadData(ctx, asset.Spot, by.Websocket.AuthConn) intNonce := time.Now().Add(time.Hour * 6).UnixMilli() strNonce := strconv.FormatInt(intNonce, 10) @@ -143,7 +144,7 @@ func (by *Bybit) WsAuth(ctx context.Context) error { Operation: "auth", Args: []any{creds.Key, intNonce, sign}, } - resp, err := by.Websocket.AuthConn.SendMessageReturnResponse(context.TODO(), request.Unset, req.RequestID, req) + resp, err := by.Websocket.AuthConn.SendMessageReturnResponse(ctx, request.Unset, req.RequestID, req) if err != nil { return err } @@ -160,7 +161,8 @@ func (by *Bybit) WsAuth(ctx context.Context) error { // Subscribe sends a websocket message to receive data from the channel func (by *Bybit) Subscribe(channelsToSubscribe subscription.List) error { - return by.handleSpotSubscription("subscribe", channelsToSubscribe) + ctx := context.TODO() + return by.handleSpotSubscription(ctx, "subscribe", channelsToSubscribe) } func (by *Bybit) handleSubscriptions(operation string, subs subscription.List) (args []SubscriptionArgument, err error) { @@ -186,10 +188,11 @@ func (by *Bybit) handleSubscriptions(operation string, subs subscription.List) ( // Unsubscribe sends a websocket message to stop receiving data from the channel func (by *Bybit) Unsubscribe(channelsToUnsubscribe subscription.List) error { - return by.handleSpotSubscription("unsubscribe", channelsToUnsubscribe) + ctx := context.TODO() + return by.handleSpotSubscription(ctx, "unsubscribe", channelsToUnsubscribe) } -func (by *Bybit) handleSpotSubscription(operation string, channelsToSubscribe subscription.List) error { +func (by *Bybit) handleSpotSubscription(ctx context.Context, operation string, channelsToSubscribe subscription.List) error { payloads, err := by.handleSubscriptions(operation, channelsToSubscribe) if err != nil { return err @@ -197,12 +200,12 @@ func (by *Bybit) handleSpotSubscription(operation string, channelsToSubscribe su for a := range payloads { var response []byte if payloads[a].auth { - response, err = by.Websocket.AuthConn.SendMessageReturnResponse(context.TODO(), request.Unset, payloads[a].RequestID, payloads[a]) + response, err = by.Websocket.AuthConn.SendMessageReturnResponse(ctx, request.Unset, payloads[a].RequestID, payloads[a]) if err != nil { return err } } else { - response, err = by.Websocket.Conn.SendMessageReturnResponse(context.TODO(), request.Unset, payloads[a].RequestID, payloads[a]) + response, err = by.Websocket.Conn.SendMessageReturnResponse(ctx, request.Unset, payloads[a].RequestID, payloads[a]) if err != nil { return err } @@ -252,7 +255,7 @@ func (by *Bybit) GetSubscriptionTemplate(_ *subscription.Subscription) (*templat } // wsReadData receives and passes on websocket messages for processing -func (by *Bybit) wsReadData(assetType asset.Item, ws websocket.Connection) { +func (by *Bybit) wsReadData(ctx context.Context, assetType asset.Item, ws websocket.Connection) { defer by.Websocket.Wg.Done() for { select { @@ -263,7 +266,7 @@ func (by *Bybit) wsReadData(assetType asset.Item, ws websocket.Connection) { if resp.Raw == nil { return } - err := by.wsHandleData(assetType, resp.Raw) + err := by.wsHandleData(ctx, assetType, resp.Raw) if err != nil { by.Websocket.DataHandler <- err } @@ -271,7 +274,7 @@ func (by *Bybit) wsReadData(assetType asset.Item, ws websocket.Connection) { } } -func (by *Bybit) wsHandleData(assetType asset.Item, respRaw []byte) error { +func (by *Bybit) wsHandleData(ctx context.Context, assetType asset.Item, respRaw []byte) error { var result WebsocketResponse err := json.Unmarshal(respRaw, &result) if err != nil { @@ -322,7 +325,7 @@ func (by *Bybit) wsHandleData(assetType asset.Item, respRaw []byte) error { case chanOrder: return by.wsProcessOrder(asset.Spot, &result) case chanWallet: - return by.wsProcessWalletPushData(asset.Spot, respRaw) + return by.wsProcessWalletPushData(ctx, asset.Spot, respRaw) case chanGreeks: return by.wsProcessGreeks(respRaw) case chanDCP: @@ -341,13 +344,13 @@ func (by *Bybit) wsProcessGreeks(resp []byte) error { return nil } -func (by *Bybit) wsProcessWalletPushData(assetType asset.Item, resp []byte) error { +func (by *Bybit) wsProcessWalletPushData(ctx context.Context, assetType asset.Item, resp []byte) error { var result WebsocketWallet err := json.Unmarshal(resp, &result) if err != nil { return err } - creds, err := by.GetCredentials(context.TODO()) + creds, err := by.GetCredentials(ctx) if err != nil { return err } diff --git a/exchanges/coinbasepro/coinbasepro_test.go b/exchanges/coinbasepro/coinbasepro_test.go index a3da1d36..a0547846 100644 --- a/exchanges/coinbasepro/coinbasepro_test.go +++ b/exchanges/coinbasepro/coinbasepro_test.go @@ -680,9 +680,9 @@ func TestWsAuth(t *testing.T) { t.Skip(websocket.ErrWebsocketNotEnabled.Error()) } var dialer gws.Dialer - err := c.Websocket.Conn.Dial(&dialer, http.Header{}) + err := c.Websocket.Conn.Dial(t.Context(), &dialer, http.Header{}) require.NoError(t, err, "Dial must not error") - go c.wsReadData() + go c.wsReadData(t.Context()) err = c.Subscribe(subscription.List{{Channel: "user", Pairs: currency.Pairs{testPair}}}) require.NoError(t, err, "Subscribe must not error") @@ -723,7 +723,7 @@ func TestWsSubscribe(t *testing.T) { } ] }`) - err := c.wsHandleData(pressXToJSON) + err := c.wsHandleData(t.Context(), pressXToJSON) if err != nil { t.Error(err) } @@ -737,7 +737,7 @@ func TestWsHeartbeat(t *testing.T) { "product_id": "BTC-USD", "time": "2014-11-07T08:19:28.464459Z" }`) - err := c.wsHandleData(pressXToJSON) + err := c.wsHandleData(t.Context(), pressXToJSON) if err != nil { t.Error(err) } @@ -795,7 +795,7 @@ func TestWsStatus(t *testing.T) { } ] }`) - err := c.wsHandleData(pressXToJSON) + err := c.wsHandleData(t.Context(), pressXToJSON) if err != nil { t.Error(err) } @@ -814,7 +814,7 @@ func TestWsTicker(t *testing.T) { "best_bid": "4388", "best_ask": "4388.01" }`) - err := c.wsHandleData(pressXToJSON) + err := c.wsHandleData(t.Context(), pressXToJSON) if err != nil { t.Error(err) } @@ -828,7 +828,7 @@ func TestWsOrderbook(t *testing.T) { "asks": [["10102.55", "0.57753524"]], "time":"2023-08-15T06:46:55.376250Z" }`) - err := c.wsHandleData(pressXToJSON) + err := c.wsHandleData(t.Context(), pressXToJSON) if err != nil { t.Error(err) } @@ -845,7 +845,7 @@ func TestWsOrderbook(t *testing.T) { ] ] }`) - err = c.wsHandleData(pressXToJSON) + err = c.wsHandleData(t.Context(), pressXToJSON) if err != nil { t.Error(err) } @@ -863,7 +863,7 @@ func TestWsOrders(t *testing.T) { "side": "buy", "order_type": "limit" }`) - err := c.wsHandleData(pressXToJSON) + err := c.wsHandleData(t.Context(), pressXToJSON) if err != nil { t.Error(err) } @@ -878,7 +878,7 @@ func TestWsOrders(t *testing.T) { "side": "buy", "order_type": "market" }`) - err = c.wsHandleData(pressXToJSON) + err = c.wsHandleData(t.Context(), pressXToJSON) if err != nil { t.Error(err) } @@ -893,7 +893,7 @@ func TestWsOrders(t *testing.T) { "remaining_size": "1.00", "side": "sell" }`) - err = c.wsHandleData(pressXToJSON) + err = c.wsHandleData(t.Context(), pressXToJSON) if err != nil { t.Error(err) } @@ -909,7 +909,7 @@ func TestWsOrders(t *testing.T) { "side": "sell", "remaining_size": "0" }`) - err = c.wsHandleData(pressXToJSON) + err = c.wsHandleData(t.Context(), pressXToJSON) if err != nil { t.Error(err) } @@ -926,7 +926,7 @@ func TestWsOrders(t *testing.T) { "price": "400.23", "side": "sell" }`) - err = c.wsHandleData(pressXToJSON) + err = c.wsHandleData(t.Context(), pressXToJSON) if err != nil { t.Error(err) } @@ -942,7 +942,7 @@ func TestWsOrders(t *testing.T) { "price": "400.23", "side": "sell" }`) - err = c.wsHandleData(pressXToJSON) + err = c.wsHandleData(t.Context(), pressXToJSON) if err != nil { t.Error(err) } @@ -957,7 +957,7 @@ func TestWsOrders(t *testing.T) { "price": "400.23", "side": "sell" }`) - err = c.wsHandleData(pressXToJSON) + err = c.wsHandleData(t.Context(), pressXToJSON) if err != nil { t.Error(err) } @@ -976,7 +976,7 @@ func TestWsOrders(t *testing.T) { "taker_fee_rate": "0.0025", "private": true }`) - err = c.wsHandleData(pressXToJSON) + err = c.wsHandleData(t.Context(), pressXToJSON) if err != nil { t.Error(err) } diff --git a/exchanges/coinbasepro/coinbasepro_websocket.go b/exchanges/coinbasepro/coinbasepro_websocket.go index 867da5ea..2e0af901 100644 --- a/exchanges/coinbasepro/coinbasepro_websocket.go +++ b/exchanges/coinbasepro/coinbasepro_websocket.go @@ -30,22 +30,23 @@ const ( // WsConnect initiates a websocket connection func (c *CoinbasePro) WsConnect() error { + ctx := context.TODO() if !c.Websocket.IsEnabled() || !c.IsEnabled() { return websocket.ErrWebsocketNotEnabled } var dialer gws.Dialer - err := c.Websocket.Conn.Dial(&dialer, http.Header{}) + err := c.Websocket.Conn.Dial(ctx, &dialer, http.Header{}) if err != nil { return err } c.Websocket.Wg.Add(1) - go c.wsReadData() + go c.wsReadData(ctx) return nil } // wsReadData receives and passes on websocket messages for processing -func (c *CoinbasePro) wsReadData() { +func (c *CoinbasePro) wsReadData(ctx context.Context) { defer c.Websocket.Wg.Done() for { @@ -53,14 +54,14 @@ func (c *CoinbasePro) wsReadData() { if resp.Raw == nil { return } - err := c.wsHandleData(resp.Raw) + err := c.wsHandleData(ctx, resp.Raw) if err != nil { c.Websocket.DataHandler <- err } } } -func (c *CoinbasePro) wsHandleData(respRaw []byte) error { +func (c *CoinbasePro) wsHandleData(ctx context.Context, respRaw []byte) error { msgType := wsMsgType{} err := json.Unmarshal(respRaw, &msgType) if err != nil { @@ -165,7 +166,7 @@ func (c *CoinbasePro) wsHandleData(respRaw []byte) error { ts = convert.TimeFromUnixTimestampDecimal(wsOrder.Timestamp) } - creds, err := c.GetCredentials(context.TODO()) + creds, err := c.GetCredentials(ctx) if err != nil { c.Websocket.DataHandler <- order.ClassificationError{ Exchange: c.Name, @@ -377,6 +378,7 @@ func (c *CoinbasePro) generateSubscriptions() (subscription.List, error) { // Subscribe sends a websocket message to receive data from the channel func (c *CoinbasePro) Subscribe(subs subscription.List) error { + ctx := context.TODO() r := &WebsocketSubscribe{ Type: "subscribe", Channels: make([]any, 0, len(subs)), @@ -394,7 +396,7 @@ func (c *CoinbasePro) Subscribe(subs subscription.List) error { } for _, s := range subs { if s.Authenticated && r.Key == "" && c.IsWebsocketAuthenticationSupported() { - if err := c.authWsSubscibeReq(r); err != nil { + if err := c.authWsSubscibeReq(ctx, r); err != nil { return err } } @@ -409,15 +411,15 @@ func (c *CoinbasePro) Subscribe(subs subscription.List) error { r.Channels = append(r.Channels, s.Channel) } } - err := c.Websocket.Conn.SendJSONMessage(context.TODO(), request.Unset, r) + err := c.Websocket.Conn.SendJSONMessage(ctx, request.Unset, r) if err == nil { err = c.Websocket.AddSuccessfulSubscriptions(c.Websocket.Conn, subs...) } return err } -func (c *CoinbasePro) authWsSubscibeReq(r *WebsocketSubscribe) error { - creds, err := c.GetCredentials(context.TODO()) +func (c *CoinbasePro) authWsSubscibeReq(ctx context.Context, r *WebsocketSubscribe) error { + creds, err := c.GetCredentials(ctx) if err != nil { return err } @@ -435,6 +437,7 @@ func (c *CoinbasePro) authWsSubscibeReq(r *WebsocketSubscribe) error { // Unsubscribe sends a websocket message to stop receiving data from the channel func (c *CoinbasePro) Unsubscribe(subs subscription.List) error { + ctx := context.TODO() r := &WebsocketSubscribe{ Type: "unsubscribe", Channels: make([]any, 0, len(subs)), @@ -445,7 +448,7 @@ func (c *CoinbasePro) Unsubscribe(subs subscription.List) error { ProductIDs: s.Pairs.Strings(), }) } - err := c.Websocket.Conn.SendJSONMessage(context.TODO(), request.Unset, r) + err := c.Websocket.Conn.SendJSONMessage(ctx, request.Unset, r) if err == nil { err = c.Websocket.RemoveSubscriptions(c.Websocket.Conn, subs...) } diff --git a/exchanges/coinut/coinut_test.go b/exchanges/coinut/coinut_test.go index c1884ce9..1d2695fa 100644 --- a/exchanges/coinut/coinut_test.go +++ b/exchanges/coinut/coinut_test.go @@ -78,17 +78,17 @@ func setupWSTestAuth(t *testing.T) { } var dialer gws.Dialer - err := c.Websocket.Conn.Dial(&dialer, http.Header{}) + err := c.Websocket.Conn.Dial(t.Context(), &dialer, http.Header{}) if err != nil { t.Fatal(err) } - go c.wsReadData() + go c.wsReadData(t.Context()) err = c.wsAuthenticate(t.Context()) if err != nil { t.Error(err) } wsSetupRan = true - _, err = c.WsGetInstruments() + _, err = c.WsGetInstruments(t.Context()) if err != nil { t.Error(err) } @@ -434,7 +434,7 @@ func TestGetDepositAddress(t *testing.T) { // TestWsAuthGetAccountBalance dials websocket, retrieves account balance func TestWsAuthGetAccountBalance(t *testing.T) { setupWSTestAuth(t) - if _, err := c.wsGetAccountBalance(); err != nil { + if _, err := c.wsGetAccountBalance(t.Context()); err != nil { t.Error(err) } } @@ -452,7 +452,7 @@ func TestWsAuthSubmitOrder(t *testing.T) { Price: 1, Side: order.Buy, } - if _, err := c.wsSubmitOrder(&ord); err != nil { + if _, err := c.wsSubmitOrder(t.Context(), &ord); err != nil { t.Error(err) } } @@ -477,7 +477,7 @@ func TestWsAuthSubmitOrders(t *testing.T) { Price: 2, Side: order.Buy, } - _, err := c.wsSubmitOrders([]WsSubmitOrderParameters{order1, order2}) + _, err := c.wsSubmitOrders(t.Context(), []WsSubmitOrderParameters{order1, order2}) if err != nil { t.Error(err) } @@ -498,7 +498,7 @@ func TestWsAuthCancelOrders(t *testing.T) { Currency: currency.NewPair(currency.LTC, currency.BTC), OrderID: 2, } - resp, err := c.wsCancelOrders([]WsCancelOrderParameters{ord, order2}) + resp, err := c.wsCancelOrders(t.Context(), []WsCancelOrderParameters{ord, order2}) if err != nil { t.Error(err) } @@ -533,7 +533,7 @@ func TestWsAuthCancelOrder(t *testing.T) { Currency: currency.NewPair(currency.LTC, currency.BTC), OrderID: 1, } - resp, err := c.wsCancelOrder(ord) + resp, err := c.wsCancelOrder(t.Context(), ord) if err != nil { t.Error(err) } @@ -545,7 +545,7 @@ func TestWsAuthCancelOrder(t *testing.T) { // TestWsAuthGetOpenOrders dials websocket, retrieves open orders func TestWsAuthGetOpenOrders(t *testing.T) { setupWSTestAuth(t) - _, err := c.wsGetOpenOrders(currency.NewPair(currency.LTC, currency.BTC).String()) + _, err := c.wsGetOpenOrders(t.Context(), currency.NewPair(currency.LTC, currency.BTC).String()) if err != nil { t.Error(err) } diff --git a/exchanges/coinut/coinut_websocket.go b/exchanges/coinut/coinut_websocket.go index 511995f4..2a9eb649 100644 --- a/exchanges/coinut/coinut_websocket.go +++ b/exchanges/coinut/coinut_websocket.go @@ -41,27 +41,28 @@ var channels map[string]chan []byte // WsConnect initiates a websocket connection func (c *COINUT) WsConnect() error { + ctx := context.TODO() if !c.Websocket.IsEnabled() || !c.IsEnabled() { return websocket.ErrWebsocketNotEnabled } var dialer gws.Dialer - err := c.Websocket.Conn.Dial(&dialer, http.Header{}) + err := c.Websocket.Conn.Dial(ctx, &dialer, http.Header{}) if err != nil { return err } c.Websocket.Wg.Add(1) - go c.wsReadData() + go c.wsReadData(ctx) if !c.instrumentMap.IsLoaded() { - _, err = c.WsGetInstruments() + _, err = c.WsGetInstruments(ctx) if err != nil { return err } } if c.IsWebsocketAuthenticationSupported() { - if err = c.wsAuthenticate(context.TODO()); err != nil { + if err = c.wsAuthenticate(ctx); err != nil { c.Websocket.SetCanUseAuthenticatedEndpoints(false) log.Errorln(log.WebsocketMgr, c.Name+" "+err.Error()) } @@ -75,11 +76,9 @@ func (c *COINUT) WsConnect() error { } // wsReadData receives and passes on websocket messages for processing -func (c *COINUT) wsReadData() { +func (c *COINUT) wsReadData(ctx context.Context) { defer c.Websocket.Wg.Done() - ctx := context.TODO() - for { resp := c.Websocket.Conn.ReadMessage() if resp.Raw == nil { @@ -473,14 +472,14 @@ func (c *COINUT) parseOrderContainer(oContainer *wsOrderContainer) (*order.Detai } // WsGetInstruments fetches instrument list and propagates a local cache -func (c *COINUT) WsGetInstruments() (Instruments, error) { +func (c *COINUT) WsGetInstruments(ctx context.Context) (Instruments, error) { var list Instruments req := wsRequest{ Request: "inst_list", SecurityType: strings.ToUpper(asset.Spot.String()), Nonce: getNonce(), } - resp, err := c.Websocket.Conn.SendMessageReturnResponse(context.TODO(), request.Unset, req.Nonce, req) + resp, err := c.Websocket.Conn.SendMessageReturnResponse(ctx, request.Unset, req.Nonce, req) if err != nil { return list, err } @@ -601,6 +600,7 @@ func (c *COINUT) GenerateDefaultSubscriptions() (subscription.List, error) { // Subscribe sends a websocket message to receive data from the channel func (c *COINUT) Subscribe(subs subscription.List) error { + ctx := context.TODO() var errs error for _, s := range subs { if len(s.Pairs) != 1 { @@ -618,7 +618,7 @@ func (c *COINUT) Subscribe(subs subscription.List) error { Subscribe: true, Nonce: getNonce(), } - err = c.Websocket.Conn.SendJSONMessage(context.TODO(), request.Unset, subscribe) + err = c.Websocket.Conn.SendJSONMessage(ctx, request.Unset, subscribe) if err == nil { err = c.Websocket.AddSuccessfulSubscriptions(c.Websocket.Conn, s) } @@ -631,6 +631,7 @@ func (c *COINUT) Subscribe(subs subscription.List) error { // Unsubscribe sends a websocket message to stop receiving data from the channel func (c *COINUT) Unsubscribe(channelToUnsubscribe subscription.List) error { + ctx := context.TODO() var errs error for _, s := range channelToUnsubscribe { if len(s.Pairs) != 1 { @@ -648,7 +649,7 @@ func (c *COINUT) Unsubscribe(channelToUnsubscribe subscription.List) error { Subscribe: false, Nonce: getNonce(), } - resp, err := c.Websocket.Conn.SendMessageReturnResponse(context.TODO(), request.Unset, subscribe.Nonce, subscribe) + resp, err := c.Websocket.Conn.SendMessageReturnResponse(ctx, request.Unset, subscribe.Nonce, subscribe) if err != nil { errs = common.AppendError(errs, err) continue @@ -691,7 +692,7 @@ func (c *COINUT) wsAuthenticate(ctx context.Context) error { } r.Hmac = hex.EncodeToString(hmac) - resp, err := c.Websocket.Conn.SendMessageReturnResponse(context.TODO(), request.Unset, r.Nonce, r) + resp, err := c.Websocket.Conn.SendMessageReturnResponse(ctx, request.Unset, r.Nonce, r) if err != nil { return err } @@ -706,7 +707,7 @@ func (c *COINUT) wsAuthenticate(ctx context.Context) error { return nil } -func (c *COINUT) wsGetAccountBalance() (*UserBalance, error) { +func (c *COINUT) wsGetAccountBalance(ctx context.Context) (*UserBalance, error) { if !c.Websocket.CanUseAuthenticatedEndpoints() { return nil, fmt.Errorf("%v not authorised to submit order", c.Name) } @@ -714,7 +715,7 @@ func (c *COINUT) wsGetAccountBalance() (*UserBalance, error) { Request: "user_balance", Nonce: getNonce(), } - resp, err := c.Websocket.Conn.SendMessageReturnResponse(context.TODO(), request.Unset, accBalance.Nonce, accBalance) + resp, err := c.Websocket.Conn.SendMessageReturnResponse(ctx, request.Unset, accBalance.Nonce, accBalance) if err != nil { return nil, err } @@ -729,7 +730,7 @@ func (c *COINUT) wsGetAccountBalance() (*UserBalance, error) { return &response, nil } -func (c *COINUT) wsSubmitOrder(o *WsSubmitOrderParameters) (*order.Detail, error) { +func (c *COINUT) wsSubmitOrder(ctx context.Context, o *WsSubmitOrderParameters) (*order.Detail, error) { if !c.Websocket.CanUseAuthenticatedEndpoints() { return nil, fmt.Errorf("%v not authorised to submit order", c.Name) } @@ -750,7 +751,7 @@ func (c *COINUT) wsSubmitOrder(o *WsSubmitOrderParameters) (*order.Detail, error if o.OrderID > 0 { orderSubmissionRequest.OrderID = o.OrderID } - resp, err := c.Websocket.Conn.SendMessageReturnResponse(context.TODO(), request.Unset, orderSubmissionRequest.Nonce, orderSubmissionRequest) + resp, err := c.Websocket.Conn.SendMessageReturnResponse(ctx, request.Unset, orderSubmissionRequest.Nonce, orderSubmissionRequest) if err != nil { return nil, err } @@ -767,7 +768,7 @@ func (c *COINUT) wsSubmitOrder(o *WsSubmitOrderParameters) (*order.Detail, error return ord, nil } -func (c *COINUT) wsSubmitOrders(orders []WsSubmitOrderParameters) ([]order.Detail, []error) { +func (c *COINUT) wsSubmitOrders(ctx context.Context, orders []WsSubmitOrderParameters) ([]order.Detail, []error) { var errs []error if !c.Websocket.CanUseAuthenticatedEndpoints() { errs = append(errs, fmt.Errorf("%v not authorised to submit orders", @@ -793,7 +794,7 @@ func (c *COINUT) wsSubmitOrders(orders []WsSubmitOrderParameters) ([]order.Detai orderRequest.Nonce = getNonce() orderRequest.Request = "new_orders" - resp, err := c.Websocket.Conn.SendMessageReturnResponse(context.TODO(), request.Unset, orderRequest.Nonce, orderRequest) + resp, err := c.Websocket.Conn.SendMessageReturnResponse(ctx, request.Unset, orderRequest.Nonce, orderRequest) if err != nil { errs = append(errs, err) return nil, errs @@ -818,7 +819,7 @@ func (c *COINUT) wsSubmitOrders(orders []WsSubmitOrderParameters) ([]order.Detai return ordersResponse, errs } -func (c *COINUT) wsGetOpenOrders(curr string) (*WsUserOpenOrdersResponse, error) { +func (c *COINUT) wsGetOpenOrders(ctx context.Context, curr string) (*WsUserOpenOrdersResponse, error) { var response *WsUserOpenOrdersResponse if !c.Websocket.CanUseAuthenticatedEndpoints() { return response, fmt.Errorf("%v not authorised to get open orders", @@ -829,7 +830,7 @@ func (c *COINUT) wsGetOpenOrders(curr string) (*WsUserOpenOrdersResponse, error) openOrdersRequest.Nonce = getNonce() openOrdersRequest.InstrumentID = c.instrumentMap.LookupID(curr) - resp, err := c.Websocket.Conn.SendMessageReturnResponse(context.TODO(), request.Unset, openOrdersRequest.Nonce, openOrdersRequest) + resp, err := c.Websocket.Conn.SendMessageReturnResponse(ctx, request.Unset, openOrdersRequest.Nonce, openOrdersRequest) if err != nil { return response, err } @@ -845,7 +846,7 @@ func (c *COINUT) wsGetOpenOrders(curr string) (*WsUserOpenOrdersResponse, error) return response, nil } -func (c *COINUT) wsCancelOrder(cancellation *WsCancelOrderParameters) (*CancelOrdersResponse, error) { +func (c *COINUT) wsCancelOrder(ctx context.Context, cancellation *WsCancelOrderParameters) (*CancelOrdersResponse, error) { var response *CancelOrdersResponse if !c.Websocket.CanUseAuthenticatedEndpoints() { return response, fmt.Errorf("%v not authorised to cancel order", c.Name) @@ -862,7 +863,7 @@ func (c *COINUT) wsCancelOrder(cancellation *WsCancelOrderParameters) (*CancelOr cancellationRequest.OrderID = cancellation.OrderID cancellationRequest.Nonce = getNonce() - resp, err := c.Websocket.Conn.SendMessageReturnResponse(context.TODO(), request.Unset, cancellationRequest.Nonce, cancellationRequest) + resp, err := c.Websocket.Conn.SendMessageReturnResponse(ctx, request.Unset, cancellationRequest.Nonce, cancellationRequest) if err != nil { return response, err } @@ -880,7 +881,7 @@ func (c *COINUT) wsCancelOrder(cancellation *WsCancelOrderParameters) (*CancelOr return response, nil } -func (c *COINUT) wsCancelOrders(cancellations []WsCancelOrderParameters) (*CancelOrdersResponse, error) { +func (c *COINUT) wsCancelOrders(ctx context.Context, cancellations []WsCancelOrderParameters) (*CancelOrdersResponse, error) { var err error var response *CancelOrdersResponse if !c.Websocket.CanUseAuthenticatedEndpoints() { @@ -903,7 +904,7 @@ func (c *COINUT) wsCancelOrders(cancellations []WsCancelOrderParameters) (*Cance cancelOrderRequest.Request = "cancel_orders" cancelOrderRequest.Nonce = getNonce() - resp, err := c.Websocket.Conn.SendMessageReturnResponse(context.TODO(), request.Unset, cancelOrderRequest.Nonce, cancelOrderRequest) + resp, err := c.Websocket.Conn.SendMessageReturnResponse(ctx, request.Unset, cancelOrderRequest.Nonce, cancelOrderRequest) if err != nil { return response, err } @@ -914,7 +915,7 @@ func (c *COINUT) wsCancelOrders(cancellations []WsCancelOrderParameters) (*Cance return response, err } -func (c *COINUT) wsGetTradeHistory(p currency.Pair, start, limit int64) (*WsTradeHistoryResponse, error) { +func (c *COINUT) wsGetTradeHistory(ctx context.Context, p currency.Pair, start, limit int64) (*WsTradeHistoryResponse, error) { var response *WsTradeHistoryResponse if !c.Websocket.CanUseAuthenticatedEndpoints() { return response, fmt.Errorf("%v not authorised to get trade history", @@ -933,7 +934,7 @@ func (c *COINUT) wsGetTradeHistory(p currency.Pair, start, limit int64) (*WsTrad req.Start = start req.Limit = limit - resp, err := c.Websocket.Conn.SendMessageReturnResponse(context.TODO(), request.Unset, req.Nonce, req) + resp, err := c.Websocket.Conn.SendMessageReturnResponse(ctx, request.Unset, req.Nonce, req) if err != nil { return response, err } diff --git a/exchanges/coinut/coinut_wrapper.go b/exchanges/coinut/coinut_wrapper.go index c2699ff2..ee85909d 100644 --- a/exchanges/coinut/coinut_wrapper.go +++ b/exchanges/coinut/coinut_wrapper.go @@ -160,7 +160,7 @@ func (c *COINUT) FetchTradablePairs(ctx context.Context, _ asset.Item) (currency var resp Instruments var err error if c.Websocket.IsConnected() { - resp, err = c.WsGetInstruments() + resp, err = c.WsGetInstruments(ctx) } else { resp, err = c.GetInstruments(ctx) } @@ -206,7 +206,7 @@ func (c *COINUT) UpdateAccountInfo(ctx context.Context, assetType asset.Item) (a var err error if c.Websocket.CanUseAuthenticatedWebsocketForWrapper() { var resp *UserBalance - resp, err = c.wsGetAccountBalance() + resp, err = c.wsGetAccountBalance(ctx) if err != nil { return info, err } @@ -307,7 +307,7 @@ func (c *COINUT) UpdateTicker(ctx context.Context, p currency.Pair, a asset.Item if !c.SupportsAsset(a) { return nil, fmt.Errorf("%w %v", asset.ErrNotSupported, a) } - err := c.loadInstrumentsIfNotLoaded() + err := c.loadInstrumentsIfNotLoaded(ctx) if err != nil { return nil, err } @@ -360,7 +360,7 @@ func (c *COINUT) UpdateOrderbook(ctx context.Context, p currency.Pair, assetType Asset: assetType, VerifyOrderbook: c.CanVerifyOrderbook, } - err := c.loadInstrumentsIfNotLoaded() + err := c.loadInstrumentsIfNotLoaded(ctx) if err != nil { return book, err } @@ -470,15 +470,14 @@ func (c *COINUT) SubmitOrder(ctx context.Context, o *order.Submit) (*order.Submi } if _, err = strconv.Atoi(o.ClientID); err != nil { - return nil, fmt.Errorf("%s - ClientID must be a number, received: %s", - c.Name, o.ClientID) + return nil, fmt.Errorf("%s - ClientID must be a number, received: %s", c.Name, o.ClientID) } var orderID string status := order.New if c.Websocket.CanUseAuthenticatedWebsocketForWrapper() { var response *order.Detail - response, err = c.wsSubmitOrder(&WsSubmitOrderParameters{ + response, err = c.wsSubmitOrder(ctx, &WsSubmitOrderParameters{ Currency: o.Pair, Side: o.Side, Amount: o.Amount, @@ -489,7 +488,7 @@ func (c *COINUT) SubmitOrder(ctx context.Context, o *order.Submit) (*order.Submi } orderID = response.OrderID } else { - err = c.loadInstrumentsIfNotLoaded() + err = c.loadInstrumentsIfNotLoaded(ctx) if err != nil { return nil, err } @@ -566,7 +565,7 @@ func (c *COINUT) CancelOrder(ctx context.Context, o *order.Cancel) error { return err } - err := c.loadInstrumentsIfNotLoaded() + err := c.loadInstrumentsIfNotLoaded(ctx) if err != nil { return err } @@ -584,10 +583,7 @@ func (c *COINUT) CancelOrder(ctx context.Context, o *order.Cancel) error { if c.Websocket.CanUseAuthenticatedWebsocketForWrapper() { var resp *CancelOrdersResponse - resp, err = c.wsCancelOrder(&WsCancelOrderParameters{ - Currency: o.Pair, - OrderID: orderIDInt, - }) + resp, err = c.wsCancelOrder(ctx, &WsCancelOrderParameters{Currency: o.Pair, OrderID: orderIDInt}) if err != nil { return err } @@ -654,13 +650,13 @@ func (c *COINUT) CancelAllOrders(ctx context.Context, details *order.Cancel) (or } var cancelAllOrdersResponse order.CancelAllResponse - err := c.loadInstrumentsIfNotLoaded() + err := c.loadInstrumentsIfNotLoaded(ctx) if err != nil { return cancelAllOrdersResponse, err } cancelAllOrdersResponse.Status = make(map[string]string) if c.Websocket.CanUseAuthenticatedWebsocketForWrapper() { - openOrders, err := c.wsGetOpenOrders(details.Pair.String()) + openOrders, err := c.wsGetOpenOrders(ctx, details.Pair.String()) if err != nil { return cancelAllOrdersResponse, err } @@ -678,7 +674,7 @@ func (c *COINUT) CancelAllOrders(ctx context.Context, details *order.Cancel) (or }) } } - resp, err := c.wsCancelOrders(ordersToCancel) + resp, err := c.wsCancelOrders(ctx, ordersToCancel) if err != nil { return cancelAllOrdersResponse, err } @@ -777,7 +773,7 @@ func (c *COINUT) GetActiveOrders(ctx context.Context, req *order.MultiOrderReque return nil, err } - err = c.loadInstrumentsIfNotLoaded() + err = c.loadInstrumentsIfNotLoaded(ctx) if err != nil { return nil, err } @@ -800,7 +796,7 @@ func (c *COINUT) GetActiveOrders(ctx context.Context, req *order.MultiOrderReque if c.Websocket.CanUseAuthenticatedWebsocketForWrapper() { for x := range currenciesToCheck { var openOrders *WsUserOpenOrdersResponse - openOrders, err = c.wsGetOpenOrders(currenciesToCheck[x]) + openOrders, err = c.wsGetOpenOrders(ctx, currenciesToCheck[x]) if err != nil { return nil, err } @@ -907,7 +903,7 @@ func (c *COINUT) GetOrderHistory(ctx context.Context, req *order.MultiOrderReque return nil, err } - err = c.loadInstrumentsIfNotLoaded() + err = c.loadInstrumentsIfNotLoaded(ctx) if err != nil { return nil, err } @@ -916,7 +912,7 @@ func (c *COINUT) GetOrderHistory(ctx context.Context, req *order.MultiOrderReque for i := range req.Pairs { for j := int64(0); ; j += 100 { var trades *WsTradeHistoryResponse - trades, err = c.wsGetTradeHistory(req.Pairs[i], j, 100) + trades, err = c.wsGetTradeHistory(ctx, req.Pairs[i], j, 100) if err != nil { return allOrders, err } @@ -1024,15 +1020,15 @@ func (c *COINUT) AuthenticateWebsocket(ctx context.Context) error { return c.wsAuthenticate(ctx) } -func (c *COINUT) loadInstrumentsIfNotLoaded() error { +func (c *COINUT) loadInstrumentsIfNotLoaded(ctx context.Context) error { if !c.instrumentMap.IsLoaded() { if c.Websocket.IsConnected() { - _, err := c.WsGetInstruments() + _, err := c.WsGetInstruments(ctx) if err != nil { return err } } else { - err := c.SeedInstruments(context.TODO()) + err := c.SeedInstruments(ctx) if err != nil { return err } diff --git a/exchanges/deribit/deribit.go b/exchanges/deribit/deribit.go index 7d288263..392b456b 100644 --- a/exchanges/deribit/deribit.go +++ b/exchanges/deribit/deribit.go @@ -2229,7 +2229,7 @@ func (d *Deribit) SendHTTPAuthRequest(ctx context.Context, ep exchange.URL, epl Data json.RawMessage `json:"result"` Error ErrInfo `json:"error"` } - err = d.SendPayload(context.Background(), epl, func() (*request.Item, error) { + err = d.SendPayload(ctx, epl, func() (*request.Item, error) { return &request.Item{ Method: method, Path: endpoint + deribitAPIVersion + "/" + common.EncodeURLValues(path, params), diff --git a/exchanges/deribit/deribit_test.go b/exchanges/deribit/deribit_test.go index fb41a438..078657ad 100644 --- a/exchanges/deribit/deribit_test.go +++ b/exchanges/deribit/deribit_test.go @@ -267,7 +267,7 @@ func TestGetMarkPriceHistory(t *testing.T) { func TestWSRetrieveMarkPriceHistory(t *testing.T) { t.Parallel() - _, err := d.WSRetrieveMarkPriceHistory("", time.Now().Add(-4*time.Hour), time.Now()) + _, err := d.WSRetrieveMarkPriceHistory(t.Context(), "", time.Now().Add(-4*time.Hour), time.Now()) require.ErrorIs(t, err, errInvalidInstrumentName) var result []MarkPriceHistory @@ -277,7 +277,7 @@ func TestWSRetrieveMarkPriceHistory(t *testing.T) { btcPerpInstrument, futureComboTradablePair.String(), } { - result, err = d.WSRetrieveMarkPriceHistory(ps, time.Now().Add(-4*time.Hour), time.Now()) + result, err = d.WSRetrieveMarkPriceHistory(t.Context(), ps, time.Now().Add(-4*time.Hour), time.Now()) require.NoErrorf(t, err, "expected %v, got %v currency pair %v", nil, err, ps) require.NotNilf(t, result, "expected value not to be nil for pair: %v", ps) } @@ -301,9 +301,9 @@ func TestGetBookSummaryByCurrency(t *testing.T) { func TestWSRetrieveBookBySummary(t *testing.T) { t.Parallel() - _, err := d.WSRetrieveBookBySummary(currency.EMPTYCODE, "") + _, err := d.WSRetrieveBookBySummary(t.Context(), currency.EMPTYCODE, "") require.ErrorIs(t, err, currency.ErrCurrencyCodeEmpty) - result, err := d.WSRetrieveBookBySummary(currency.SOL, "") + result, err := d.WSRetrieveBookBySummary(t.Context(), currency.SOL, "") require.NoError(t, err) assert.NotNil(t, result) } @@ -329,7 +329,7 @@ func TestGetBookSummaryByInstrument(t *testing.T) { func TestWSRetrieveBookSummaryByInstrument(t *testing.T) { t.Parallel() - _, err := d.WSRetrieveBookSummaryByInstrument("") + _, err := d.WSRetrieveBookSummaryByInstrument(t.Context(), "") require.ErrorIs(t, err, errInvalidInstrumentName) var result []BookSummaryData for _, ps := range []string{ @@ -339,7 +339,7 @@ func TestWSRetrieveBookSummaryByInstrument(t *testing.T) { d.optionPairToString(optionsTradablePair), optionComboTradablePair.String(), } { - result, err = d.WSRetrieveBookSummaryByInstrument(ps) + result, err = d.WSRetrieveBookSummaryByInstrument(t.Context(), ps) require.NoErrorf(t, err, "expected nil, got %v for pair %s", err, ps) require.NotNilf(t, result, "expected result not to be nil for pair %s", ps) } @@ -356,10 +356,10 @@ func TestGetContractSize(t *testing.T) { func TestWSRetrieveContractSize(t *testing.T) { t.Parallel() - _, err := d.WSRetrieveContractSize("") + _, err := d.WSRetrieveContractSize(t.Context(), "") require.ErrorIs(t, err, errInvalidInstrumentName) - result, err := d.WSRetrieveContractSize(btcPerpInstrument) + result, err := d.WSRetrieveContractSize(t.Context(), btcPerpInstrument) require.NoError(t, err) assert.NotNil(t, result) } @@ -373,7 +373,7 @@ func TestGetCurrencies(t *testing.T) { func TestWSRetrieveCurrencies(t *testing.T) { t.Parallel() - result, err := d.WSRetrieveCurrencies() + result, err := d.WSRetrieveCurrencies(t.Context()) require.NoError(t, err) assert.NotNil(t, result) } @@ -390,10 +390,10 @@ func TestGetDeliveryPrices(t *testing.T) { func TestWSRetrieveDeliveryPrices(t *testing.T) { t.Parallel() - _, err := d.WSRetrieveDeliveryPrices("", 0, 5) + _, err := d.WSRetrieveDeliveryPrices(t.Context(), "", 0, 5) require.ErrorIs(t, err, errUnsupportedIndexName) - result, err := d.WSRetrieveDeliveryPrices("btc_usd", 0, 5) + result, err := d.WSRetrieveDeliveryPrices(t.Context(), "btc_usd", 0, 5) require.NoError(t, err) assert.NotNil(t, result) } @@ -411,10 +411,10 @@ func TestGetFundingChartData(t *testing.T) { func TestWSRetrieveFundingChartData(t *testing.T) { t.Parallel() - _, err := d.WSRetrieveFundingChartData("", "8h") + _, err := d.WSRetrieveFundingChartData(t.Context(), "", "8h") require.ErrorIs(t, err, errInvalidInstrumentName) - result, err := d.WSRetrieveFundingChartData(btcPerpInstrument, "8h") + result, err := d.WSRetrieveFundingChartData(t.Context(), btcPerpInstrument, "8h") require.NoError(t, err) assert.NotNil(t, result) } @@ -431,9 +431,9 @@ func TestGetFundingRateHistory(t *testing.T) { func TestWSRetrieveFundingRateHistory(t *testing.T) { t.Parallel() - _, err := d.WSRetrieveFundingRateHistory("", time.Now().Add(-time.Hour), time.Now()) + _, err := d.WSRetrieveFundingRateHistory(t.Context(), "", time.Now().Add(-time.Hour), time.Now()) require.ErrorIs(t, err, errInvalidInstrumentName) - result, err := d.WSRetrieveFundingRateHistory(btcPerpInstrument, time.Now().Add(-time.Hour), time.Now()) + result, err := d.WSRetrieveFundingRateHistory(t.Context(), btcPerpInstrument, time.Now().Add(-time.Hour), time.Now()) require.NoError(t, err) assert.NotNil(t, result) } @@ -452,10 +452,10 @@ func TestGetFundingRateValue(t *testing.T) { func TestWSRetrieveFundingRateValue(t *testing.T) { t.Parallel() - _, err := d.WSRetrieveFundingRateValue(btcPerpInstrument, time.Now(), time.Now().Add(-time.Hour*8)) + _, err := d.WSRetrieveFundingRateValue(t.Context(), btcPerpInstrument, time.Now(), time.Now().Add(-time.Hour*8)) require.ErrorIs(t, err, common.ErrStartAfterEnd) - result, err := d.WSRetrieveFundingRateValue(btcPerpInstrument, time.Now().Add(-time.Hour*8), time.Now()) + result, err := d.WSRetrieveFundingRateValue(t.Context(), btcPerpInstrument, time.Now().Add(-time.Hour*8), time.Now()) require.NoError(t, err) assert.NotNil(t, result) } @@ -485,10 +485,10 @@ func TestGetHistoricalVolatility(t *testing.T) { func TestWSRetrieveHistoricalVolatility(t *testing.T) { t.Parallel() - _, err := d.WSRetrieveHistoricalVolatility(currency.EMPTYCODE) + _, err := d.WSRetrieveHistoricalVolatility(t.Context(), currency.EMPTYCODE) require.ErrorIs(t, err, currency.ErrCurrencyCodeEmpty) - result, err := d.WSRetrieveHistoricalVolatility(currency.SOL) + result, err := d.WSRetrieveHistoricalVolatility(t.Context(), currency.SOL) require.NoError(t, err) assert.NotNil(t, result) } @@ -504,9 +504,9 @@ func TestGetCurrencyIndexPrice(t *testing.T) { func TestWSRetrieveCurrencyIndexPrice(t *testing.T) { t.Parallel() - _, err := d.WSRetrieveCurrencyIndexPrice(currency.EMPTYCODE) + _, err := d.WSRetrieveCurrencyIndexPrice(t.Context(), currency.EMPTYCODE) require.ErrorIs(t, err, currency.ErrCurrencyCodeEmpty) - result, err := d.WSRetrieveCurrencyIndexPrice(currency.BTC) + result, err := d.WSRetrieveCurrencyIndexPrice(t.Context(), currency.BTC) require.NoError(t, err) assert.NotNil(t, result) } @@ -522,9 +522,9 @@ func TestGetIndexPrice(t *testing.T) { func TestWSRetrieveIndexPrice(t *testing.T) { t.Parallel() - _, err := d.WSRetrieveIndexPrice("") + _, err := d.WSRetrieveIndexPrice(t.Context(), "") require.ErrorIs(t, err, errUnsupportedIndexName) - result, err := d.WSRetrieveIndexPrice("ada_usd") + result, err := d.WSRetrieveIndexPrice(t.Context(), "ada_usd") require.NoError(t, err) assert.NotNil(t, result) } @@ -538,7 +538,7 @@ func TestGetIndexPriceNames(t *testing.T) { func TestWSRetrieveIndexPriceNames(t *testing.T) { t.Parallel() - result, err := d.WSRetrieveIndexPriceNames() + result, err := d.WSRetrieveIndexPriceNames(t.Context()) require.NoError(t, err) assert.NotNil(t, result) } @@ -558,12 +558,12 @@ func TestGetInstrumentData(t *testing.T) { func TestWSRetrieveInstrumentData(t *testing.T) { t.Parallel() - _, err := d.WSRetrieveInstrumentData("") + _, err := d.WSRetrieveInstrumentData(t.Context(), "") require.ErrorIs(t, err, errInvalidInstrumentName) var result *InstrumentData for assetType, cp := range assetTypeToPairsMap { - result, err = d.WSRetrieveInstrumentData(d.formatPairString(assetType, cp)) + result, err = d.WSRetrieveInstrumentData(t.Context(), d.formatPairString(assetType, cp)) require.NoErrorf(t, err, "expected nil, got %v for asset type %s pair %s", err, assetType, cp) require.NotNilf(t, result, "expected result not to be nil for asset type %s pair %s", assetType, cp) } @@ -586,10 +586,10 @@ func TestGetInstruments(t *testing.T) { func TestWSRetrieveInstrumentsData(t *testing.T) { t.Parallel() - _, err := d.WSRetrieveInstrumentsData(currency.EMPTYCODE, "", false) + _, err := d.WSRetrieveInstrumentsData(t.Context(), currency.EMPTYCODE, "", false) require.ErrorIs(t, err, currency.ErrCurrencyCodeEmpty) - result, err := d.WSRetrieveInstrumentsData(currency.BTC, "", false) + result, err := d.WSRetrieveInstrumentsData(t.Context(), currency.BTC, "", false) require.NoError(t, err) assert.NotNil(t, result) } @@ -606,20 +606,20 @@ func TestGetLastSettlementsByCurrency(t *testing.T) { func TestWSRetrieveLastSettlementsByCurrency(t *testing.T) { t.Parallel() - _, err := d.WSRetrieveLastSettlementsByCurrency(currency.EMPTYCODE, "delivery", "5", 0, time.Now().Add(-time.Hour)) + _, err := d.WSRetrieveLastSettlementsByCurrency(t.Context(), currency.EMPTYCODE, "delivery", "5", 0, time.Now().Add(-time.Hour)) require.ErrorIs(t, err, currency.ErrCurrencyCodeEmpty) - result, err := d.WSRetrieveLastSettlementsByCurrency(currency.BTC, "delivery", "5", 0, time.Now().Add(-time.Hour)) + result, err := d.WSRetrieveLastSettlementsByCurrency(t.Context(), currency.BTC, "delivery", "5", 0, time.Now().Add(-time.Hour)) require.NoError(t, err) assert.NotNil(t, result) } func TestWSRetrieveLastSettlementsByInstrument(t *testing.T) { t.Parallel() - _, err := d.WSRetrieveLastSettlementsByInstrument("", "settlement", "5", 0, time.Now().Add(-2*time.Hour)) + _, err := d.WSRetrieveLastSettlementsByInstrument(t.Context(), "", "settlement", "5", 0, time.Now().Add(-2*time.Hour)) require.ErrorIs(t, err, errInvalidInstrumentName) - result, err := d.WSRetrieveLastSettlementsByInstrument(d.formatFuturesTradablePair(futuresTradablePair), "settlement", "5", 0, time.Now().Add(-2*time.Hour)) + result, err := d.WSRetrieveLastSettlementsByInstrument(t.Context(), d.formatFuturesTradablePair(futuresTradablePair), "settlement", "5", 0, time.Now().Add(-2*time.Hour)) require.NoError(t, err) assert.NotNil(t, result) } @@ -646,10 +646,10 @@ func TestGetLastTradesByCurrency(t *testing.T) { func TestWSRetrieveLastTradesByCurrency(t *testing.T) { t.Parallel() - _, err := d.WSRetrieveLastTradesByCurrency(currency.EMPTYCODE, "option", "36798", "36799", "asc", 0, true) + _, err := d.WSRetrieveLastTradesByCurrency(t.Context(), currency.EMPTYCODE, "option", "36798", "36799", "asc", 0, true) require.ErrorIs(t, err, currency.ErrCurrencyCodeEmpty) - result, err := d.WSRetrieveLastTradesByCurrency(currency.BTC, "option", "36798", "36799", "asc", 0, true) + result, err := d.WSRetrieveLastTradesByCurrency(t.Context(), currency.BTC, "option", "36798", "36799", "asc", 0, true) require.NoError(t, err) assert.NotNil(t, result) } @@ -669,13 +669,13 @@ func TestGetLastTradesByCurrencyAndTime(t *testing.T) { func TestWSRetrieveLastTradesByCurrencyAndTime(t *testing.T) { t.Parallel() - _, err := d.WSRetrieveLastTradesByCurrencyAndTime(currency.EMPTYCODE, "", "", 0, false, time.Now().Add(-8*time.Hour), time.Now()) + _, err := d.WSRetrieveLastTradesByCurrencyAndTime(t.Context(), currency.EMPTYCODE, "", "", 0, false, time.Now().Add(-8*time.Hour), time.Now()) require.ErrorIs(t, err, currency.ErrCurrencyCodeEmpty) - result, err := d.WSRetrieveLastTradesByCurrencyAndTime(currency.BTC, "", "", 0, false, time.Now().Add(-8*time.Hour), time.Now()) + result, err := d.WSRetrieveLastTradesByCurrencyAndTime(t.Context(), currency.BTC, "", "", 0, false, time.Now().Add(-8*time.Hour), time.Now()) require.NoError(t, err) require.NotNil(t, result) - result, err = d.WSRetrieveLastTradesByCurrencyAndTime(currency.BTC, "option", "asc", 25, false, time.Now().Add(-8*time.Hour), time.Now()) + result, err = d.WSRetrieveLastTradesByCurrencyAndTime(t.Context(), currency.BTC, "option", "asc", 25, false, time.Now().Add(-8*time.Hour), time.Now()) require.NoError(t, err) assert.NotNil(t, result) } @@ -694,11 +694,11 @@ func TestGetLastTradesByInstrument(t *testing.T) { func TestWSRetrieveLastTradesByInstrument(t *testing.T) { t.Parallel() - _, err := d.WSRetrieveLastTradesByInstrument("", "", "", "", 0, false) + _, err := d.WSRetrieveLastTradesByInstrument(t.Context(), "", "", "", "", 0, false) require.ErrorIs(t, err, errInvalidInstrumentName) for assetType, cp := range assetTypeToPairsMap { - result, err := d.WSRetrieveLastTradesByInstrument(d.formatPairString(assetType, cp), "30500", "31500", "desc", 0, true) + result, err := d.WSRetrieveLastTradesByInstrument(t.Context(), d.formatPairString(assetType, cp), "30500", "31500", "desc", 0, true) require.NoErrorf(t, err, "expected %v, got %v currency asset %v pair %v", nil, err, assetType, cp) require.NotNilf(t, result, "expected value not to be nil for asset %v pair: %v", assetType, cp) } @@ -718,11 +718,11 @@ func TestGetLastTradesByInstrumentAndTime(t *testing.T) { func TestWSRetrieveLastTradesByInstrumentAndTime(t *testing.T) { t.Parallel() - _, err := d.WSRetrieveLastTradesByInstrumentAndTime("", "", 0, false, time.Now().Add(-8*time.Hour), time.Now()) + _, err := d.WSRetrieveLastTradesByInstrumentAndTime(t.Context(), "", "", 0, false, time.Now().Add(-8*time.Hour), time.Now()) require.ErrorIs(t, err, errInvalidInstrumentName) for assetType, cp := range assetTypeToPairsMap { - result, err := d.WSRetrieveLastTradesByInstrumentAndTime(d.formatPairString(assetType, cp), "", 0, true, time.Now().Add(-8*time.Hour), time.Now()) + result, err := d.WSRetrieveLastTradesByInstrumentAndTime(t.Context(), d.formatPairString(assetType, cp), "", 0, true, time.Now().Add(-8*time.Hour), time.Now()) require.NoErrorf(t, err, "expected %v, got %v currency pair %v", nil, err, cp) require.NotNilf(t, result, "expected value not to be nil for pair: %v", cp) } @@ -793,12 +793,12 @@ func TestWSRetrieveOrderbookData(t *testing.T) { if !d.Websocket.IsConnected() { t.Skip("websocket is not connected") } - _, err := d.WSRetrieveOrderbookData("", 0) + _, err := d.WSRetrieveOrderbookData(t.Context(), "", 0) require.ErrorIs(t, err, errInvalidInstrumentName) var result *Orderbook for assetType, cp := range assetTypeToPairsMap { - result, err = d.WSRetrieveOrderbookData(d.formatPairString(assetType, cp), 0) + result, err = d.WSRetrieveOrderbookData(t.Context(), d.formatPairString(assetType, cp), 0) require.NoErrorf(t, err, "expected %v, got %v currency pair %v", nil, err, cp) require.NotNilf(t, result, "expected value not to be nil for pair: %v", cp) } @@ -825,18 +825,18 @@ func TestGetOrderbookByInstrumentID(t *testing.T) { func TestWSRetrieveOrderbookByInstrumentID(t *testing.T) { t.Parallel() - combos, err := d.WSRetrieveComboIDs(currency.BTC, "") + combos, err := d.WSRetrieveComboIDs(t.Context(), currency.BTC, "") require.NoError(t, err) if len(combos) == 0 { t.Skip("no combo instance found for currency BTC") } - _, err = d.WSRetrieveOrderbookByInstrumentID(0, 50) + _, err = d.WSRetrieveOrderbookByInstrumentID(t.Context(), 0, 50) require.ErrorIs(t, err, errInvalidInstrumentID) - comboD, err := d.WSRetrieveComboDetails(combos[0]) + comboD, err := d.WSRetrieveComboDetails(t.Context(), combos[0]) require.NoError(t, err) require.NotNil(t, comboD) - result, err := d.WSRetrieveOrderbookByInstrumentID(comboD.InstrumentID, 50) + result, err := d.WSRetrieveOrderbookByInstrumentID(t.Context(), comboD.InstrumentID, 50) require.NoError(t, err) assert.NotNil(t, result) } @@ -850,7 +850,7 @@ func TestGetSupportedIndexNames(t *testing.T) { func TestWsRetrieveSupportedIndexNames(t *testing.T) { t.Parallel() - result, err := d.WsRetrieveSupportedIndexNames("derivative") + result, err := d.WsRetrieveSupportedIndexNames(t.Context(), "derivative") require.NoError(t, err) assert.NotNil(t, result) } @@ -866,9 +866,9 @@ func TestGetRequestForQuote(t *testing.T) { func TestWSRetrieveRequestForQuote(t *testing.T) { t.Parallel() - _, err := d.WSRetrieveRequestForQuote(currency.EMPTYCODE, d.GetAssetKind(asset.Futures)) + _, err := d.WSRetrieveRequestForQuote(t.Context(), currency.EMPTYCODE, d.GetAssetKind(asset.Futures)) require.ErrorIs(t, err, currency.ErrCurrencyCodeEmpty) - result, err := d.WSRetrieveRequestForQuote(currency.BTC, d.GetAssetKind(asset.Futures)) + result, err := d.WSRetrieveRequestForQuote(t.Context(), currency.BTC, d.GetAssetKind(asset.Futures)) require.NoError(t, err) assert.NotNil(t, result) } @@ -882,7 +882,7 @@ func TestGetTradeVolumes(t *testing.T) { func TestWSRetrieveTradeVolumes(t *testing.T) { t.Parallel() - result, err := d.WSRetrieveTradeVolumes(false) + result, err := d.WSRetrieveTradeVolumes(t.Context(), false) require.NoError(t, err) assert.NotNil(t, result) } @@ -902,12 +902,12 @@ func TestGetTradingViewChartData(t *testing.T) { func TestWSRetrievesTradingViewChartData(t *testing.T) { t.Parallel() - _, err := d.WSRetrievesTradingViewChartData("", "60", time.Now().Add(-time.Hour), time.Now()) + _, err := d.WSRetrievesTradingViewChartData(t.Context(), "", "60", time.Now().Add(-time.Hour), time.Now()) require.ErrorIs(t, err, errInvalidInstrumentName) - result, err := d.WSRetrievesTradingViewChartData(btcPerpInstrument, "60", time.Now().Add(-time.Hour), time.Now()) + result, err := d.WSRetrievesTradingViewChartData(t.Context(), btcPerpInstrument, "60", time.Now().Add(-time.Hour), time.Now()) require.NoError(t, err) require.NotNil(t, result) - result, err = d.WSRetrievesTradingViewChartData(spotTradablePair.String(), "60", time.Now().Add(-time.Hour), time.Now()) + result, err = d.WSRetrievesTradingViewChartData(t.Context(), spotTradablePair.String(), "60", time.Now().Add(-time.Hour), time.Now()) require.NoError(t, err) assert.NotNil(t, result) } @@ -928,14 +928,14 @@ func TestGetVolatilityIndexData(t *testing.T) { func TestWSRetrieveVolatilityIndexData(t *testing.T) { t.Parallel() - _, err := d.WSRetrieveVolatilityIndexData(currency.EMPTYCODE, "60", time.Now().Add(-time.Hour), time.Now()) + _, err := d.WSRetrieveVolatilityIndexData(t.Context(), currency.EMPTYCODE, "60", time.Now().Add(-time.Hour), time.Now()) require.ErrorIs(t, err, currency.ErrCurrencyCodeEmpty) - _, err = d.WSRetrieveVolatilityIndexData(currency.BTC, "", time.Now().Add(-time.Hour), time.Now()) + _, err = d.WSRetrieveVolatilityIndexData(t.Context(), currency.BTC, "", time.Now().Add(-time.Hour), time.Now()) require.ErrorIs(t, err, errResolutionNotSet) - _, err = d.WSRetrieveVolatilityIndexData(currency.BTC, "60", time.Now(), time.Now().Add(-time.Hour)) + _, err = d.WSRetrieveVolatilityIndexData(t.Context(), currency.BTC, "60", time.Now(), time.Now().Add(-time.Hour)) require.ErrorIs(t, err, common.ErrStartAfterEnd) - result, err := d.WSRetrieveVolatilityIndexData(currency.BTC, "60", time.Now().Add(-time.Hour), time.Now()) + result, err := d.WSRetrieveVolatilityIndexData(t.Context(), currency.BTC, "60", time.Now().Add(-time.Hour), time.Now()) require.NoError(t, err) assert.NotNil(t, result) } @@ -952,10 +952,10 @@ func TestGetPublicTicker(t *testing.T) { func TestWSRetrievePublicTicker(t *testing.T) { t.Parallel() - _, err := d.WSRetrievePublicTicker("") + _, err := d.WSRetrievePublicTicker(t.Context(), "") require.ErrorIs(t, err, errInvalidInstrumentName) - result, err := d.WSRetrievePublicTicker(btcPerpInstrument) + result, err := d.WSRetrievePublicTicker(t.Context(), btcPerpInstrument) require.NoError(t, err) assert.NotNil(t, result) } @@ -973,11 +973,11 @@ func TestGetAccountSummary(t *testing.T) { func TestWSRetrieveAccountSummary(t *testing.T) { t.Parallel() - _, err := d.WSRetrieveAccountSummary(currency.EMPTYCODE, false) + _, err := d.WSRetrieveAccountSummary(t.Context(), currency.EMPTYCODE, false) require.ErrorIs(t, err, currency.ErrCurrencyCodeEmpty) sharedtestvalues.SkipTestIfCredentialsUnset(t, d) - result, err := d.WSRetrieveAccountSummary(currency.BTC, false) + result, err := d.WSRetrieveAccountSummary(t.Context(), currency.BTC, false) require.NoError(t, err) assert.NotNil(t, result) } @@ -997,13 +997,13 @@ func TestCancelTransferByID(t *testing.T) { func TestWSCancelTransferByID(t *testing.T) { t.Parallel() - _, err := d.WSCancelTransferByID(currency.EMPTYCODE, "", 23487) + _, err := d.WSCancelTransferByID(t.Context(), currency.EMPTYCODE, "", 23487) require.ErrorIs(t, err, currency.ErrCurrencyCodeEmpty) - _, err = d.WSCancelTransferByID(currency.BTC, "", 0) + _, err = d.WSCancelTransferByID(t.Context(), currency.BTC, "", 0) require.ErrorIs(t, err, errInvalidID) sharedtestvalues.SkipTestIfCredentialsUnset(t, d, canManipulateRealOrders) - result, err := d.WSCancelTransferByID(currency.BTC, "", 23487) + result, err := d.WSCancelTransferByID(t.Context(), currency.BTC, "", 23487) require.NoError(t, err) assert.NotNil(t, result) } @@ -1026,11 +1026,11 @@ func TestGetTransfers(t *testing.T) { func TestWSRetrieveTransfers(t *testing.T) { t.Parallel() - _, err := d.WSRetrieveTransfers(currency.EMPTYCODE, 0, 0) + _, err := d.WSRetrieveTransfers(t.Context(), currency.EMPTYCODE, 0, 0) require.ErrorIs(t, err, currency.ErrCurrencyCodeEmpty) sharedtestvalues.SkipTestIfCredentialsUnset(t, d) - result, err := d.WSRetrieveTransfers(currency.BTC, 0, 0) + result, err := d.WSRetrieveTransfers(t.Context(), currency.BTC, 0, 0) require.NoError(t, err) assert.NotNil(t, result) } @@ -1055,13 +1055,13 @@ func TestCancelWithdrawal(t *testing.T) { func TestWSCancelWithdrawal(t *testing.T) { t.Parallel() - _, err := d.WSCancelWithdrawal(currency.EMPTYCODE, 123844) + _, err := d.WSCancelWithdrawal(t.Context(), currency.EMPTYCODE, 123844) require.ErrorIs(t, err, currency.ErrCurrencyCodeEmpty) - _, err = d.WSCancelWithdrawal(currency.BTC, 0) + _, err = d.WSCancelWithdrawal(t.Context(), currency.BTC, 0) require.ErrorIs(t, err, errInvalidID) sharedtestvalues.SkipTestIfCredentialsUnset(t, d, canManipulateRealOrders) - result, err := d.WSCancelWithdrawal(currency.BTC, 123844) + result, err := d.WSCancelWithdrawal(t.Context(), currency.BTC, 123844) require.NoError(t, err) assert.NotNil(t, result) } @@ -1079,11 +1079,11 @@ func TestCreateDepositAddress(t *testing.T) { func TestWSCreateDepositAddress(t *testing.T) { t.Parallel() - _, err := d.WSCreateDepositAddress(currency.EMPTYCODE) + _, err := d.WSCreateDepositAddress(t.Context(), currency.EMPTYCODE) require.ErrorIs(t, err, currency.ErrCurrencyCodeEmpty) sharedtestvalues.SkipTestIfCredentialsUnset(t, d, canManipulateRealOrders) - result, err := d.WSCreateDepositAddress(currency.SOL) + result, err := d.WSCreateDepositAddress(t.Context(), currency.SOL) require.NoError(t, err) assert.NotNil(t, result) } @@ -1101,11 +1101,11 @@ func TestGetCurrentDepositAddress(t *testing.T) { func TestWSRetrieveCurrentDepositAddress(t *testing.T) { t.Parallel() - _, err := d.WSRetrieveCurrentDepositAddress(currency.EMPTYCODE) + _, err := d.WSRetrieveCurrentDepositAddress(t.Context(), currency.EMPTYCODE) require.ErrorIs(t, err, currency.ErrCurrencyCodeEmpty) sharedtestvalues.SkipTestIfCredentialsUnset(t, d) - result, err := d.WSRetrieveCurrentDepositAddress(currency.ETH) + result, err := d.WSRetrieveCurrentDepositAddress(t.Context(), currency.ETH) require.NoError(t, err) assert.NotNil(t, result) } @@ -1128,11 +1128,11 @@ func TestGetDeposits(t *testing.T) { func TestWSRetrieveDeposits(t *testing.T) { t.Parallel() - _, err := d.WSRetrieveDeposits(currency.EMPTYCODE, 25, 0) + _, err := d.WSRetrieveDeposits(t.Context(), currency.EMPTYCODE, 25, 0) require.ErrorIs(t, err, currency.ErrCurrencyCodeEmpty) sharedtestvalues.SkipTestIfCredentialsUnset(t, d) - result, err := d.WSRetrieveDeposits(currency.BTC, 25, 0) + result, err := d.WSRetrieveDeposits(t.Context(), currency.BTC, 25, 0) require.NoError(t, err) assert.NotNil(t, result) } @@ -1155,11 +1155,11 @@ func TestGetWithdrawals(t *testing.T) { func TestWSRetrieveWithdrawals(t *testing.T) { t.Parallel() - _, err := d.WSRetrieveWithdrawals(currency.EMPTYCODE, 25, 0) + _, err := d.WSRetrieveWithdrawals(t.Context(), currency.EMPTYCODE, 25, 0) require.ErrorIs(t, err, currency.ErrCurrencyCodeEmpty) sharedtestvalues.SkipTestIfCredentialsUnset(t, d) - result, err := d.WSRetrieveWithdrawals(currency.BTC, 25, 0) + result, err := d.WSRetrieveWithdrawals(t.Context(), currency.BTC, 25, 0) require.NoError(t, err) assert.NotNil(t, result) } @@ -1181,15 +1181,15 @@ func TestSubmitTransferBetweenSubAccounts(t *testing.T) { func TestWsSubmitTransferBetweenSubAccounts(t *testing.T) { t.Parallel() - _, err := d.WsSubmitTransferBetweenSubAccounts(currency.EMPTYCODE, 12345, 2, "") + _, err := d.WsSubmitTransferBetweenSubAccounts(t.Context(), currency.EMPTYCODE, 12345, 2, "") require.ErrorIs(t, err, currency.ErrCurrencyCodeEmpty) - _, err = d.WsSubmitTransferBetweenSubAccounts(currency.EURR, 0, 2, "") + _, err = d.WsSubmitTransferBetweenSubAccounts(t.Context(), currency.EURR, 0, 2, "") require.ErrorIs(t, err, errInvalidAmount) - _, err = d.WsSubmitTransferBetweenSubAccounts(currency.EURR, 12345, -1, "") + _, err = d.WsSubmitTransferBetweenSubAccounts(t.Context(), currency.EURR, 12345, -1, "") require.ErrorIs(t, err, errInvalidDestinationID) sharedtestvalues.SkipTestIfCredentialsUnset(t, d, canManipulateRealOrders) - result, err := d.WsSubmitTransferBetweenSubAccounts(currency.EURR, 12345, 2, "") + result, err := d.WsSubmitTransferBetweenSubAccounts(t.Context(), currency.EURR, 12345, 2, "") require.NoError(t, err) assert.NotNil(t, result) } @@ -1211,15 +1211,15 @@ func TestSubmitTransferToSubAccount(t *testing.T) { func TestWSSubmitTransferToSubAccount(t *testing.T) { t.Parallel() - _, err := d.WSSubmitTransferToSubAccount(currency.EMPTYCODE, 0.01, 13434) + _, err := d.WSSubmitTransferToSubAccount(t.Context(), currency.EMPTYCODE, 0.01, 13434) require.ErrorIs(t, err, currency.ErrCurrencyCodeEmpty) - _, err = d.WSSubmitTransferToSubAccount(currency.BTC, 0, 13434) + _, err = d.WSSubmitTransferToSubAccount(t.Context(), currency.BTC, 0, 13434) require.ErrorIs(t, err, errInvalidAmount) - _, err = d.WSSubmitTransferToSubAccount(currency.BTC, 0.01, 0) + _, err = d.WSSubmitTransferToSubAccount(t.Context(), currency.BTC, 0.01, 0) require.ErrorIs(t, err, errInvalidDestinationID) sharedtestvalues.SkipTestIfCredentialsUnset(t, d, canManipulateRealOrders) - result, err := d.WSSubmitTransferToSubAccount(currency.BTC, 0.01, 13434) + result, err := d.WSSubmitTransferToSubAccount(t.Context(), currency.BTC, 0.01, 13434) require.NoError(t, err) assert.NotNil(t, result) } @@ -1241,15 +1241,15 @@ func TestSubmitTransferToUser(t *testing.T) { func TestWSSubmitTransferToUser(t *testing.T) { t.Parallel() - _, err := d.WSSubmitTransferToUser(currency.EMPTYCODE, "", "0x4aa0753d798d668056920094d65321a8e8913e26", 0.001) + _, err := d.WSSubmitTransferToUser(t.Context(), currency.EMPTYCODE, "", "0x4aa0753d798d668056920094d65321a8e8913e26", 0.001) require.ErrorIs(t, err, currency.ErrCurrencyCodeEmpty) - _, err = d.WSSubmitTransferToUser(currency.BTC, "", "0x4aa0753d798d668056920094d65321a8e8913e26", 0) + _, err = d.WSSubmitTransferToUser(t.Context(), currency.BTC, "", "0x4aa0753d798d668056920094d65321a8e8913e26", 0) require.ErrorIs(t, err, errInvalidAmount) - _, err = d.WSSubmitTransferToUser(currency.BTC, "", "", 0.001) + _, err = d.WSSubmitTransferToUser(t.Context(), currency.BTC, "", "", 0.001) require.ErrorIs(t, err, errInvalidCryptoAddress) sharedtestvalues.SkipTestIfCredentialsUnset(t, d, canManipulateRealOrders) - result, err := d.WSSubmitTransferToUser(currency.BTC, "", "", 0.001) + result, err := d.WSSubmitTransferToUser(t.Context(), currency.BTC, "", "", 0.001) require.NoError(t, err) assert.NotNil(t, result) } @@ -1275,15 +1275,15 @@ func TestSubmitWithdraw(t *testing.T) { } func TestWSSubmitWithdraw(t *testing.T) { - _, err := d.WSSubmitWithdraw(currency.EMPTYCODE, core.BitcoinDonationAddress, "", 0.001) + _, err := d.WSSubmitWithdraw(t.Context(), currency.EMPTYCODE, core.BitcoinDonationAddress, "", 0.001) require.ErrorIs(t, err, currency.ErrCurrencyCodeEmpty) - _, err = d.WSSubmitWithdraw(currency.BTC, core.BitcoinDonationAddress, "", 0) + _, err = d.WSSubmitWithdraw(t.Context(), currency.BTC, core.BitcoinDonationAddress, "", 0) require.ErrorIs(t, err, errInvalidAmount) - _, err = d.WSSubmitWithdraw(currency.BTC, "", "", 0.001) + _, err = d.WSSubmitWithdraw(t.Context(), currency.BTC, "", "", 0.001) require.ErrorIs(t, err, errInvalidCryptoAddress) sharedtestvalues.SkipTestIfCredentialsUnset(t, d, canManipulateRealOrders) - result, err := d.WSSubmitWithdraw(currency.BTC, core.BitcoinDonationAddress, "", 0.001) + result, err := d.WSSubmitWithdraw(t.Context(), currency.BTC, core.BitcoinDonationAddress, "", 0.001) require.NoError(t, err) assert.NotNil(t, result) } @@ -1297,7 +1297,7 @@ func TestGetAnnouncements(t *testing.T) { func TestWSRetrieveAnnouncements(t *testing.T) { t.Parallel() - result, err := d.WSRetrieveAnnouncements(time.Now(), 5) + result, err := d.WSRetrieveAnnouncements(t.Context(), time.Now(), 5) require.NoError(t, err) assert.NotNil(t, result) } @@ -1313,7 +1313,7 @@ func TestGetAccessLog(t *testing.T) { func TestWSRetrieveAccessLog(t *testing.T) { t.Parallel() sharedtestvalues.SkipTestIfCredentialsUnset(t, d) - result, err := d.WSRetrieveAccessLog(0, 0) + result, err := d.WSRetrieveAccessLog(t.Context(), 0, 0) require.NoError(t, err) assert.NotNil(t, result) } @@ -1335,11 +1335,11 @@ func TestChangeAPIKeyName(t *testing.T) { func TestWSChangeAPIKeyName(t *testing.T) { t.Parallel() - _, err := d.WSChangeAPIKeyName(0, "TestKey123") + _, err := d.WSChangeAPIKeyName(t.Context(), 0, "TestKey123") require.ErrorIs(t, err, errInvalidID) sharedtestvalues.SkipTestIfCredentialsUnset(t, d, canManipulateAPIEndpoints) - result, err := d.WSChangeAPIKeyName(1, "TestKey123") + result, err := d.WSChangeAPIKeyName(t.Context(), 1, "TestKey123") require.NoError(t, err) assert.NotNil(t, result) } @@ -1357,11 +1357,11 @@ func TestChangeMarginModel(t *testing.T) { func TestWsChangeMarginModel(t *testing.T) { t.Parallel() - _, err := d.WsChangeMarginModel(2, "", false) + _, err := d.WsChangeMarginModel(t.Context(), 2, "", false) require.ErrorIs(t, err, errInvalidMarginModel) sharedtestvalues.SkipTestIfCredentialsUnset(t, d, canManipulateRealOrders) - result, err := d.WsChangeMarginModel(2, "segregated_pm", false) + result, err := d.WsChangeMarginModel(t.Context(), 2, "segregated_pm", false) require.NoError(t, err) assert.NotNil(t, result) } @@ -1379,11 +1379,11 @@ func TestChangeScopeInAPIKey(t *testing.T) { func TestWSChangeScopeInAPIKey(t *testing.T) { t.Parallel() - _, err := d.WSChangeScopeInAPIKey(0, "account:read_write") + _, err := d.WSChangeScopeInAPIKey(t.Context(), 0, "account:read_write") require.ErrorIs(t, err, errInvalidID) sharedtestvalues.SkipTestIfCredentialsUnset(t, d, canManipulateAPIEndpoints) - result, err := d.WSChangeScopeInAPIKey(1, "account:read_write") + result, err := d.WSChangeScopeInAPIKey(t.Context(), 1, "account:read_write") require.NoError(t, err) assert.NotNil(t, result) } @@ -1402,13 +1402,13 @@ func TestChangeSubAccountName(t *testing.T) { func TestWSChangeSubAccountName(t *testing.T) { t.Parallel() - err := d.WSChangeSubAccountName(0, "new_sub") + err := d.WSChangeSubAccountName(t.Context(), 0, "new_sub") require.ErrorIs(t, err, errInvalidID) - err = d.WSChangeSubAccountName(312313, "") + err = d.WSChangeSubAccountName(t.Context(), 312313, "") require.ErrorIs(t, err, errInvalidUsername) sharedtestvalues.SkipTestIfCredentialsUnset(t, d, canManipulateRealOrders) - err = d.WSChangeSubAccountName(1, "new_sub") + err = d.WSChangeSubAccountName(t.Context(), 1, "new_sub") assert.NoError(t, err) } @@ -1423,7 +1423,7 @@ func TestCreateAPIKey(t *testing.T) { func TestWSCreateAPIKey(t *testing.T) { t.Parallel() sharedtestvalues.SkipTestIfCredentialsUnset(t, d, canManipulateAPIEndpoints) - result, err := d.WSCreateAPIKey("account:read_write", "new_sub", false) + result, err := d.WSCreateAPIKey(t.Context(), "account:read_write", "new_sub", false) require.NoError(t, err) assert.NotNil(t, result) } @@ -1439,7 +1439,7 @@ func TestCreateSubAccount(t *testing.T) { func TestWSCreateSubAccount(t *testing.T) { t.Parallel() sharedtestvalues.SkipTestIfCredentialsUnset(t, d, canManipulateRealOrders) - result, err := d.WSCreateSubAccount() + result, err := d.WSCreateSubAccount(t.Context()) require.NoError(t, err) assert.NotNil(t, result) } @@ -1456,10 +1456,10 @@ func TestDisableAPIKey(t *testing.T) { func TestWSDisableAPIKey(t *testing.T) { t.Parallel() - _, err := d.WSDisableAPIKey(0) + _, err := d.WSDisableAPIKey(t.Context(), 0) require.ErrorIs(t, err, errInvalidID) sharedtestvalues.SkipTestIfCredentialsUnset(t, d, canManipulateAPIEndpoints) - result, err := d.WSDisableAPIKey(1) + result, err := d.WSDisableAPIKey(t.Context(), 1) require.NoError(t, err) assert.NotNil(t, result) } @@ -1479,13 +1479,13 @@ func TestEditAPIKey(t *testing.T) { func TestWsEditAPIKey(t *testing.T) { t.Parallel() - _, err := d.WsEditAPIKey(0, "trade", "", false, []string{"read", "read_write"}, []string{}) + _, err := d.WsEditAPIKey(t.Context(), 0, "trade", "", false, []string{"read", "read_write"}, []string{}) require.ErrorIs(t, err, errInvalidAPIKeyID) - _, err = d.WsEditAPIKey(1234, "", "", false, []string{"read", "read_write"}, []string{}) + _, err = d.WsEditAPIKey(t.Context(), 1234, "", "", false, []string{"read", "read_write"}, []string{}) require.ErrorIs(t, err, errMaxScopeIsRequired) sharedtestvalues.SkipTestIfCredentialsUnset(t, d, canManipulateAPIEndpoints) - result, err := d.WsEditAPIKey(1234, "trade", "", false, []string{"read", "read_write"}, []string{}) + result, err := d.WsEditAPIKey(t.Context(), 1234, "trade", "", false, []string{"read", "read_write"}, []string{}) require.NoError(t, err) assert.NotNil(t, result) } @@ -1500,7 +1500,7 @@ func TestEnableAffiliateProgram(t *testing.T) { func TestWSEnableAffiliateProgram(t *testing.T) { t.Parallel() sharedtestvalues.SkipTestIfCredentialsUnset(t, d, canManipulateRealOrders) - err := d.WSEnableAffiliateProgram() + err := d.WSEnableAffiliateProgram(t.Context()) assert.NoError(t, err) } @@ -1515,7 +1515,7 @@ func TestEnableAPIKey(t *testing.T) { func TestWSEnableAPIKey(t *testing.T) { t.Parallel() sharedtestvalues.SkipTestIfCredentialsUnset(t, d, canManipulateAPIEndpoints) - result, err := d.WSEnableAPIKey(1) + result, err := d.WSEnableAPIKey(t.Context(), 1) require.NoError(t, err) assert.NotNil(t, result) } @@ -1531,7 +1531,7 @@ func TestGetAffiliateProgramInfo(t *testing.T) { func TestWSRetrieveAffiliateProgramInfo(t *testing.T) { t.Parallel() sharedtestvalues.SkipTestIfCredentialsUnset(t, d) - result, err := d.WSRetrieveAffiliateProgramInfo() + result, err := d.WSRetrieveAffiliateProgramInfo(t.Context()) require.NoError(t, err) assert.NotNil(t, result) } @@ -1547,7 +1547,7 @@ func TestGetEmailLanguage(t *testing.T) { func TestWSRetrieveEmailLanguage(t *testing.T) { t.Parallel() sharedtestvalues.SkipTestIfCredentialsUnset(t, d) - result, err := d.WSRetrieveEmailLanguage() + result, err := d.WSRetrieveEmailLanguage(t.Context()) require.NoError(t, err) assert.NotNil(t, result) } @@ -1563,7 +1563,7 @@ func TestGetNewAnnouncements(t *testing.T) { func TestWSRetrieveNewAnnouncements(t *testing.T) { t.Parallel() sharedtestvalues.SkipTestIfCredentialsUnset(t, d) - result, err := d.WSRetrieveNewAnnouncements() + result, err := d.WSRetrieveNewAnnouncements(t.Context()) require.NoError(t, err) assert.NotNil(t, result) } @@ -1581,11 +1581,11 @@ func TestGetPosition(t *testing.T) { func TestWSRetrievePosition(t *testing.T) { t.Parallel() - _, err := d.WSRetrievePosition("") + _, err := d.WSRetrievePosition(t.Context(), "") require.ErrorIs(t, err, errInvalidInstrumentName) sharedtestvalues.SkipTestIfCredentialsUnset(t, d) - result, err := d.WSRetrievePosition(btcPerpInstrument) + result, err := d.WSRetrievePosition(t.Context(), btcPerpInstrument) require.NoError(t, err) assert.NotNil(t, result) } @@ -1601,7 +1601,7 @@ func TestGetSubAccounts(t *testing.T) { func TestWSRetrieveSubAccounts(t *testing.T) { t.Parallel() sharedtestvalues.SkipTestIfCredentialsUnset(t, d) - result, err := d.WSRetrieveSubAccounts(false) + result, err := d.WSRetrieveSubAccounts(t.Context(), false) require.NoError(t, err) assert.NotNil(t, result) } @@ -1619,11 +1619,11 @@ func TestGetSubAccountDetails(t *testing.T) { func TestWSRetrieveSubAccountDetails(t *testing.T) { t.Parallel() - _, err := d.WSRetrieveSubAccountDetails(currency.EMPTYCODE, false) + _, err := d.WSRetrieveSubAccountDetails(t.Context(), currency.EMPTYCODE, false) require.ErrorIs(t, err, currency.ErrCurrencyCodeEmpty) sharedtestvalues.SkipTestIfCredentialsUnset(t, d) - result, err := d.WSRetrieveSubAccountDetails(currency.BTC, false) + result, err := d.WSRetrieveSubAccountDetails(t.Context(), currency.BTC, false) require.NoError(t, err) assert.NotNil(t, result) } @@ -1644,14 +1644,14 @@ func TestGetPositions(t *testing.T) { func TestWSRetrievePositions(t *testing.T) { t.Parallel() - _, err := d.WSRetrievePositions(currency.EMPTYCODE, "option") + _, err := d.WSRetrievePositions(t.Context(), currency.EMPTYCODE, "option") require.ErrorIs(t, err, currency.ErrCurrencyCodeEmpty) sharedtestvalues.SkipTestIfCredentialsUnset(t, d) - result, err := d.WSRetrievePositions(currency.BTC, "option") + result, err := d.WSRetrievePositions(t.Context(), currency.BTC, "option") require.NoError(t, err) require.NotNil(t, result) - result, err = d.WSRetrievePositions(currency.ETH, "") + result, err = d.WSRetrievePositions(t.Context(), currency.ETH, "") require.NoError(t, err) assert.NotNil(t, result) } @@ -1674,11 +1674,11 @@ func TestGetTransactionLog(t *testing.T) { func TestWSRetrieveTransactionLog(t *testing.T) { t.Parallel() - _, err := d.WSRetrieveTransactionLog(currency.EMPTYCODE, "trade", time.Now().Add(-24*time.Hour), time.Now(), 5, 0) + _, err := d.WSRetrieveTransactionLog(t.Context(), currency.EMPTYCODE, "trade", time.Now().Add(-24*time.Hour), time.Now(), 5, 0) require.ErrorIs(t, err, currency.ErrCurrencyCodeEmpty) sharedtestvalues.SkipTestIfCredentialsUnset(t, d) - result, err := d.WSRetrieveTransactionLog(currency.BTC, "trade", time.Now().Add(-24*time.Hour), time.Now(), 5, 0) + result, err := d.WSRetrieveTransactionLog(t.Context(), currency.BTC, "trade", time.Now().Add(-24*time.Hour), time.Now(), 5, 0) require.NoError(t, err) assert.NotNil(t, result) } @@ -1694,7 +1694,7 @@ func TestGetUserLocks(t *testing.T) { func TestWSRetrieveUserLocks(t *testing.T) { t.Parallel() sharedtestvalues.SkipTestIfCredentialsUnset(t, d) - result, err := d.WSRetrieveUserLocks() + result, err := d.WSRetrieveUserLocks(t.Context()) require.NoError(t, err) assert.NotNil(t, result) } @@ -1710,7 +1710,7 @@ func TestListAPIKeys(t *testing.T) { func TestWSListAPIKeys(t *testing.T) { t.Parallel() sharedtestvalues.SkipTestIfCredentialsUnset(t, d) - result, err := d.WSListAPIKeys("") + result, err := d.WSListAPIKeys(t.Context(), "") require.NoError(t, err) assert.NotNil(t, result) } @@ -1727,10 +1727,10 @@ func TestGetCustodyAccounts(t *testing.T) { func TestWsRetrieveCustodyAccounts(t *testing.T) { t.Parallel() - _, err := d.WsRetrieveCustodyAccounts(currency.EMPTYCODE) + _, err := d.WsRetrieveCustodyAccounts(t.Context(), currency.EMPTYCODE) require.ErrorIs(t, err, currency.ErrCurrencyCodeEmpty) sharedtestvalues.SkipTestIfCredentialsUnset(t, d) - result, err := d.WsRetrieveCustodyAccounts(currency.BTC) + result, err := d.WsRetrieveCustodyAccounts(t.Context(), currency.BTC) require.NoError(t, err) assert.NotNil(t, result) } @@ -1746,10 +1746,10 @@ func TestRemoveAPIKey(t *testing.T) { func TestWSRemoveAPIKey(t *testing.T) { t.Parallel() - err := d.WSRemoveAPIKey(0) + err := d.WSRemoveAPIKey(t.Context(), 0) require.ErrorIs(t, err, errInvalidID) sharedtestvalues.SkipTestIfCredentialsUnset(t, d, canManipulateAPIEndpoints) - err = d.WSRemoveAPIKey(1) + err = d.WSRemoveAPIKey(t.Context(), 1) assert.NoError(t, err) } @@ -1763,7 +1763,7 @@ func TestRemoveSubAccount(t *testing.T) { func TestWSRemoveSubAccount(t *testing.T) { t.Parallel() sharedtestvalues.SkipTestIfCredentialsUnset(t, d, canManipulateAPIEndpoints) - err := d.WSRemoveSubAccount(1) + err := d.WSRemoveSubAccount(t.Context(), 1) assert.NoError(t, err) } @@ -1779,10 +1779,10 @@ func TestResetAPIKey(t *testing.T) { func TestWSResetAPIKey(t *testing.T) { t.Parallel() - err := d.WSResetAPIKey(0) + err := d.WSResetAPIKey(t.Context(), 0) require.ErrorIs(t, err, errInvalidID) sharedtestvalues.SkipTestIfCredentialsUnset(t, d, canManipulateAPIEndpoints) - err = d.WSResetAPIKey(1) + err = d.WSResetAPIKey(t.Context(), 1) assert.NoError(t, err) } @@ -1808,13 +1808,13 @@ func TestSetEmailForSubAccount(t *testing.T) { func TestWSSetEmailForSubAccount(t *testing.T) { t.Parallel() - err := d.WSSetEmailForSubAccount(0, "wrongemail@wrongemail.com") + err := d.WSSetEmailForSubAccount(t.Context(), 0, "wrongemail@wrongemail.com") require.ErrorIs(t, err, errInvalidID) - err = d.WSSetEmailForSubAccount(1, "") + err = d.WSSetEmailForSubAccount(t.Context(), 1, "") require.ErrorIs(t, err, errInvalidEmailAddress) sharedtestvalues.SkipTestIfCredentialsUnset(t, d, canManipulateRealOrders) - err = d.WSSetEmailForSubAccount(1, "wrongemail@wrongemail.com") + err = d.WSSetEmailForSubAccount(t.Context(), 1, "wrongemail@wrongemail.com") assert.NoError(t, err) } @@ -1830,11 +1830,11 @@ func TestSetEmailLanguage(t *testing.T) { func TestWSSetEmailLanguage(t *testing.T) { t.Parallel() - err := d.WSSetEmailLanguage("") + err := d.WSSetEmailLanguage(t.Context(), "") require.ErrorIs(t, err, errLanguageIsRequired) sharedtestvalues.SkipTestIfCredentialsUnset(t, d, canManipulateRealOrders) - err = d.WSSetEmailLanguage("en") + err = d.WSSetEmailLanguage(t.Context(), "en") assert.NoError(t, err) } @@ -1850,11 +1850,11 @@ func TestSetSelfTradingConfig(t *testing.T) { func TestWsSetSelfTradingConfig(t *testing.T) { t.Parallel() - _, err := d.WsSetSelfTradingConfig("", false) + _, err := d.WsSetSelfTradingConfig(t.Context(), "", false) require.ErrorIs(t, err, errTradeModeIsRequired) sharedtestvalues.SkipTestIfCredentialsUnset(t, d, canManipulateRealOrders) - result, err := d.WsSetSelfTradingConfig("reject_taker", false) + result, err := d.WsSetSelfTradingConfig(t.Context(), "reject_taker", false) require.NoError(t, err) assert.NotNil(t, result) } @@ -1871,11 +1871,11 @@ func TestToggleNotificationsFromSubAccount(t *testing.T) { func TestWSToggleNotificationsFromSubAccount(t *testing.T) { t.Parallel() - err := d.WSToggleNotificationsFromSubAccount(0, false) + err := d.WSToggleNotificationsFromSubAccount(t.Context(), 0, false) require.ErrorIs(t, err, errInvalidID) sharedtestvalues.SkipTestIfCredentialsUnset(t, d, canManipulateRealOrders) - err = d.WSToggleNotificationsFromSubAccount(1, false) + err = d.WSToggleNotificationsFromSubAccount(t.Context(), 1, false) assert.NoError(t, err) } @@ -1892,11 +1892,11 @@ func TestTogglePortfolioMargining(t *testing.T) { func TestWSTogglePortfolioMargining(t *testing.T) { t.Parallel() - _, err := d.WSTogglePortfolioMargining(0, false, false) + _, err := d.WSTogglePortfolioMargining(t.Context(), 0, false, false) require.ErrorIs(t, err, errUserIDRequired) sharedtestvalues.SkipTestIfCredentialsUnset(t, d, canManipulateRealOrders) - result, err := d.WSTogglePortfolioMargining(1234, false, false) + result, err := d.WSTogglePortfolioMargining(t.Context(), 1234, false, false) require.NoError(t, err) assert.NotNil(t, result) } @@ -1913,11 +1913,11 @@ func TestToggleSubAccountLogin(t *testing.T) { func TestWSToggleSubAccountLogin(t *testing.T) { t.Parallel() - err := d.WSToggleSubAccountLogin(-1, false) + err := d.WSToggleSubAccountLogin(t.Context(), -1, false) require.ErrorIs(t, err, errInvalidID) sharedtestvalues.SkipTestIfCredentialsUnset(t, d, canManipulateRealOrders) - err = d.WSToggleSubAccountLogin(1, false) + err = d.WSToggleSubAccountLogin(t.Context(), 1, false) assert.NoError(t, err) } @@ -1952,9 +1952,9 @@ func TestSubmitBuy(t *testing.T) { func TestWSSubmitBuy(t *testing.T) { t.Parallel() - _, err := d.WSSubmitBuy(&OrderBuyAndSellParams{}) + _, err := d.WSSubmitBuy(t.Context(), &OrderBuyAndSellParams{}) require.ErrorIs(t, err, common.ErrNilPointer) - _, err = d.WSSubmitBuy(&OrderBuyAndSellParams{ + _, err = d.WSSubmitBuy(t.Context(), &OrderBuyAndSellParams{ Instrument: "", OrderType: "limit", Label: "testOrder", TimeInForce: "", Trigger: "", Advanced: "", @@ -1964,7 +1964,7 @@ func TestWSSubmitBuy(t *testing.T) { require.ErrorIs(t, err, errInvalidInstrumentName) sharedtestvalues.SkipTestIfCredentialsUnset(t, d, canManipulateRealOrders) - result, err := d.WSSubmitBuy(&OrderBuyAndSellParams{ + result, err := d.WSSubmitBuy(t.Context(), &OrderBuyAndSellParams{ Instrument: btcPerpInstrument, OrderType: "limit", Label: "testOrder", TimeInForce: "", Trigger: "", Advanced: "", @@ -1996,9 +1996,9 @@ func TestWSSubmitSell(t *testing.T) { t.Parallel() info, err := d.GetInstrument(t.Context(), btcPerpInstrument) require.NoError(t, err) - _, err = d.WSSubmitSell(&OrderBuyAndSellParams{}) + _, err = d.WSSubmitSell(t.Context(), &OrderBuyAndSellParams{}) require.ErrorIs(t, err, common.ErrNilPointer) - _, err = d.WSSubmitSell(&OrderBuyAndSellParams{ + _, err = d.WSSubmitSell(t.Context(), &OrderBuyAndSellParams{ Instrument: "", OrderType: "limit", Label: "testOrder", TimeInForce: "", Trigger: "", Advanced: "", Amount: info.ContractSize * 3, @@ -2008,7 +2008,7 @@ func TestWSSubmitSell(t *testing.T) { require.ErrorIs(t, err, errInvalidInstrumentName) sharedtestvalues.SkipTestIfCredentialsUnset(t, d, canManipulateRealOrders) - result, err := d.WSSubmitSell(&OrderBuyAndSellParams{ + result, err := d.WSSubmitSell(t.Context(), &OrderBuyAndSellParams{ Instrument: btcPerpInstrument, OrderType: "limit", Label: "testOrder", TimeInForce: "", Trigger: "", Advanced: "", Amount: info.ContractSize * 3, @@ -2045,21 +2045,21 @@ func TestEditOrderByLabel(t *testing.T) { func TestWSEditOrderByLabel(t *testing.T) { t.Parallel() - _, err := d.WSEditOrderByLabel(&OrderBuyAndSellParams{}) + _, err := d.WSEditOrderByLabel(t.Context(), &OrderBuyAndSellParams{}) require.ErrorIs(t, err, common.ErrNilPointer) - _, err = d.WSEditOrderByLabel(&OrderBuyAndSellParams{ + _, err = d.WSEditOrderByLabel(t.Context(), &OrderBuyAndSellParams{ Label: "incorrectUserLabel", Instrument: "", Advanced: "", Amount: 1, Price: 30000, TriggerPrice: 0, PostOnly: false, ReduceOnly: false, RejectPostOnly: false, MMP: false, }) require.ErrorIs(t, err, errInvalidInstrumentName) - _, err = d.WSEditOrderByLabel(&OrderBuyAndSellParams{ + _, err = d.WSEditOrderByLabel(t.Context(), &OrderBuyAndSellParams{ Label: "incorrectUserLabel", Instrument: btcPerpInstrument, Advanced: "", Amount: 0, Price: 30000, TriggerPrice: 0, PostOnly: false, ReduceOnly: false, RejectPostOnly: false, MMP: false, }) require.ErrorIs(t, err, errInvalidAmount) sharedtestvalues.SkipTestIfCredentialsUnset(t, d, canManipulateRealOrders) - result, err := d.WSEditOrderByLabel(&OrderBuyAndSellParams{ + result, err := d.WSEditOrderByLabel(t.Context(), &OrderBuyAndSellParams{ Label: "incorrectUserLabel", Instrument: btcPerpInstrument, Advanced: "", Amount: 1, Price: 30000, TriggerPrice: 0, PostOnly: false, ReduceOnly: false, RejectPostOnly: false, MMP: false, }) @@ -2085,11 +2085,11 @@ func TestSubmitCancel(t *testing.T) { func TestWSSubmitCancel(t *testing.T) { t.Parallel() - _, err := d.WSSubmitCancel("") + _, err := d.WSSubmitCancel(t.Context(), "") require.ErrorIs(t, err, errInvalidID) sharedtestvalues.SkipTestIfCredentialsUnset(t, d, canManipulateRealOrders) - result, err := d.WSSubmitCancel("incorrectID") + result, err := d.WSSubmitCancel(t.Context(), "incorrectID") require.NoError(t, err) assert.NotNil(t, result) } @@ -2105,7 +2105,7 @@ func TestSubmitCancelAll(t *testing.T) { func TestWSSubmitCancelAll(t *testing.T) { t.Parallel() sharedtestvalues.SkipTestIfCredentialsUnset(t, d, canManipulateRealOrders) - result, err := d.WSSubmitCancelAll(true) + result, err := d.WSSubmitCancelAll(t.Context(), true) require.NoError(t, err) assert.NotNil(t, result) } @@ -2123,11 +2123,11 @@ func TestSubmitCancelAllByCurrency(t *testing.T) { func TestWSSubmitCancelAllByCurrency(t *testing.T) { t.Parallel() - _, err := d.WSSubmitCancelAllByCurrency(currency.EMPTYCODE, "option", "", true) + _, err := d.WSSubmitCancelAllByCurrency(t.Context(), currency.EMPTYCODE, "option", "", true) require.ErrorIs(t, err, currency.ErrCurrencyCodeEmpty) sharedtestvalues.SkipTestIfCredentialsUnset(t, d, canManipulateRealOrders) - result, err := d.WSSubmitCancelAllByCurrency(currency.BTC, "option", "", true) + result, err := d.WSSubmitCancelAllByCurrency(t.Context(), currency.BTC, "option", "", true) require.NoError(t, err) assert.NotNil(t, result) } @@ -2145,11 +2145,11 @@ func TestSubmitCancelAllByKind(t *testing.T) { func TestWsSubmitCancelAllByKind(t *testing.T) { t.Parallel() - _, err := d.WsSubmitCancelAllByKind(currency.EMPTYCODE, "option_combo", "trigger_all", true) + _, err := d.WsSubmitCancelAllByKind(t.Context(), currency.EMPTYCODE, "option_combo", "trigger_all", true) require.ErrorIs(t, err, currency.ErrCurrencyCodeEmpty) sharedtestvalues.SkipTestIfCredentialsUnset(t, d, canManipulateRealOrders) - result, err := d.WsSubmitCancelAllByKind(currency.ETH, "option_combo", "trigger_all", true) + result, err := d.WsSubmitCancelAllByKind(t.Context(), currency.ETH, "option_combo", "trigger_all", true) require.NoError(t, err) assert.NotNil(t, result) } @@ -2167,11 +2167,11 @@ func TestSubmitCancelAllByInstrument(t *testing.T) { func TestWSSubmitCancelAllByInstrument(t *testing.T) { t.Parallel() - _, err := d.WSSubmitCancelAllByInstrument("", "all", true, true) + _, err := d.WSSubmitCancelAllByInstrument(t.Context(), "", "all", true, true) require.ErrorIs(t, err, errInvalidInstrumentName) sharedtestvalues.SkipTestIfCredentialsUnset(t, d, canManipulateRealOrders) - result, err := d.WSSubmitCancelAllByInstrument(btcPerpInstrument, "all", true, true) + result, err := d.WSSubmitCancelAllByInstrument(t.Context(), btcPerpInstrument, "all", true, true) require.NoError(t, err) assert.NotNil(t, result) } @@ -2187,7 +2187,7 @@ func TestSubmitCancelByLabel(t *testing.T) { func TestWSSubmitCancelByLabel(t *testing.T) { t.Parallel() sharedtestvalues.SkipTestIfCredentialsUnset(t, d, canManipulateRealOrders) - result, err := d.WSSubmitCancelByLabel("incorrectOrderLabel", currency.EMPTYCODE, true) + result, err := d.WSSubmitCancelByLabel(t.Context(), "incorrectOrderLabel", currency.EMPTYCODE, true) require.NoError(t, err) assert.NotNil(t, result) } @@ -2205,11 +2205,11 @@ func TestSubmitCancelQuotes(t *testing.T) { func TestWSSubmitCancelQuotes(t *testing.T) { t.Parallel() - _, err := d.WSSubmitCancelQuotes(currency.EMPTYCODE, 0, 0, "all", "", futuresTradablePair.String(), "future", true) + _, err := d.WSSubmitCancelQuotes(t.Context(), currency.EMPTYCODE, 0, 0, "all", "", futuresTradablePair.String(), "future", true) require.ErrorIs(t, err, currency.ErrCurrencyCodeEmpty) sharedtestvalues.SkipTestIfCredentialsUnset(t, d, canManipulateRealOrders) - result, err := d.WSSubmitCancelQuotes(currency.BTC, 0, 0, "all", "", futuresTradablePair.String(), "future", true) + result, err := d.WSSubmitCancelQuotes(t.Context(), currency.BTC, 0, 0, "all", "", futuresTradablePair.String(), "future", true) require.NoError(t, err) assert.NotNil(t, result) } @@ -2227,11 +2227,11 @@ func TestSubmitClosePosition(t *testing.T) { func TestWSSubmitClosePosition(t *testing.T) { t.Parallel() - _, err := d.WSSubmitClosePosition("", "limit", 35000) + _, err := d.WSSubmitClosePosition(t.Context(), "", "limit", 35000) require.ErrorIs(t, err, errInvalidInstrumentName) sharedtestvalues.SkipTestIfCredentialsUnset(t, d, canManipulateRealOrders) - result, err := d.WSSubmitClosePosition(d.formatFuturesTradablePair(futuresTradablePair), "limit", 35000) + result, err := d.WSSubmitClosePosition(t.Context(), d.formatFuturesTradablePair(futuresTradablePair), "limit", 35000) require.NoError(t, err) assert.NotNil(t, result) } @@ -2253,11 +2253,11 @@ func TestGetMargins(t *testing.T) { func TestWSRetrieveMargins(t *testing.T) { t.Parallel() - _, err := d.WSRetrieveMargins("", 5, 35000) + _, err := d.WSRetrieveMargins(t.Context(), "", 5, 35000) require.ErrorIs(t, err, errInvalidInstrumentName) sharedtestvalues.SkipTestIfCredentialsUnset(t, d) - result, err := d.WSRetrieveMargins(d.formatFuturesTradablePair(futuresTradablePair), 5, 35000) + result, err := d.WSRetrieveMargins(t.Context(), d.formatFuturesTradablePair(futuresTradablePair), 5, 35000) require.NoError(t, err) assert.NotNil(t, result) } @@ -2275,11 +2275,11 @@ func TestGetMMPConfig(t *testing.T) { func TestWSRetrieveMMPConfig(t *testing.T) { t.Parallel() - _, err := d.WSRetrieveMMPConfig(currency.EMPTYCODE) + _, err := d.WSRetrieveMMPConfig(t.Context(), currency.EMPTYCODE) require.ErrorIs(t, err, currency.ErrCurrencyCodeEmpty) sharedtestvalues.SkipTestIfCredentialsUnset(t, d) - result, err := d.WSRetrieveMMPConfig(currency.ETH) + result, err := d.WSRetrieveMMPConfig(t.Context(), currency.ETH) require.NoError(t, err) assert.NotNil(t, result) } @@ -2302,11 +2302,11 @@ func TestGetOpenOrdersByCurrency(t *testing.T) { func TestWSRetrieveOpenOrdersByCurrency(t *testing.T) { t.Parallel() - _, err := d.WSRetrieveOpenOrdersByCurrency(currency.EMPTYCODE, "option", "all") + _, err := d.WSRetrieveOpenOrdersByCurrency(t.Context(), currency.EMPTYCODE, "option", "all") require.ErrorIs(t, err, currency.ErrCurrencyCodeEmpty) sharedtestvalues.SkipTestIfCredentialsUnset(t, d) - result, err := d.WSRetrieveOpenOrdersByCurrency(currency.BTC, "option", "all") + result, err := d.WSRetrieveOpenOrdersByCurrency(t.Context(), currency.BTC, "option", "all") require.NoError(t, err) assert.NotNil(t, result) } @@ -2324,11 +2324,11 @@ func TestGetOpenOrdersByLabel(t *testing.T) { func TestWSRetrieveOpenOrdersByLabel(t *testing.T) { t.Parallel() - _, err := d.WSRetrieveOpenOrdersByLabel(currency.EMPTYCODE, "the-label") + _, err := d.WSRetrieveOpenOrdersByLabel(t.Context(), currency.EMPTYCODE, "the-label") require.ErrorIs(t, err, currency.ErrCurrencyCodeEmpty) sharedtestvalues.SkipTestIfCredentialsUnset(t, d, canManipulateRealOrders) - result, err := d.WSRetrieveOpenOrdersByLabel(currency.EURR, "the-label") + result, err := d.WSRetrieveOpenOrdersByLabel(t.Context(), currency.EURR, "the-label") require.NoError(t, err) assert.NotNil(t, result) } @@ -2346,11 +2346,11 @@ func TestGetOpenOrdersByInstrument(t *testing.T) { func TestWSRetrieveOpenOrdersByInstrument(t *testing.T) { t.Parallel() - _, err := d.WSRetrieveOpenOrdersByInstrument("", "all") + _, err := d.WSRetrieveOpenOrdersByInstrument(t.Context(), "", "all") require.ErrorIs(t, err, errInvalidInstrumentName) sharedtestvalues.SkipTestIfCredentialsUnset(t, d) - result, err := d.WSRetrieveOpenOrdersByInstrument(btcPerpInstrument, "all") + result, err := d.WSRetrieveOpenOrdersByInstrument(t.Context(), btcPerpInstrument, "all") require.NoError(t, err) assert.NotNil(t, result) } @@ -2368,11 +2368,11 @@ func TestGetOrderHistoryByCurrency(t *testing.T) { func TestWSRetrieveOrderHistoryByCurrency(t *testing.T) { t.Parallel() - _, err := d.WSRetrieveOrderHistoryByCurrency(currency.EMPTYCODE, "future", 0, 0, false, false) + _, err := d.WSRetrieveOrderHistoryByCurrency(t.Context(), currency.EMPTYCODE, "future", 0, 0, false, false) require.ErrorIs(t, err, currency.ErrCurrencyCodeEmpty) sharedtestvalues.SkipTestIfCredentialsUnset(t, d) - result, err := d.WSRetrieveOrderHistoryByCurrency(currency.BTC, "future", 0, 0, false, false) + result, err := d.WSRetrieveOrderHistoryByCurrency(t.Context(), currency.BTC, "future", 0, 0, false, false) require.NoError(t, err) assert.NotNil(t, result) } @@ -2390,11 +2390,11 @@ func TestGetOrderHistoryByInstrument(t *testing.T) { func TestWSRetrieveOrderHistoryByInstrument(t *testing.T) { t.Parallel() - _, err := d.WSRetrieveOrderHistoryByInstrument("", 0, 0, false, false) + _, err := d.WSRetrieveOrderHistoryByInstrument(t.Context(), "", 0, 0, false, false) require.ErrorIs(t, err, errInvalidInstrumentName) sharedtestvalues.SkipTestIfCredentialsUnset(t, d) - result, err := d.WSRetrieveOrderHistoryByInstrument(btcPerpInstrument, 0, 0, false, false) + result, err := d.WSRetrieveOrderHistoryByInstrument(t.Context(), btcPerpInstrument, 0, 0, false, false) require.NoError(t, err) assert.NotNil(t, result) } @@ -2412,11 +2412,11 @@ func TestGetOrderMarginsByID(t *testing.T) { func TestWSRetrieveOrderMarginsByID(t *testing.T) { t.Parallel() - _, err := d.WSRetrieveOrderMarginsByID([]string{}) + _, err := d.WSRetrieveOrderMarginsByID(t.Context(), []string{}) require.ErrorIs(t, err, errInvalidID) sharedtestvalues.SkipTestIfCredentialsUnset(t, d) - result, err := d.WSRetrieveOrderMarginsByID([]string{"ETH-349280", "ETH-349279", "ETH-349278"}) + result, err := d.WSRetrieveOrderMarginsByID(t.Context(), []string{"ETH-349280", "ETH-349279", "ETH-349278"}) require.NoError(t, err) assert.NotNil(t, result) } @@ -2434,11 +2434,11 @@ func TestGetOrderState(t *testing.T) { func TestWSRetrievesOrderState(t *testing.T) { t.Parallel() - _, err := d.WSRetrievesOrderState("") + _, err := d.WSRetrievesOrderState(t.Context(), "") require.ErrorIs(t, err, errInvalidID) sharedtestvalues.SkipTestIfCredentialsUnset(t, d) - result, err := d.WSRetrievesOrderState("brokenid123") + result, err := d.WSRetrievesOrderState(t.Context(), "brokenid123") require.NoError(t, err) assert.NotNil(t, result) } @@ -2456,11 +2456,11 @@ func TestGetOrderStateByLabel(t *testing.T) { func TestWsRetrieveOrderStateByLabel(t *testing.T) { t.Parallel() - _, err := d.WsRetrieveOrderStateByLabel(currency.EMPTYCODE, "the-label") + _, err := d.WsRetrieveOrderStateByLabel(t.Context(), currency.EMPTYCODE, "the-label") require.ErrorIs(t, err, currency.ErrCurrencyCodeEmpty) sharedtestvalues.SkipTestIfCredentialsUnset(t, d) - result, err := d.WsRetrieveOrderStateByLabel(currency.EURR, "the-label") + result, err := d.WsRetrieveOrderStateByLabel(t.Context(), currency.EURR, "the-label") require.NoError(t, err) assert.NotNil(t, result) } @@ -2478,11 +2478,11 @@ func TestGetTriggerOrderHistory(t *testing.T) { func TestWSRetrieveTriggerOrderHistory(t *testing.T) { t.Parallel() - _, err := d.WSRetrieveTriggerOrderHistory(currency.EMPTYCODE, "", "", 0) + _, err := d.WSRetrieveTriggerOrderHistory(t.Context(), currency.EMPTYCODE, "", "", 0) require.ErrorIs(t, err, currency.ErrCurrencyCodeEmpty) sharedtestvalues.SkipTestIfCredentialsUnset(t, d) - result, err := d.WSRetrieveTriggerOrderHistory(currency.ETH, "", "", 0) + result, err := d.WSRetrieveTriggerOrderHistory(t.Context(), currency.ETH, "", "", 0) require.NoError(t, err) assert.NotNil(t, result) } @@ -2505,11 +2505,11 @@ func TestGetUserTradesByCurrency(t *testing.T) { func TestWSRetrieveUserTradesByCurrency(t *testing.T) { t.Parallel() - _, err := d.WSRetrieveUserTradesByCurrency(currency.EMPTYCODE, "future", "", "", "asc", 0, false) + _, err := d.WSRetrieveUserTradesByCurrency(t.Context(), currency.EMPTYCODE, "future", "", "", "asc", 0, false) require.ErrorIs(t, err, currency.ErrCurrencyCodeEmpty) sharedtestvalues.SkipTestIfCredentialsUnset(t, d) - result, err := d.WSRetrieveUserTradesByCurrency(currency.ETH, "future", "", "", "asc", 0, false) + result, err := d.WSRetrieveUserTradesByCurrency(t.Context(), currency.ETH, "future", "", "", "asc", 0, false) require.NoError(t, err) assert.NotNil(t, result) } @@ -2527,11 +2527,11 @@ func TestGetUserTradesByCurrencyAndTime(t *testing.T) { func TestWSRetrieveUserTradesByCurrencyAndTime(t *testing.T) { t.Parallel() - _, err := d.WSRetrieveUserTradesByCurrencyAndTime(currency.EMPTYCODE, "future", "default", 5, time.Now().Add(-time.Hour*4), time.Now()) + _, err := d.WSRetrieveUserTradesByCurrencyAndTime(t.Context(), currency.EMPTYCODE, "future", "default", 5, time.Now().Add(-time.Hour*4), time.Now()) require.ErrorIs(t, err, currency.ErrCurrencyCodeEmpty) sharedtestvalues.SkipTestIfCredentialsUnset(t, d) - result, err := d.WSRetrieveUserTradesByCurrencyAndTime(currency.ETH, "future", "default", 5, time.Now().Add(-time.Hour*4), time.Now()) + result, err := d.WSRetrieveUserTradesByCurrencyAndTime(t.Context(), currency.ETH, "future", "default", 5, time.Now().Add(-time.Hour*4), time.Now()) require.NoError(t, err) assert.NotNil(t, result) } @@ -2549,11 +2549,11 @@ func TestGetUserTradesByInstrument(t *testing.T) { func TestWsRetrieveUserTradesByInstrument(t *testing.T) { t.Parallel() - _, err := d.WsRetrieveUserTradesByInstrument("", "asc", 5, 10, 4, true) + _, err := d.WsRetrieveUserTradesByInstrument(t.Context(), "", "asc", 5, 10, 4, true) require.ErrorIs(t, err, errInvalidInstrumentName) sharedtestvalues.SkipTestIfCredentialsUnset(t, d) - result, err := d.WsRetrieveUserTradesByInstrument(btcPerpInstrument, "asc", 5, 10, 4, true) + result, err := d.WsRetrieveUserTradesByInstrument(t.Context(), btcPerpInstrument, "asc", 5, 10, 4, true) require.NoError(t, err) assert.NotNil(t, result) } @@ -2571,11 +2571,11 @@ func TestGetUserTradesByInstrumentAndTime(t *testing.T) { func TestWSRetrieveUserTradesByInstrumentAndTime(t *testing.T) { t.Parallel() - _, err := d.WSRetrieveUserTradesByInstrumentAndTime("", "asc", 10, false, time.Now().Add(-time.Hour), time.Now()) + _, err := d.WSRetrieveUserTradesByInstrumentAndTime(t.Context(), "", "asc", 10, false, time.Now().Add(-time.Hour), time.Now()) require.ErrorIs(t, err, errInvalidInstrumentName) sharedtestvalues.SkipTestIfCredentialsUnset(t, d) - result, err := d.WSRetrieveUserTradesByInstrumentAndTime(btcPerpInstrument, "asc", 10, false, time.Now().Add(-time.Hour), time.Now()) + result, err := d.WSRetrieveUserTradesByInstrumentAndTime(t.Context(), btcPerpInstrument, "asc", 10, false, time.Now().Add(-time.Hour), time.Now()) require.NoError(t, err) assert.NotNil(t, result) } @@ -2593,11 +2593,11 @@ func TestGetUserTradesByOrder(t *testing.T) { func TestWSRetrieveUserTradesByOrder(t *testing.T) { t.Parallel() - _, err := d.WSRetrieveUserTradesByOrder("", "default") + _, err := d.WSRetrieveUserTradesByOrder(t.Context(), "", "default") require.ErrorIs(t, err, errInvalidID) sharedtestvalues.SkipTestIfCredentialsUnset(t, d) - result, err := d.WSRetrieveUserTradesByOrder("wrongOrderID", "default") + result, err := d.WSRetrieveUserTradesByOrder(t.Context(), "wrongOrderID", "default") require.NoError(t, err) assert.NotNil(t, result) } @@ -2614,11 +2614,11 @@ func TestResetMMP(t *testing.T) { func TestWSResetMMP(t *testing.T) { t.Parallel() - err := d.WSResetMMP(currency.EMPTYCODE) + err := d.WSResetMMP(t.Context(), currency.EMPTYCODE) require.ErrorIs(t, err, currency.ErrCurrencyCodeEmpty) sharedtestvalues.SkipTestIfCredentialsUnset(t, d) - err = d.WSResetMMP(currency.BTC) + err = d.WSResetMMP(t.Context(), currency.BTC) assert.NoError(t, err) } @@ -2634,11 +2634,11 @@ func TestSendRequestForQuote(t *testing.T) { func TestWSSendRequestForQuote(t *testing.T) { t.Parallel() - err := d.WSSendRequestForQuote("", 1000, order.Buy) + err := d.WSSendRequestForQuote(t.Context(), "", 1000, order.Buy) require.ErrorIs(t, err, errInvalidInstrumentName) sharedtestvalues.SkipTestIfCredentialsUnset(t, d) - err = d.WSSendRequestForQuote(d.formatFuturesTradablePair(futuresTradablePair), 1000, order.Buy) + err = d.WSSendRequestForQuote(t.Context(), d.formatFuturesTradablePair(futuresTradablePair), 1000, order.Buy) assert.NoError(t, err) } @@ -2654,11 +2654,11 @@ func TestSetMMPConfig(t *testing.T) { func TestWSSetMMPConfig(t *testing.T) { t.Parallel() - err := d.WSSetMMPConfig(currency.EMPTYCODE, kline.FiveMin, 5, 0, 0) + err := d.WSSetMMPConfig(t.Context(), currency.EMPTYCODE, kline.FiveMin, 5, 0, 0) require.ErrorIs(t, err, currency.ErrCurrencyCodeEmpty) sharedtestvalues.SkipTestIfCredentialsUnset(t, d) - err = d.WSSetMMPConfig(currency.BTC, kline.FiveMin, 5, 0, 0) + err = d.WSSetMMPConfig(t.Context(), currency.BTC, kline.FiveMin, 5, 0, 0) assert.NoError(t, err) } @@ -2675,11 +2675,11 @@ func TestGetSettlementHistoryByCurency(t *testing.T) { func TestWSRetrieveSettlementHistoryByCurency(t *testing.T) { t.Parallel() - _, err := d.WSRetrieveSettlementHistoryByCurency(currency.EMPTYCODE, "settlement", "", 10, time.Now().Add(-time.Hour)) + _, err := d.WSRetrieveSettlementHistoryByCurency(t.Context(), currency.EMPTYCODE, "settlement", "", 10, time.Now().Add(-time.Hour)) require.ErrorIs(t, err, currency.ErrCurrencyCodeEmpty) sharedtestvalues.SkipTestIfCredentialsUnset(t, d) - result, err := d.WSRetrieveSettlementHistoryByCurency(currency.BTC, "settlement", "", 10, time.Now().Add(-time.Hour)) + result, err := d.WSRetrieveSettlementHistoryByCurency(t.Context(), currency.BTC, "settlement", "", 10, time.Now().Add(-time.Hour)) require.NoError(t, err) assert.NotNil(t, result) } @@ -2700,11 +2700,11 @@ func TestGetSettlementHistoryByInstrument(t *testing.T) { func TestWSRetrieveSettlementHistoryByInstrument(t *testing.T) { t.Parallel() - _, err := d.WSRetrieveSettlementHistoryByInstrument("", "settlement", "", 10, time.Now().Add(-time.Hour)) + _, err := d.WSRetrieveSettlementHistoryByInstrument(t.Context(), "", "settlement", "", 10, time.Now().Add(-time.Hour)) require.ErrorIs(t, err, errInvalidInstrumentName) sharedtestvalues.SkipTestIfCredentialsUnset(t, d) - result, err := d.WSRetrieveSettlementHistoryByInstrument(btcPerpInstrument, "settlement", "", 10, time.Now().Add(-time.Hour)) + result, err := d.WSRetrieveSettlementHistoryByInstrument(t.Context(), btcPerpInstrument, "settlement", "", 10, time.Now().Add(-time.Hour)) require.NoError(t, err) assert.NotNil(t, result) } @@ -2724,11 +2724,11 @@ func TestSubmitEdit(t *testing.T) { func TestWSSubmitEdit(t *testing.T) { t.Parallel() - _, err := d.WSSubmitEdit(&OrderBuyAndSellParams{}) + _, err := d.WSSubmitEdit(t.Context(), &OrderBuyAndSellParams{}) require.ErrorIs(t, err, common.ErrNilPointer) sharedtestvalues.SkipTestIfCredentialsUnset(t, d, canManipulateRealOrders) - result, err := d.WSSubmitEdit(&OrderBuyAndSellParams{ + result, err := d.WSSubmitEdit(t.Context(), &OrderBuyAndSellParams{ OrderID: "incorrectID", Advanced: "", TriggerPrice: 0.001, @@ -2753,10 +2753,10 @@ func TestGetComboIDS(t *testing.T) { func TestWSRetrieveComboIDS(t *testing.T) { t.Parallel() - _, err := d.WSRetrieveComboIDs(currency.EMPTYCODE, "") + _, err := d.WSRetrieveComboIDs(t.Context(), currency.EMPTYCODE, "") require.ErrorIs(t, err, currency.ErrCurrencyCodeEmpty) - combos, err := d.WSRetrieveComboIDs(currency.BTC, "") + combos, err := d.WSRetrieveComboIDs(t.Context(), currency.BTC, "") require.NoError(t, err) assert.NotEmpty(t, combos) } @@ -2773,10 +2773,10 @@ func TestGetComboDetails(t *testing.T) { func TestWSRetrieveComboDetails(t *testing.T) { t.Parallel() - _, err := d.WSRetrieveComboDetails("") + _, err := d.WSRetrieveComboDetails(t.Context(), "") require.ErrorIs(t, err, errInvalidComboID) - result, err := d.WSRetrieveComboDetails(futureComboTradablePair.String()) + result, err := d.WSRetrieveComboDetails(t.Context(), futureComboTradablePair.String()) require.NoError(t, err) assert.NotNil(t, result) } @@ -2857,16 +2857,16 @@ func TestCreateCombo(t *testing.T) { func TestWSCreateCombo(t *testing.T) { t.Parallel() - _, err := d.WSCreateCombo([]ComboParam{}) + _, err := d.WSCreateCombo(t.Context(), []ComboParam{}) require.ErrorIs(t, err, errNoArgumentPassed) instruments, err := d.GetEnabledPairs(asset.Futures) require.NoError(t, err) if len(instruments) < 2 { t.Skip("no enough instrument found") } - _, err = d.WSCreateCombo([]ComboParam{}) + _, err = d.WSCreateCombo(t.Context(), []ComboParam{}) require.ErrorIs(t, err, errNoArgumentPassed) - _, err = d.WSCreateCombo([]ComboParam{ + _, err = d.WSCreateCombo(t.Context(), []ComboParam{ { InstrumentName: instruments[0].String(), Direction: "sell", @@ -2878,7 +2878,7 @@ func TestWSCreateCombo(t *testing.T) { }, }) require.ErrorIs(t, err, errInvalidAmount) - _, err = d.WSCreateCombo([]ComboParam{ + _, err = d.WSCreateCombo(t.Context(), []ComboParam{ { InstrumentName: instruments[0].String(), Amount: 123, @@ -2892,7 +2892,7 @@ func TestWSCreateCombo(t *testing.T) { require.ErrorIs(t, err, errInvalidOrderSideOrDirection) sharedtestvalues.SkipTestIfCredentialsUnset(t, d, canManipulateRealOrders) - result, err := d.WSCreateCombo([]ComboParam{ + result, err := d.WSCreateCombo(t.Context(), []ComboParam{ { InstrumentName: instruments[0].String(), Direction: "sell", @@ -2944,16 +2944,16 @@ func TestVerifyBlockTrade(t *testing.T) { func TestWSVerifyBlockTrade(t *testing.T) { t.Parallel() - _, err := d.WSVerifyBlockTrade(time.Now(), "", "maker", currency.EMPTYCODE, []BlockTradeParam{}) + _, err := d.WSVerifyBlockTrade(t.Context(), time.Now(), "", "maker", currency.EMPTYCODE, []BlockTradeParam{}) require.ErrorIs(t, err, errMissingNonce) - _, err = d.WSVerifyBlockTrade(time.Now(), "nonce-string", "", currency.EMPTYCODE, []BlockTradeParam{}) + _, err = d.WSVerifyBlockTrade(t.Context(), time.Now(), "nonce-string", "", currency.EMPTYCODE, []BlockTradeParam{}) require.ErrorIs(t, err, errInvalidTradeRole) - _, err = d.WSVerifyBlockTrade(time.Now(), "nonce-string", "maker", currency.EMPTYCODE, []BlockTradeParam{}) + _, err = d.WSVerifyBlockTrade(t.Context(), time.Now(), "nonce-string", "maker", currency.EMPTYCODE, []BlockTradeParam{}) require.ErrorIs(t, err, errNoArgumentPassed) info, err := d.GetInstrument(t.Context(), btcPerpInstrument) require.NoError(t, err) require.NotNil(t, info) - _, err = d.WSVerifyBlockTrade(time.Time{}, "nonce-string", "maker", currency.EMPTYCODE, []BlockTradeParam{ + _, err = d.WSVerifyBlockTrade(t.Context(), time.Time{}, "nonce-string", "maker", currency.EMPTYCODE, []BlockTradeParam{ { Price: 0.777 * 25000, InstrumentName: btcPerpInstrument, @@ -2964,7 +2964,7 @@ func TestWSVerifyBlockTrade(t *testing.T) { require.ErrorIs(t, err, errZeroTimestamp) sharedtestvalues.SkipTestIfCredentialsUnset(t, d) - result, err := d.WSVerifyBlockTrade(time.Now(), "sdjkafdad", "maker", currency.EMPTYCODE, []BlockTradeParam{ + result, err := d.WSVerifyBlockTrade(t.Context(), time.Now(), "sdjkafdad", "maker", currency.EMPTYCODE, []BlockTradeParam{ { Price: 0.777 * 28000, InstrumentName: btcPerpInstrument, @@ -2978,7 +2978,7 @@ func TestWSVerifyBlockTrade(t *testing.T) { func TestInvalidateBlockTradeSignature(t *testing.T) { t.Parallel() - err := d.WsInvalidateBlockTradeSignature("") + err := d.WsInvalidateBlockTradeSignature(t.Context(), "") require.ErrorIs(t, err, errMissingSignature) sharedtestvalues.SkipTestIfCredentialsUnset(t, d) err = d.InvalidateBlockTradeSignature(t.Context(), "verified_signature_string") @@ -2987,10 +2987,10 @@ func TestInvalidateBlockTradeSignature(t *testing.T) { func TestWsInvalidateBlockTradeSignature(t *testing.T) { t.Parallel() - err := d.WsInvalidateBlockTradeSignature("") + err := d.WsInvalidateBlockTradeSignature(t.Context(), "") require.ErrorIs(t, err, errMissingSignature) sharedtestvalues.SkipTestIfCredentialsUnset(t, d) - err = d.WsInvalidateBlockTradeSignature("verified_signature_string") + err = d.WsInvalidateBlockTradeSignature(t.Context(), "verified_signature_string") assert.NoError(t, err) } @@ -3030,16 +3030,16 @@ func TestExecuteBlockTrade(t *testing.T) { func TestWSExecuteBlockTrade(t *testing.T) { t.Parallel() - _, err := d.WSExecuteBlockTrade(time.Now(), "", "maker", currency.EMPTYCODE, []BlockTradeParam{}) + _, err := d.WSExecuteBlockTrade(t.Context(), time.Now(), "", "maker", currency.EMPTYCODE, []BlockTradeParam{}) require.ErrorIs(t, err, errMissingNonce) - _, err = d.WSExecuteBlockTrade(time.Now(), "nonce-string", "", currency.EMPTYCODE, []BlockTradeParam{}) + _, err = d.WSExecuteBlockTrade(t.Context(), time.Now(), "nonce-string", "", currency.EMPTYCODE, []BlockTradeParam{}) require.ErrorIs(t, err, errInvalidTradeRole) - _, err = d.WSExecuteBlockTrade(time.Now(), "nonce-string", "maker", currency.EMPTYCODE, []BlockTradeParam{}) + _, err = d.WSExecuteBlockTrade(t.Context(), time.Now(), "nonce-string", "maker", currency.EMPTYCODE, []BlockTradeParam{}) require.ErrorIs(t, err, errNoArgumentPassed) info, err := d.GetInstrument(t.Context(), btcPerpInstrument) require.NoError(t, err) require.NotNil(t, info) - _, err = d.WSExecuteBlockTrade(time.Time{}, "nonce-string", "maker", currency.EMPTYCODE, []BlockTradeParam{{ + _, err = d.WSExecuteBlockTrade(t.Context(), time.Time{}, "nonce-string", "maker", currency.EMPTYCODE, []BlockTradeParam{{ Price: 0.777 * 22000, InstrumentName: btcPerpInstrument, Direction: "buy", @@ -3048,7 +3048,7 @@ func TestWSExecuteBlockTrade(t *testing.T) { require.ErrorIs(t, err, errZeroTimestamp) sharedtestvalues.SkipTestIfCredentialsUnset(t, d, canManipulateRealOrders) - result, err := d.WSExecuteBlockTrade(time.Now(), "sdjkafdad", "maker", currency.EMPTYCODE, []BlockTradeParam{ + result, err := d.WSExecuteBlockTrade(t.Context(), time.Now(), "sdjkafdad", "maker", currency.EMPTYCODE, []BlockTradeParam{ { Price: 0.777 * 22000, InstrumentName: btcPerpInstrument, @@ -3078,11 +3078,11 @@ func TestGetUserBlocTrade(t *testing.T) { func TestWSRetrieveUserBlockTrade(t *testing.T) { t.Parallel() - _, err := d.WSRetrieveUserBlockTrade("") + _, err := d.WSRetrieveUserBlockTrade(t.Context(), "") require.ErrorIs(t, err, errMissingBlockTradeID) sharedtestvalues.SkipTestIfCredentialsUnset(t, d) - result, err := d.WSRetrieveUserBlockTrade("12345567") + result, err := d.WSRetrieveUserBlockTrade(t.Context(), "12345567") require.NoError(t, err) assert.NotNil(t, result) } @@ -3100,11 +3100,11 @@ func TestGetLastBlockTradesbyCurrency(t *testing.T) { func TestWSRetrieveLastBlockTradesByCurrency(t *testing.T) { t.Parallel() - _, err := d.WSRetrieveLastBlockTradesByCurrency(currency.EMPTYCODE, "", "", 5) + _, err := d.WSRetrieveLastBlockTradesByCurrency(t.Context(), currency.EMPTYCODE, "", "", 5) require.ErrorIs(t, err, currency.ErrCurrencyCodeEmpty) sharedtestvalues.SkipTestIfCredentialsUnset(t, d) - result, err := d.WSRetrieveLastBlockTradesByCurrency(currency.SOL, "", "", 5) + result, err := d.WSRetrieveLastBlockTradesByCurrency(t.Context(), currency.SOL, "", "", 5) require.NoError(t, err) assert.NotNil(t, result) } @@ -3163,13 +3163,13 @@ func TestMovePositions(t *testing.T) { func TestWSMovePositions(t *testing.T) { t.Parallel() - _, err := d.WSMovePositions(currency.EMPTYCODE, 123, 345, []BlockTradeParam{}) + _, err := d.WSMovePositions(t.Context(), currency.EMPTYCODE, 123, 345, []BlockTradeParam{}) require.ErrorIs(t, err, currency.ErrCurrencyCodeEmpty) - _, err = d.WSMovePositions(currency.BTC, 0, 345, []BlockTradeParam{}) + _, err = d.WSMovePositions(t.Context(), currency.BTC, 0, 345, []BlockTradeParam{}) require.ErrorIs(t, err, errMissingSubAccountID) - _, err = d.WSMovePositions(currency.BTC, 123, 0, []BlockTradeParam{}) + _, err = d.WSMovePositions(t.Context(), currency.BTC, 123, 0, []BlockTradeParam{}) require.ErrorIs(t, err, errMissingSubAccountID) - _, err = d.WSMovePositions(currency.BTC, 123, 345, []BlockTradeParam{ + _, err = d.WSMovePositions(t.Context(), currency.BTC, 123, 345, []BlockTradeParam{ { Price: 0.777 * 25000, InstrumentName: "", @@ -3178,7 +3178,7 @@ func TestWSMovePositions(t *testing.T) { }, }) require.ErrorIs(t, err, errInvalidInstrumentName) - _, err = d.WSMovePositions(currency.BTC, 123, 345, []BlockTradeParam{ + _, err = d.WSMovePositions(t.Context(), currency.BTC, 123, 345, []BlockTradeParam{ { Price: 0.777 * 25000, InstrumentName: "BTC-PERPETUAL", @@ -3187,7 +3187,7 @@ func TestWSMovePositions(t *testing.T) { }, }) require.ErrorIs(t, err, errInvalidAmount) - _, err = d.WSMovePositions(currency.BTC, 123, 345, []BlockTradeParam{ + _, err = d.WSMovePositions(t.Context(), currency.BTC, 123, 345, []BlockTradeParam{ { Price: -4, InstrumentName: "BTC-PERPETUAL", @@ -3201,7 +3201,7 @@ func TestWSMovePositions(t *testing.T) { require.NotNil(t, info) sharedtestvalues.SkipTestIfCredentialsUnset(t, d, canManipulateRealOrders) - result, err := d.WSMovePositions(currency.BTC, 123, 345, []BlockTradeParam{ + result, err := d.WSMovePositions(t.Context(), currency.BTC, 123, 345, []BlockTradeParam{ { Price: 0.777 * 25000, InstrumentName: btcPerpInstrument, @@ -3273,11 +3273,11 @@ func TestSimulateBlockTrade(t *testing.T) { func TestWsSimulateBlockTrade(t *testing.T) { t.Parallel() - _, err := d.WsSimulateBlockTrade("", []BlockTradeParam{}) + _, err := d.WsSimulateBlockTrade(t.Context(), "", []BlockTradeParam{}) require.ErrorIs(t, err, errInvalidTradeRole) - _, err = d.WsSimulateBlockTrade("maker", []BlockTradeParam{}) + _, err = d.WsSimulateBlockTrade(t.Context(), "maker", []BlockTradeParam{}) require.ErrorIs(t, err, errNoArgumentPassed) - _, err = d.WsSimulateBlockTrade("maker", []BlockTradeParam{ + _, err = d.WsSimulateBlockTrade(t.Context(), "maker", []BlockTradeParam{ { Price: 0.777 * 25000, InstrumentName: "", @@ -3286,7 +3286,7 @@ func TestWsSimulateBlockTrade(t *testing.T) { }, }) require.ErrorIs(t, err, errInvalidInstrumentName) - _, err = d.WsSimulateBlockTrade("maker", []BlockTradeParam{ + _, err = d.WsSimulateBlockTrade(t.Context(), "maker", []BlockTradeParam{ { Price: 0.777 * 25000, InstrumentName: btcPerpInstrument, @@ -3295,7 +3295,7 @@ func TestWsSimulateBlockTrade(t *testing.T) { }, }) require.ErrorIs(t, err, errInvalidOrderSideOrDirection) - _, err = d.WsSimulateBlockTrade("maker", []BlockTradeParam{ + _, err = d.WsSimulateBlockTrade(t.Context(), "maker", []BlockTradeParam{ { Price: 0.777 * 25000, InstrumentName: btcPerpInstrument, @@ -3304,7 +3304,7 @@ func TestWsSimulateBlockTrade(t *testing.T) { }, }) require.ErrorIs(t, err, errInvalidAmount) - _, err = d.WsSimulateBlockTrade("maker", []BlockTradeParam{ + _, err = d.WsSimulateBlockTrade(t.Context(), "maker", []BlockTradeParam{ { Price: -1, InstrumentName: btcPerpInstrument, @@ -3318,7 +3318,7 @@ func TestWsSimulateBlockTrade(t *testing.T) { info, err := d.GetInstrument(t.Context(), "BTC-PERPETUAL") require.NoError(t, err) require.NotNil(t, info) - result, err := d.WsSimulateBlockTrade("taker", []BlockTradeParam{ + result, err := d.WsSimulateBlockTrade(t.Context(), "taker", []BlockTradeParam{ { Price: 0.777 * 25000, InstrumentName: btcPerpInstrument, @@ -3758,7 +3758,7 @@ func TestProcessPushData(t *testing.T) { for k, v := range websocketPushData { t.Run(k, func(t *testing.T) { t.Parallel() - err := d.wsHandleData([]byte(v)) + err := d.wsHandleData(t.Context(), []byte(v)) require.NoErrorf(t, err, "%s: Received unexpected error for", k) }) } @@ -3798,10 +3798,10 @@ func TestOptionPairToString(t *testing.T) { func TestWSRetrieveCombos(t *testing.T) { t.Parallel() - _, err := d.WSRetrieveCombos(currency.EMPTYCODE) + _, err := d.WSRetrieveCombos(t.Context(), currency.EMPTYCODE) require.ErrorIs(t, err, currency.ErrCurrencyCodeEmpty) - result, err := d.WSRetrieveCombos(futureComboTradablePair.Base) + result, err := d.WSRetrieveCombos(t.Context(), futureComboTradablePair.Base) require.NoError(t, err) assert.NotNil(t, result) } @@ -3852,7 +3852,7 @@ func TestGetLockedStatus(t *testing.T) { func TestSayHello(t *testing.T) { t.Parallel() - result, err := d.SayHello("Thrasher", "") + result, err := d.SayHello(t.Context(), "Thrasher", "") require.NoError(t, err) assert.NotNil(t, result) } @@ -3860,7 +3860,7 @@ func TestSayHello(t *testing.T) { func TestWsRetrieveCancelOnDisconnect(t *testing.T) { t.Parallel() sharedtestvalues.SkipTestIfCredentialsUnset(t, d) - result, err := d.WsRetrieveCancelOnDisconnect("connection") + result, err := d.WsRetrieveCancelOnDisconnect(t.Context(), "connection") require.NoError(t, err) assert.NotNil(t, result) } @@ -3868,7 +3868,7 @@ func TestWsRetrieveCancelOnDisconnect(t *testing.T) { func TestWsDisableCancelOnDisconnect(t *testing.T) { t.Parallel() sharedtestvalues.SkipTestIfCredentialsUnset(t, d, canManipulateRealOrders) - result, err := d.WsDisableCancelOnDisconnect("connection") + result, err := d.WsDisableCancelOnDisconnect(t.Context(), "connection") require.NoError(t, err) assert.NotNil(t, result) } @@ -3884,7 +3884,7 @@ func TestEnableCancelOnDisconnect(t *testing.T) { func TestWsEnableCancelOnDisconnect(t *testing.T) { t.Parallel() sharedtestvalues.SkipTestIfCredentialsUnset(t, d, canManipulateRealOrders) - result, err := d.WsEnableCancelOnDisconnect("connection") + result, err := d.WsEnableCancelOnDisconnect(t.Context(), "connection") require.NoError(t, err) assert.NotNil(t, result) } @@ -3892,7 +3892,7 @@ func TestWsEnableCancelOnDisconnect(t *testing.T) { func TestLogout(t *testing.T) { t.Parallel() sharedtestvalues.SkipTestIfCredentialsUnset(t, d, canManipulateRealOrders) - err := d.WsLogout(true) + err := d.WsLogout(t.Context(), true) assert.NoError(t, err) } @@ -3912,7 +3912,7 @@ func TestExchangeToken(t *testing.T) { func TestWsExchangeToken(t *testing.T) { t.Parallel() sharedtestvalues.SkipTestIfCredentialsUnset(t, d) - result, err := d.WsExchangeToken("1568800656974.1CWcuzUS.MGy49NK4hpTwvR1OYWfpqMEkH4T4oDg4tNIcrM7KdeyxXRcSFqiGzA_D4Cn7mqWocHmlS89FFmUYcmaN2H7lNKKTnhRg5EtrzsFCCiuyN0Wv9y-LbGLV3-Ojv_kbD50FoScQ8BDXS5b_w6Ir1MqEdQ3qFZ3MLcvlPiIgG2BqyJX3ybYnVpIlrVrrdYD1-lkjLcjxOBNJvvUKNUAzkQ", 1234) + result, err := d.WsExchangeToken(t.Context(), "1568800656974.1CWcuzUS.MGy49NK4hpTwvR1OYWfpqMEkH4T4oDg4tNIcrM7KdeyxXRcSFqiGzA_D4Cn7mqWocHmlS89FFmUYcmaN2H7lNKKTnhRg5EtrzsFCCiuyN0Wv9y-LbGLV3-Ojv_kbD50FoScQ8BDXS5b_w6Ir1MqEdQ3qFZ3MLcvlPiIgG2BqyJX3ybYnVpIlrVrrdYD1-lkjLcjxOBNJvvUKNUAzkQ", 1234) require.NoError(t, err) assert.NotNil(t, result) } @@ -3932,13 +3932,13 @@ func TestForkToken(t *testing.T) { func TestWsForkToken(t *testing.T) { t.Parallel() - _, err := d.WsForkToken("", "Sami") + _, err := d.WsForkToken(t.Context(), "", "Sami") require.ErrorIs(t, err, errRefreshTokenRequired) - _, err = d.WsForkToken("1568800656974.1CWcuzUS.MGy49NK4hpTwvR1OYWfpqMEkH4T4oDg4tNIcrM7KdeyxXRcSFqiGzA_D4Cn7mqWocHmlS89FFmUYcmaN2H7lNKKTnhRg5EtrzsFCCiuyN0Wv9y-LbGLV3-Ojv_kbD50FoScQ8BDXS5b_w6Ir1MqEdQ3qFZ3MLcvlPiIgG2BqyJX3ybYnVpIlrVrrdYD1-lkjLcjxOBNJvvUKNUAzkQ", "") + _, err = d.WsForkToken(t.Context(), "1568800656974.1CWcuzUS.MGy49NK4hpTwvR1OYWfpqMEkH4T4oDg4tNIcrM7KdeyxXRcSFqiGzA_D4Cn7mqWocHmlS89FFmUYcmaN2H7lNKKTnhRg5EtrzsFCCiuyN0Wv9y-LbGLV3-Ojv_kbD50FoScQ8BDXS5b_w6Ir1MqEdQ3qFZ3MLcvlPiIgG2BqyJX3ybYnVpIlrVrrdYD1-lkjLcjxOBNJvvUKNUAzkQ", "") require.ErrorIs(t, err, errSessionNameRequired) sharedtestvalues.SkipTestIfCredentialsUnset(t, d, canManipulateAPIEndpoints) - result, err := d.WsForkToken("1568800656974.1CWcuzUS.MGy49NK4hpTwvR1OYWfpqMEkH4T4oDg4tNIcrM7KdeyxXRcSFqiGzA_D4Cn7mqWocHmlS89FFmUYcmaN2H7lNKKTnhRg5EtrzsFCCiuyN0Wv9y-LbGLV3-Ojv_kbD50FoScQ8BDXS5b_w6Ir1MqEdQ3qFZ3MLcvlPiIgG2BqyJX3ybYnVpIlrVrrdYD1-lkjLcjxOBNJvvUKNUAzkQ", "Sami") + result, err := d.WsForkToken(t.Context(), "1568800656974.1CWcuzUS.MGy49NK4hpTwvR1OYWfpqMEkH4T4oDg4tNIcrM7KdeyxXRcSFqiGzA_D4Cn7mqWocHmlS89FFmUYcmaN2H7lNKKTnhRg5EtrzsFCCiuyN0Wv9y-LbGLV3-Ojv_kbD50FoScQ8BDXS5b_w6Ir1MqEdQ3qFZ3MLcvlPiIgG2BqyJX3ybYnVpIlrVrrdYD1-lkjLcjxOBNJvvUKNUAzkQ", "Sami") require.NoError(t, err) assert.NotNil(t, result) } diff --git a/exchanges/deribit/deribit_types.go b/exchanges/deribit/deribit_types.go index cdcfd713..b4656877 100644 --- a/exchanges/deribit/deribit_types.go +++ b/exchanges/deribit/deribit_types.go @@ -119,7 +119,7 @@ type ContractSizeData struct { // CurrencyData stores data for currencies type CurrencyData struct { CoinType string `json:"coin_type"` - Currency string `json:"currency"` + Currency string `json:"currency"` // TODO: change to currency.Code CurrencyLong string `json:"currency_long"` FeePrecision int64 `json:"fee_precision"` MinConfirmations int64 `json:"min_confirmations"` diff --git a/exchanges/deribit/deribit_websocket.go b/exchanges/deribit/deribit_websocket.go index 78e5b7cb..0f38bd04 100644 --- a/exchanges/deribit/deribit_websocket.go +++ b/exchanges/deribit/deribit_websocket.go @@ -124,24 +124,25 @@ var ( // WsConnect starts a new connection with the websocket API func (d *Deribit) WsConnect() error { + ctx := context.TODO() if !d.Websocket.IsEnabled() || !d.IsEnabled() { return websocket.ErrWebsocketNotEnabled } var dialer gws.Dialer - err := d.Websocket.Conn.Dial(&dialer, http.Header{}) + err := d.Websocket.Conn.Dial(ctx, &dialer, http.Header{}) if err != nil { return err } d.Websocket.Wg.Add(1) - go d.wsReadData() + go d.wsReadData(ctx) if d.Websocket.CanUseAuthenticatedEndpoints() { - err = d.wsLogin(context.TODO()) + err = d.wsLogin(ctx) if err != nil { log.Errorf(log.ExchangeSys, "%v - authentication failed: %v\n", d.Name, err) d.Websocket.SetCanUseAuthenticatedEndpoints(false) } } - return d.Websocket.Conn.SendJSONMessage(context.TODO(), request.Unset, setHeartBeatMessage) + return d.Websocket.Conn.SendJSONMessage(ctx, request.Unset, setHeartBeatMessage) } func (d *Deribit) wsLogin(ctx context.Context) error { @@ -173,7 +174,7 @@ func (d *Deribit) wsLogin(ctx context.Context) error { "signature": hex.EncodeToString(hmac), }, } - resp, err := d.Websocket.Conn.SendMessageReturnResponse(context.TODO(), request.Unset, req.ID, req) + resp, err := d.Websocket.Conn.SendMessageReturnResponse(ctx, request.Unset, req.ID, req) if err != nil { d.Websocket.SetCanUseAuthenticatedEndpoints(false) return err @@ -190,7 +191,7 @@ func (d *Deribit) wsLogin(ctx context.Context) error { } // wsReadData receives and passes on websocket messages for processing -func (d *Deribit) wsReadData() { +func (d *Deribit) wsReadData(ctx context.Context) { defer d.Websocket.Wg.Done() for { @@ -199,21 +200,21 @@ func (d *Deribit) wsReadData() { return } - err := d.wsHandleData(resp.Raw) + err := d.wsHandleData(ctx, resp.Raw) if err != nil { d.Websocket.DataHandler <- err } } } -func (d *Deribit) wsHandleData(respRaw []byte) error { +func (d *Deribit) wsHandleData(ctx context.Context, respRaw []byte) error { var response WsResponse err := json.Unmarshal(respRaw, &response) if err != nil { return fmt.Errorf("%s - err %s could not parse websocket data: %s", d.Name, err, respRaw) } if response.Method == "heartbeat" { - return d.Websocket.Conn.SendJSONMessage(context.TODO(), request.Unset, pingMessage) + return d.Websocket.Conn.SendJSONMessage(ctx, request.Unset, pingMessage) } if response.ID > 2 { if !d.Websocket.Match.IncomingWithData(response.ID, respRaw) { @@ -795,21 +796,19 @@ func (d *Deribit) GetSubscriptionTemplate(_ *subscription.Subscription) (*templa // Subscribe sends a websocket message to receive data from the channel func (d *Deribit) Subscribe(subs subscription.List) error { - errs := d.handleSubscription("public/subscribe", subs.Public()) - return common.AppendError(errs, - d.handleSubscription("private/subscribe", subs.Private()), - ) + ctx := context.TODO() + errs := d.handleSubscription(ctx, "public/subscribe", subs.Public()) + return common.AppendError(errs, d.handleSubscription(ctx, "private/subscribe", subs.Private())) } // Unsubscribe sends a websocket message to stop receiving data from the channel func (d *Deribit) Unsubscribe(subs subscription.List) error { - errs := d.handleSubscription("public/unsubscribe", subs.Public()) - return common.AppendError(errs, - d.handleSubscription("private/unsubscribe", subs.Private()), - ) + ctx := context.TODO() + errs := d.handleSubscription(ctx, "public/unsubscribe", subs.Public()) + return common.AppendError(errs, d.handleSubscription(ctx, "private/unsubscribe", subs.Private())) } -func (d *Deribit) handleSubscription(method string, subs subscription.List) error { +func (d *Deribit) handleSubscription(ctx context.Context, method string, subs subscription.List) error { var err error subs, err = subs.ExpandTemplates(d) if err != nil || len(subs) == 0 { @@ -823,7 +822,7 @@ func (d *Deribit) handleSubscription(method string, subs subscription.List) erro Params: map[string][]string{"channels": subs.QualifiedChannels()}, } - data, err := d.Websocket.Conn.SendMessageReturnResponse(context.TODO(), request.Unset, r.ID, r) + data, err := d.Websocket.Conn.SendMessageReturnResponse(ctx, request.Unset, r.ID, r) if err != nil { return err } diff --git a/exchanges/deribit/deribit_wrapper.go b/exchanges/deribit/deribit_wrapper.go index 92c49e26..d0c01a3e 100644 --- a/exchanges/deribit/deribit_wrapper.go +++ b/exchanges/deribit/deribit_wrapper.go @@ -256,7 +256,7 @@ func (d *Deribit) UpdateTicker(ctx context.Context, p currency.Pair, assetType a instrumentID := d.formatPairString(assetType, p) var tickerData *TickerData if d.Websocket.IsConnected() { - tickerData, err = d.WSRetrievePublicTicker(instrumentID) + tickerData, err = d.WSRetrievePublicTicker(ctx, instrumentID) } else { tickerData, err = d.GetPublicTicker(ctx, instrumentID) } @@ -296,7 +296,7 @@ func (d *Deribit) UpdateOrderbook(ctx context.Context, p currency.Pair, assetTyp instrumentID := d.formatPairString(assetType, p) var obData *Orderbook if d.Websocket.IsConnected() { - obData, err = d.WSRetrieveOrderbookData(instrumentID, 50) + obData, err = d.WSRetrieveOrderbookData(ctx, instrumentID, 50) } else { obData, err = d.GetOrderbook(ctx, instrumentID, 50) } @@ -348,7 +348,7 @@ func (d *Deribit) UpdateAccountInfo(ctx context.Context, _ asset.Item) (account. for x := range currencies { var data *AccountSummaryData if d.Websocket.IsConnected() && d.Websocket.CanUseAuthenticatedWebsocketForWrapper() { - data, err = d.WSRetrieveAccountSummary(currency.NewCode(currencies[x].Currency), false) + data, err = d.WSRetrieveAccountSummary(ctx, currency.NewCode(currencies[x].Currency), false) } else { data, err = d.GetAccountSummary(ctx, currency.NewCode(currencies[x].Currency), false) } @@ -371,7 +371,7 @@ func (d *Deribit) GetAccountFundingHistory(ctx context.Context) ([]exchange.Fund var currencies []CurrencyData var err error if d.Websocket.IsConnected() { - currencies, err = d.WSRetrieveCurrencies() + currencies, err = d.WSRetrieveCurrencies(ctx) } else { currencies, err = d.GetCurrencies(ctx) } @@ -382,7 +382,7 @@ func (d *Deribit) GetAccountFundingHistory(ctx context.Context) ([]exchange.Fund for x := range currencies { var deposits *DepositsData if d.Websocket.IsConnected() && d.Websocket.CanUseAuthenticatedWebsocketForWrapper() { - deposits, err = d.WSRetrieveDeposits(currency.NewCode(currencies[x].Currency), 100, 0) + deposits, err = d.WSRetrieveDeposits(ctx, currency.NewCode(currencies[x].Currency), 100, 0) } else { deposits, err = d.GetDeposits(ctx, currency.NewCode(currencies[x].Currency), 100, 0) } @@ -403,7 +403,7 @@ func (d *Deribit) GetAccountFundingHistory(ctx context.Context) ([]exchange.Fund } var withdrawalData *WithdrawalsData if d.Websocket.IsConnected() && d.Websocket.CanUseAuthenticatedWebsocketForWrapper() { - withdrawalData, err = d.WSRetrieveWithdrawals(currency.NewCode(currencies[x].Currency), 100, 0) + withdrawalData, err = d.WSRetrieveWithdrawals(ctx, currency.NewCode(currencies[x].Currency), 100, 0) } else { withdrawalData, err = d.GetWithdrawals(ctx, currency.NewCode(currencies[x].Currency), 100, 0) } @@ -431,7 +431,7 @@ func (d *Deribit) GetWithdrawalsHistory(ctx context.Context, c currency.Code, _ var currencies []CurrencyData var err error if d.Websocket.IsConnected() { - currencies, err = d.WSRetrieveCurrencies() + currencies, err = d.WSRetrieveCurrencies(ctx) } else { currencies, err = d.GetCurrencies(ctx) } @@ -445,7 +445,7 @@ func (d *Deribit) GetWithdrawalsHistory(ctx context.Context, c currency.Code, _ } var withdrawalData *WithdrawalsData if d.Websocket.IsConnected() && d.Websocket.CanUseAuthenticatedWebsocketForWrapper() { - withdrawalData, err = d.WSRetrieveWithdrawals(currency.NewCode(currencies[x].Currency), 100, 0) + withdrawalData, err = d.WSRetrieveWithdrawals(ctx, currency.NewCode(currencies[x].Currency), 100, 0) } else { withdrawalData, err = d.GetWithdrawals(ctx, currency.NewCode(currencies[x].Currency), 100, 0) } @@ -480,12 +480,9 @@ func (d *Deribit) GetRecentTrades(ctx context.Context, p currency.Pair, assetTyp resp := []trade.Data{} var trades *PublicTradesData if d.Websocket.IsConnected() { - trades, err = d.WSRetrieveLastTradesByInstrument( - instrumentID, "", "", "", 0, false) + trades, err = d.WSRetrieveLastTradesByInstrument(ctx, instrumentID, "", "", "", 0, false) } else { - trades, err = d.GetLastTradesByInstrument( - ctx, - instrumentID, "", "", "", 0, false) + trades, err = d.GetLastTradesByInstrument(ctx, instrumentID, "", "", "", 0, false) } if err != nil { return nil, err @@ -532,7 +529,7 @@ func (d *Deribit) GetHistoricTrades(ctx context.Context, p currency.Pair, assetT hasMore := true for hasMore { if d.Websocket.IsConnected() { - tradesData, err = d.WSRetrieveLastTradesByInstrumentAndTime(instrumentID, "asc", 100, true, timestampStart, timestampEnd) + tradesData, err = d.WSRetrieveLastTradesByInstrumentAndTime(ctx, instrumentID, "asc", 100, true, timestampStart, timestampEnd) } else { tradesData, err = d.GetLastTradesByInstrumentAndTime(ctx, instrumentID, "asc", 100, timestampStart, timestampEnd) } @@ -603,7 +600,7 @@ func (d *Deribit) SubmitOrder(ctx context.Context, s *order.Submit) (*order.Subm switch { case s.Side.IsLong(): if d.Websocket.IsConnected() && d.Websocket.CanUseAuthenticatedWebsocketForWrapper() { - data, err = d.WSSubmitBuy(reqParams) + data, err = d.WSSubmitBuy(ctx, reqParams) } else { data, err = d.SubmitBuy(ctx, reqParams) } @@ -616,7 +613,7 @@ func (d *Deribit) SubmitOrder(ctx context.Context, s *order.Submit) (*order.Subm orderID = data.Order.OrderID case s.Side.IsShort(): if d.Websocket.IsConnected() && d.Websocket.CanUseAuthenticatedWebsocketForWrapper() { - data, err = d.WSSubmitSell(reqParams) + data, err = d.WSSubmitSell(ctx, reqParams) } else { data, err = d.SubmitSell(ctx, reqParams) } @@ -655,7 +652,7 @@ func (d *Deribit) ModifyOrder(ctx context.Context, action *order.Modify) (*order Price: action.Price, } if d.Websocket.IsConnected() && d.Websocket.CanUseAuthenticatedWebsocketForWrapper() { - modify, err = d.WSSubmitEdit(reqParam) + modify, err = d.WSSubmitEdit(ctx, reqParam) } else { modify, err = d.SubmitEdit(ctx, reqParam) } @@ -680,7 +677,7 @@ func (d *Deribit) CancelOrder(ctx context.Context, ord *order.Cancel) error { return err } if d.Websocket.IsConnected() && d.Websocket.CanUseAuthenticatedWebsocketForWrapper() { - _, err = d.WSSubmitCancel(ord.OrderID) + _, err = d.WSSubmitCancel(ctx, ord.OrderID) } else { _, err = d.SubmitCancel(ctx, ord.OrderID) } @@ -717,7 +714,7 @@ func (d *Deribit) CancelAllOrders(ctx context.Context, orderCancellation *order. return order.CancelAllResponse{}, fmt.Errorf("%s: orderType %v is not valid", d.Name, orderCancellation.Type) } if d.Websocket.IsConnected() && d.Websocket.CanUseAuthenticatedWebsocketForWrapper() { - cancelData, err = d.WSSubmitCancelAllByInstrument(pairFmt.Format(orderCancellation.Pair), orderTypeStr, true, true) + cancelData, err = d.WSSubmitCancelAllByInstrument(ctx, pairFmt.Format(orderCancellation.Pair), orderTypeStr, true, true) } else { cancelData, err = d.SubmitCancelAllByInstrument(ctx, pairFmt.Format(orderCancellation.Pair), orderTypeStr, true, true) } @@ -744,7 +741,7 @@ func (d *Deribit) GetOrderInfo(ctx context.Context, orderID string, _ currency.P var orderInfo *OrderData var err error if d.Websocket.IsConnected() && d.Websocket.CanUseAuthenticatedWebsocketForWrapper() { - orderInfo, err = d.WSRetrievesOrderState(orderID) + orderInfo, err = d.WSRetrievesOrderState(ctx, orderID) } else { orderInfo, err = d.GetOrderState(ctx, orderID) } @@ -801,7 +798,7 @@ func (d *Deribit) GetDepositAddress(ctx context.Context, cryptocurrency currency var addressData *DepositAddressData var err error if d.Websocket.IsConnected() && d.Websocket.CanUseAuthenticatedWebsocketForWrapper() { - addressData, err = d.WSRetrieveCurrentDepositAddress(cryptocurrency) + addressData, err = d.WSRetrieveCurrentDepositAddress(ctx, cryptocurrency) } else { addressData, err = d.GetCurrentDepositAddress(ctx, cryptocurrency) } @@ -823,7 +820,7 @@ func (d *Deribit) WithdrawCryptocurrencyFunds(ctx context.Context, withdrawReque } var withdrawData *WithdrawData if d.Websocket.IsConnected() && d.Websocket.CanUseAuthenticatedWebsocketForWrapper() { - withdrawData, err = d.WSSubmitWithdraw(withdrawRequest.Currency, withdrawRequest.Crypto.Address, "", withdrawRequest.Amount) + withdrawData, err = d.WSSubmitWithdraw(ctx, withdrawRequest.Currency, withdrawRequest.Crypto.Address, "", withdrawRequest.Amount) } else { withdrawData, err = d.SubmitWithdraw(ctx, withdrawRequest.Currency, withdrawRequest.Crypto.Address, "", withdrawRequest.Amount) } @@ -872,7 +869,7 @@ func (d *Deribit) GetActiveOrders(ctx context.Context, getOrdersRequest *order.M } var ordersData []OrderData if d.Websocket.IsConnected() && d.Websocket.CanUseAuthenticatedWebsocketForWrapper() { - ordersData, err = d.WSRetrieveOpenOrdersByInstrument(fmtPair.String(), oTypeString) + ordersData, err = d.WSRetrieveOpenOrdersByInstrument(ctx, fmtPair.String(), oTypeString) } else { ordersData, err = d.GetOpenOrdersByInstrument(ctx, fmtPair.String(), oTypeString) } @@ -943,7 +940,7 @@ func (d *Deribit) GetOrderHistory(ctx context.Context, getOrdersRequest *order.M } var ordersData []OrderData if d.Websocket.IsConnected() && d.Websocket.CanUseAuthenticatedWebsocketForWrapper() { - ordersData, err = d.WSRetrieveOrderHistoryByInstrument(fmtPair.String(), 100, 0, true, true) + ordersData, err = d.WSRetrieveOrderHistoryByInstrument(ctx, fmtPair.String(), 100, 0, true, true) } else { ordersData, err = d.GetOrderHistoryByInstrument(ctx, fmtPair.String(), 100, 0, true, true) } @@ -1052,7 +1049,7 @@ func (d *Deribit) GetHistoricCandles(ctx context.Context, pair currency.Pair, a case asset.Futures, asset.Spot: var tradingViewData *TVChartData if d.Websocket.IsConnected() { - tradingViewData, err = d.WSRetrievesTradingViewChartData(d.formatFuturesTradablePair(req.RequestFormatted), intervalString, start, end) + tradingViewData, err = d.WSRetrievesTradingViewChartData(ctx, d.formatFuturesTradablePair(req.RequestFormatted), intervalString, start, end) } else { tradingViewData, err = d.GetTradingViewChart(ctx, d.formatFuturesTradablePair(req.RequestFormatted), intervalString, start, end) } @@ -1107,7 +1104,7 @@ func (d *Deribit) GetHistoricCandlesExtended(ctx context.Context, pair currency. return nil, err } if d.Websocket.IsConnected() { - tradingViewData, err = d.WSRetrievesTradingViewChartData(d.formatFuturesTradablePair(req.RequestFormatted), intervalString, req.RangeHolder.Ranges[x].Start.Time, req.RangeHolder.Ranges[x].End.Time) + tradingViewData, err = d.WSRetrievesTradingViewChartData(ctx, d.formatFuturesTradablePair(req.RequestFormatted), intervalString, req.RangeHolder.Ranges[x].Start.Time, req.RangeHolder.Ranges[x].End.Time) } else { tradingViewData, err = d.GetTradingViewChart(ctx, d.formatFuturesTradablePair(req.RequestFormatted), intervalString, req.RangeHolder.Ranges[x].Start.Time, req.RangeHolder.Ranges[x].End.Time) } @@ -1167,7 +1164,7 @@ func (d *Deribit) GetFuturesContractDetails(ctx context.Context, item asset.Item var marketSummary []*InstrumentData var err error if d.Websocket.IsConnected() { - marketSummary, err = d.WSRetrieveInstrumentsData(currency.NewCode(ccy), d.GetAssetKind(item), false) + marketSummary, err = d.WSRetrieveInstrumentsData(ctx, currency.NewCode(ccy), d.GetAssetKind(item), false) } else { marketSummary, err = d.GetInstruments(ctx, currency.NewCode(ccy), d.GetAssetKind(item), false) } @@ -1227,7 +1224,7 @@ func (d *Deribit) UpdateOrderExecutionLimits(ctx context.Context, a asset.Item) var instrumentsData []*InstrumentData var err error if d.Websocket.IsConnected() { - instrumentsData, err = d.WSRetrieveInstrumentsData(currency.NewCode(x), d.GetAssetKind(a), false) + instrumentsData, err = d.WSRetrieveInstrumentsData(ctx, currency.NewCode(x), d.GetAssetKind(a), false) } else { instrumentsData, err = d.GetInstruments(ctx, currency.NewCode(x), d.GetAssetKind(a), false) } @@ -1276,7 +1273,7 @@ func (d *Deribit) GetFuturesPositionSummary(ctx context.Context, r *futures.Posi } var pos []PositionData if d.Websocket.IsConnected() && d.Websocket.CanUseAuthenticatedWebsocketForWrapper() { - pos, err = d.WSRetrievePositions(fPair.Base, d.GetAssetKind(r.Asset)) + pos, err = d.WSRetrievePositions(ctx, fPair.Base, d.GetAssetKind(r.Asset)) } else { pos, err = d.GetPositions(ctx, fPair.Base, d.GetAssetKind(r.Asset)) } @@ -1358,7 +1355,7 @@ func (d *Deribit) GetOpenInterest(ctx context.Context, k ...key.PairAsset) ([]fu p := d.formatPairString(k[i].Asset, cp) var oi []BookSummaryData if d.Websocket.IsConnected() { - oi, err = d.WSRetrieveBookSummaryByInstrument(p) + oi, err = d.WSRetrieveBookSummaryByInstrument(ctx, p) } else { oi, err = d.GetBookSummaryByInstrument(ctx, p) } @@ -1519,7 +1516,7 @@ func (d *Deribit) GetHistoricalFundingRates(ctx context.Context, r *fundingrate. for ed.After(r.StartDate) { var records []FundingRateHistory if d.Websocket.IsConnected() { - records, err = d.WSRetrieveFundingRateHistory(p, r.StartDate, ed) + records, err = d.WSRetrieveFundingRateHistory(ctx, p, r.StartDate, ed) } else { records, err = d.GetFundingRateHistory(ctx, p, r.StartDate, ed) } diff --git a/exchanges/deribit/deribit_ws_endpoints.go b/exchanges/deribit/deribit_ws_endpoints.go index c491efb7..26c49d4d 100644 --- a/exchanges/deribit/deribit_ws_endpoints.go +++ b/exchanges/deribit/deribit_ws_endpoints.go @@ -18,7 +18,7 @@ import ( ) // WSRetrieveBookBySummary retrieves book summary data for currency requested through websocket connection. -func (d *Deribit) WSRetrieveBookBySummary(ccy currency.Code, kind string) ([]BookSummaryData, error) { +func (d *Deribit) WSRetrieveBookBySummary(ctx context.Context, ccy currency.Code, kind string) ([]BookSummaryData, error) { if ccy.IsEmpty() { return nil, currency.ErrCurrencyCodeEmpty } @@ -32,11 +32,11 @@ func (d *Deribit) WSRetrieveBookBySummary(ccy currency.Code, kind string) ([]Boo input.Kind = kind } var resp []BookSummaryData - return resp, d.SendWSRequest(nonMatchingEPL, getBookByCurrency, input, &resp, false) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, getBookByCurrency, input, &resp, false) } // WSRetrieveBookSummaryByInstrument retrieves book summary data for instrument requested through the websocket connection. -func (d *Deribit) WSRetrieveBookSummaryByInstrument(instrument string) ([]BookSummaryData, error) { +func (d *Deribit) WSRetrieveBookSummaryByInstrument(ctx context.Context, instrument string) ([]BookSummaryData, error) { if instrument == "" { return nil, fmt.Errorf("%w, instrument_name is missing", errInvalidInstrumentName) } @@ -46,11 +46,11 @@ func (d *Deribit) WSRetrieveBookSummaryByInstrument(instrument string) ([]BookSu Instrument: instrument, } var resp []BookSummaryData - return resp, d.SendWSRequest(nonMatchingEPL, getBookByInstrument, input, &resp, false) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, getBookByInstrument, input, &resp, false) } // WSRetrieveContractSize retrieves contract size for instrument requested through the websocket connection. -func (d *Deribit) WSRetrieveContractSize(instrument string) (*ContractSizeData, error) { +func (d *Deribit) WSRetrieveContractSize(ctx context.Context, instrument string) (*ContractSizeData, error) { if instrument == "" { return nil, fmt.Errorf("%w, instrument_name is missing", errInvalidInstrumentName) } @@ -60,17 +60,17 @@ func (d *Deribit) WSRetrieveContractSize(instrument string) (*ContractSizeData, Instrument: instrument, } var resp *ContractSizeData - return resp, d.SendWSRequest(nonMatchingEPL, getContractSize, input, &resp, false) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, getContractSize, input, &resp, false) } // WSRetrieveCurrencies retrieves all cryptocurrencies supported by the API through the websocket connection. -func (d *Deribit) WSRetrieveCurrencies() ([]CurrencyData, error) { +func (d *Deribit) WSRetrieveCurrencies(ctx context.Context) ([]CurrencyData, error) { var resp []CurrencyData - return resp, d.SendWSRequest(nonMatchingEPL, getCurrencies, nil, &resp, false) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, getCurrencies, nil, &resp, false) } // WSRetrieveDeliveryPrices retrieves delivery prices using index name through the websocket connection. -func (d *Deribit) WSRetrieveDeliveryPrices(indexName string, offset, count int64) (*IndexDeliveryPrice, error) { +func (d *Deribit) WSRetrieveDeliveryPrices(ctx context.Context, indexName string, offset, count int64) (*IndexDeliveryPrice, error) { if indexName == "" { return nil, errUnsupportedIndexName } @@ -84,12 +84,12 @@ func (d *Deribit) WSRetrieveDeliveryPrices(indexName string, offset, count int64 Count: count, } var resp *IndexDeliveryPrice - return resp, d.SendWSRequest(nonMatchingEPL, getDeliveryPrices, input, &resp, false) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, getDeliveryPrices, input, &resp, false) } // WSRetrieveFundingChartData retrieves funding chart data for the requested instrument and time length through the websocket connection. // supported lengths: 8h, 24h, 1m <-(1month) -func (d *Deribit) WSRetrieveFundingChartData(instrument, length string) (*FundingChartData, error) { +func (d *Deribit) WSRetrieveFundingChartData(ctx context.Context, instrument, length string) (*FundingChartData, error) { if instrument == "" { return nil, fmt.Errorf("%w, instrument_name is missing", errInvalidInstrumentName) } @@ -104,11 +104,11 @@ func (d *Deribit) WSRetrieveFundingChartData(instrument, length string) (*Fundin Length: length, } var resp *FundingChartData - return resp, d.SendWSRequest(nonMatchingEPL, getFundingChartData, input, &resp, false) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, getFundingChartData, input, &resp, false) } // WSRetrieveFundingRateHistory retrieves hourly historical interest rate for requested PERPETUAL instrument through the websocket connection. -func (d *Deribit) WSRetrieveFundingRateHistory(instrumentName string, startTime, endTime time.Time) ([]FundingRateHistory, error) { +func (d *Deribit) WSRetrieveFundingRateHistory(ctx context.Context, instrumentName string, startTime, endTime time.Time) ([]FundingRateHistory, error) { if instrumentName == "" { return nil, fmt.Errorf("%w, instrument_name is missing", errInvalidInstrumentName) } @@ -126,11 +126,11 @@ func (d *Deribit) WSRetrieveFundingRateHistory(instrumentName string, startTime, EndTime: endTime.UnixMilli(), } var resp []FundingRateHistory - return resp, d.SendWSRequest(nonMatchingEPL, getFundingRateHistory, input, &resp, false) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, getFundingRateHistory, input, &resp, false) } // WSRetrieveFundingRateValue retrieves funding rate value data through the websocket connection. -func (d *Deribit) WSRetrieveFundingRateValue(instrument string, startTime, endTime time.Time) (float64, error) { +func (d *Deribit) WSRetrieveFundingRateValue(ctx context.Context, instrument string, startTime, endTime time.Time) (float64, error) { if instrument == "" { return 0, fmt.Errorf("%w, instrument_name is missing", errInvalidInstrumentName) } @@ -147,11 +147,11 @@ func (d *Deribit) WSRetrieveFundingRateValue(instrument string, startTime, endTi EndTimestamp: endTime.UnixMilli(), } var resp float64 - return resp, d.SendWSRequest(nonMatchingEPL, getFundingRateValue, input, &resp, false) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, getFundingRateValue, input, &resp, false) } // WSRetrieveHistoricalVolatility retrieves historical volatility data -func (d *Deribit) WSRetrieveHistoricalVolatility(ccy currency.Code) ([]HistoricalVolatilityData, error) { +func (d *Deribit) WSRetrieveHistoricalVolatility(ctx context.Context, ccy currency.Code) ([]HistoricalVolatilityData, error) { if ccy.IsEmpty() { return nil, currency.ErrCurrencyCodeEmpty } @@ -161,11 +161,11 @@ func (d *Deribit) WSRetrieveHistoricalVolatility(ccy currency.Code) ([]Historica Currency: ccy, } var data []HistoricalVolatilityData - return data, d.SendWSRequest(nonMatchingEPL, getHistoricalVolatility, input, &data, false) + return data, d.SendWSRequest(ctx, nonMatchingEPL, getHistoricalVolatility, input, &data, false) } // WSRetrieveCurrencyIndexPrice the current index price for the instruments, for the selected currency through the websocket connection. -func (d *Deribit) WSRetrieveCurrencyIndexPrice(ccy currency.Code) (map[string]float64, error) { +func (d *Deribit) WSRetrieveCurrencyIndexPrice(ctx context.Context, ccy currency.Code) (map[string]float64, error) { if ccy.IsEmpty() { return nil, currency.ErrCurrencyCodeEmpty } @@ -175,11 +175,11 @@ func (d *Deribit) WSRetrieveCurrencyIndexPrice(ccy currency.Code) (map[string]fl Currency: ccy, } var resp map[string]float64 - return resp, d.SendWSRequest(nonMatchingEPL, getCurrencyIndexPrice, input, &resp, false) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, getCurrencyIndexPrice, input, &resp, false) } // WSRetrieveIndexPrice retrieves price data for the requested index through the websocket connection. -func (d *Deribit) WSRetrieveIndexPrice(index string) (*IndexPriceData, error) { +func (d *Deribit) WSRetrieveIndexPrice(ctx context.Context, index string) (*IndexPriceData, error) { if index == "" { return nil, fmt.Errorf("%w index can not be empty", errUnsupportedIndexName) } @@ -189,17 +189,17 @@ func (d *Deribit) WSRetrieveIndexPrice(index string) (*IndexPriceData, error) { IndexName: index, } var resp *IndexPriceData - return resp, d.SendWSRequest(nonMatchingEPL, getIndexPrice, input, &resp, false) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, getIndexPrice, input, &resp, false) } // WSRetrieveIndexPriceNames names of indexes through the websocket connection. -func (d *Deribit) WSRetrieveIndexPriceNames() ([]string, error) { +func (d *Deribit) WSRetrieveIndexPriceNames(ctx context.Context) ([]string, error) { var resp []string - return resp, d.SendWSRequest(nonMatchingEPL, getIndexPriceNames, nil, &resp, false) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, getIndexPriceNames, nil, &resp, false) } // WSRetrieveInstrumentData retrieves data for a requested instrument through the websocket connection. -func (d *Deribit) WSRetrieveInstrumentData(instrument string) (*InstrumentData, error) { +func (d *Deribit) WSRetrieveInstrumentData(ctx context.Context, instrument string) (*InstrumentData, error) { if instrument == "" { return nil, fmt.Errorf("%w, instrument_name is missing", errInvalidInstrumentName) } @@ -209,11 +209,11 @@ func (d *Deribit) WSRetrieveInstrumentData(instrument string) (*InstrumentData, Instrument: instrument, } var resp *InstrumentData - return resp, d.SendWSRequest(nonMatchingEPL, getInstrument, input, &resp, false) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, getInstrument, input, &resp, false) } // WSRetrieveInstrumentsData gets data for all available instruments -func (d *Deribit) WSRetrieveInstrumentsData(ccy currency.Code, kind string, expired bool) ([]*InstrumentData, error) { +func (d *Deribit) WSRetrieveInstrumentsData(ctx context.Context, ccy currency.Code, kind string, expired bool) ([]*InstrumentData, error) { if ccy.IsEmpty() { return nil, currency.ErrCurrencyCodeEmpty } @@ -227,11 +227,11 @@ func (d *Deribit) WSRetrieveInstrumentsData(ccy currency.Code, kind string, expi Kind: kind, } var resp []*InstrumentData - return resp, d.SendWSRequest(nonMatchingEPL, getInstruments, input, &resp, false) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, getInstruments, input, &resp, false) } // WSRetrieveLastSettlementsByCurrency retrieves last settlement data by currency through the websocket connection. -func (d *Deribit) WSRetrieveLastSettlementsByCurrency(ccy currency.Code, settlementType, continuation string, count int64, startTime time.Time) (*SettlementsData, error) { +func (d *Deribit) WSRetrieveLastSettlementsByCurrency(ctx context.Context, ccy currency.Code, settlementType, continuation string, count int64, startTime time.Time) (*SettlementsData, error) { if ccy.IsEmpty() { return nil, currency.ErrCurrencyCodeEmpty } @@ -249,11 +249,11 @@ func (d *Deribit) WSRetrieveLastSettlementsByCurrency(ccy currency.Code, settlem SearchStartTimestamp: startTime.UnixMilli(), } var resp *SettlementsData - return resp, d.SendWSRequest(nonMatchingEPL, getLastSettlementsByCurrency, input, &resp, false) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, getLastSettlementsByCurrency, input, &resp, false) } // WSRetrieveLastSettlementsByInstrument retrieves last settlement data for requested instrument through the websocket connection. -func (d *Deribit) WSRetrieveLastSettlementsByInstrument(instrument, settlementType, continuation string, count int64, startTime time.Time) (*SettlementsData, error) { +func (d *Deribit) WSRetrieveLastSettlementsByInstrument(ctx context.Context, instrument, settlementType, continuation string, count int64, startTime time.Time) (*SettlementsData, error) { if instrument == "" { return nil, fmt.Errorf("%w, instrument_name is missing", errInvalidInstrumentName) } @@ -273,11 +273,11 @@ func (d *Deribit) WSRetrieveLastSettlementsByInstrument(instrument, settlementTy input.SearchStartTimestamp = startTime.UnixMilli() } var resp *SettlementsData - return resp, d.SendWSRequest(nonMatchingEPL, getLastSettlementsByInstrument, input, &resp, false) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, getLastSettlementsByInstrument, input, &resp, false) } // WSRetrieveLastTradesByCurrency retrieves last trades for requested currency through the websocket connection. -func (d *Deribit) WSRetrieveLastTradesByCurrency(ccy currency.Code, kind, startID, endID, sorting string, count int64, includeOld bool) (*PublicTradesData, error) { +func (d *Deribit) WSRetrieveLastTradesByCurrency(ctx context.Context, ccy currency.Code, kind, startID, endID, sorting string, count int64, includeOld bool) (*PublicTradesData, error) { if ccy.IsEmpty() { return nil, currency.ErrCurrencyCodeEmpty } @@ -299,11 +299,11 @@ func (d *Deribit) WSRetrieveLastTradesByCurrency(ccy currency.Code, kind, startI Sorting: sorting, } var resp *PublicTradesData - return resp, d.SendWSRequest(nonMatchingEPL, getLastTradesByCurrency, input, &resp, false) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, getLastTradesByCurrency, input, &resp, false) } // WSRetrieveLastTradesByCurrencyAndTime retrieves last trades for requested currency and time intervals through the websocket connection. -func (d *Deribit) WSRetrieveLastTradesByCurrencyAndTime(ccy currency.Code, kind, sorting string, count int64, includeOld bool, startTime, endTime time.Time) (*PublicTradesData, error) { +func (d *Deribit) WSRetrieveLastTradesByCurrencyAndTime(ctx context.Context, ccy currency.Code, kind, sorting string, count int64, includeOld bool, startTime, endTime time.Time) (*PublicTradesData, error) { if ccy.IsEmpty() { return nil, currency.ErrCurrencyCodeEmpty } @@ -328,11 +328,11 @@ func (d *Deribit) WSRetrieveLastTradesByCurrencyAndTime(ccy currency.Code, kind, Sorting: sorting, } var resp *PublicTradesData - return resp, d.SendWSRequest(nonMatchingEPL, getLastTradesByCurrencyAndTime, input, &resp, false) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, getLastTradesByCurrencyAndTime, input, &resp, false) } // WSRetrieveLastTradesByInstrument retrieves last trades for requested instrument requested through the websocket connection. -func (d *Deribit) WSRetrieveLastTradesByInstrument(instrument, startSeq, endSeq, sorting string, count int64, includeOld bool) (*PublicTradesData, error) { +func (d *Deribit) WSRetrieveLastTradesByInstrument(ctx context.Context, instrument, startSeq, endSeq, sorting string, count int64, includeOld bool) (*PublicTradesData, error) { if instrument == "" { return nil, fmt.Errorf("%w, instrument_name is missing", errInvalidInstrumentName) } @@ -352,11 +352,11 @@ func (d *Deribit) WSRetrieveLastTradesByInstrument(instrument, startSeq, endSeq, IncludeOld: includeOld, } var resp *PublicTradesData - return resp, d.SendWSRequest(nonMatchingEPL, getLastTradesByInstrument, input, &resp, false) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, getLastTradesByInstrument, input, &resp, false) } // WSRetrieveLastTradesByInstrumentAndTime retrieves last trades for requested instrument requested and time intervals through the websocket connection. -func (d *Deribit) WSRetrieveLastTradesByInstrumentAndTime(instrument, sorting string, count int64, includeOld bool, startTime, endTime time.Time) (*PublicTradesData, error) { +func (d *Deribit) WSRetrieveLastTradesByInstrumentAndTime(ctx context.Context, instrument, sorting string, count int64, includeOld bool, startTime, endTime time.Time) (*PublicTradesData, error) { if instrument == "" { return nil, fmt.Errorf("%w, instrument_name is missing", errInvalidInstrumentName) } @@ -379,11 +379,11 @@ func (d *Deribit) WSRetrieveLastTradesByInstrumentAndTime(instrument, sorting st input.StartTimestamp = startTime.UnixMilli() input.EndTimestamp = endTime.UnixMilli() var resp *PublicTradesData - return resp, d.SendWSRequest(nonMatchingEPL, getLastTradesByInstrumentAndTime, input, &resp, false) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, getLastTradesByInstrumentAndTime, input, &resp, false) } // WSRetrieveMarkPriceHistory retrieves data for mark price history through the websocket connection. -func (d *Deribit) WSRetrieveMarkPriceHistory(instrument string, startTime, endTime time.Time) ([]MarkPriceHistory, error) { +func (d *Deribit) WSRetrieveMarkPriceHistory(ctx context.Context, instrument string, startTime, endTime time.Time) ([]MarkPriceHistory, error) { if instrument == "" { return nil, fmt.Errorf("%w, instrument_name is missing", errInvalidInstrumentName) } @@ -400,11 +400,11 @@ func (d *Deribit) WSRetrieveMarkPriceHistory(instrument string, startTime, endTi EndTimestamp: endTime.UnixMilli(), } var resp []MarkPriceHistory - return resp, d.SendWSRequest(nonMatchingEPL, getMarkPriceHistory, input, &resp, false) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, getMarkPriceHistory, input, &resp, false) } // WSRetrieveOrderbookData retrieves data orderbook of requested instrument through the web-socket connection. -func (d *Deribit) WSRetrieveOrderbookData(instrument string, depth int64) (*Orderbook, error) { +func (d *Deribit) WSRetrieveOrderbookData(ctx context.Context, instrument string, depth int64) (*Orderbook, error) { if instrument == "" { return nil, fmt.Errorf("%w, instrument_name is missing", errInvalidInstrumentName) } @@ -416,11 +416,11 @@ func (d *Deribit) WSRetrieveOrderbookData(instrument string, depth int64) (*Orde Depth: depth, } var resp *Orderbook - return resp, d.SendWSRequest(nonMatchingEPL, getOrderbook, input, &resp, false) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, getOrderbook, input, &resp, false) } // WSRetrieveOrderbookByInstrumentID retrieves orderbook by instrument ID through websocket connection. -func (d *Deribit) WSRetrieveOrderbookByInstrumentID(instrumentID int64, depth float64) (*Orderbook, error) { +func (d *Deribit) WSRetrieveOrderbookByInstrumentID(ctx context.Context, instrumentID int64, depth float64) (*Orderbook, error) { if instrumentID == 0 { return nil, errInvalidInstrumentID } @@ -432,23 +432,23 @@ func (d *Deribit) WSRetrieveOrderbookByInstrumentID(instrumentID int64, depth fl Depth: depth, } var resp *Orderbook - return resp, d.SendWSRequest(nonMatchingEPL, getOrderbookByInstrumentID, input, &resp, false) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, getOrderbookByInstrumentID, input, &resp, false) } // WsRetrieveSupportedIndexNames retrieves the identifiers of all supported Price Indexes // 'type' represents Type of a cryptocurrency price index. possible 'all', 'spot', 'derivative' -func (d *Deribit) WsRetrieveSupportedIndexNames(priceIndexType string) ([]string, error) { +func (d *Deribit) WsRetrieveSupportedIndexNames(ctx context.Context, priceIndexType string) ([]string, error) { input := &struct { PriceIndexType string `json:"type,omitempty"` }{ PriceIndexType: priceIndexType, } var resp []string - return resp, d.SendWSRequest(nonMatchingEPL, "public/get_supported_index_names", input, &resp, false) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, "public/get_supported_index_names", input, &resp, false) } // WSRetrieveRequestForQuote retrieves RFQ information. -func (d *Deribit) WSRetrieveRequestForQuote(ccy currency.Code, kind string) ([]RequestForQuote, error) { +func (d *Deribit) WSRetrieveRequestForQuote(ctx context.Context, ccy currency.Code, kind string) ([]RequestForQuote, error) { if ccy.IsEmpty() { return nil, currency.ErrCurrencyCodeEmpty } @@ -460,22 +460,22 @@ func (d *Deribit) WSRetrieveRequestForQuote(ccy currency.Code, kind string) ([]R Kind: kind, } var resp []RequestForQuote - return resp, d.SendWSRequest(nonMatchingEPL, getRFQ, input, &resp, false) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, getRFQ, input, &resp, false) } // WSRetrieveTradeVolumes retrieves trade volumes' data of all instruments through the websocket connection. -func (d *Deribit) WSRetrieveTradeVolumes(extended bool) ([]TradeVolumesData, error) { +func (d *Deribit) WSRetrieveTradeVolumes(ctx context.Context, extended bool) ([]TradeVolumesData, error) { input := &struct { Extended bool `json:"extended,omitempty"` }{ Extended: extended, } var resp []TradeVolumesData - return resp, d.SendWSRequest(nonMatchingEPL, getTradeVolumes, input, &resp, false) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, getTradeVolumes, input, &resp, false) } // WSRetrievesTradingViewChartData retrieves volatility index data for the requested instrument through the websocket connection. -func (d *Deribit) WSRetrievesTradingViewChartData(instrument, resolution string, startTime, endTime time.Time) (*TVChartData, error) { +func (d *Deribit) WSRetrievesTradingViewChartData(ctx context.Context, instrument, resolution string, startTime, endTime time.Time) (*TVChartData, error) { if instrument == "" { return nil, fmt.Errorf("%w, instrument_name is missing", errInvalidInstrumentName) } @@ -497,11 +497,11 @@ func (d *Deribit) WSRetrievesTradingViewChartData(instrument, resolution string, EndTimestamp: endTime.UnixMilli(), } var resp *TVChartData - return resp, d.SendWSRequest(nonMatchingEPL, getTradingViewChartData, input, &resp, false) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, getTradingViewChartData, input, &resp, false) } // WSRetrieveVolatilityIndexData retrieves volatility index data for the requested currency through the websocket connection. -func (d *Deribit) WSRetrieveVolatilityIndexData(ccy currency.Code, resolution string, startTime, endTime time.Time) ([]VolatilityIndexData, error) { +func (d *Deribit) WSRetrieveVolatilityIndexData(ctx context.Context, ccy currency.Code, resolution string, startTime, endTime time.Time) ([]VolatilityIndexData, error) { if ccy.IsEmpty() { return nil, currency.ErrCurrencyCodeEmpty } @@ -524,7 +524,7 @@ func (d *Deribit) WSRetrieveVolatilityIndexData(ccy currency.Code, resolution st EndTimestamp: endTime.UnixMilli(), } var resp VolatilityIndexRawData - err = d.SendWSRequest(nonMatchingEPL, getVolatilityIndex, input, &resp, false) + err = d.SendWSRequest(ctx, nonMatchingEPL, getVolatilityIndex, input, &resp, false) if err != nil { return nil, err } @@ -542,7 +542,7 @@ func (d *Deribit) WSRetrieveVolatilityIndexData(ccy currency.Code, resolution st } // WSRetrievePublicTicker retrieves public ticker data of the instrument requested through the websocket connection. -func (d *Deribit) WSRetrievePublicTicker(instrument string) (*TickerData, error) { +func (d *Deribit) WSRetrievePublicTicker(ctx context.Context, instrument string) (*TickerData, error) { if instrument == "" { return nil, fmt.Errorf("%w, instrument_name is missing", errInvalidInstrumentName) } @@ -552,11 +552,11 @@ func (d *Deribit) WSRetrievePublicTicker(instrument string) (*TickerData, error) Instrument: instrument, } var resp *TickerData - return resp, d.SendWSRequest(nonMatchingEPL, getTicker, input, &resp, false) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, getTicker, input, &resp, false) } // WSRetrieveAccountSummary retrieves account summary data for the requested instrument through the websocket connection. -func (d *Deribit) WSRetrieveAccountSummary(ccy currency.Code, extended bool) (*AccountSummaryData, error) { +func (d *Deribit) WSRetrieveAccountSummary(ctx context.Context, ccy currency.Code, extended bool) (*AccountSummaryData, error) { if ccy.IsEmpty() { return nil, currency.ErrCurrencyCodeEmpty } @@ -568,11 +568,11 @@ func (d *Deribit) WSRetrieveAccountSummary(ccy currency.Code, extended bool) (*A Extended: extended, } var resp *AccountSummaryData - return resp, d.SendWSRequest(nonMatchingEPL, getAccountSummary, input, &resp, true) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, getAccountSummary, input, &resp, true) } // WSCancelWithdrawal cancels withdrawal request for a given currency by its id through the websocket connection. -func (d *Deribit) WSCancelWithdrawal(ccy currency.Code, id int64) (*CancelWithdrawalData, error) { +func (d *Deribit) WSCancelWithdrawal(ctx context.Context, ccy currency.Code, id int64) (*CancelWithdrawalData, error) { if ccy.IsEmpty() { return nil, currency.ErrCurrencyCodeEmpty } @@ -587,11 +587,11 @@ func (d *Deribit) WSCancelWithdrawal(ccy currency.Code, id int64) (*CancelWithdr ID: id, } var resp *CancelWithdrawalData - return resp, d.SendWSRequest(nonMatchingEPL, cancelWithdrawal, input, &resp, true) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, cancelWithdrawal, input, &resp, true) } // WSCancelTransferByID cancels transfer by ID through the websocket connection. -func (d *Deribit) WSCancelTransferByID(ccy currency.Code, tfa string, id int64) (*AccountSummaryData, error) { +func (d *Deribit) WSCancelTransferByID(ctx context.Context, ccy currency.Code, tfa string, id int64) (*AccountSummaryData, error) { if ccy.IsEmpty() { return nil, currency.ErrCurrencyCodeEmpty } @@ -608,11 +608,11 @@ func (d *Deribit) WSCancelTransferByID(ccy currency.Code, tfa string, id int64) TwoFactorAuthenticationCode: tfa, } var resp *AccountSummaryData - return resp, d.SendWSRequest(nonMatchingEPL, cancelTransferByID, input, &resp, true) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, cancelTransferByID, input, &resp, true) } // WSCreateDepositAddress creates a deposit address for the currency requested through the websocket connection. -func (d *Deribit) WSCreateDepositAddress(ccy currency.Code) (*DepositAddressData, error) { +func (d *Deribit) WSCreateDepositAddress(ctx context.Context, ccy currency.Code) (*DepositAddressData, error) { if ccy.IsEmpty() { return nil, currency.ErrCurrencyCodeEmpty } @@ -622,11 +622,11 @@ func (d *Deribit) WSCreateDepositAddress(ccy currency.Code) (*DepositAddressData Currency: ccy, } var resp *DepositAddressData - return resp, d.SendWSRequest(nonMatchingEPL, createDepositAddress, input, &resp, true) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, createDepositAddress, input, &resp, true) } // WSRetrieveDeposits retrieves the deposits of a given currency through the websocket connection. -func (d *Deribit) WSRetrieveDeposits(ccy currency.Code, count, offset int64) (*DepositsData, error) { +func (d *Deribit) WSRetrieveDeposits(ctx context.Context, ccy currency.Code, count, offset int64) (*DepositsData, error) { if ccy.IsEmpty() { return nil, currency.ErrCurrencyCodeEmpty } @@ -640,11 +640,11 @@ func (d *Deribit) WSRetrieveDeposits(ccy currency.Code, count, offset int64) (*D Offset: offset, } var resp *DepositsData - return resp, d.SendWSRequest(nonMatchingEPL, getDeposits, input, &resp, true) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, getDeposits, input, &resp, true) } // WSRetrieveTransfers retrieves data for the requested currency through the websocket connection. -func (d *Deribit) WSRetrieveTransfers(ccy currency.Code, count, offset int64) (*TransfersData, error) { +func (d *Deribit) WSRetrieveTransfers(ctx context.Context, ccy currency.Code, count, offset int64) (*TransfersData, error) { if ccy.IsEmpty() { return nil, currency.ErrCurrencyCodeEmpty } @@ -658,11 +658,11 @@ func (d *Deribit) WSRetrieveTransfers(ccy currency.Code, count, offset int64) (* Offset: offset, } var resp *TransfersData - return resp, d.SendWSRequest(nonMatchingEPL, getTransfers, input, &resp, true) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, getTransfers, input, &resp, true) } // WSRetrieveCurrentDepositAddress retrieves the current deposit address for the requested currency through the websocket connection. -func (d *Deribit) WSRetrieveCurrentDepositAddress(ccy currency.Code) (*DepositAddressData, error) { +func (d *Deribit) WSRetrieveCurrentDepositAddress(ctx context.Context, ccy currency.Code) (*DepositAddressData, error) { if ccy.IsEmpty() { return nil, currency.ErrCurrencyCodeEmpty } @@ -672,7 +672,7 @@ func (d *Deribit) WSRetrieveCurrentDepositAddress(ccy currency.Code) (*DepositAd Currency: ccy, } var resp *DepositAddressData - err := d.SendWSRequest(nonMatchingEPL, getCurrentDepositAddress, input, &resp, true) + err := d.SendWSRequest(ctx, nonMatchingEPL, getCurrentDepositAddress, input, &resp, true) if err != nil { return nil, err } else if resp == nil { @@ -682,7 +682,7 @@ func (d *Deribit) WSRetrieveCurrentDepositAddress(ccy currency.Code) (*DepositAd } // WSRetrieveWithdrawals retrieves withdrawals data for a requested currency through the websocket connection. -func (d *Deribit) WSRetrieveWithdrawals(ccy currency.Code, count, offset int64) (*WithdrawalsData, error) { +func (d *Deribit) WSRetrieveWithdrawals(ctx context.Context, ccy currency.Code, count, offset int64) (*WithdrawalsData, error) { if ccy.IsEmpty() { return nil, currency.ErrCurrencyCodeEmpty } @@ -696,11 +696,11 @@ func (d *Deribit) WSRetrieveWithdrawals(ccy currency.Code, count, offset int64) Offset: offset, } var resp *WithdrawalsData - return resp, d.SendWSRequest(nonMatchingEPL, getWithdrawals, input, &resp, true) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, getWithdrawals, input, &resp, true) } // WsSubmitTransferBetweenSubAccounts transfer funds between two (sub)accounts. -func (d *Deribit) WsSubmitTransferBetweenSubAccounts(ccy currency.Code, amount float64, destinationID int64, source string) (*TransferData, error) { +func (d *Deribit) WsSubmitTransferBetweenSubAccounts(ctx context.Context, ccy currency.Code, amount float64, destinationID int64, source string) (*TransferData, error) { if ccy.IsEmpty() { return nil, currency.ErrCurrencyCodeEmpty } @@ -722,11 +722,11 @@ func (d *Deribit) WsSubmitTransferBetweenSubAccounts(ccy currency.Code, amount f Source: source, } var resp *TransferData - return resp, d.SendWSRequest(nonMatchingEPL, submitTransferBetweenSubAccounts, input, &resp, true) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, submitTransferBetweenSubAccounts, input, &resp, true) } // WSSubmitTransferToSubAccount submits a request to transfer a currency to a subaccount -func (d *Deribit) WSSubmitTransferToSubAccount(ccy currency.Code, amount float64, destinationID int64) (*TransferData, error) { +func (d *Deribit) WSSubmitTransferToSubAccount(ctx context.Context, ccy currency.Code, amount float64, destinationID int64) (*TransferData, error) { if ccy.IsEmpty() { return nil, currency.ErrCurrencyCodeEmpty } @@ -746,11 +746,11 @@ func (d *Deribit) WSSubmitTransferToSubAccount(ccy currency.Code, amount float64 Amount: amount, } var resp *TransferData - return resp, d.SendWSRequest(nonMatchingEPL, submitTransferToSubaccount, input, &resp, true) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, submitTransferToSubaccount, input, &resp, true) } // WSSubmitTransferToUser submits a request to transfer a currency to another user through the websocket connection. -func (d *Deribit) WSSubmitTransferToUser(ccy currency.Code, tfa, destinationAddress string, amount float64) (*TransferData, error) { +func (d *Deribit) WSSubmitTransferToUser(ctx context.Context, ccy currency.Code, tfa, destinationAddress string, amount float64) (*TransferData, error) { if ccy.IsEmpty() { return nil, currency.ErrCurrencyCodeEmpty } @@ -772,13 +772,13 @@ func (d *Deribit) WSSubmitTransferToUser(ccy currency.Code, tfa, destinationAddr Amount: amount, } var resp *TransferData - return resp, d.SendWSRequest(nonMatchingEPL, submitTransferToUser, input, &resp, true) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, submitTransferToUser, input, &resp, true) } // ---------------------------------------------------------------------------- // WSSubmitWithdraw submits a withdrawal request to the exchange for the requested currency through the websocket connection. -func (d *Deribit) WSSubmitWithdraw(ccy currency.Code, address, priority string, amount float64) (*WithdrawData, error) { +func (d *Deribit) WSSubmitWithdraw(ctx context.Context, ccy currency.Code, address, priority string, amount float64) (*WithdrawData, error) { if ccy.IsEmpty() { return nil, currency.ErrCurrencyCodeEmpty } @@ -800,11 +800,11 @@ func (d *Deribit) WSSubmitWithdraw(ccy currency.Code, address, priority string, Amount: amount, } var resp *WithdrawData - return resp, d.SendWSRequest(nonMatchingEPL, submitWithdraw, input, &resp, true) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, submitWithdraw, input, &resp, true) } // WSRetrieveAnnouncements retrieves announcements through the websocket connection. Default "start_timestamp" parameter value is current timestamp, "count" parameter value must be between 1 and 50, default is 5. -func (d *Deribit) WSRetrieveAnnouncements(startTime time.Time, count int64) ([]Announcement, error) { +func (d *Deribit) WSRetrieveAnnouncements(ctx context.Context, startTime time.Time, count int64) ([]Announcement, error) { input := &struct { StartTime int64 `json:"start_time,omitempty"` Count int64 `json:"count,omitempty"` @@ -816,11 +816,11 @@ func (d *Deribit) WSRetrieveAnnouncements(startTime time.Time, count int64) ([]A input.Count = count } var resp []Announcement - return resp, d.SendWSRequest(nonMatchingEPL, getAnnouncements, input, &resp, false) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, getAnnouncements, input, &resp, false) } // WSChangeAPIKeyName changes the name of the api key requested through the websocket connection. -func (d *Deribit) WSChangeAPIKeyName(id int64, name string) (*APIKeyData, error) { +func (d *Deribit) WSChangeAPIKeyName(ctx context.Context, id int64, name string) (*APIKeyData, error) { if id <= 0 { return nil, fmt.Errorf("%w, invalid api key id", errInvalidID) } @@ -835,13 +835,13 @@ func (d *Deribit) WSChangeAPIKeyName(id int64, name string) (*APIKeyData, error) Name: name, } var resp *APIKeyData - return resp, d.SendWSRequest(nonMatchingEPL, changeAPIKeyName, input, &resp, true) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, changeAPIKeyName, input, &resp, true) } // WsChangeMarginModel change margin model // Margin model: 'cross_pm', 'cross_sm', 'segregated_pm', 'segregated_sm' // 'dry_run': If true request returns the result without switching the margining model. Default: false -func (d *Deribit) WsChangeMarginModel(userID int64, marginModel string, dryRun bool) ([]TogglePortfolioMarginResponse, error) { +func (d *Deribit) WsChangeMarginModel(ctx context.Context, userID int64, marginModel string, dryRun bool) ([]TogglePortfolioMarginResponse, error) { if marginModel == "" { return nil, errInvalidMarginModel } @@ -855,11 +855,11 @@ func (d *Deribit) WsChangeMarginModel(userID int64, marginModel string, dryRun b DryRun: dryRun, } var resp []TogglePortfolioMarginResponse - return resp, d.SendWSRequest(nonMatchingEPL, changeMarginModel, input, &resp, true) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, changeMarginModel, input, &resp, true) } // WSChangeScopeInAPIKey changes the name of the requested subaccount id through the websocket connection. -func (d *Deribit) WSChangeScopeInAPIKey(id int64, maxScope string) (*APIKeyData, error) { +func (d *Deribit) WSChangeScopeInAPIKey(ctx context.Context, id int64, maxScope string) (*APIKeyData, error) { if id <= 0 { return nil, fmt.Errorf("%w, invalid api key id", errInvalidID) } @@ -871,11 +871,11 @@ func (d *Deribit) WSChangeScopeInAPIKey(id int64, maxScope string) (*APIKeyData, MaxScope: maxScope, } var resp *APIKeyData - return resp, d.SendWSRequest(nonMatchingEPL, changeScopeInAPIKey, input, &resp, true) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, changeScopeInAPIKey, input, &resp, true) } // WSChangeSubAccountName retrieves changes the name of the requested subaccount id through the websocket connection. -func (d *Deribit) WSChangeSubAccountName(sid int64, name string) error { +func (d *Deribit) WSChangeSubAccountName(ctx context.Context, sid int64, name string) error { if sid <= 0 { return fmt.Errorf("%w, invalid subaccount user id", errInvalidID) } @@ -890,7 +890,7 @@ func (d *Deribit) WSChangeSubAccountName(sid int64, name string) error { Name: name, } var resp string - err := d.SendWSRequest(nonMatchingEPL, changeSubAccountName, input, &resp, true) + err := d.SendWSRequest(ctx, nonMatchingEPL, changeSubAccountName, input, &resp, true) if err != nil { return err } @@ -901,7 +901,7 @@ func (d *Deribit) WSChangeSubAccountName(sid int64, name string) error { } // WSCreateAPIKey creates an api key based on the provided settings through the websocket connection. -func (d *Deribit) WSCreateAPIKey(maxScope, name string, defaultKey bool) (*APIKeyData, error) { +func (d *Deribit) WSCreateAPIKey(ctx context.Context, maxScope, name string, defaultKey bool) (*APIKeyData, error) { input := &struct { MaxScope string `json:"max_scope"` Name string `json:"name,omitempty"` @@ -913,17 +913,17 @@ func (d *Deribit) WSCreateAPIKey(maxScope, name string, defaultKey bool) (*APIKe } var resp *APIKeyData - return resp, d.SendWSRequest(nonMatchingEPL, createAPIKey, input, &resp, true) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, createAPIKey, input, &resp, true) } // WSCreateSubAccount creates a new subaccount through the websocket connection. -func (d *Deribit) WSCreateSubAccount() (*SubAccountData, error) { +func (d *Deribit) WSCreateSubAccount(ctx context.Context) (*SubAccountData, error) { var resp *SubAccountData - return resp, d.SendWSRequest(nonMatchingEPL, createSubAccount, nil, &resp, true) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, createSubAccount, nil, &resp, true) } // WSDisableAPIKey disables the api key linked to the provided id through the websocket connection. -func (d *Deribit) WSDisableAPIKey(id int64) (*APIKeyData, error) { +func (d *Deribit) WSDisableAPIKey(ctx context.Context, id int64) (*APIKeyData, error) { if id <= 0 { return nil, fmt.Errorf("%w, invalid api key id", errInvalidID) } @@ -933,7 +933,7 @@ func (d *Deribit) WSDisableAPIKey(id int64) (*APIKeyData, error) { ID: id, } var resp *APIKeyData - return resp, d.SendWSRequest(nonMatchingEPL, disableAPIKey, input, &resp, true) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, disableAPIKey, input, &resp, true) } // WsEditAPIKey edits existing API key. At least one parameter is required. @@ -942,7 +942,7 @@ func (d *Deribit) WSDisableAPIKey(id int64) (*APIKeyData, error) { // wallet:[read, read_write, none], // account:[read, read_write, none], // block_trade:[read, read_write, none]. -func (d *Deribit) WsEditAPIKey(id int64, maxScope, name string, enabled bool, enabledFeatures, ipWhitelist []string) (*APIKeyData, error) { +func (d *Deribit) WsEditAPIKey(ctx context.Context, id int64, maxScope, name string, enabled bool, enabledFeatures, ipWhitelist []string) (*APIKeyData, error) { if id == 0 { return nil, errInvalidAPIKeyID } @@ -965,13 +965,13 @@ func (d *Deribit) WsEditAPIKey(id int64, maxScope, name string, enabled bool, en IPWhitelist: ipWhitelist, } var resp *APIKeyData - return resp, d.SendWSRequest(nonMatchingEPL, editAPIKey, input, &resp, true) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, editAPIKey, input, &resp, true) } // WSEnableAffiliateProgram enables the affiliate program through the websocket connection. -func (d *Deribit) WSEnableAffiliateProgram() error { +func (d *Deribit) WSEnableAffiliateProgram(ctx context.Context) error { var resp string - err := d.SendWSRequest(nonMatchingEPL, enableAffiliateProgram, nil, &resp, true) + err := d.SendWSRequest(ctx, nonMatchingEPL, enableAffiliateProgram, nil, &resp, true) if err != nil { return err } @@ -982,16 +982,16 @@ func (d *Deribit) WSEnableAffiliateProgram() error { } // WSEnableAPIKey enables the api key linked to the provided id through the websocket connection. -func (d *Deribit) WSEnableAPIKey(id int64) (*APIKeyData, error) { +func (d *Deribit) WSEnableAPIKey(ctx context.Context, id int64) (*APIKeyData, error) { if id <= 0 { return nil, fmt.Errorf("%w, invalid api key id", errInvalidID) } var resp *APIKeyData - return resp, d.SendWSRequest(nonMatchingEPL, enableAPIKey, map[string]int64{"id": id}, &resp, true) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, enableAPIKey, map[string]int64{"id": id}, &resp, true) } // WSRetrieveAccessLog lists access logs for the user through the websocket connection. -func (d *Deribit) WSRetrieveAccessLog(offset, count int64) (*AccessLog, error) { +func (d *Deribit) WSRetrieveAccessLog(ctx context.Context, offset, count int64) (*AccessLog, error) { input := &struct { Offset int64 `json:"offset,omitempty"` Count int64 `json:"count,omitempty"` @@ -1000,44 +1000,44 @@ func (d *Deribit) WSRetrieveAccessLog(offset, count int64) (*AccessLog, error) { Count: count, } var resp *AccessLog - return resp, d.SendWSRequest(nonMatchingEPL, getAccessLog, input, &resp, true) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, getAccessLog, input, &resp, true) } // WSRetrieveAffiliateProgramInfo retrieves the affiliate program info through the websocket connection. -func (d *Deribit) WSRetrieveAffiliateProgramInfo() (*AffiliateProgramInfo, error) { +func (d *Deribit) WSRetrieveAffiliateProgramInfo(ctx context.Context) (*AffiliateProgramInfo, error) { var resp *AffiliateProgramInfo - return resp, d.SendWSRequest(nonMatchingEPL, getAffiliateProgramInfo, nil, &resp, true) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, getAffiliateProgramInfo, nil, &resp, true) } // WSRetrieveEmailLanguage retrieves the current language set for the email through the websocket connection. -func (d *Deribit) WSRetrieveEmailLanguage() (string, error) { +func (d *Deribit) WSRetrieveEmailLanguage(ctx context.Context) (string, error) { var resp string - return resp, d.SendWSRequest(nonMatchingEPL, getEmailLanguage, nil, &resp, true) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, getEmailLanguage, nil, &resp, true) } // WSRetrieveNewAnnouncements retrieves new announcements through the websocket connection. -func (d *Deribit) WSRetrieveNewAnnouncements() ([]Announcement, error) { +func (d *Deribit) WSRetrieveNewAnnouncements(ctx context.Context) ([]Announcement, error) { var resp []Announcement - return resp, d.SendWSRequest(nonMatchingEPL, getNewAnnouncements, nil, &resp, true) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, getNewAnnouncements, nil, &resp, true) } // WSRetrievePosition retrieves the data of all positions in the requested instrument name through the websocket connection. -func (d *Deribit) WSRetrievePosition(instrument string) (*PositionData, error) { +func (d *Deribit) WSRetrievePosition(ctx context.Context, instrument string) (*PositionData, error) { if instrument == "" { return nil, fmt.Errorf("%w, instrument_name is missing", errInvalidInstrumentName) } var resp *PositionData - return resp, d.SendWSRequest(nonMatchingEPL, getPosition, map[string]string{"instrument_name": instrument}, &resp, true) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, getPosition, map[string]string{"instrument_name": instrument}, &resp, true) } // WSRetrieveSubAccounts retrieves all subaccounts' data through the websocket connection. -func (d *Deribit) WSRetrieveSubAccounts(withPortfolio bool) ([]SubAccountData, error) { +func (d *Deribit) WSRetrieveSubAccounts(ctx context.Context, withPortfolio bool) ([]SubAccountData, error) { var resp []SubAccountData - return resp, d.SendWSRequest(nonMatchingEPL, getSubAccounts, map[string]bool{"with_portfolio": withPortfolio}, &resp, true) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, getSubAccounts, map[string]bool{"with_portfolio": withPortfolio}, &resp, true) } // WSRetrieveSubAccountDetails retrieves sub-account detail information through the websocket connection. -func (d *Deribit) WSRetrieveSubAccountDetails(ccy currency.Code, withOpenOrders bool) ([]SubAccountDetail, error) { +func (d *Deribit) WSRetrieveSubAccountDetails(ctx context.Context, ccy currency.Code, withOpenOrders bool) ([]SubAccountDetail, error) { if ccy.IsEmpty() { return nil, currency.ErrCurrencyCodeEmpty } @@ -1049,11 +1049,11 @@ func (d *Deribit) WSRetrieveSubAccountDetails(ccy currency.Code, withOpenOrders WithOpenOrders: withOpenOrders, } var resp []SubAccountDetail - return resp, d.SendWSRequest(nonMatchingEPL, getSubAccountDetails, input, &resp, true) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, getSubAccountDetails, input, &resp, true) } // WSRetrievePositions retrieves positions data of the user account through the websocket connection. -func (d *Deribit) WSRetrievePositions(ccy currency.Code, kind string) ([]PositionData, error) { +func (d *Deribit) WSRetrievePositions(ctx context.Context, ccy currency.Code, kind string) ([]PositionData, error) { if ccy.IsEmpty() { return nil, currency.ErrCurrencyCodeEmpty } @@ -1065,11 +1065,11 @@ func (d *Deribit) WSRetrievePositions(ccy currency.Code, kind string) ([]Positio Kind: kind, } var resp []PositionData - return resp, d.SendWSRequest(nonMatchingEPL, getPositions, input, &resp, true) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, getPositions, input, &resp, true) } // WSRetrieveTransactionLog retrieves transaction logs data through the websocket connection. -func (d *Deribit) WSRetrieveTransactionLog(ccy currency.Code, query string, startTime, endTime time.Time, count, continuation int64) (*TransactionsData, error) { +func (d *Deribit) WSRetrieveTransactionLog(ctx context.Context, ccy currency.Code, query string, startTime, endTime time.Time, count, continuation int64) (*TransactionsData, error) { if ccy.IsEmpty() { return nil, currency.ErrCurrencyCodeEmpty } @@ -1092,37 +1092,37 @@ func (d *Deribit) WSRetrieveTransactionLog(ccy currency.Code, query string, star Continuation: continuation, } var resp *TransactionsData - return resp, d.SendWSRequest(nonMatchingEPL, getTransactionLog, input, &resp, true) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, getTransactionLog, input, &resp, true) } // WSRetrieveUserLocks retrieves information about locks on user account through the websocket connection. -func (d *Deribit) WSRetrieveUserLocks() ([]UserLock, error) { +func (d *Deribit) WSRetrieveUserLocks(ctx context.Context) ([]UserLock, error) { var resp []UserLock - return resp, d.SendWSRequest(nonMatchingEPL, getUserLocks, nil, &resp, true) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, getUserLocks, nil, &resp, true) } // WSListAPIKeys retrieves all the api keys associated with a user account through the websocket connection. -func (d *Deribit) WSListAPIKeys(tfa string) ([]APIKeyData, error) { +func (d *Deribit) WSListAPIKeys(ctx context.Context, tfa string) ([]APIKeyData, error) { var resp []APIKeyData - return resp, d.SendWSRequest(nonMatchingEPL, listAPIKeys, map[string]string{"tfa": tfa}, &resp, true) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, listAPIKeys, map[string]string{"tfa": tfa}, &resp, true) } // WsRetrieveCustodyAccounts retrieves user custody accounts -func (d *Deribit) WsRetrieveCustodyAccounts(ccy currency.Code) ([]CustodyAccount, error) { +func (d *Deribit) WsRetrieveCustodyAccounts(ctx context.Context, ccy currency.Code) ([]CustodyAccount, error) { if ccy.IsEmpty() { return nil, currency.ErrCurrencyCodeEmpty } var resp []CustodyAccount - return resp, d.SendWSRequest(nonMatchingEPL, listCustodyAccounts, &map[string]string{"currency": ccy.String()}, &resp, true) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, listCustodyAccounts, &map[string]string{"currency": ccy.String()}, &resp, true) } // WSRemoveAPIKey removes api key vid ID through the websocket connection. -func (d *Deribit) WSRemoveAPIKey(id int64) error { +func (d *Deribit) WSRemoveAPIKey(ctx context.Context, id int64) error { if id <= 0 { return fmt.Errorf("%w, invalid api key id", errInvalidID) } var resp string - err := d.SendWSRequest(nonMatchingEPL, removeAPIKey, map[string]int64{"id": id}, &resp, true) + err := d.SendWSRequest(ctx, nonMatchingEPL, removeAPIKey, map[string]int64{"id": id}, &resp, true) if err != nil { return err } @@ -1133,9 +1133,9 @@ func (d *Deribit) WSRemoveAPIKey(id int64) error { } // WSRemoveSubAccount removes a subaccount given its id through the websocket connection. -func (d *Deribit) WSRemoveSubAccount(subAccountID int64) error { +func (d *Deribit) WSRemoveSubAccount(ctx context.Context, subAccountID int64) error { var resp string - err := d.SendWSRequest(nonMatchingEPL, removeSubAccount, map[string]int64{"subaccount_id": subAccountID}, &resp, true) + err := d.SendWSRequest(ctx, nonMatchingEPL, removeSubAccount, map[string]int64{"subaccount_id": subAccountID}, &resp, true) if err != nil { return err } @@ -1146,12 +1146,12 @@ func (d *Deribit) WSRemoveSubAccount(subAccountID int64) error { } // WSResetAPIKey sets an announcement as read through the websocket connection. -func (d *Deribit) WSResetAPIKey(id int64) error { +func (d *Deribit) WSResetAPIKey(ctx context.Context, id int64) error { if id <= 0 { return fmt.Errorf("%w, invalid announcement id", errInvalidID) } var resp string - err := d.SendWSRequest(nonMatchingEPL, resetAPIKey, map[string]int64{"announcement_id": id}, &resp, true) + err := d.SendWSRequest(ctx, nonMatchingEPL, resetAPIKey, map[string]int64{"announcement_id": id}, &resp, true) if err != nil { return err } @@ -1162,7 +1162,7 @@ func (d *Deribit) WSResetAPIKey(id int64) error { } // WSSetEmailForSubAccount links an email given to the designated subaccount through the websocket connection. -func (d *Deribit) WSSetEmailForSubAccount(sid int64, email string) error { +func (d *Deribit) WSSetEmailForSubAccount(ctx context.Context, sid int64, email string) error { if sid <= 0 { return fmt.Errorf("%w, invalid subaccount user id", errInvalidID) } @@ -1177,7 +1177,7 @@ func (d *Deribit) WSSetEmailForSubAccount(sid int64, email string) error { SID: sid, } var resp string - err := d.SendWSRequest(nonMatchingEPL, setEmailForSubAccount, input, &resp, true) + err := d.SendWSRequest(ctx, nonMatchingEPL, setEmailForSubAccount, input, &resp, true) if err != nil { return err } @@ -1188,12 +1188,12 @@ func (d *Deribit) WSSetEmailForSubAccount(sid int64, email string) error { } // WSSetEmailLanguage sets a requested language for an email through the websocket connection. -func (d *Deribit) WSSetEmailLanguage(language string) error { +func (d *Deribit) WSSetEmailLanguage(ctx context.Context, language string) error { if language == "" { return errLanguageIsRequired } var resp string - err := d.SendWSRequest(nonMatchingEPL, setEmailLanguage, map[string]string{"language": language}, &resp, true) + err := d.SendWSRequest(ctx, nonMatchingEPL, setEmailLanguage, map[string]string{"language": language}, &resp, true) if err != nil { return err } @@ -1206,7 +1206,7 @@ func (d *Deribit) WSSetEmailLanguage(language string) error { // WsSetSelfTradingConfig configure self trading behavior through the websocket connection. // mode: Self trading prevention behavior. Possible values: 'reject_taker', 'cancel_maker' // extended_to_subaccounts: If value is true trading is prevented between subaccounts of given account -func (d *Deribit) WsSetSelfTradingConfig(mode string, extendedToSubaccounts bool) (string, error) { +func (d *Deribit) WsSetSelfTradingConfig(ctx context.Context, mode string, extendedToSubaccounts bool) (string, error) { if mode == "" { return "", errTradeModeIsRequired } @@ -1218,11 +1218,11 @@ func (d *Deribit) WsSetSelfTradingConfig(mode string, extendedToSubaccounts bool ExtendedToSubAccounts: extendedToSubaccounts, } var resp string - return resp, d.SendWSRequest(nonMatchingEPL, setSelfTradingConfig, input, &resp, true) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, setSelfTradingConfig, input, &resp, true) } // WSToggleNotificationsFromSubAccount toggles the notifications from a subaccount specified through the websocket connection. -func (d *Deribit) WSToggleNotificationsFromSubAccount(sid int64, state bool) error { +func (d *Deribit) WSToggleNotificationsFromSubAccount(ctx context.Context, sid int64, state bool) error { if sid <= 0 { return fmt.Errorf("%w, invalid subaccount user id", errInvalidID) } @@ -1234,7 +1234,7 @@ func (d *Deribit) WSToggleNotificationsFromSubAccount(sid int64, state bool) err State: state, } var resp string - err := d.SendWSRequest(nonMatchingEPL, toggleNotificationsFromSubAccount, input, &resp, true) + err := d.SendWSRequest(ctx, nonMatchingEPL, toggleNotificationsFromSubAccount, input, &resp, true) if err != nil { return err } @@ -1245,7 +1245,7 @@ func (d *Deribit) WSToggleNotificationsFromSubAccount(sid int64, state bool) err } // WSTogglePortfolioMargining toggle between SM and PM models through the websocket connection. -func (d *Deribit) WSTogglePortfolioMargining(userID int64, enabled, dryRun bool) ([]TogglePortfolioMarginResponse, error) { +func (d *Deribit) WSTogglePortfolioMargining(ctx context.Context, userID int64, enabled, dryRun bool) ([]TogglePortfolioMarginResponse, error) { if userID == 0 { return nil, errUserIDRequired } @@ -1259,11 +1259,11 @@ func (d *Deribit) WSTogglePortfolioMargining(userID int64, enabled, dryRun bool) DryRun: dryRun, } var resp []TogglePortfolioMarginResponse - return resp, d.SendWSRequest(nonMatchingEPL, togglePortfolioMargining, input, &resp, true) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, togglePortfolioMargining, input, &resp, true) } // WSToggleSubAccountLogin toggles access for subaccount login through the websocket connection. -func (d *Deribit) WSToggleSubAccountLogin(sid int64, state bool) error { +func (d *Deribit) WSToggleSubAccountLogin(ctx context.Context, sid int64, state bool) error { if sid <= 0 { return fmt.Errorf("%w, invalid subaccount user id", errInvalidID) } @@ -1275,7 +1275,7 @@ func (d *Deribit) WSToggleSubAccountLogin(sid int64, state bool) error { State: state, } var resp string - err := d.SendWSRequest(nonMatchingEPL, toggleSubAccountLogin, input, &resp, true) + err := d.SendWSRequest(ctx, nonMatchingEPL, toggleSubAccountLogin, input, &resp, true) if err != nil { return err } @@ -1286,7 +1286,7 @@ func (d *Deribit) WSToggleSubAccountLogin(sid int64, state bool) error { } // WSSubmitBuy submits a private buy request through the websocket connection. -func (d *Deribit) WSSubmitBuy(arg *OrderBuyAndSellParams) (*PrivateTradeData, error) { +func (d *Deribit) WSSubmitBuy(ctx context.Context, arg *OrderBuyAndSellParams) (*PrivateTradeData, error) { if arg == nil || *arg == (OrderBuyAndSellParams{}) { return nil, fmt.Errorf("%w parameter is required", common.ErrNilPointer) } @@ -1294,11 +1294,11 @@ func (d *Deribit) WSSubmitBuy(arg *OrderBuyAndSellParams) (*PrivateTradeData, er return nil, fmt.Errorf("%w, instrument_name is missing", errInvalidInstrumentName) } var resp *PrivateTradeData - return resp, d.SendWSRequest(matchingEPL, submitBuy, &arg, &resp, true) + return resp, d.SendWSRequest(ctx, matchingEPL, submitBuy, &arg, &resp, true) } // WSSubmitSell submits a sell request with the parameters provided through the websocket connection. -func (d *Deribit) WSSubmitSell(arg *OrderBuyAndSellParams) (*PrivateTradeData, error) { +func (d *Deribit) WSSubmitSell(ctx context.Context, arg *OrderBuyAndSellParams) (*PrivateTradeData, error) { if arg == nil || *arg == (OrderBuyAndSellParams{}) { return nil, fmt.Errorf("%w parameter is required", common.ErrNilPointer) } @@ -1306,11 +1306,11 @@ func (d *Deribit) WSSubmitSell(arg *OrderBuyAndSellParams) (*PrivateTradeData, e return nil, fmt.Errorf("%w, instrument_name is missing", errInvalidInstrumentName) } var resp *PrivateTradeData - return resp, d.SendWSRequest(matchingEPL, submitSell, &arg, &resp, true) + return resp, d.SendWSRequest(ctx, matchingEPL, submitSell, &arg, &resp, true) } // WSSubmitEdit submits an edit order request through the websocket connection. -func (d *Deribit) WSSubmitEdit(arg *OrderBuyAndSellParams) (*PrivateTradeData, error) { +func (d *Deribit) WSSubmitEdit(ctx context.Context, arg *OrderBuyAndSellParams) (*PrivateTradeData, error) { if arg == nil || *arg == (OrderBuyAndSellParams{}) { return nil, common.ErrNilPointer } @@ -1321,11 +1321,11 @@ func (d *Deribit) WSSubmitEdit(arg *OrderBuyAndSellParams) (*PrivateTradeData, e return nil, errInvalidAmount } var resp *PrivateTradeData - return resp, d.SendWSRequest(matchingEPL, submitEdit, &arg, &resp, true) + return resp, d.SendWSRequest(ctx, matchingEPL, submitEdit, &arg, &resp, true) } // WSEditOrderByLabel submits an edit order request sorted via label through the websocket connection. -func (d *Deribit) WSEditOrderByLabel(arg *OrderBuyAndSellParams) (*PrivateTradeData, error) { +func (d *Deribit) WSEditOrderByLabel(ctx context.Context, arg *OrderBuyAndSellParams) (*PrivateTradeData, error) { if arg == nil || *arg == (OrderBuyAndSellParams{}) { return nil, fmt.Errorf("%w argument cannot be null", common.ErrNilPointer) } @@ -1336,26 +1336,26 @@ func (d *Deribit) WSEditOrderByLabel(arg *OrderBuyAndSellParams) (*PrivateTradeD return nil, errInvalidAmount } var resp *PrivateTradeData - return resp, d.SendWSRequest(nonMatchingEPL, editByLabel, &arg, &resp, true) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, editByLabel, &arg, &resp, true) } // WSSubmitCancel sends a request to cancel the order via its orderID through the websocket connection. -func (d *Deribit) WSSubmitCancel(orderID string) (*PrivateCancelData, error) { +func (d *Deribit) WSSubmitCancel(ctx context.Context, orderID string) (*PrivateCancelData, error) { if orderID == "" { return nil, fmt.Errorf("%w, no order ID specified", errInvalidID) } var resp *PrivateCancelData - return resp, d.SendWSRequest(matchingEPL, submitCancel, map[string]string{"order_id": orderID}, &resp, true) + return resp, d.SendWSRequest(ctx, matchingEPL, submitCancel, map[string]string{"order_id": orderID}, &resp, true) } // WSSubmitCancelAll sends a request to cancel all user orders in all currencies and instruments -func (d *Deribit) WSSubmitCancelAll(detailed bool) (*MultipleCancelResponse, error) { +func (d *Deribit) WSSubmitCancelAll(ctx context.Context, detailed bool) (*MultipleCancelResponse, error) { var resp *MultipleCancelResponse - return resp, d.SendWSRequest(matchingEPL, submitCancelAll, map[string]bool{"detailed": detailed}, &resp, true) + return resp, d.SendWSRequest(ctx, matchingEPL, submitCancelAll, map[string]bool{"detailed": detailed}, &resp, true) } // WSSubmitCancelAllByCurrency sends a request to cancel all user orders for the specified currency through the websocket connection. -func (d *Deribit) WSSubmitCancelAllByCurrency(ccy currency.Code, kind, orderType string, detailed bool) (*MultipleCancelResponse, error) { +func (d *Deribit) WSSubmitCancelAllByCurrency(ctx context.Context, ccy currency.Code, kind, orderType string, detailed bool) (*MultipleCancelResponse, error) { if ccy.IsEmpty() { return nil, currency.ErrCurrencyCodeEmpty } @@ -1371,11 +1371,11 @@ func (d *Deribit) WSSubmitCancelAllByCurrency(ccy currency.Code, kind, orderType Detailed: detailed, } var resp *MultipleCancelResponse - return resp, d.SendWSRequest(matchingEPL, submitCancelAllByCurrency, input, &resp, true) + return resp, d.SendWSRequest(ctx, matchingEPL, submitCancelAllByCurrency, input, &resp, true) } // WSSubmitCancelAllByInstrument sends a request to cancel all user orders for the specified instrument through the websocket connection. -func (d *Deribit) WSSubmitCancelAllByInstrument(instrument, orderType string, detailed, includeCombos bool) (*MultipleCancelResponse, error) { +func (d *Deribit) WSSubmitCancelAllByInstrument(ctx context.Context, instrument, orderType string, detailed, includeCombos bool) (*MultipleCancelResponse, error) { if instrument == "" { return nil, errInvalidInstrumentName } @@ -1391,12 +1391,12 @@ func (d *Deribit) WSSubmitCancelAllByInstrument(instrument, orderType string, de IncludeCombos: includeCombos, } var resp *MultipleCancelResponse - return resp, d.SendWSRequest(matchingEPL, submitCancelAllByInstrument, input, &resp, true) + return resp, d.SendWSRequest(ctx, matchingEPL, submitCancelAllByInstrument, input, &resp, true) } // WsSubmitCancelAllByKind cancels all orders in currency(currencies), optionally filtered by instrument kind and/or order type. // 'kind' Instrument kind. Possible values: 'future', 'option', 'spot', 'future_combo', 'option_combo', 'combo', 'any' -func (d *Deribit) WsSubmitCancelAllByKind(ccy currency.Code, kind, orderType string, detailed bool) (*MultipleCancelResponse, error) { +func (d *Deribit) WsSubmitCancelAllByKind(ctx context.Context, ccy currency.Code, kind, orderType string, detailed bool) (*MultipleCancelResponse, error) { if ccy.IsEmpty() { return nil, currency.ErrCurrencyCodeEmpty } @@ -1412,11 +1412,11 @@ func (d *Deribit) WsSubmitCancelAllByKind(ccy currency.Code, kind, orderType str Detailed: detailed, } var resp *MultipleCancelResponse - return resp, d.SendWSRequest(matchingEPL, submitCancelAllByKind, input, &resp, true) + return resp, d.SendWSRequest(ctx, matchingEPL, submitCancelAllByKind, input, &resp, true) } // WSSubmitCancelByLabel sends a request to cancel all user orders for the specified label through the websocket connection. -func (d *Deribit) WSSubmitCancelByLabel(label string, ccy currency.Code, detailed bool) (*MultipleCancelResponse, error) { +func (d *Deribit) WSSubmitCancelByLabel(ctx context.Context, label string, ccy currency.Code, detailed bool) (*MultipleCancelResponse, error) { input := &struct { Label string `json:"label"` Currency string `json:"currency,omitempty"` @@ -1427,14 +1427,14 @@ func (d *Deribit) WSSubmitCancelByLabel(label string, ccy currency.Code, detaile Detailed: detailed, } var resp *MultipleCancelResponse - return resp, d.SendWSRequest(matchingEPL, submitCancelByLabel, input, &resp, true) + return resp, d.SendWSRequest(ctx, matchingEPL, submitCancelByLabel, input, &resp, true) } // WSSubmitCancelQuotes cancels quotes based on the provided type. // // possible cancel_type values are delta, 'quote_set_id', 'instrument', 'instrument_kind', 'currency', and 'all' // possible kind values are future 'option', 'spot', 'future_combo', 'option_combo', 'combo', and 'any' -func (d *Deribit) WSSubmitCancelQuotes(ccy currency.Code, minDelta, maxDelta float64, cancelType, quoteSetID, instrumentName, kind string, detailed bool) (*MultipleCancelResponse, error) { +func (d *Deribit) WSSubmitCancelQuotes(ctx context.Context, ccy currency.Code, minDelta, maxDelta float64, cancelType, quoteSetID, instrumentName, kind string, detailed bool) (*MultipleCancelResponse, error) { if ccy.IsEmpty() { return nil, currency.ErrCurrencyCodeEmpty } @@ -1461,11 +1461,11 @@ func (d *Deribit) WSSubmitCancelQuotes(ccy currency.Code, minDelta, maxDelta flo QuoteSetID: quoteSetID, } var resp *MultipleCancelResponse - return resp, d.SendWSRequest(matchingEPL, submitCancelQuotes, input, &resp, true) + return resp, d.SendWSRequest(ctx, matchingEPL, submitCancelQuotes, input, &resp, true) } // WSSubmitClosePosition sends a request to cancel all user orders for the specified label through the websocket connection. -func (d *Deribit) WSSubmitClosePosition(instrument, orderType string, price float64) (*PrivateTradeData, error) { +func (d *Deribit) WSSubmitClosePosition(ctx context.Context, instrument, orderType string, price float64) (*PrivateTradeData, error) { if instrument == "" { return nil, errInvalidInstrumentName } @@ -1479,11 +1479,11 @@ func (d *Deribit) WSSubmitClosePosition(instrument, orderType string, price floa Price: price, } var resp *PrivateTradeData - return resp, d.SendWSRequest(matchingEPL, submitClosePosition, input, &resp, true) + return resp, d.SendWSRequest(ctx, matchingEPL, submitClosePosition, input, &resp, true) } // WSRetrieveMargins sends a request to fetch account margins data through the websocket connection. -func (d *Deribit) WSRetrieveMargins(instrument string, amount, price float64) (*MarginsData, error) { +func (d *Deribit) WSRetrieveMargins(ctx context.Context, instrument string, amount, price float64) (*MarginsData, error) { if instrument == "" { return nil, errInvalidInstrumentName } @@ -1503,20 +1503,20 @@ func (d *Deribit) WSRetrieveMargins(instrument string, amount, price float64) (* Price: price, } var resp *MarginsData - return resp, d.SendWSRequest(nonMatchingEPL, getMargins, input, &resp, true) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, getMargins, input, &resp, true) } // WSRetrieveMMPConfig sends a request to fetch the config for MMP of the requested currency through the websocket connection. -func (d *Deribit) WSRetrieveMMPConfig(ccy currency.Code) (*MMPConfigData, error) { +func (d *Deribit) WSRetrieveMMPConfig(ctx context.Context, ccy currency.Code) (*MMPConfigData, error) { if ccy.IsEmpty() { return nil, currency.ErrCurrencyCodeEmpty } var resp *MMPConfigData - return resp, d.SendWSRequest(nonMatchingEPL, getMMPConfig, map[string]currency.Code{"currency": ccy}, &resp, true) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, getMMPConfig, map[string]currency.Code{"currency": ccy}, &resp, true) } // WSRetrieveOpenOrdersByCurrency retrieves open order by symbol and kind -func (d *Deribit) WSRetrieveOpenOrdersByCurrency(ccy currency.Code, kind, orderType string) ([]OrderData, error) { +func (d *Deribit) WSRetrieveOpenOrdersByCurrency(ctx context.Context, ccy currency.Code, kind, orderType string) ([]OrderData, error) { if ccy.IsEmpty() { return nil, currency.ErrCurrencyCodeEmpty } @@ -1530,11 +1530,11 @@ func (d *Deribit) WSRetrieveOpenOrdersByCurrency(ccy currency.Code, kind, orderT OrderType: orderType, } var resp []OrderData - return resp, d.SendWSRequest(nonMatchingEPL, getOpenOrdersByCurrency, input, &resp, true) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, getOpenOrdersByCurrency, input, &resp, true) } // WSRetrieveOpenOrdersByLabel retrieves open order by label and currency -func (d *Deribit) WSRetrieveOpenOrdersByLabel(ccy currency.Code, label string) ([]OrderData, error) { +func (d *Deribit) WSRetrieveOpenOrdersByLabel(ctx context.Context, ccy currency.Code, label string) ([]OrderData, error) { if ccy.IsEmpty() { return nil, currency.ErrCurrencyCodeEmpty } @@ -1546,11 +1546,11 @@ func (d *Deribit) WSRetrieveOpenOrdersByLabel(ccy currency.Code, label string) ( Label: label, } var resp []OrderData - return resp, d.SendWSRequest(nonMatchingEPL, getOpenOrdersByLabel, input, &resp, true) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, getOpenOrdersByLabel, input, &resp, true) } // WSRetrieveOpenOrdersByInstrument sends a request to fetch open orders data sorted by requested params through the websocket connection. -func (d *Deribit) WSRetrieveOpenOrdersByInstrument(instrument, orderType string) ([]OrderData, error) { +func (d *Deribit) WSRetrieveOpenOrdersByInstrument(ctx context.Context, instrument, orderType string) ([]OrderData, error) { if instrument == "" { return nil, errInvalidInstrumentName } @@ -1562,11 +1562,11 @@ func (d *Deribit) WSRetrieveOpenOrdersByInstrument(instrument, orderType string) Type: orderType, } var resp []OrderData - return resp, d.SendWSRequest(nonMatchingEPL, getOpenOrdersByInstrument, input, &resp, true) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, getOpenOrdersByInstrument, input, &resp, true) } // WSRetrieveOrderHistoryByCurrency sends a request to fetch order history according to given params and currency through the websocket connection. -func (d *Deribit) WSRetrieveOrderHistoryByCurrency(ccy currency.Code, kind string, count, offset int64, includeOld, includeUnfilled bool) ([]OrderData, error) { +func (d *Deribit) WSRetrieveOrderHistoryByCurrency(ctx context.Context, ccy currency.Code, kind string, count, offset int64, includeOld, includeUnfilled bool) ([]OrderData, error) { if ccy.IsEmpty() { return nil, currency.ErrCurrencyCodeEmpty } @@ -1586,11 +1586,11 @@ func (d *Deribit) WSRetrieveOrderHistoryByCurrency(ccy currency.Code, kind strin IncludeUnfilled: includeUnfilled, } var resp []OrderData - return resp, d.SendWSRequest(nonMatchingEPL, getOrderHistoryByCurrency, input, &resp, true) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, getOrderHistoryByCurrency, input, &resp, true) } // WSRetrieveOrderHistoryByInstrument sends a request to fetch order history according to given params and instrument through the websocket connection. -func (d *Deribit) WSRetrieveOrderHistoryByInstrument(instrument string, count, offset int64, includeOld, includeUnfilled bool) ([]OrderData, error) { +func (d *Deribit) WSRetrieveOrderHistoryByInstrument(ctx context.Context, instrument string, count, offset int64, includeOld, includeUnfilled bool) ([]OrderData, error) { if instrument == "" { return nil, errInvalidInstrumentName } @@ -1608,29 +1608,29 @@ func (d *Deribit) WSRetrieveOrderHistoryByInstrument(instrument string, count, o IncludeUnfilled: includeUnfilled, } var resp []OrderData - return resp, d.SendWSRequest(nonMatchingEPL, getOrderHistoryByInstrument, input, &resp, true) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, getOrderHistoryByInstrument, input, &resp, true) } // WSRetrieveOrderMarginsByID sends a request to fetch order margins data according to their ids through the websocket connection. -func (d *Deribit) WSRetrieveOrderMarginsByID(ids []string) ([]OrderData, error) { +func (d *Deribit) WSRetrieveOrderMarginsByID(ctx context.Context, ids []string) ([]OrderData, error) { if len(ids) == 0 { return nil, fmt.Errorf("%w, order ids cannot be empty", errInvalidID) } var resp []OrderData - return resp, d.SendWSRequest(nonMatchingEPL, getOrderMarginByIDs, map[string][]string{"ids": ids}, &resp, true) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, getOrderMarginByIDs, map[string][]string{"ids": ids}, &resp, true) } // WSRetrievesOrderState sends a request to fetch order state of the order id provided -func (d *Deribit) WSRetrievesOrderState(orderID string) (*OrderData, error) { +func (d *Deribit) WSRetrievesOrderState(ctx context.Context, orderID string) (*OrderData, error) { if orderID == "" { return nil, fmt.Errorf("%w, no order ID specified", errInvalidID) } var resp *OrderData - return resp, d.SendWSRequest(nonMatchingEPL, getOrderState, map[string]string{"order_id": orderID}, &resp, true) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, getOrderState, map[string]string{"order_id": orderID}, &resp, true) } // WsRetrieveOrderStateByLabel retrieves an order state by label and currency -func (d *Deribit) WsRetrieveOrderStateByLabel(ccy currency.Code, label string) ([]OrderData, error) { +func (d *Deribit) WsRetrieveOrderStateByLabel(ctx context.Context, ccy currency.Code, label string) ([]OrderData, error) { if ccy.IsEmpty() { return nil, currency.ErrCurrencyCodeEmpty } @@ -1642,11 +1642,11 @@ func (d *Deribit) WsRetrieveOrderStateByLabel(ccy currency.Code, label string) ( Label: label, } var resp []OrderData - return resp, d.SendWSRequest(nonMatchingEPL, getOrderStateByLabel, input, &resp, true) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, getOrderStateByLabel, input, &resp, true) } // WSRetrieveTriggerOrderHistory sends a request to fetch order state of the order id provided through the websocket connection. -func (d *Deribit) WSRetrieveTriggerOrderHistory(ccy currency.Code, instrumentName, continuation string, count int64) (*OrderData, error) { +func (d *Deribit) WSRetrieveTriggerOrderHistory(ctx context.Context, ccy currency.Code, instrumentName, continuation string, count int64) (*OrderData, error) { if ccy.IsEmpty() { return nil, currency.ErrCurrencyCodeEmpty } @@ -1662,11 +1662,11 @@ func (d *Deribit) WSRetrieveTriggerOrderHistory(ccy currency.Code, instrumentNam Count: count, } var resp *OrderData - return resp, d.SendWSRequest(nonMatchingEPL, getTriggerOrderHistory, input, &resp, true) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, getTriggerOrderHistory, input, &resp, true) } // WSRetrieveUserTradesByCurrency sends a request to fetch user trades sorted by currency through the websocket connection. -func (d *Deribit) WSRetrieveUserTradesByCurrency(ccy currency.Code, kind, startID, endID, sorting string, count int64, includeOld bool) (*UserTradesData, error) { +func (d *Deribit) WSRetrieveUserTradesByCurrency(ctx context.Context, ccy currency.Code, kind, startID, endID, sorting string, count int64, includeOld bool) (*UserTradesData, error) { if ccy.IsEmpty() { return nil, currency.ErrCurrencyCodeEmpty } @@ -1688,11 +1688,11 @@ func (d *Deribit) WSRetrieveUserTradesByCurrency(ccy currency.Code, kind, startI IncludeOld: includeOld, } var resp *UserTradesData - return resp, d.SendWSRequest(nonMatchingEPL, getUserTradesByCurrency, input, &resp, true) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, getUserTradesByCurrency, input, &resp, true) } // WSRetrieveUserTradesByCurrencyAndTime retrieves user trades sorted by currency and time through the websocket connection. -func (d *Deribit) WSRetrieveUserTradesByCurrencyAndTime(ccy currency.Code, kind, sorting string, count int64, startTime, endTime time.Time) (*UserTradesData, error) { +func (d *Deribit) WSRetrieveUserTradesByCurrencyAndTime(ctx context.Context, ccy currency.Code, kind, sorting string, count int64, startTime, endTime time.Time) (*UserTradesData, error) { if ccy.IsEmpty() { return nil, currency.ErrCurrencyCodeEmpty } @@ -1716,11 +1716,11 @@ func (d *Deribit) WSRetrieveUserTradesByCurrencyAndTime(ccy currency.Code, kind, input.EndTime = endTime.UnixMilli() } var resp *UserTradesData - return resp, d.SendWSRequest(nonMatchingEPL, getUserTradesByCurrencyAndTime, input, &resp, true) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, getUserTradesByCurrencyAndTime, input, &resp, true) } // WsRetrieveUserTradesByInstrument retrieves user trades sorted by instrument through the websocket connection. -func (d *Deribit) WsRetrieveUserTradesByInstrument(instrument, sorting string, startSeq, endSeq, count int64, includeOld bool) (*UserTradesData, error) { +func (d *Deribit) WsRetrieveUserTradesByInstrument(ctx context.Context, instrument, sorting string, startSeq, endSeq, count int64, includeOld bool) (*UserTradesData, error) { if instrument == "" { return nil, errInvalidInstrumentName } @@ -1740,11 +1740,11 @@ func (d *Deribit) WsRetrieveUserTradesByInstrument(instrument, sorting string, s IncludeOld: includeOld, } var resp *UserTradesData - return resp, d.SendWSRequest(nonMatchingEPL, getUserTradesByInstrument, input, &resp, true) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, getUserTradesByInstrument, input, &resp, true) } // WSRetrieveUserTradesByInstrumentAndTime retrieves user trades sorted by instrument and time through the websocket connection. -func (d *Deribit) WSRetrieveUserTradesByInstrumentAndTime(instrument, sorting string, count int64, includeOld bool, startTime, endTime time.Time) (*UserTradesData, error) { +func (d *Deribit) WSRetrieveUserTradesByInstrumentAndTime(ctx context.Context, instrument, sorting string, count int64, includeOld bool, startTime, endTime time.Time) (*UserTradesData, error) { if instrument == "" { return nil, errInvalidInstrumentName } @@ -1767,11 +1767,11 @@ func (d *Deribit) WSRetrieveUserTradesByInstrumentAndTime(instrument, sorting st IncludeOld: includeOld, } var resp *UserTradesData - return resp, d.SendWSRequest(nonMatchingEPL, getUserTradesByInstrumentAndTime, input, &resp, true) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, getUserTradesByInstrumentAndTime, input, &resp, true) } // WSRetrieveUserTradesByOrder retrieves user trades fetched by orderID through the web socket connection. -func (d *Deribit) WSRetrieveUserTradesByOrder(orderID, sorting string) (*UserTradesData, error) { +func (d *Deribit) WSRetrieveUserTradesByOrder(ctx context.Context, orderID, sorting string) (*UserTradesData, error) { if orderID == "" { return nil, fmt.Errorf("%w, no order ID specified", errInvalidID) } @@ -1783,16 +1783,16 @@ func (d *Deribit) WSRetrieveUserTradesByOrder(orderID, sorting string) (*UserTra Sorting: sorting, } var resp *UserTradesData - return resp, d.SendWSRequest(nonMatchingEPL, getUserTradesByOrder, input, &resp, true) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, getUserTradesByOrder, input, &resp, true) } // WSResetMMP sends a request to reset MMP for a currency provided through the websocket connection. -func (d *Deribit) WSResetMMP(ccy currency.Code) error { +func (d *Deribit) WSResetMMP(ctx context.Context, ccy currency.Code) error { if ccy.IsEmpty() { return currency.ErrCurrencyCodeEmpty } var resp string - err := d.SendWSRequest(nonMatchingEPL, resetMMP, map[string]currency.Code{"currency": ccy}, &resp, true) + err := d.SendWSRequest(ctx, nonMatchingEPL, resetMMP, map[string]currency.Code{"currency": ccy}, &resp, true) if err != nil { return err } @@ -1803,7 +1803,7 @@ func (d *Deribit) WSResetMMP(ccy currency.Code) error { } // WSSendRequestForQuote sends RFQ on a given instrument through the websocket connection. -func (d *Deribit) WSSendRequestForQuote(instrumentName string, amount float64, side order.Side) error { +func (d *Deribit) WSSendRequestForQuote(ctx context.Context, instrumentName string, amount float64, side order.Side) error { if instrumentName == "" { return errInvalidInstrumentName } @@ -1817,7 +1817,7 @@ func (d *Deribit) WSSendRequestForQuote(instrumentName string, amount float64, s Side: side.String(), } var resp string - err := d.SendWSRequest(nonMatchingEPL, sendRFQ, input, &resp, true) + err := d.SendWSRequest(ctx, nonMatchingEPL, sendRFQ, input, &resp, true) if err != nil { return err } @@ -1828,7 +1828,7 @@ func (d *Deribit) WSSendRequestForQuote(instrumentName string, amount float64, s } // WSSetMMPConfig sends a request to set the given parameter values to the mmp config for the provided currency through the websocket connection. -func (d *Deribit) WSSetMMPConfig(ccy currency.Code, interval kline.Interval, frozenTime int64, quantityLimit, deltaLimit float64) error { +func (d *Deribit) WSSetMMPConfig(ctx context.Context, ccy currency.Code, interval kline.Interval, frozenTime int64, quantityLimit, deltaLimit float64) error { if ccy.IsEmpty() { return currency.ErrCurrencyCodeEmpty } @@ -1847,7 +1847,7 @@ func (d *Deribit) WSSetMMPConfig(ccy currency.Code, interval kline.Interval, fro params["delta_limit"] = deltaLimit } var resp string - err = d.SendWSRequest(nonMatchingEPL, setMMPConfig, params, &resp, true) + err = d.SendWSRequest(ctx, nonMatchingEPL, setMMPConfig, params, &resp, true) if err != nil { return err } @@ -1858,7 +1858,7 @@ func (d *Deribit) WSSetMMPConfig(ccy currency.Code, interval kline.Interval, fro } // WSRetrieveSettlementHistoryByInstrument sends a request to fetch settlement history data sorted by instrument through the websocket connection. -func (d *Deribit) WSRetrieveSettlementHistoryByInstrument(instrument, settlementType, continuation string, count int64, searchStartTimeStamp time.Time) (*PrivateSettlementsHistoryData, error) { +func (d *Deribit) WSRetrieveSettlementHistoryByInstrument(ctx context.Context, instrument, settlementType, continuation string, count int64, searchStartTimeStamp time.Time) (*PrivateSettlementsHistoryData, error) { if instrument == "" { return nil, errInvalidInstrumentName } @@ -1878,11 +1878,11 @@ func (d *Deribit) WSRetrieveSettlementHistoryByInstrument(instrument, settlement input.SearchStartTimestamp = searchStartTimeStamp.UnixMilli() } var resp *PrivateSettlementsHistoryData - return resp, d.SendWSRequest(nonMatchingEPL, getSettlementHistoryByInstrument, input, &resp, true) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, getSettlementHistoryByInstrument, input, &resp, true) } // WSRetrieveSettlementHistoryByCurency sends a request to fetch settlement history data sorted by currency through the websocket connection. -func (d *Deribit) WSRetrieveSettlementHistoryByCurency(ccy currency.Code, settlementType, continuation string, count int64, searchStartTimeStamp time.Time) (*PrivateSettlementsHistoryData, error) { +func (d *Deribit) WSRetrieveSettlementHistoryByCurency(ctx context.Context, ccy currency.Code, settlementType, continuation string, count int64, searchStartTimeStamp time.Time) (*PrivateSettlementsHistoryData, error) { if ccy.IsEmpty() { return nil, currency.ErrCurrencyCodeEmpty } @@ -1902,12 +1902,12 @@ func (d *Deribit) WSRetrieveSettlementHistoryByCurency(ccy currency.Code, settle input.SearchStartTimestamp = searchStartTimeStamp.UnixMilli() } var resp *PrivateSettlementsHistoryData - return resp, d.SendWSRequest(nonMatchingEPL, getSettlementHistoryByCurrency, input, &resp, true) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, getSettlementHistoryByCurrency, input, &resp, true) } // WSRetrieveComboIDs Retrieves available combos. // This method can be used to get the list of all combos, or only the list of combos in the given state. -func (d *Deribit) WSRetrieveComboIDs(ccy currency.Code, state string) ([]string, error) { +func (d *Deribit) WSRetrieveComboIDs(ctx context.Context, ccy currency.Code, state string) ([]string, error) { if ccy.IsEmpty() { return nil, currency.ErrCurrencyCodeEmpty } @@ -1919,29 +1919,29 @@ func (d *Deribit) WSRetrieveComboIDs(ccy currency.Code, state string) ([]string, State: state, } var resp []string - return resp, d.SendWSRequest(nonMatchingEPL, getComboIDs, input, &resp, false) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, getComboIDs, input, &resp, false) } // WSRetrieveComboDetails retrieves information about a combo through the websocket connection. -func (d *Deribit) WSRetrieveComboDetails(comboID string) (*ComboDetail, error) { +func (d *Deribit) WSRetrieveComboDetails(ctx context.Context, comboID string) (*ComboDetail, error) { if comboID == "" { return nil, errInvalidComboID } var resp *ComboDetail - return resp, d.SendWSRequest(nonMatchingEPL, getComboDetails, map[string]string{"combo_id": comboID}, &resp, false) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, getComboDetails, map[string]string{"combo_id": comboID}, &resp, false) } // WSRetrieveCombos retrieves information about active combos through the websocket connection. -func (d *Deribit) WSRetrieveCombos(ccy currency.Code) ([]ComboDetail, error) { +func (d *Deribit) WSRetrieveCombos(ctx context.Context, ccy currency.Code) ([]ComboDetail, error) { if ccy.IsEmpty() { return nil, currency.ErrCurrencyCodeEmpty } var resp []ComboDetail - return resp, d.SendWSRequest(nonMatchingEPL, getCombos, map[string]currency.Code{"currency": ccy}, &resp, false) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, getCombos, map[string]currency.Code{"currency": ccy}, &resp, false) } // WSCreateCombo verifies and creates a combo book or returns an existing combo matching given trades through the websocket connection. -func (d *Deribit) WSCreateCombo(args []ComboParam) (*ComboDetail, error) { +func (d *Deribit) WSCreateCombo(ctx context.Context, args []ComboParam) (*ComboDetail, error) { if len(args) == 0 { return nil, errNoArgumentPassed } @@ -1958,47 +1958,47 @@ func (d *Deribit) WSCreateCombo(args []ComboParam) (*ComboDetail, error) { } } var resp *ComboDetail - return resp, d.SendWSRequest(nonMatchingEPL, createCombos, map[string]any{"trades": args}, &resp, true) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, createCombos, map[string]any{"trades": args}, &resp, true) } // WsLogout gracefully close websocket connection, when COD (Cancel On Disconnect) is enabled orders are not cancelled -func (d *Deribit) WsLogout(invalidateToken bool) error { +func (d *Deribit) WsLogout(ctx context.Context, invalidateToken bool) error { input := struct { InvalidateToken bool `json:"invalidate_token,omitempty"` }{ InvalidateToken: invalidateToken, } - return d.SendWSRequest(nonMatchingEPL, "private/logout", input, &struct{}{}, true) + return d.SendWSRequest(ctx, nonMatchingEPL, "private/logout", input, &struct{}{}, true) } // WsEnableCancelOnDisconnect enable Cancel On Disconnect for the connection. // After enabling Cancel On Disconnect all orders created by the connection will be removed when the connection is closed. -func (d *Deribit) WsEnableCancelOnDisconnect(scope string) (string, error) { +func (d *Deribit) WsEnableCancelOnDisconnect(ctx context.Context, scope string) (string, error) { input := &struct { Scope string `json:"scope,omitempty"` }{ Scope: scope, } var resp string - return resp, d.SendWSRequest(nonMatchingEPL, "private/enable_cancel_on_disconnect", input, &resp, true) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, "private/enable_cancel_on_disconnect", input, &resp, true) } // WsDisableCancelOnDisconnect isable Cancel On Disconnect for the connection. // When change is applied for the account, then every newly opened connection will start with inactive Cancel on Disconnect. // scope: possible values are 'connection', 'account' -func (d *Deribit) WsDisableCancelOnDisconnect(scope string) (string, error) { +func (d *Deribit) WsDisableCancelOnDisconnect(ctx context.Context, scope string) (string, error) { input := &struct { Scope string `json:"scope,omitempty"` }{ Scope: scope, } var resp string - return resp, d.SendWSRequest(nonMatchingEPL, "private/disable_cancel_on_disconnect", input, &resp, true) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, "private/disable_cancel_on_disconnect", input, &resp, true) } // SayHello method used to introduce the client software connected to Deribit platform over websocket. // It returns version information -func (d *Deribit) SayHello(clientName, clientVersion string) (*Info, error) { +func (d *Deribit) SayHello(ctx context.Context, clientName, clientVersion string) (*Info, error) { if clientName == "" { return nil, errors.New("client name is required") } @@ -2010,24 +2010,24 @@ func (d *Deribit) SayHello(clientName, clientVersion string) (*Info, error) { ClientVersion: clientVersion, } var resp *Info - return resp, d.SendWSRequest(nonMatchingEPL, "public/hello", input, &resp, false) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, "public/hello", input, &resp, false) } // WsRetrieveCancelOnDisconnect read current Cancel On Disconnect configuration for the account. // 'scope': Specifies if Cancel On Disconnect change should be applied/checked for the current connection or the account (default - connection) // Scope connection can be used only when working via Websocket. -func (d *Deribit) WsRetrieveCancelOnDisconnect(scope string) (*CancelOnDisconnect, error) { +func (d *Deribit) WsRetrieveCancelOnDisconnect(ctx context.Context, scope string) (*CancelOnDisconnect, error) { input := &struct { Scope string `json:"scope,omitempty"` }{ Scope: scope, } var resp *CancelOnDisconnect - return resp, d.SendWSRequest(nonMatchingEPL, "private/get_cancel_on_disconnect", input, &resp, true) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, "private/get_cancel_on_disconnect", input, &resp, true) } // WsExchangeToken generates a token for a new subject id. This method can be used to switch between subaccounts. -func (d *Deribit) WsExchangeToken(refreshToken string, subjectID int64) (*RefreshTokenInfo, error) { +func (d *Deribit) WsExchangeToken(ctx context.Context, refreshToken string, subjectID int64) (*RefreshTokenInfo, error) { if refreshToken == "" { return nil, errRefreshTokenRequired } @@ -2042,11 +2042,11 @@ func (d *Deribit) WsExchangeToken(refreshToken string, subjectID int64) (*Refres SubjectID: subjectID, } var resp *RefreshTokenInfo - return resp, d.SendWSRequest(nonMatchingEPL, "public/exchange_token", input, &resp, true) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, "public/exchange_token", input, &resp, true) } // WsForkToken generates a token for a new named session. This method can be used only with session scoped tokens. -func (d *Deribit) WsForkToken(refreshToken, sessionName string) (*RefreshTokenInfo, error) { +func (d *Deribit) WsForkToken(ctx context.Context, refreshToken, sessionName string) (*RefreshTokenInfo, error) { if refreshToken == "" { return nil, errRefreshTokenRequired } @@ -2061,19 +2061,19 @@ func (d *Deribit) WsForkToken(refreshToken, sessionName string) (*RefreshTokenIn SessionName: sessionName, } var resp *RefreshTokenInfo - return resp, d.SendWSRequest(nonMatchingEPL, "public/fork_token", input, &resp, true) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, "public/fork_token", input, &resp, true) } // UnsubscribeAll unsubscribe from all the public channels subscribed so far. -func (d *Deribit) UnsubscribeAll() (string, error) { +func (d *Deribit) UnsubscribeAll(ctx context.Context) (string, error) { var resp string - return resp, d.SendWSRequest(nonMatchingEPL, "public/unsubscribe_all", nil, &resp, false) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, "public/unsubscribe_all", nil, &resp, false) } // UnsubscribeAllPrivateChannels sends an unsubscribe request to cancel all private channels subscriptions -func (d *Deribit) UnsubscribeAllPrivateChannels() (string, error) { +func (d *Deribit) UnsubscribeAllPrivateChannels(ctx context.Context) (string, error) { var resp string - return resp, d.SendWSRequest(nonMatchingEPL, "private/unsubscribe_all", nil, &resp, false) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, "private/unsubscribe_all", nil, &resp, false) } // ------------------------------------------------------------------------------------------------ @@ -2081,7 +2081,7 @@ func (d *Deribit) UnsubscribeAllPrivateChannels() (string, error) { // WSExecuteBlockTrade executes a block trade request // The whole request have to be exact the same as in private/verify_block_trade, only role field should be set appropriately - it basically means that both sides have to agree on the same timestamp, nonce, trades fields and server will assure that role field is different between sides (each party accepted own role). // Using the same timestamp and nonce by both sides in private/verify_block_trade assures that even if unintentionally both sides execute given block trade with valid counterparty_signature, the given block trade will be executed only once -func (d *Deribit) WSExecuteBlockTrade(timestampMS time.Time, nonce, role string, ccy currency.Code, trades []BlockTradeParam) ([]BlockTradeResponse, error) { +func (d *Deribit) WSExecuteBlockTrade(ctx context.Context, timestampMS time.Time, nonce, role string, ccy currency.Code, trades []BlockTradeParam) ([]BlockTradeResponse, error) { if nonce == "" { return nil, errMissingNonce } @@ -2106,7 +2106,7 @@ func (d *Deribit) WSExecuteBlockTrade(timestampMS time.Time, nonce, role string, return nil, fmt.Errorf("%w, trade price can't be negative", errInvalidPrice) } } - signature, err := d.WSVerifyBlockTrade(timestampMS, nonce, role, ccy, trades) + signature, err := d.WSVerifyBlockTrade(ctx, timestampMS, nonce, role, ccy, trades) if err != nil { return nil, err } @@ -2126,11 +2126,11 @@ func (d *Deribit) WSExecuteBlockTrade(timestampMS time.Time, nonce, role string, Currency: ccy.String(), } var resp []BlockTradeResponse - return resp, d.SendWSRequest(matchingEPL, executeBlockTrades, input, &resp, true) + return resp, d.SendWSRequest(ctx, matchingEPL, executeBlockTrades, input, &resp, true) } // WSVerifyBlockTrade verifies and creates block trade signature through the websocket connection. -func (d *Deribit) WSVerifyBlockTrade(timestampMS time.Time, nonce, role string, ccy currency.Code, trades []BlockTradeParam) (string, error) { +func (d *Deribit) WSVerifyBlockTrade(ctx context.Context, timestampMS time.Time, nonce, role string, ccy currency.Code, trades []BlockTradeParam) (string, error) { if nonce == "" { return "", errMissingNonce } @@ -2175,18 +2175,18 @@ func (d *Deribit) WSVerifyBlockTrade(timestampMS time.Time, nonce, role string, resp := &struct { Signature string `json:"signature"` }{} - return resp.Signature, d.SendWSRequest(matchingEPL, verifyBlockTrades, input, &resp, true) + return resp.Signature, d.SendWSRequest(ctx, matchingEPL, verifyBlockTrades, input, &resp, true) } // WsInvalidateBlockTradeSignature user at any time (before the private/execute_block_trade is called) can invalidate its own signature effectively cancelling block trade through the websocket connection. -func (d *Deribit) WsInvalidateBlockTradeSignature(signature string) error { +func (d *Deribit) WsInvalidateBlockTradeSignature(ctx context.Context, signature string) error { if signature == "" { return errMissingSignature } params := url.Values{} params.Set("signature", signature) var resp string - err := d.SendWSRequest(nonMatchingEPL, invalidateBlockTradesSignature, params, &resp, true) + err := d.SendWSRequest(ctx, nonMatchingEPL, invalidateBlockTradesSignature, params, &resp, true) if err != nil { return err } @@ -2197,16 +2197,16 @@ func (d *Deribit) WsInvalidateBlockTradeSignature(signature string) error { } // WSRetrieveUserBlockTrade returns information about users block trade through the websocket connection. -func (d *Deribit) WSRetrieveUserBlockTrade(id string) ([]BlockTradeData, error) { +func (d *Deribit) WSRetrieveUserBlockTrade(ctx context.Context, id string) ([]BlockTradeData, error) { if id == "" { return nil, errMissingBlockTradeID } var resp []BlockTradeData - return resp, d.SendWSRequest(nonMatchingEPL, getBlockTrades, map[string]string{"id": id}, &resp, true) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, getBlockTrades, map[string]string{"id": id}, &resp, true) } // WSRetrieveLastBlockTradesByCurrency returns list of last users block trades through the websocket connection. -func (d *Deribit) WSRetrieveLastBlockTradesByCurrency(ccy currency.Code, startID, endID string, count int64) ([]BlockTradeData, error) { +func (d *Deribit) WSRetrieveLastBlockTradesByCurrency(ctx context.Context, ccy currency.Code, startID, endID string, count int64) ([]BlockTradeData, error) { if ccy.IsEmpty() { return nil, currency.ErrCurrencyCodeEmpty } @@ -2222,11 +2222,11 @@ func (d *Deribit) WSRetrieveLastBlockTradesByCurrency(ccy currency.Code, startID Count: count, } var resp []BlockTradeData - return resp, d.SendWSRequest(nonMatchingEPL, getLastBlockTradesByCurrency, input, &resp, true) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, getLastBlockTradesByCurrency, input, &resp, true) } // WSMovePositions moves positions from source subaccount to target subaccount through the websocket connection. -func (d *Deribit) WSMovePositions(ccy currency.Code, sourceSubAccountUID, targetSubAccountUID int64, trades []BlockTradeParam) ([]BlockTradeMoveResponse, error) { +func (d *Deribit) WSMovePositions(ctx context.Context, ccy currency.Code, sourceSubAccountUID, targetSubAccountUID int64, trades []BlockTradeParam) ([]BlockTradeMoveResponse, error) { if ccy.IsEmpty() { return nil, currency.ErrCurrencyCodeEmpty } @@ -2259,11 +2259,11 @@ func (d *Deribit) WSMovePositions(ccy currency.Code, sourceSubAccountUID, target SourceUID: sourceSubAccountUID, } var resp []BlockTradeMoveResponse - return resp, d.SendWSRequest(nonMatchingEPL, movePositions, input, &resp, true) + return resp, d.SendWSRequest(ctx, nonMatchingEPL, movePositions, input, &resp, true) } // WsSimulateBlockTrade checks if a block trade can be executed through the websocket -func (d *Deribit) WsSimulateBlockTrade(role string, trades []BlockTradeParam) (bool, error) { +func (d *Deribit) WsSimulateBlockTrade(ctx context.Context, role string, trades []BlockTradeParam) (bool, error) { if role != roleMaker && role != roleTaker { return false, errInvalidTradeRole } @@ -2293,12 +2293,12 @@ func (d *Deribit) WsSimulateBlockTrade(role string, trades []BlockTradeParam) (b Trades: trades, } var resp bool - return resp, d.SendWSRequest(matchingEPL, simulateBlockPosition, input, resp, true) + return resp, d.SendWSRequest(ctx, matchingEPL, simulateBlockPosition, input, resp, true) } // SendWSRequest sends a request through the websocket connection. // both authenticated and public endpoints are allowed. -func (d *Deribit) SendWSRequest(epl request.EndpointLimit, method string, params, response any, authenticated bool) error { +func (d *Deribit) SendWSRequest(ctx context.Context, epl request.EndpointLimit, method string, params, response any, authenticated bool) error { if authenticated && !d.Websocket.CanUseAuthenticatedEndpoints() { return errWebsocketConnectionNotAuthenticated } @@ -2309,7 +2309,7 @@ func (d *Deribit) SendWSRequest(epl request.EndpointLimit, method string, params Params: params, } resp := &wsResponse{Result: response} - err := d.sendWsPayload(epl, input, resp) + err := d.sendWsPayload(ctx, epl, input, resp) if err != nil { return err } @@ -2327,12 +2327,13 @@ func (d *Deribit) SendWSRequest(epl request.EndpointLimit, method string, params } // sendWsPayload handles sending Websocket requests -func (d *Deribit) sendWsPayload(ep request.EndpointLimit, input *WsRequest, response *wsResponse) error { +// TODO: Refactor to use rate limiting system +func (d *Deribit) sendWsPayload(ctx context.Context, ep request.EndpointLimit, input *WsRequest, response *wsResponse) error { if input == nil { return fmt.Errorf("%w, input can not be ", common.ErrNilPointer) } deadline := time.Now().Add(websocketRequestTimeout) - ctx, cancelFunc := context.WithDeadline(context.Background(), deadline) + ctx, cancelFunc := context.WithDeadline(ctx, deadline) defer func() { if time.Now().After(deadline) { cancelFunc() @@ -2349,7 +2350,7 @@ func (d *Deribit) sendWsPayload(ep request.EndpointLimit, input *WsRequest, resp log.Debugf(log.RequestSys, "%s attempt %d", d.Name, attempt) } var payload []byte - payload, err = d.Websocket.Conn.SendMessageReturnResponse(context.TODO(), request.Unset, input.ID, input) + payload, err = d.Websocket.Conn.SendMessageReturnResponse(ctx, request.Unset, input.ID, input) if err != nil { return err } diff --git a/exchanges/exchange.go b/exchanges/exchange.go index 728c3fc5..396c9448 100644 --- a/exchanges/exchange.go +++ b/exchanges/exchange.go @@ -1773,7 +1773,7 @@ func (b *Base) GetOpenInterest(context.Context, ...key.PairAsset) ([]futures.Ope } // ParallelChanOp performs a single method call in parallel across streams and waits to return any errors -func (b *Base) ParallelChanOp(channels subscription.List, m func(subscription.List) error, batchSize int) error { +func (b *Base) ParallelChanOp(ctx context.Context, channels subscription.List, m func(context.Context, subscription.List) error, batchSize int) error { wg := sync.WaitGroup{} errC := make(chan error, len(channels)) @@ -1781,7 +1781,7 @@ func (b *Base) ParallelChanOp(channels subscription.List, m func(subscription.Li wg.Add(1) go func(c subscription.List) { defer wg.Done() - if err := m(c); err != nil { + if err := m(ctx, c); err != nil { errC <- err } }(b) diff --git a/exchanges/exchange_test.go b/exchanges/exchange_test.go index 2dfc2bc2..e74fc473 100644 --- a/exchanges/exchange_test.go +++ b/exchanges/exchange_test.go @@ -2601,7 +2601,7 @@ func TestParallelChanOp(t *testing.T) { b := Base{} errC := make(chan error, 1) go func() { - errC <- b.ParallelChanOp(c, func(c subscription.List) error { + errC <- b.ParallelChanOp(t.Context(), c, func(_ context.Context, c subscription.List) error { time.Sleep(300 * time.Millisecond) run <- struct{}{} switch c[0].Channel { diff --git a/exchanges/gateio/gateio_test.go b/exchanges/gateio/gateio_test.go index b9218b71..f100878c 100644 --- a/exchanges/gateio/gateio_test.go +++ b/exchanges/gateio/gateio_test.go @@ -2089,8 +2089,7 @@ func TestFuturesDataHandler(t *testing.T) { t.Parallel() g := new(Gateio) //nolint:govet // Intentional shadow to avoid future copy/paste mistakes require.NoError(t, testexch.Setup(g), "Test instance Setup must not error") - testexch.FixtureToDataHandler(t, "testdata/wsFutures.json", func(m []byte) error { - ctx := t.Context() + testexch.FixtureToDataHandler(t, "testdata/wsFutures.json", func(ctx context.Context, m []byte) error { if strings.Contains(string(m), "futures.balances") { ctx = account.DeployCredentialsToContext(ctx, &account.Credentials{Key: "test", Secret: "test"}) } diff --git a/exchanges/gateio/gateio_websocket.go b/exchanges/gateio/gateio_websocket.go index e9afb4a4..0d108126 100644 --- a/exchanges/gateio/gateio_websocket.go +++ b/exchanges/gateio/gateio_websocket.go @@ -84,7 +84,7 @@ func (g *Gateio) WsConnectSpot(ctx context.Context, conn websocket.Connection) e if err != nil { return err } - err = conn.DialContext(ctx, &gws.Dialer{}, http.Header{}) + err = conn.Dial(ctx, &gws.Dialer{}, http.Header{}) if err != nil { return err } diff --git a/exchanges/gateio/gateio_websocket_delivery_futures.go b/exchanges/gateio/gateio_websocket_delivery_futures.go index 33227d29..7227b3b0 100644 --- a/exchanges/gateio/gateio_websocket_delivery_futures.go +++ b/exchanges/gateio/gateio_websocket_delivery_futures.go @@ -41,7 +41,7 @@ func (g *Gateio) WsDeliveryFuturesConnect(ctx context.Context, conn websocket.Co if err := g.CurrencyPairs.IsAssetEnabled(asset.DeliveryFutures); err != nil { return err } - if err := conn.DialContext(ctx, &gws.Dialer{}, http.Header{}); err != nil { + if err := conn.Dial(ctx, &gws.Dialer{}, http.Header{}); err != nil { return err } pingMessage, err := json.Marshal(WsInput{ @@ -64,7 +64,8 @@ func (g *Gateio) WsDeliveryFuturesConnect(ctx context.Context, conn websocket.Co // GenerateDeliveryFuturesDefaultSubscriptions returns delivery futures default subscriptions params. // TODO: Update to use the new subscription template system func (g *Gateio) GenerateDeliveryFuturesDefaultSubscriptions() (subscription.List, error) { - _, err := g.GetCredentials(context.Background()) + ctx := context.TODO() + _, err := g.GetCredentials(ctx) if err != nil { g.Websocket.SetCanUseAuthenticatedEndpoints(false) } diff --git a/exchanges/gateio/gateio_websocket_futures.go b/exchanges/gateio/gateio_websocket_futures.go index 601b40b6..67a539e8 100644 --- a/exchanges/gateio/gateio_websocket_futures.go +++ b/exchanges/gateio/gateio_websocket_futures.go @@ -65,7 +65,7 @@ func (g *Gateio) WsFuturesConnect(ctx context.Context, conn websocket.Connection if err := g.CurrencyPairs.IsAssetEnabled(a); err != nil { return err } - if err := conn.DialContext(ctx, &gws.Dialer{}, http.Header{}); err != nil { + if err := conn.Dial(ctx, &gws.Dialer{}, http.Header{}); err != nil { return err } pingMessage, err := json.Marshal(WsInput{ diff --git a/exchanges/gateio/gateio_websocket_option.go b/exchanges/gateio/gateio_websocket_option.go index 11f1f533..2b219a07 100644 --- a/exchanges/gateio/gateio_websocket_option.go +++ b/exchanges/gateio/gateio_websocket_option.go @@ -71,7 +71,7 @@ func (g *Gateio) WsOptionsConnect(ctx context.Context, conn websocket.Connection if err != nil { return err } - err = conn.DialContext(ctx, &gws.Dialer{}, http.Header{}) + err = conn.Dial(ctx, &gws.Dialer{}, http.Header{}) if err != nil { return err } @@ -95,16 +95,17 @@ func (g *Gateio) WsOptionsConnect(ctx context.Context, conn websocket.Connection // GenerateOptionsDefaultSubscriptions generates list of channel subscriptions for options asset type. // TODO: Update to use the new subscription template system func (g *Gateio) GenerateOptionsDefaultSubscriptions() (subscription.List, error) { + ctx := context.TODO() channelsToSubscribe := defaultOptionsSubscriptions var userID int64 if g.Websocket.CanUseAuthenticatedEndpoints() { var err error - _, err = g.GetCredentials(context.TODO()) + _, err = g.GetCredentials(ctx) if err != nil { g.Websocket.SetCanUseAuthenticatedEndpoints(false) goto getEnabledPairs } - response, err := g.GetSubAccountBalances(context.Background(), "") + response, err := g.GetSubAccountBalances(ctx, "") if err != nil { return nil, err } diff --git a/exchanges/gemini/gemini_websocket.go b/exchanges/gemini/gemini_websocket.go index d105c7b3..76803bd7 100644 --- a/exchanges/gemini/gemini_websocket.go +++ b/exchanges/gemini/gemini_websocket.go @@ -59,12 +59,13 @@ var comms = make(chan websocket.Response) // WsConnect initiates a websocket connection func (g *Gemini) WsConnect() error { + ctx := context.TODO() if !g.Websocket.IsEnabled() || !g.IsEnabled() { return websocket.ErrWebsocketNotEnabled } var dialer gws.Dialer - err := g.Websocket.Conn.Dial(&dialer, http.Header{}) + err := g.Websocket.Conn.Dial(ctx, &dialer, http.Header{}) if err != nil { return err } @@ -74,7 +75,7 @@ func (g *Gemini) WsConnect() error { go g.wsFunnelConnectionData(g.Websocket.Conn) if g.Websocket.CanUseAuthenticatedEndpoints() { - err := g.WsAuth(context.TODO(), &dialer) + err := g.WsAuth(ctx, &dialer) if err != nil { log.Errorf(log.ExchangeSys, "%v - websocket authentication failed: %v\n", g.Name, err) g.Websocket.SetCanUseAuthenticatedEndpoints(false) @@ -98,15 +99,17 @@ func (g *Gemini) GetSubscriptionTemplate(_ *subscription.Subscription) (*templat // Subscribe sends a websocket message to receive data from the channel func (g *Gemini) Subscribe(subs subscription.List) error { - return g.manageSubs(subs, wsSubscribeOp) + ctx := context.TODO() + return g.manageSubs(ctx, subs, wsSubscribeOp) } // Unsubscribe sends a websocket message to stop receiving data from the channel func (g *Gemini) Unsubscribe(subs subscription.List) error { - return g.manageSubs(subs, wsUnsubscribeOp) + ctx := context.TODO() + return g.manageSubs(ctx, subs, wsUnsubscribeOp) } -func (g *Gemini) manageSubs(subs subscription.List, op wsSubOp) error { +func (g *Gemini) manageSubs(ctx context.Context, subs subscription.List, op wsSubOp) error { req := wsSubscribeRequest{ Type: op, Subscriptions: make([]wsSubscriptions, 0, len(subs)), @@ -118,7 +121,7 @@ func (g *Gemini) manageSubs(subs subscription.List, op wsSubOp) error { }) } - if err := g.Websocket.Conn.SendJSONMessage(context.TODO(), request.Unset, req); err != nil { + if err := g.Websocket.Conn.SendJSONMessage(ctx, request.Unset, req); err != nil { return err } @@ -165,7 +168,7 @@ func (g *Gemini) WsAuth(ctx context.Context, dialer *gws.Dialer) error { headers.Add("X-GEMINI-SIGNATURE", hex.EncodeToString(hmac)) headers.Add("Cache-Control", "no-cache") - err = g.Websocket.AuthConn.Dial(dialer, headers) + err = g.Websocket.AuthConn.Dial(ctx, dialer, headers) if err != nil { return fmt.Errorf("%v Websocket connection %v error. Error %v", g.Name, endpoint, err) } diff --git a/exchanges/hitbtc/hitbtc_test.go b/exchanges/hitbtc/hitbtc_test.go index 211a813b..1367ccdf 100644 --- a/exchanges/hitbtc/hitbtc_test.go +++ b/exchanges/hitbtc/hitbtc_test.go @@ -445,7 +445,7 @@ func setupWsAuth(t *testing.T) { } var dialer gws.Dialer - err := h.Websocket.Conn.Dial(&dialer, http.Header{}) + err := h.Websocket.Conn.Dial(t.Context(), &dialer, http.Header{}) if err != nil { t.Fatal(err) } @@ -470,7 +470,7 @@ func TestWsCancelOrder(t *testing.T) { if !canManipulateRealOrders { t.Skip("canManipulateRealOrders false, skipping test") } - _, err := h.wsCancelOrder("ImNotARealOrderID") + _, err := h.wsCancelOrder(t.Context(), "ImNotARealOrderID") if err != nil { t.Fatal(err) } @@ -482,10 +482,7 @@ func TestWsPlaceOrder(t *testing.T) { if !canManipulateRealOrders { t.Skip("canManipulateRealOrders false, skipping test") } - _, err := h.wsPlaceOrder(currency.NewPair(currency.LTC, currency.BTC), - order.Buy.String(), - 1, - 1) + _, err := h.wsPlaceOrder(t.Context(), currency.NewPair(currency.LTC, currency.BTC), order.Buy.String(), 1, 1) if err != nil { t.Fatal(err) } @@ -497,7 +494,7 @@ func TestWsReplaceOrder(t *testing.T) { if !canManipulateRealOrders { t.Skip("canManipulateRealOrders false, skipping test") } - _, err := h.wsReplaceOrder("ImNotARealOrderID", 1, 1) + _, err := h.wsReplaceOrder(t.Context(), "ImNotARealOrderID", 1, 1) if err != nil { t.Fatal(err) } @@ -506,7 +503,7 @@ func TestWsReplaceOrder(t *testing.T) { // TestWsGetActiveOrders dials websocket, sends get active orders request. func TestWsGetActiveOrders(t *testing.T) { setupWsAuth(t) - if _, err := h.wsGetActiveOrders(); err != nil { + if _, err := h.wsGetActiveOrders(t.Context()); err != nil { t.Fatal(err) } } @@ -514,7 +511,7 @@ func TestWsGetActiveOrders(t *testing.T) { // TestWsGetTradingBalance dials websocket, sends get trading balance request. func TestWsGetTradingBalance(t *testing.T) { setupWsAuth(t) - if _, err := h.wsGetTradingBalance(); err != nil { + if _, err := h.wsGetTradingBalance(t.Context()); err != nil { t.Fatal(err) } } @@ -522,7 +519,7 @@ func TestWsGetTradingBalance(t *testing.T) { // TestWsGetTradingBalance dials websocket, sends get trading balance request. func TestWsGetTrades(t *testing.T) { setupWsAuth(t) - _, err := h.wsGetTrades(currency.NewPair(currency.ETH, currency.BTC), 1000, "ASC", "id") + _, err := h.wsGetTrades(t.Context(), currency.NewPair(currency.ETH, currency.BTC), 1000, "ASC", "id") if err != nil { t.Fatal(err) } @@ -531,7 +528,7 @@ func TestWsGetTrades(t *testing.T) { // TestWsGetTradingBalance dials websocket, sends get trading balance request. func TestWsGetSymbols(t *testing.T) { setupWsAuth(t) - _, err := h.wsGetSymbols(currency.NewPair(currency.ETH, currency.BTC)) + _, err := h.wsGetSymbols(t.Context(), currency.NewPair(currency.ETH, currency.BTC)) if err != nil { t.Fatal(err) } @@ -540,7 +537,7 @@ func TestWsGetSymbols(t *testing.T) { // TestWsGetCurrencies dials websocket, sends get trading balance request. func TestWsGetCurrencies(t *testing.T) { setupWsAuth(t) - _, err := h.wsGetCurrencies(currency.BTC) + _, err := h.wsGetCurrencies(t.Context(), currency.BTC) if err != nil { t.Fatal(err) } diff --git a/exchanges/hitbtc/hitbtc_websocket.go b/exchanges/hitbtc/hitbtc_websocket.go index d96df533..ee2ca1f7 100644 --- a/exchanges/hitbtc/hitbtc_websocket.go +++ b/exchanges/hitbtc/hitbtc_websocket.go @@ -53,11 +53,12 @@ var defaultSubscriptions = subscription.List{ // WsConnect starts a new connection with the websocket API func (h *HitBTC) WsConnect() error { + ctx := context.TODO() if !h.Websocket.IsEnabled() || !h.IsEnabled() { return websocket.ErrWebsocketNotEnabled } var dialer gws.Dialer - err := h.Websocket.Conn.Dial(&dialer, http.Header{}) + err := h.Websocket.Conn.Dial(ctx, &dialer, http.Header{}) if err != nil { return err } @@ -66,7 +67,7 @@ func (h *HitBTC) WsConnect() error { go h.wsReadData() if h.Websocket.CanUseAuthenticatedEndpoints() { - err = h.wsLogin(context.TODO()) + err = h.wsLogin(ctx) if err != nil { log.Errorf(log.ExchangeSys, "%v - authentication failed: %v\n", h.Name, err) } @@ -502,15 +503,17 @@ const ( // Subscribe sends a websocket message to receive data from the channel func (h *HitBTC) Subscribe(subs subscription.List) error { - return h.ParallelChanOp(subs, func(subs subscription.List) error { return h.manageSubs(subscribeOp, subs) }, 1) + ctx := context.TODO() + return h.ParallelChanOp(ctx, subs, func(ctx context.Context, subs subscription.List) error { return h.manageSubs(ctx, subscribeOp, subs) }, 1) } // Unsubscribe sends a websocket message to stop receiving data from the channel func (h *HitBTC) Unsubscribe(subs subscription.List) error { - return h.ParallelChanOp(subs, func(subs subscription.List) error { return h.manageSubs(unsubscribeOp, subs) }, 1) + ctx := context.TODO() + return h.ParallelChanOp(ctx, subs, func(ctx context.Context, subs subscription.List) error { return h.manageSubs(ctx, unsubscribeOp, subs) }, 1) } -func (h *HitBTC) manageSubs(op string, subs subscription.List) error { +func (h *HitBTC) manageSubs(ctx context.Context, op string, subs subscription.List) error { var errs error subs, errs = subs.ExpandTemplates(h) for _, s := range subs { @@ -523,7 +526,7 @@ func (h *HitBTC) manageSubs(op string, subs subscription.List) error { continue } r.Method = op + r.Method - err := h.Websocket.Conn.SendJSONMessage(context.TODO(), request.Unset, r) // v2 api does not return an ID with errors, so we don't use ReturnResponse + err := h.Websocket.Conn.SendJSONMessage(ctx, request.Unset, r) // v2 api does not return an ID with errors, so we don't use ReturnResponse if err == nil { if op == subscribeOp { err = h.Websocket.AddSuccessfulSubscriptions(h.Websocket.Conn, s) @@ -565,7 +568,7 @@ func (h *HitBTC) wsLogin(ctx context.Context) error { ID: h.Websocket.Conn.GenerateMessageID(false), } - err = h.Websocket.Conn.SendJSONMessage(context.TODO(), request.Unset, req) + err = h.Websocket.Conn.SendJSONMessage(ctx, request.Unset, req) if err != nil { h.Websocket.SetCanUseAuthenticatedEndpoints(false) return err @@ -575,7 +578,7 @@ func (h *HitBTC) wsLogin(ctx context.Context) error { } // wsPlaceOrder sends a websocket message to submit an order -func (h *HitBTC) wsPlaceOrder(pair currency.Pair, side string, price, quantity float64) (*WsSubmitOrderSuccessResponse, error) { +func (h *HitBTC) wsPlaceOrder(ctx context.Context, pair currency.Pair, side string, price, quantity float64) (*WsSubmitOrderSuccessResponse, error) { if !h.Websocket.CanUseAuthenticatedEndpoints() { return nil, fmt.Errorf("%v not authenticated, cannot place order", h.Name) } @@ -597,7 +600,7 @@ func (h *HitBTC) wsPlaceOrder(pair currency.Pair, side string, price, quantity f }, ID: id, } - resp, err := h.Websocket.Conn.SendMessageReturnResponse(context.TODO(), request.Unset, id, req) + resp, err := h.Websocket.Conn.SendMessageReturnResponse(ctx, request.Unset, id, req) if err != nil { return nil, fmt.Errorf("%v %v", h.Name, err) } @@ -613,7 +616,7 @@ func (h *HitBTC) wsPlaceOrder(pair currency.Pair, side string, price, quantity f } // wsCancelOrder sends a websocket message to cancel an order -func (h *HitBTC) wsCancelOrder(clientOrderID string) (*WsCancelOrderResponse, error) { +func (h *HitBTC) wsCancelOrder(ctx context.Context, clientOrderID string) (*WsCancelOrderResponse, error) { if !h.Websocket.CanUseAuthenticatedEndpoints() { return nil, fmt.Errorf("%v not authenticated, cannot place order", h.Name) } @@ -624,7 +627,7 @@ func (h *HitBTC) wsCancelOrder(clientOrderID string) (*WsCancelOrderResponse, er }, ID: h.Websocket.Conn.GenerateMessageID(false), } - resp, err := h.Websocket.Conn.SendMessageReturnResponse(context.TODO(), request.Unset, req.ID, req) + resp, err := h.Websocket.Conn.SendMessageReturnResponse(ctx, request.Unset, req.ID, req) if err != nil { return nil, fmt.Errorf("%v %v", h.Name, err) } @@ -640,7 +643,7 @@ func (h *HitBTC) wsCancelOrder(clientOrderID string) (*WsCancelOrderResponse, er } // wsReplaceOrder sends a websocket message to replace an order -func (h *HitBTC) wsReplaceOrder(clientOrderID string, quantity, price float64) (*WsReplaceOrderResponse, error) { +func (h *HitBTC) wsReplaceOrder(ctx context.Context, clientOrderID string, quantity, price float64) (*WsReplaceOrderResponse, error) { if !h.Websocket.CanUseAuthenticatedEndpoints() { return nil, fmt.Errorf("%v not authenticated, cannot place order", h.Name) } @@ -654,7 +657,7 @@ func (h *HitBTC) wsReplaceOrder(clientOrderID string, quantity, price float64) ( }, ID: h.Websocket.Conn.GenerateMessageID(false), } - resp, err := h.Websocket.Conn.SendMessageReturnResponse(context.TODO(), request.Unset, req.ID, req) + resp, err := h.Websocket.Conn.SendMessageReturnResponse(ctx, request.Unset, req.ID, req) if err != nil { return nil, fmt.Errorf("%v %v", h.Name, err) } @@ -670,7 +673,7 @@ func (h *HitBTC) wsReplaceOrder(clientOrderID string, quantity, price float64) ( } // wsGetActiveOrders sends a websocket message to get all active orders -func (h *HitBTC) wsGetActiveOrders() (*wsActiveOrdersResponse, error) { +func (h *HitBTC) wsGetActiveOrders(ctx context.Context) (*wsActiveOrdersResponse, error) { if !h.Websocket.CanUseAuthenticatedEndpoints() { return nil, fmt.Errorf("%v not authenticated, cannot get active orders", h.Name) } @@ -679,7 +682,7 @@ func (h *HitBTC) wsGetActiveOrders() (*wsActiveOrdersResponse, error) { Params: WsReplaceOrderRequestData{}, ID: h.Websocket.Conn.GenerateMessageID(false), } - resp, err := h.Websocket.Conn.SendMessageReturnResponse(context.TODO(), request.Unset, req.ID, req) + resp, err := h.Websocket.Conn.SendMessageReturnResponse(ctx, request.Unset, req.ID, req) if err != nil { return nil, fmt.Errorf("%v %v", h.Name, err) } @@ -695,7 +698,7 @@ func (h *HitBTC) wsGetActiveOrders() (*wsActiveOrdersResponse, error) { } // wsGetTradingBalance sends a websocket message to get trading balance -func (h *HitBTC) wsGetTradingBalance() (*WsGetTradingBalanceResponse, error) { +func (h *HitBTC) wsGetTradingBalance(ctx context.Context) (*WsGetTradingBalanceResponse, error) { if !h.Websocket.CanUseAuthenticatedEndpoints() { return nil, fmt.Errorf("%v not authenticated, cannot place order", h.Name) } @@ -704,7 +707,7 @@ func (h *HitBTC) wsGetTradingBalance() (*WsGetTradingBalanceResponse, error) { Params: WsReplaceOrderRequestData{}, ID: h.Websocket.Conn.GenerateMessageID(false), } - resp, err := h.Websocket.Conn.SendMessageReturnResponse(context.TODO(), request.Unset, req.ID, req) + resp, err := h.Websocket.Conn.SendMessageReturnResponse(ctx, request.Unset, req.ID, req) if err != nil { return nil, fmt.Errorf("%v %v", h.Name, err) } @@ -720,7 +723,7 @@ func (h *HitBTC) wsGetTradingBalance() (*WsGetTradingBalanceResponse, error) { } // wsGetCurrencies sends a websocket message to get trading balance -func (h *HitBTC) wsGetCurrencies(currencyItem currency.Code) (*WsGetCurrenciesResponse, error) { +func (h *HitBTC) wsGetCurrencies(ctx context.Context, currencyItem currency.Code) (*WsGetCurrenciesResponse, error) { req := WsGetCurrenciesRequest{ Method: "getCurrency", Params: WsGetCurrenciesRequestParameters{ @@ -728,7 +731,7 @@ func (h *HitBTC) wsGetCurrencies(currencyItem currency.Code) (*WsGetCurrenciesRe }, ID: h.Websocket.Conn.GenerateMessageID(false), } - resp, err := h.Websocket.Conn.SendMessageReturnResponse(context.TODO(), request.Unset, req.ID, req) + resp, err := h.Websocket.Conn.SendMessageReturnResponse(ctx, request.Unset, req.ID, req) if err != nil { return nil, fmt.Errorf("%v %v", h.Name, err) } @@ -744,7 +747,7 @@ func (h *HitBTC) wsGetCurrencies(currencyItem currency.Code) (*WsGetCurrenciesRe } // wsGetSymbols sends a websocket message to get trading balance -func (h *HitBTC) wsGetSymbols(c currency.Pair) (*WsGetSymbolsResponse, error) { +func (h *HitBTC) wsGetSymbols(ctx context.Context, c currency.Pair) (*WsGetSymbolsResponse, error) { fPair, err := h.FormatExchangeCurrency(c, asset.Spot) if err != nil { return nil, err @@ -757,7 +760,7 @@ func (h *HitBTC) wsGetSymbols(c currency.Pair) (*WsGetSymbolsResponse, error) { }, ID: h.Websocket.Conn.GenerateMessageID(false), } - resp, err := h.Websocket.Conn.SendMessageReturnResponse(context.TODO(), request.Unset, req.ID, req) + resp, err := h.Websocket.Conn.SendMessageReturnResponse(ctx, request.Unset, req.ID, req) if err != nil { return nil, fmt.Errorf("%v %v", h.Name, err) } @@ -773,7 +776,7 @@ func (h *HitBTC) wsGetSymbols(c currency.Pair) (*WsGetSymbolsResponse, error) { } // wsGetSymbols sends a websocket message to get trading balance -func (h *HitBTC) wsGetTrades(c currency.Pair, limit int64, sort, by string) (*WsGetTradesResponse, error) { +func (h *HitBTC) wsGetTrades(ctx context.Context, c currency.Pair, limit int64, sort, by string) (*WsGetTradesResponse, error) { fPair, err := h.FormatExchangeCurrency(c, asset.Spot) if err != nil { return nil, err @@ -789,7 +792,7 @@ func (h *HitBTC) wsGetTrades(c currency.Pair, limit int64, sort, by string) (*Ws }, ID: h.Websocket.Conn.GenerateMessageID(false), } - resp, err := h.Websocket.Conn.SendMessageReturnResponse(context.TODO(), request.Unset, req.ID, req) + resp, err := h.Websocket.Conn.SendMessageReturnResponse(ctx, request.Unset, req.ID, req) if err != nil { return nil, fmt.Errorf("%v %v", h.Name, err) } diff --git a/exchanges/hitbtc/hitbtc_wrapper.go b/exchanges/hitbtc/hitbtc_wrapper.go index f2771b6d..cfe5ce2b 100644 --- a/exchanges/hitbtc/hitbtc_wrapper.go +++ b/exchanges/hitbtc/hitbtc_wrapper.go @@ -439,7 +439,7 @@ func (h *HitBTC) SubmitOrder(ctx context.Context, o *order.Submit) (*order.Submi status := order.New if h.Websocket.IsConnected() && h.Websocket.CanUseAuthenticatedEndpoints() { var response *WsSubmitOrderSuccessResponse - response, err = h.wsPlaceOrder(o.Pair, o.Side.String(), o.Amount, o.Price) + response, err = h.wsPlaceOrder(ctx, o.Pair, o.Side.String(), o.Amount, o.Price) if err != nil { return nil, err } diff --git a/exchanges/huobi/huobi_websocket.go b/exchanges/huobi/huobi_websocket.go index 376ee27b..21b3b348 100644 --- a/exchanges/huobi/huobi_websocket.go +++ b/exchanges/huobi/huobi_websocket.go @@ -76,32 +76,32 @@ var subscriptionNames = map[string]string{ // WsConnect initiates a new websocket connection func (h *HUOBI) WsConnect() error { + ctx := context.TODO() if !h.Websocket.IsEnabled() || !h.IsEnabled() { return websocket.ErrWebsocketNotEnabled } - if err := h.Websocket.Conn.Dial(&gws.Dialer{}, http.Header{}); err != nil { + if err := h.Websocket.Conn.Dial(ctx, &gws.Dialer{}, http.Header{}); err != nil { return err } h.Websocket.Wg.Add(1) - go h.wsReadMsgs(h.Websocket.Conn) + go h.wsReadMsgs(ctx, h.Websocket.Conn) if h.IsWebsocketAuthenticationSupported() { - ctx := context.Background() if err := h.wsAuthConnect(ctx); err != nil { h.Websocket.SetCanUseAuthenticatedEndpoints(false) return fmt.Errorf("error authenticating websocket: %w", err) } h.Websocket.SetCanUseAuthenticatedEndpoints(true) h.Websocket.Wg.Add(1) - go h.wsReadMsgs(h.Websocket.AuthConn) + go h.wsReadMsgs(ctx, h.Websocket.AuthConn) } return nil } // wsReadMsgs reads and processes messages from a websocket connection -func (h *HUOBI) wsReadMsgs(s websocket.Connection) { +func (h *HUOBI) wsReadMsgs(ctx context.Context, s websocket.Connection) { defer h.Websocket.Wg.Done() for { msg := s.ReadMessage() @@ -109,13 +109,13 @@ func (h *HUOBI) wsReadMsgs(s websocket.Connection) { return } - if err := h.wsHandleData(msg.Raw); err != nil { + if err := h.wsHandleData(ctx, msg.Raw); err != nil { h.Websocket.DataHandler <- err } } } -func (h *HUOBI) wsHandleData(respRaw []byte) error { +func (h *HUOBI) wsHandleData(ctx context.Context, respRaw []byte) error { if id, err := jsonparser.GetString(respRaw, "id"); err == nil { if h.Websocket.Match.IncomingWithData(id, respRaw) { return nil @@ -123,13 +123,13 @@ func (h *HUOBI) wsHandleData(respRaw []byte) error { } if pingValue, err := jsonparser.GetInt(respRaw, "ping"); err == nil { - return h.wsHandleV1ping(int(pingValue)) + return h.wsHandleV1ping(ctx, int(pingValue)) } if action, err := jsonparser.GetString(respRaw, "action"); err == nil { switch action { case "ping": - return h.wsHandleV2ping(respRaw) + return h.wsHandleV2ping(ctx, respRaw) case wsSubOp, wsUnsubOp: return h.wsHandleV2subResp(action, respRaw) } @@ -155,20 +155,20 @@ func (h *HUOBI) wsHandleData(respRaw []byte) error { } // wsHandleV1ping handles v1 style pings, currently only used with public connections -func (h *HUOBI) wsHandleV1ping(pingValue int) error { - if err := h.Websocket.Conn.SendJSONMessage(context.Background(), request.Unset, json.RawMessage(`{"pong":`+strconv.Itoa(pingValue)+`}`)); err != nil { +func (h *HUOBI) wsHandleV1ping(ctx context.Context, pingValue int) error { + if err := h.Websocket.Conn.SendJSONMessage(ctx, request.Unset, json.RawMessage(`{"pong":`+strconv.Itoa(pingValue)+`}`)); err != nil { return fmt.Errorf("error sending pong response: %w", err) } return nil } // wsHandleV2ping handles v2 style pings, currently only used with private connections -func (h *HUOBI) wsHandleV2ping(respRaw []byte) error { +func (h *HUOBI) wsHandleV2ping(ctx context.Context, respRaw []byte) error { ts, err := jsonparser.GetInt(respRaw, "data", "ts") if err != nil { return fmt.Errorf("error getting ts from auth ping: %w", err) } - if err := h.Websocket.AuthConn.SendJSONMessage(context.Background(), request.Unset, json.RawMessage(`{"action":"pong","data":{"ts":`+strconv.Itoa(int(ts))+`}}`)); err != nil { + if err := h.Websocket.AuthConn.SendJSONMessage(ctx, request.Unset, json.RawMessage(`{"action":"pong","data":{"ts":`+strconv.Itoa(int(ts))+`}}`)); err != nil { return fmt.Errorf("error sending auth pong response: %w", err) } return nil @@ -497,17 +497,19 @@ func (h *HUOBI) GetSubscriptionTemplate(_ *subscription.Subscription) (*template // Subscribe sends a websocket message to receive data from the channel func (h *HUOBI) Subscribe(subs subscription.List) error { + ctx := context.TODO() subs, errs := subs.ExpandTemplates(h) - return common.AppendError(errs, h.ParallelChanOp(subs, func(l subscription.List) error { return h.manageSubs(wsSubOp, l) }, 1)) + return common.AppendError(errs, h.ParallelChanOp(ctx, subs, func(ctx context.Context, l subscription.List) error { return h.manageSubs(ctx, wsSubOp, l) }, 1)) } // Unsubscribe sends a websocket message to stop receiving data from the channel func (h *HUOBI) Unsubscribe(subs subscription.List) error { + ctx := context.TODO() subs, errs := subs.ExpandTemplates(h) - return common.AppendError(errs, h.ParallelChanOp(subs, func(l subscription.List) error { return h.manageSubs(wsUnsubOp, l) }, 1)) + return common.AppendError(errs, h.ParallelChanOp(ctx, subs, func(ctx context.Context, l subscription.List) error { return h.manageSubs(ctx, wsUnsubOp, l) }, 1)) } -func (h *HUOBI) manageSubs(op string, subs subscription.List) error { +func (h *HUOBI) manageSubs(ctx context.Context, op string, subs subscription.List) error { if len(subs) != 1 { return subscription.ErrBatchingNotSupported } @@ -532,7 +534,6 @@ func (h *HUOBI) manageSubs(op string, subs subscription.List) error { return fmt.Errorf("%w: %s; error: %w", websocket.ErrSubscriptionFailure, s, err) } } - ctx := context.Background() respRaw, err := c.SendMessageReturnResponse(ctx, request.Unset, wsSubOp+":"+s.QualifiedChannel, req) if err == nil { err = getErrResp(respRaw) @@ -565,7 +566,7 @@ func (h *HUOBI) wsGenerateSignature(creds *account.Credentials, timestamp string } func (h *HUOBI) wsAuthConnect(ctx context.Context) error { - if err := h.Websocket.AuthConn.Dial(&gws.Dialer{}, http.Header{}); err != nil { + if err := h.Websocket.AuthConn.Dial(ctx, &gws.Dialer{}, http.Header{}); err != nil { return fmt.Errorf("authenticated dial failed: %w", err) } if err := h.wsLogin(ctx); err != nil { @@ -598,7 +599,7 @@ func (h *HUOBI) wsLogin(ctx context.Context) error { }, } c := h.Websocket.AuthConn - if err := c.SendJSONMessage(context.Background(), request.Unset, req); err != nil { + if err := c.SendJSONMessage(ctx, request.Unset, req); err != nil { return err } resp := c.ReadMessage() diff --git a/exchanges/huobi/huobi_wrapper.go b/exchanges/huobi/huobi_wrapper.go index cf93196a..ced06e1e 100644 --- a/exchanges/huobi/huobi_wrapper.go +++ b/exchanges/huobi/huobi_wrapper.go @@ -173,11 +173,11 @@ func (h *HUOBI) SetDefaults() { } // Bootstrap ensures that future contract expiry codes are loaded if AutoPairUpdates is not enabled -func (h *HUOBI) Bootstrap(_ context.Context) (continueBootstrap bool, err error) { +func (h *HUOBI) Bootstrap(ctx context.Context) (continueBootstrap bool, err error) { continueBootstrap = true if !h.GetEnabledFeatures().AutoPairUpdates && h.SupportsAsset(asset.Futures) { - _, err = h.FetchTradablePairs(context.Background(), asset.Futures) + _, err = h.FetchTradablePairs(ctx, asset.Futures) } return diff --git a/exchanges/kraken/kraken_test.go b/exchanges/kraken/kraken_test.go index 339a4c2b..e0dbdacf 100644 --- a/exchanges/kraken/kraken_test.go +++ b/exchanges/kraken/kraken_test.go @@ -1172,7 +1172,7 @@ func TestWsAddOrder(t *testing.T) { k := testexch.MockWsInstance[Kraken](t, curryWsMockUpgrader(t, mockWsServer)) //nolint:govet // Intentional shadow to avoid future copy/paste mistakes require.True(t, k.IsWebsocketAuthenticationSupported(), "WS must be authenticated") - id, err := k.wsAddOrder(&WsAddOrderRequest{ + id, err := k.wsAddOrder(t.Context(), &WsAddOrderRequest{ OrderType: order.Limit.Lower(), OrderSide: order.Buy.Lower(), Pair: "XBT/USD", @@ -1189,20 +1189,20 @@ func TestWsCancelOrders(t *testing.T) { k := testexch.MockWsInstance[Kraken](t, curryWsMockUpgrader(t, mockWsServer)) //nolint:govet // Intentional shadow to avoid future copy/paste mistakes require.True(t, k.IsWebsocketAuthenticationSupported(), "WS must be authenticated") - err := k.wsCancelOrders([]string{"RABBIT", "BATFISH", "SQUIRREL", "CATFISH", "MOUSE"}) + err := k.wsCancelOrders(t.Context(), []string{"RABBIT", "BATFISH", "SQUIRREL", "CATFISH", "MOUSE"}) assert.ErrorIs(t, err, errCancellingOrder, "Should error cancelling order") assert.ErrorContains(t, err, "BATFISH", "Should error containing txn id") assert.ErrorContains(t, err, "CATFISH", "Should error containing txn id") assert.ErrorContains(t, err, "[EOrder:Unknown order]", "Should error containing server error") - err = k.wsCancelOrders([]string{"RABBIT", "SQUIRREL", "MOUSE"}) + err = k.wsCancelOrders(t.Context(), []string{"RABBIT", "SQUIRREL", "MOUSE"}) assert.NoError(t, err, "Should not error with valid ids") } func TestWsCancelAllOrders(t *testing.T) { sharedtestvalues.SkipTestIfCredentialsUnset(t, k, canManipulateRealOrders) testexch.SetupWs(t, k) - _, err := k.wsCancelAllOrders() + _, err := k.wsCancelAllOrders(t.Context()) require.NoError(t, err, "wsCancelAllOrders must not error") } @@ -1486,12 +1486,12 @@ func TestWsOrderbookMax10Depth(t *testing.T) { } for x := range websocketXDGUSDOrderbookUpdates { - err := k.wsHandleData([]byte(websocketXDGUSDOrderbookUpdates[x])) + err := k.wsHandleData(t.Context(), []byte(websocketXDGUSDOrderbookUpdates[x])) require.NoError(t, err, "wsHandleData must not error") } for x := range websocketLUNAEUROrderbookUpdates { - err := k.wsHandleData([]byte(websocketLUNAEUROrderbookUpdates[x])) + err := k.wsHandleData(t.Context(), []byte(websocketLUNAEUROrderbookUpdates[x])) // TODO: Known issue with LUNA pairs and big number float precision // storage and checksum calc. Might need to store raw strings as fields // in the orderbook.Level struct. @@ -1503,7 +1503,7 @@ func TestWsOrderbookMax10Depth(t *testing.T) { // This has less than 10 bids and still needs a checksum calc. for x := range websocketGSTEUROrderbookUpdates { - err := k.wsHandleData([]byte(websocketGSTEUROrderbookUpdates[x])) + err := k.wsHandleData(t.Context(), []byte(websocketGSTEUROrderbookUpdates[x])) require.NoError(t, err, "wsHandleData must not error") } } diff --git a/exchanges/kraken/kraken_websocket.go b/exchanges/kraken/kraken_websocket.go index c6cc8b2d..9da5ffff 100644 --- a/exchanges/kraken/kraken_websocket.go +++ b/exchanges/kraken/kraken_websocket.go @@ -95,27 +95,28 @@ var defaultSubscriptions = subscription.List{ // WsConnect initiates a websocket connection func (k *Kraken) WsConnect() error { + ctx := context.TODO() if !k.Websocket.IsEnabled() || !k.IsEnabled() { return websocket.ErrWebsocketNotEnabled } var dialer gws.Dialer - err := k.Websocket.Conn.Dial(&dialer, http.Header{}) + err := k.Websocket.Conn.Dial(ctx, &dialer, http.Header{}) if err != nil { return err } comms := make(chan websocket.Response) k.Websocket.Wg.Add(2) - go k.wsReadData(comms) + go k.wsReadData(ctx, comms) go k.wsFunnelConnectionData(k.Websocket.Conn, comms) if k.IsWebsocketAuthenticationSupported() { - if authToken, err := k.GetWebsocketToken(context.TODO()); err != nil { + if authToken, err := k.GetWebsocketToken(ctx); err != nil { k.Websocket.SetCanUseAuthenticatedEndpoints(false) log.Errorf(log.ExchangeSys, "%s - authentication failed: %v\n", k.Name, err) } else { - if err := k.Websocket.AuthConn.Dial(&dialer, http.Header{}); err != nil { + if err := k.Websocket.AuthConn.Dial(ctx, &dialer, http.Header{}); err != nil { k.Websocket.SetCanUseAuthenticatedEndpoints(false) log.Errorf(log.ExchangeSys, "%s - failed to connect to authenticated endpoint: %v\n", k.Name, err) } else { @@ -146,7 +147,7 @@ func (k *Kraken) wsFunnelConnectionData(ws websocket.Connection, comms chan webs } // wsReadData receives and passes on websocket messages for processing -func (k *Kraken) wsReadData(comms chan websocket.Response) { +func (k *Kraken) wsReadData(ctx context.Context, comms chan websocket.Response) { defer k.Websocket.Wg.Done() for { @@ -154,7 +155,7 @@ func (k *Kraken) wsReadData(comms chan websocket.Response) { case <-k.Websocket.ShutdownC: select { case resp := <-comms: - err := k.wsHandleData(resp.Raw) + err := k.wsHandleData(ctx, resp.Raw) if err != nil { select { case k.Websocket.DataHandler <- err: @@ -166,7 +167,7 @@ func (k *Kraken) wsReadData(comms chan websocket.Response) { } return case resp := <-comms: - err := k.wsHandleData(resp.Raw) + err := k.wsHandleData(ctx, resp.Raw) if err != nil { k.Websocket.DataHandler <- err } @@ -174,7 +175,7 @@ func (k *Kraken) wsReadData(comms chan websocket.Response) { } } -func (k *Kraken) wsHandleData(respRaw []byte) error { +func (k *Kraken) wsHandleData(_ context.Context, respRaw []byte) error { if strings.HasPrefix(string(respRaw), "[") { var msg []any if err := json.Unmarshal(respRaw, &msg); err != nil { @@ -994,6 +995,7 @@ func (k *Kraken) generateSubscriptions() (subscription.List, error) { // Subscribe adds a channel subscription to the websocket func (k *Kraken) Subscribe(in subscription.List) error { + ctx := context.TODO() in, errs := in.ExpandTemplates(k) // Collect valid new subs and add to websocket in Subscribing state @@ -1012,7 +1014,7 @@ func (k *Kraken) Subscribe(in subscription.List) error { groupedSubs := subs.GroupPairs() errs = common.AppendError(errs, - k.ParallelChanOp(groupedSubs, func(s subscription.List) error { return k.manageSubs(krakenWsSubscribe, s) }, 1), + k.ParallelChanOp(ctx, groupedSubs, func(ctx context.Context, s subscription.List) error { return k.manageSubs(ctx, krakenWsSubscribe, s) }, 1), ) for _, s := range subs { @@ -1029,6 +1031,7 @@ func (k *Kraken) Subscribe(in subscription.List) error { // Unsubscribe removes a channel subscriptions from the websocket func (k *Kraken) Unsubscribe(keys subscription.List) error { + ctx := context.TODO() var errs error // Make sure we have the concrete subscriptions, since we will change the state subs := make(subscription.List, 0, len(keys)) @@ -1049,12 +1052,12 @@ func (k *Kraken) Unsubscribe(keys subscription.List) error { subs = subs.GroupPairs() return common.AppendError(errs, - k.ParallelChanOp(subs, func(s subscription.List) error { return k.manageSubs(krakenWsUnsubscribe, s) }, 1), + k.ParallelChanOp(ctx, subs, func(ctx context.Context, s subscription.List) error { return k.manageSubs(ctx, krakenWsUnsubscribe, s) }, 1), ) } // manageSubs handles both websocket channel subscribe and unsubscribe -func (k *Kraken) manageSubs(op string, subs subscription.List) error { +func (k *Kraken) manageSubs(ctx context.Context, op string, subs subscription.List) error { if len(subs) != 1 { return subscription.ErrBatchingNotSupported } @@ -1087,7 +1090,7 @@ func (k *Kraken) manageSubs(op string, subs subscription.List) error { conn = k.Websocket.AuthConn } - resps, err := conn.SendMessageReturnResponses(context.TODO(), request.Unset, r.RequestID, r, len(s.Pairs)) + resps, err := conn.SendMessageReturnResponses(ctx, request.Unset, r.RequestID, r, len(s.Pairs)) // Ignore an overall timeout, because we'll track individual subscriptions in handleSubResps err = common.ExcludeError(err, websocket.ErrSignatureTimeout) @@ -1291,14 +1294,14 @@ func fqChannelNameSub(s *subscription.Subscription) error { } // wsAddOrder creates an order, returned order ID if success -func (k *Kraken) wsAddOrder(req *WsAddOrderRequest) (string, error) { +func (k *Kraken) wsAddOrder(ctx context.Context, req *WsAddOrderRequest) (string, error) { if req == nil { return "", common.ErrNilPointer } req.RequestID = k.Websocket.AuthConn.GenerateMessageID(false) req.Event = krakenWsAddOrder req.Token = k.websocketAuthToken() - jsonResp, err := k.Websocket.AuthConn.SendMessageReturnResponse(context.TODO(), request.Unset, req.RequestID, req) + jsonResp, err := k.Websocket.AuthConn.SendMessageReturnResponse(ctx, request.Unset, req.RequestID, req) if err != nil { return "", err } @@ -1320,12 +1323,12 @@ func (k *Kraken) wsAddOrder(req *WsAddOrderRequest) (string, error) { // wsCancelOrders cancels open orders concurrently // It does not use the multiple txId facility of the cancelOrder API because the errors are not specific -func (k *Kraken) wsCancelOrders(orderIDs []string) error { +func (k *Kraken) wsCancelOrders(ctx context.Context, orderIDs []string) error { errs := common.CollectErrors(len(orderIDs)) for _, id := range orderIDs { go func() { defer errs.Wg.Done() - errs.C <- k.wsCancelOrder(id) + errs.C <- k.wsCancelOrder(ctx, id) }() } @@ -1333,7 +1336,7 @@ func (k *Kraken) wsCancelOrders(orderIDs []string) error { } // wsCancelOrder cancels an open order -func (k *Kraken) wsCancelOrder(orderID string) error { +func (k *Kraken) wsCancelOrder(ctx context.Context, orderID string) error { id := k.Websocket.AuthConn.GenerateMessageID(false) req := WsCancelOrderRequest{ Event: krakenWsCancelOrder, @@ -1342,7 +1345,7 @@ func (k *Kraken) wsCancelOrder(orderID string) error { RequestID: id, } - resp, err := k.Websocket.AuthConn.SendMessageReturnResponse(context.TODO(), request.Unset, id, req) + resp, err := k.Websocket.AuthConn.SendMessageReturnResponse(ctx, request.Unset, id, req) if err != nil { return fmt.Errorf("%w %s: %w", errCancellingOrder, orderID, err) } @@ -1364,7 +1367,7 @@ func (k *Kraken) wsCancelOrder(orderID string) error { // wsCancelAllOrders cancels all opened orders // Returns number (count param) of affected orders or 0 if no open orders found -func (k *Kraken) wsCancelAllOrders() (*WsCancelOrderResponse, error) { +func (k *Kraken) wsCancelAllOrders(ctx context.Context) (*WsCancelOrderResponse, error) { id := k.Websocket.AuthConn.GenerateMessageID(false) req := WsCancelOrderRequest{ Event: krakenWsCancelAll, @@ -1372,7 +1375,7 @@ func (k *Kraken) wsCancelAllOrders() (*WsCancelOrderResponse, error) { RequestID: id, } - jsonResp, err := k.Websocket.AuthConn.SendMessageReturnResponse(context.TODO(), request.Unset, id, req) + jsonResp, err := k.Websocket.AuthConn.SendMessageReturnResponse(ctx, request.Unset, id, req) if err != nil { return &WsCancelOrderResponse{}, err } diff --git a/exchanges/kraken/kraken_wrapper.go b/exchanges/kraken/kraken_wrapper.go index 9ae15a7d..39184671 100644 --- a/exchanges/kraken/kraken_wrapper.go +++ b/exchanges/kraken/kraken_wrapper.go @@ -232,10 +232,10 @@ func (k *Kraken) Setup(exch *config.Exchange) error { } // Bootstrap provides initialisation for an exchange -func (k *Kraken) Bootstrap(_ context.Context) (continueBootstrap bool, err error) { +func (k *Kraken) Bootstrap(ctx context.Context) (continueBootstrap bool, err error) { continueBootstrap = true - if err = k.SeedAssets(context.TODO()); err != nil { + if err = k.SeedAssets(ctx); err != nil { err = fmt.Errorf("failed to Seed Assets: %w", err) } @@ -700,7 +700,7 @@ func (k *Kraken) SubmitOrder(ctx context.Context, s *order.Submit) (*order.Submi timeInForce = "IOC" } if k.Websocket.CanUseAuthenticatedWebsocketForWrapper() { - orderID, err = k.wsAddOrder(&WsAddOrderRequest{ + orderID, err = k.wsAddOrder(ctx, &WsAddOrderRequest{ OrderType: s.Type.Lower(), OrderSide: s.Side.Lower(), Pair: s.Pair.Format(currency.PairFormat{Uppercase: true, Delimiter: "/"}).String(), // required pair format: ISO 4217-A3 @@ -781,7 +781,7 @@ func (k *Kraken) CancelOrder(ctx context.Context, o *order.Cancel) error { switch o.AssetType { case asset.Spot: if k.Websocket.CanUseAuthenticatedWebsocketForWrapper() { - return k.wsCancelOrders([]string{o.OrderID}) + return k.wsCancelOrders(ctx, []string{o.OrderID}) } _, err := k.CancelExistingOrder(ctx, o.OrderID) return err @@ -798,7 +798,7 @@ func (k *Kraken) CancelOrder(ctx context.Context, o *order.Cancel) error { } // CancelBatchOrders cancels an orders by their corresponding ID numbers -func (k *Kraken) CancelBatchOrders(_ context.Context, o []order.Cancel) (*order.CancelBatchResponse, error) { +func (k *Kraken) CancelBatchOrders(ctx context.Context, o []order.Cancel) (*order.CancelBatchResponse, error) { if !k.Websocket.CanUseAuthenticatedWebsocketForWrapper() { return nil, common.ErrFunctionNotSupported } @@ -811,7 +811,7 @@ func (k *Kraken) CancelBatchOrders(_ context.Context, o []order.Cancel) (*order. ordersList[i] = o[i].OrderID } - err := k.wsCancelOrders(ordersList) + err := k.wsCancelOrders(ctx, ordersList) return nil, err } @@ -826,7 +826,7 @@ func (k *Kraken) CancelAllOrders(ctx context.Context, req *order.Cancel) (order. switch req.AssetType { case asset.Spot: if k.Websocket.CanUseAuthenticatedWebsocketForWrapper() { - resp, err := k.wsCancelAllOrders() + resp, err := k.wsCancelAllOrders(ctx) if err != nil { return cancelAllOrdersResponse, err } @@ -843,7 +843,7 @@ func (k *Kraken) CancelAllOrders(ctx context.Context, req *order.Cancel) (order. for orderID := range openOrders.Open { var err error if k.Websocket.CanUseAuthenticatedWebsocketForWrapper() { - err = k.wsCancelOrders([]string{orderID}) + err = k.wsCancelOrders(ctx, []string{orderID}) } else { _, err = k.CancelExistingOrder(ctx, orderID) } diff --git a/exchanges/kucoin/kucoin_test.go b/exchanges/kucoin/kucoin_test.go index 36075f7b..a0c6c355 100644 --- a/exchanges/kucoin/kucoin_test.go +++ b/exchanges/kucoin/kucoin_test.go @@ -64,13 +64,14 @@ func TestMain(m *testing.M) { ku.Websocket.SetCanUseAuthenticatedEndpoints(true) } - getFirstTradablePairOfAssets() + ctx := context.Background() + getFirstTradablePairOfAssets(ctx) assertToTradablePairMap = map[asset.Item]currency.Pair{ asset.Spot: spotTradablePair, asset.Margin: marginTradablePair, asset.Futures: futuresTradablePair, } - ku.setupOrderbookManager() + ku.setupOrderbookManager(ctx) fetchedFuturesOrderbook = map[string]bool{} os.Exit(m.Run()) @@ -2932,8 +2933,8 @@ func TestGetFundingHistory(t *testing.T) { assert.NotNil(t, result) } -func getFirstTradablePairOfAssets() { - if err := ku.UpdateTradablePairs(context.Background(), true); err != nil { +func getFirstTradablePairOfAssets(ctx context.Context) { + if err := ku.UpdateTradablePairs(ctx, true); err != nil { log.Fatalf("Kucoin error while updating tradable pairs. %v", err) } enabledPairs, err := ku.GetEnabledPairs(asset.Spot) @@ -2981,7 +2982,7 @@ func TestProcessOrderbook(t *testing.T) { err = ku.processOrderbook([]byte(orderbookLevel5PushData), "BTC-USDT", "") assert.NoError(t, err) assert.NotNil(t, result) - err = ku.wsHandleData([]byte(orderbookLevel5PushData)) + err = ku.wsHandleData(t.Context(), []byte(orderbookLevel5PushData)) assert.NoError(t, err) assert.NotNil(t, result) } diff --git a/exchanges/kucoin/kucoin_websocket.go b/exchanges/kucoin/kucoin_websocket.go index 2cf60241..1f711b8b 100644 --- a/exchanges/kucoin/kucoin_websocket.go +++ b/exchanges/kucoin/kucoin_websocket.go @@ -118,6 +118,7 @@ var defaultSubscriptions = subscription.List{ // WsConnect creates a new websocket connection. func (ku *Kucoin) WsConnect() error { + ctx := context.TODO() if !ku.Websocket.IsEnabled() || !ku.IsEnabled() { return websocket.ErrWebsocketNotEnabled } @@ -128,19 +129,19 @@ func (ku *Kucoin) WsConnect() error { dialer.HandshakeTimeout = ku.Config.HTTPTimeout dialer.Proxy = http.ProxyFromEnvironment var instances *WSInstanceServers - _, err := ku.GetCredentials(context.Background()) + _, err := ku.GetCredentials(ctx) if err != nil { ku.Websocket.SetCanUseAuthenticatedEndpoints(false) } if ku.Websocket.CanUseAuthenticatedEndpoints() { - instances, err = ku.GetAuthenticatedInstanceServers(context.Background()) + instances, err = ku.GetAuthenticatedInstanceServers(ctx) if err != nil { ku.Websocket.DataHandler <- err ku.Websocket.SetCanUseAuthenticatedEndpoints(false) } } if instances == nil { - instances, err = ku.GetInstanceServers(context.Background()) + instances, err = ku.GetInstanceServers(ctx) if err != nil { return err } @@ -149,19 +150,19 @@ func (ku *Kucoin) WsConnect() error { return errors.New("no websocket instance server found") } ku.Websocket.Conn.SetURL(instances.InstanceServers[0].Endpoint + "?token=" + instances.Token) - err = ku.Websocket.Conn.Dial(&dialer, http.Header{}) + err = ku.Websocket.Conn.Dial(ctx, &dialer, http.Header{}) if err != nil { return fmt.Errorf("%v - Unable to connect to Websocket. Error: %s", ku.Name, err) } ku.Websocket.Wg.Add(1) - go ku.wsReadData() + go ku.wsReadData(ctx) ku.Websocket.Conn.SetupPingHandler(request.Unset, websocket.PingHandler{ Delay: time.Millisecond * time.Duration(instances.InstanceServers[0].PingTimeout), Message: []byte(`{"type":"ping"}`), MessageType: gws.TextMessage, }) - ku.setupOrderbookManager() + ku.setupOrderbookManager(ctx) return nil } @@ -201,14 +202,14 @@ func (ku *Kucoin) GetAuthenticatedInstanceServers(ctx context.Context) (*WSInsta } // wsReadData receives and passes on websocket messages for processing -func (ku *Kucoin) wsReadData() { +func (ku *Kucoin) wsReadData(ctx context.Context) { defer ku.Websocket.Wg.Done() for { resp := ku.Websocket.Conn.ReadMessage() if resp.Raw == nil { return } - err := ku.wsHandleData(resp.Raw) + err := ku.wsHandleData(ctx, resp.Raw) if err != nil { ku.Websocket.DataHandler <- err } @@ -216,7 +217,7 @@ func (ku *Kucoin) wsReadData() { } // wsHandleData processes a websocket incoming data. -func (ku *Kucoin) wsHandleData(respData []byte) error { +func (ku *Kucoin) wsHandleData(ctx context.Context, respData []byte) error { resp := WsPushData{} if err := json.Unmarshal(respData, &resp); err != nil { return err @@ -257,7 +258,7 @@ func (ku *Kucoin) wsHandleData(respData []byte) error { case privateSpotTradeOrders: return ku.processOrderChangeEvent(resp.Data, topicInfo[0]) case accountBalanceChannel: - return ku.processAccountBalanceChange(resp.Data) + return ku.processAccountBalanceChange(ctx, resp.Data) case marginPositionChannel: if resp.Subject == "debt.ratio" { var response WsDebtRatioChange @@ -279,13 +280,13 @@ func (ku *Kucoin) wsHandleData(respData []byte) error { var response WsFuturesExecutionData return ku.processData(resp.Data, &response) case futuresOrderbookChannel: - if err := ku.ensureFuturesOrderbookSnapshotLoaded(topicInfo[1]); err != nil { + if err := ku.ensureFuturesOrderbookSnapshotLoaded(ctx, topicInfo[1]); err != nil { return err } - return ku.processFuturesOrderbookLevel2(resp.Data, topicInfo[1]) + return ku.processFuturesOrderbookLevel2(ctx, resp.Data, topicInfo[1]) case futuresOrderbookDepth5Channel, futuresOrderbookDepth50Channel: - if err := ku.ensureFuturesOrderbookSnapshotLoaded(topicInfo[1]); err != nil { + if err := ku.ensureFuturesOrderbookSnapshotLoaded(ctx, topicInfo[1]); err != nil { return err } return ku.processFuturesOrderbookSnapshot(resp.Data, topicInfo[1]) @@ -310,7 +311,7 @@ func (ku *Kucoin) wsHandleData(respData []byte) error { var response WsFuturesOrderMarginEvent return ku.processData(resp.Data, &response) case "availableBalance.change": - return ku.processFuturesAccountBalanceEvent(resp.Data) + return ku.processFuturesAccountBalanceEvent(ctx, resp.Data) case "withdrawHold.change": var response WsFuturesWithdrawalAmountAndTransferOutAmountEvent return ku.processData(resp.Data, &response) @@ -353,12 +354,12 @@ func (ku *Kucoin) processData(respData []byte, resp any) error { } // processFuturesAccountBalanceEvent used to process futures account balance change incoming data. -func (ku *Kucoin) processFuturesAccountBalanceEvent(respData []byte) error { +func (ku *Kucoin) processFuturesAccountBalanceEvent(ctx context.Context, respData []byte) error { resp := WsFuturesAvailableBalance{} if err := json.Unmarshal(respData, &resp); err != nil { return err } - creds, err := ku.GetCredentials(context.TODO()) + creds, err := ku.GetCredentials(ctx) if err != nil { return err } @@ -507,7 +508,7 @@ func (ku *Kucoin) processFuturesMarkPriceAndIndexPrice(respData []byte, instrume } // ensureFuturesOrderbookSnapshotLoaded makes sure an initial futures orderbook snapshot is loaded -func (ku *Kucoin) ensureFuturesOrderbookSnapshotLoaded(symbol string) error { +func (ku *Kucoin) ensureFuturesOrderbookSnapshotLoaded(ctx context.Context, symbol string) error { fetchedFuturesOrderbookMutex.Lock() defer fetchedFuturesOrderbookMutex.Unlock() if fetchedFuturesOrderbook[symbol] { @@ -522,7 +523,7 @@ func (ku *Kucoin) ensureFuturesOrderbookSnapshotLoaded(symbol string) error { if err != nil { return err } - orderbooks, err := ku.UpdateOrderbook(context.Background(), cp, asset.Futures) + orderbooks, err := ku.UpdateOrderbook(ctx, cp, asset.Futures) if err != nil { return err } @@ -555,12 +556,12 @@ func (ku *Kucoin) processFuturesOrderbookSnapshot(respData []byte, instrument st } // ProcessFuturesOrderbookLevel2 processes a V2 futures account orderbook data. -func (ku *Kucoin) processFuturesOrderbookLevel2(respData []byte, instrument string) error { +func (ku *Kucoin) processFuturesOrderbookLevel2(ctx context.Context, respData []byte, instrument string) error { resp := WsFuturesOrderbookInfo{} if err := json.Unmarshal(respData, &resp); err != nil { return err } - detail, err := ku.GetFuturesPartOrderbook100(context.Background(), instrument) + detail, err := ku.GetFuturesPartOrderbook100(ctx, instrument) if err != nil { return err } @@ -686,13 +687,13 @@ func (ku *Kucoin) processMarginLendingTradeOrderEvent(respData []byte) error { } // processAccountBalanceChange processes an account balance change -func (ku *Kucoin) processAccountBalanceChange(respData []byte) error { +func (ku *Kucoin) processAccountBalanceChange(ctx context.Context, respData []byte) error { response := WsAccountBalance{} err := json.Unmarshal(respData, &response) if err != nil { return err } - creds, err := ku.GetCredentials(context.TODO()) + creds, err := ku.GetCredentials(ctx) if err != nil { return err } @@ -1032,15 +1033,17 @@ func (ku *Kucoin) processMarketSnapshot(respData []byte, topic string) error { // Subscribe sends a websocket message to receive data from the channel func (ku *Kucoin) Subscribe(subscriptions subscription.List) error { - return ku.manageSubscriptions(subscriptions, "subscribe") + ctx := context.TODO() + return ku.manageSubscriptions(ctx, subscriptions, "subscribe") } // Unsubscribe sends a websocket message to stop receiving data from the channel func (ku *Kucoin) Unsubscribe(subscriptions subscription.List) error { - return ku.manageSubscriptions(subscriptions, "unsubscribe") + ctx := context.TODO() + return ku.manageSubscriptions(ctx, subscriptions, "unsubscribe") } -func (ku *Kucoin) manageSubscriptions(subs subscription.List, operation string) error { +func (ku *Kucoin) manageSubscriptions(ctx context.Context, subs subscription.List, operation string) error { var errs error for _, s := range subs { msgID := strconv.FormatInt(ku.Websocket.Conn.GenerateMessageID(false), 10) @@ -1051,7 +1054,7 @@ func (ku *Kucoin) manageSubscriptions(subs subscription.List, operation string) PrivateChannel: s.Authenticated, Response: true, } - if respRaw, err := ku.Websocket.Conn.SendMessageReturnResponse(context.TODO(), request.Unset, "msgID:"+msgID, req); err != nil { + if respRaw, err := ku.Websocket.Conn.SendMessageReturnResponse(ctx, request.Unset, "msgID:"+msgID, req); err != nil { errs = common.AppendError(errs, err) } else { rType, err := jsonparser.GetUnsafeString(respRaw, "type") @@ -1131,7 +1134,7 @@ type job struct { } // setupOrderbookManager sets up the orderbook manager for websocket orderbook data handling. -func (ku *Kucoin) setupOrderbookManager() { +func (ku *Kucoin) setupOrderbookManager(ctx context.Context) { locker.Lock() defer locker.Unlock() if ku.obm == nil { @@ -1155,7 +1158,7 @@ func (ku *Kucoin) setupOrderbookManager() { } for range maxWSOrderbookWorkers { // 10 workers for synchronising book - ku.SynchroniseWebsocketOrderbook() + ku.SynchroniseWebsocketOrderbook(ctx) } } @@ -1248,7 +1251,7 @@ func (o *orderbookManager) setNeedsFetchingBook(pair currency.Pair, assetType as // SynchroniseWebsocketOrderbook synchronises full orderbook for currency pair // asset -func (ku *Kucoin) SynchroniseWebsocketOrderbook() { +func (ku *Kucoin) SynchroniseWebsocketOrderbook(ctx context.Context) { ku.Websocket.Wg.Add(1) go func() { defer ku.Websocket.Wg.Done() @@ -1263,7 +1266,7 @@ func (ku *Kucoin) SynchroniseWebsocketOrderbook() { } } case j := <-ku.obm.jobs: - err := ku.processJob(j.Pair, j.AssetType) + err := ku.processJob(ctx, j.Pair, j.AssetType) if err != nil { log.Errorf(log.WebsocketMgr, "%s processing websocket orderbook error %v", @@ -1316,8 +1319,8 @@ func (ku *Kucoin) SeedLocalCacheWithBook(p currency.Pair, orderbookNew *Orderboo } // processJob fetches and processes orderbook updates -func (ku *Kucoin) processJob(p currency.Pair, assetType asset.Item) error { - err := ku.SeedLocalCache(context.TODO(), p, assetType) +func (ku *Kucoin) processJob(ctx context.Context, p currency.Pair, assetType asset.Item) error { + err := ku.SeedLocalCache(ctx, p, assetType) if err != nil { err = ku.obm.StopFetchingBook(p, assetType) if err != nil { diff --git a/exchanges/okx/okx_business_websocket.go b/exchanges/okx/okx_business_websocket.go index 0e29b292..e0557ed7 100644 --- a/exchanges/okx/okx_business_websocket.go +++ b/exchanges/okx/okx_business_websocket.go @@ -44,7 +44,7 @@ var ( ) // WsConnectBusiness connects to a business websocket channel. -func (ok *Okx) WsConnectBusiness() error { +func (ok *Okx) WsConnectBusiness(ctx context.Context) error { if !ok.Websocket.IsEnabled() || !ok.IsEnabled() { return websocket.ErrWebsocketNotEnabled } @@ -53,12 +53,12 @@ func (ok *Okx) WsConnectBusiness() error { dialer.WriteBufferSize = 8192 ok.Websocket.Conn.SetURL(okxBusinessWebsocketURL) - err := ok.Websocket.Conn.Dial(&dialer, http.Header{}) + err := ok.Websocket.Conn.Dial(ctx, &dialer, http.Header{}) if err != nil { return err } ok.Websocket.Wg.Add(1) - go ok.wsReadData(ok.Websocket.Conn) + go ok.wsReadData(ctx, ok.Websocket.Conn) if ok.Verbose { log.Debugf(log.ExchangeSys, "Successful connection to %v\n", ok.Websocket.GetWebsocketURL()) @@ -69,7 +69,7 @@ func (ok *Okx) WsConnectBusiness() error { Delay: time.Second * 20, }) if ok.Websocket.CanUseAuthenticatedEndpoints() { - err = ok.WsSpreadAuth(context.TODO()) + err = ok.WsSpreadAuth(ctx) if err != nil { log.Errorf(log.ExchangeSys, "Error connecting auth socket: %s\n", err.Error()) ok.Websocket.SetCanUseAuthenticatedEndpoints(false) @@ -158,18 +158,18 @@ func (ok *Okx) GenerateDefaultBusinessSubscriptions() ([]subscription.Subscripti } // BusinessSubscribe sends a websocket subscription request to several channels to receive data. -func (ok *Okx) BusinessSubscribe(channelsToSubscribe subscription.List) error { - return ok.handleBusinessSubscription(operationSubscribe, channelsToSubscribe) +func (ok *Okx) BusinessSubscribe(ctx context.Context, channelsToSubscribe subscription.List) error { + return ok.handleBusinessSubscription(ctx, operationSubscribe, channelsToSubscribe) } // BusinessUnsubscribe sends a websocket unsubscription request to several channels to receive data. -func (ok *Okx) BusinessUnsubscribe(channelsToUnsubscribe subscription.List) error { - return ok.handleBusinessSubscription(operationUnsubscribe, channelsToUnsubscribe) +func (ok *Okx) BusinessUnsubscribe(ctx context.Context, channelsToUnsubscribe subscription.List) error { + return ok.handleBusinessSubscription(ctx, operationUnsubscribe, channelsToUnsubscribe) } // handleBusinessSubscription sends a subscription and unsubscription information thought the business websocket endpoint. // as of the okx, exchange this endpoint sends subscription and unsubscription messages but with a list of json objects. -func (ok *Okx) handleBusinessSubscription(operation string, subscriptions subscription.List) error { +func (ok *Okx) handleBusinessSubscription(ctx context.Context, operation string, subscriptions subscription.List) error { wsSubscriptionReq := WSSubscriptionInformationList{Operation: operation} var channels subscription.List var authChannels subscription.List @@ -210,7 +210,7 @@ func (ok *Okx) handleBusinessSubscription(operation string, subscriptions subscr } if len(chunk) > maxConnByteLen { i-- - err = ok.Websocket.Conn.SendJSONMessage(context.Background(), request.UnAuth, wsSubscriptionReq) + err = ok.Websocket.Conn.SendJSONMessage(ctx, request.UnAuth, wsSubscriptionReq) if err != nil { return err } @@ -227,7 +227,7 @@ func (ok *Okx) handleBusinessSubscription(operation string, subscriptions subscr continue } } - err = ok.Websocket.Conn.SendJSONMessage(context.Background(), request.UnAuth, wsSubscriptionReq) + err = ok.Websocket.Conn.SendJSONMessage(ctx, request.UnAuth, wsSubscriptionReq) if err != nil { return err } diff --git a/exchanges/okx/okx_test.go b/exchanges/okx/okx_test.go index dfb86f7a..b9e3e912 100644 --- a/exchanges/okx/okx_test.go +++ b/exchanges/okx/okx_test.go @@ -4031,7 +4031,7 @@ func TestPushData(t *testing.T) { ok.API.AuthenticatedSupport = false ok.API.AuthenticatedWebsocketSupport = false } - err = ok.WsHandleData([]byte(pushDataMap[x])) + err = ok.WsHandleData(t.Context(), []byte(pushDataMap[x])) require.NoErrorf(t, err, "Okx %s error %s", x, err) } } @@ -4045,7 +4045,7 @@ func TestPushDataDynamic(t *testing.T) { } var err error for x := range dataMap { - err = ok.WsHandleData([]byte(dataMap[x])) + err = ok.WsHandleData(t.Context(), []byte(dataMap[x])) require.NoError(t, err) } } diff --git a/exchanges/okx/okx_websocket.go b/exchanges/okx/okx_websocket.go index 3d39b19b..a00b453b 100644 --- a/exchanges/okx/okx_websocket.go +++ b/exchanges/okx/okx_websocket.go @@ -237,6 +237,7 @@ var subscriptionNames = map[string]string{ // WsConnect initiates a websocket connection func (ok *Okx) WsConnect() error { + ctx := context.TODO() if !ok.Websocket.IsEnabled() || !ok.IsEnabled() { return websocket.ErrWebsocketNotEnabled } @@ -244,12 +245,12 @@ func (ok *Okx) WsConnect() error { dialer.ReadBufferSize = 8192 dialer.WriteBufferSize = 8192 - err := ok.Websocket.Conn.Dial(&dialer, http.Header{}) + err := ok.Websocket.Conn.Dial(ctx, &dialer, http.Header{}) if err != nil { return err } ok.Websocket.Wg.Add(1) - go ok.wsReadData(ok.Websocket.Conn) + go ok.wsReadData(ctx, ok.Websocket.Conn) if ok.Verbose { log.Debugf(log.ExchangeSys, "Successful connection to %v\n", ok.Websocket.GetWebsocketURL()) @@ -260,7 +261,7 @@ func (ok *Okx) WsConnect() error { Delay: time.Second * 20, }) if ok.Websocket.CanUseAuthenticatedEndpoints() { - err = ok.WsAuth(context.TODO()) + err = ok.WsAuth(ctx) if err != nil { log.Errorf(log.ExchangeSys, "Error connecting auth socket: %s\n", err.Error()) ok.Websocket.SetCanUseAuthenticatedEndpoints(false) @@ -279,12 +280,12 @@ func (ok *Okx) WsAuth(ctx context.Context) error { return err } var dialer gws.Dialer - err = ok.Websocket.AuthConn.Dial(&dialer, http.Header{}) + err = ok.Websocket.AuthConn.Dial(ctx, &dialer, http.Header{}) if err != nil { return err } ok.Websocket.Wg.Add(1) - go ok.wsReadData(ok.Websocket.AuthConn) + go ok.wsReadData(ctx, ok.Websocket.AuthConn) ok.Websocket.AuthConn.SetupPingHandler(request.Unset, websocket.PingHandler{ MessageType: gws.TextMessage, Message: pingMsg, @@ -315,14 +316,14 @@ func (ok *Okx) WsAuth(ctx context.Context) error { } // wsReadData sends msgs from public and auth websockets to data handler -func (ok *Okx) wsReadData(ws websocket.Connection) { +func (ok *Okx) wsReadData(ctx context.Context, ws websocket.Connection) { defer ok.Websocket.Wg.Done() for { resp := ws.ReadMessage() if resp.Raw == nil { return } - if err := ok.WsHandleData(resp.Raw); err != nil { + if err := ok.WsHandleData(ctx, resp.Raw); err != nil { ok.Websocket.DataHandler <- err } } @@ -330,17 +331,19 @@ func (ok *Okx) wsReadData(ws websocket.Connection) { // Subscribe sends a websocket subscription request to several channels to receive data. func (ok *Okx) Subscribe(channelsToSubscribe subscription.List) error { - return ok.handleSubscription(operationSubscribe, channelsToSubscribe) + ctx := context.TODO() + return ok.handleSubscription(ctx, operationSubscribe, channelsToSubscribe) } // Unsubscribe sends a websocket unsubscription request to several channels to receive data. func (ok *Okx) Unsubscribe(channelsToUnsubscribe subscription.List) error { - return ok.handleSubscription(operationUnsubscribe, channelsToUnsubscribe) + ctx := context.TODO() + return ok.handleSubscription(ctx, operationUnsubscribe, channelsToUnsubscribe) } // handleSubscription sends a subscription and unsubscription information thought the websocket endpoint. // as of the okx, exchange this endpoint sends subscription and unsubscription messages but with a list of json objects. -func (ok *Okx) handleSubscription(operation string, subs subscription.List) error { +func (ok *Okx) handleSubscription(ctx context.Context, operation string, subs subscription.List) error { reqs := WSSubscriptionInformationList{Operation: operation} authRequests := WSSubscriptionInformationList{Operation: operation} var channels subscription.List @@ -364,7 +367,7 @@ func (ok *Okx) handleSubscription(operation string, subs subscription.List) erro if len(authChunk) > maxConnByteLen { authRequests.Arguments = authRequests.Arguments[:len(authRequests.Arguments)-1] i-- - err = ok.Websocket.AuthConn.SendJSONMessage(context.TODO(), request.Unset, authRequests) + err = ok.Websocket.AuthConn.SendJSONMessage(ctx, request.Unset, authRequests) if err != nil { return err } @@ -388,7 +391,7 @@ func (ok *Okx) handleSubscription(operation string, subs subscription.List) erro } if len(chunk) > maxConnByteLen { i-- - err = ok.Websocket.Conn.SendJSONMessage(context.TODO(), request.Unset, reqs) + err = ok.Websocket.Conn.SendJSONMessage(ctx, request.Unset, reqs) if err != nil { return err } @@ -408,13 +411,13 @@ func (ok *Okx) handleSubscription(operation string, subs subscription.List) erro } if len(reqs.Arguments) > 0 { - if err := ok.Websocket.Conn.SendJSONMessage(context.TODO(), request.Unset, reqs); err != nil { + if err := ok.Websocket.Conn.SendJSONMessage(ctx, request.Unset, reqs); err != nil { return err } } if len(authRequests.Arguments) > 0 && ok.Websocket.CanUseAuthenticatedEndpoints() { - if err := ok.Websocket.AuthConn.SendJSONMessage(context.TODO(), request.Unset, authRequests); err != nil { + if err := ok.Websocket.AuthConn.SendJSONMessage(ctx, request.Unset, authRequests); err != nil { return err } } @@ -427,7 +430,7 @@ func (ok *Okx) handleSubscription(operation string, subs subscription.List) erro } // WsHandleData will read websocket raw data and pass to appropriate handler -func (ok *Okx) WsHandleData(respRaw []byte) error { +func (ok *Okx) WsHandleData(ctx context.Context, respRaw []byte) error { if id, _ := jsonparser.GetString(respRaw, "id"); id != "" { return ok.Websocket.Match.RequireMatchWithData(id, respRaw) } @@ -491,7 +494,7 @@ func (ok *Okx) WsHandleData(respRaw []byte) error { var response WsPositionResponse return ok.wsProcessPushData(respRaw, &response) case channelBalanceAndPosition: - return ok.wsProcessBalanceAndPosition(respRaw) + return ok.wsProcessBalanceAndPosition(ctx, respRaw) case channelOrders: return ok.wsProcessOrders(respRaw) case channelAlgoOrders: @@ -1442,12 +1445,12 @@ func (ok *Okx) wsProcessBlockPublicTrades(data []byte) error { return trade.AddTradesToBuffer(trades...) } -func (ok *Okx) wsProcessBalanceAndPosition(data []byte) error { +func (ok *Okx) wsProcessBalanceAndPosition(ctx context.Context, data []byte) error { var resp WsBalanceAndPosition if err := json.Unmarshal(data, &resp); err != nil { return err } - creds, err := ok.GetCredentials(context.TODO()) + creds, err := ok.GetCredentials(ctx) if err != nil { return err } diff --git a/exchanges/okx/okx_wrapper.go b/exchanges/okx/okx_wrapper.go index 9e4c2fdd..530f60f7 100644 --- a/exchanges/okx/okx_wrapper.go +++ b/exchanges/okx/okx_wrapper.go @@ -2113,7 +2113,7 @@ func (ok *Okx) GetAvailableTransferChains(ctx context.Context, cryptocurrency cu // getInstrumentsForOptions returns the instruments for options asset type func (ok *Okx) getInstrumentsForOptions(ctx context.Context) ([]Instrument, error) { - underlyings, err := ok.GetPublicUnderlyings(context.Background(), instTypeOption) + underlyings, err := ok.GetPublicUnderlyings(ctx, instTypeOption) if err != nil { return nil, err } @@ -2896,7 +2896,7 @@ func (ok *Okx) GetOpenInterest(ctx context.Context, k ...key.PairAsset) ([]futur switch instType { case instTypeOption: var underlyings []string - underlyings, err = ok.GetPublicUnderlyings(context.Background(), instTypeOption) + underlyings, err = ok.GetPublicUnderlyings(ctx, instTypeOption) if err != nil { return nil, err } @@ -2961,7 +2961,7 @@ func (ok *Okx) GetOpenInterest(ctx context.Context, k ...key.PairAsset) ([]futur switch instTypes[k[0].Asset] { case instTypeOption: var underlyings []string - underlyings, err = ok.GetPublicUnderlyings(context.Background(), instTypeOption) + underlyings, err = ok.GetPublicUnderlyings(ctx, instTypeOption) if err != nil { return nil, err } diff --git a/exchanges/poloniex/poloniex_test.go b/exchanges/poloniex/poloniex_test.go index de7e4ecc..68e1a10c 100644 --- a/exchanges/poloniex/poloniex_test.go +++ b/exchanges/poloniex/poloniex_test.go @@ -548,7 +548,7 @@ func TestWsAuth(t *testing.T) { t.Skip(websocket.ErrWebsocketNotEnabled.Error()) } var dialer gws.Dialer - err := p.Websocket.Conn.Dial(&dialer, http.Header{}) + err := p.Websocket.Conn.Dial(t.Context(), &dialer, http.Header{}) if err != nil { t.Fatal(err) } @@ -557,7 +557,7 @@ func TestWsAuth(t *testing.T) { if err != nil { t.Fatal(err) } - err = p.wsSendAuthorisedCommand(creds.Secret, creds.Key, "subscribe") + err = p.wsSendAuthorisedCommand(t.Context(), creds.Secret, creds.Key, "subscribe") if err != nil { t.Fatal(err) } diff --git a/exchanges/poloniex/poloniex_websocket.go b/exchanges/poloniex/poloniex_websocket.go index 8d06f277..fc241ce8 100644 --- a/exchanges/poloniex/poloniex_websocket.go +++ b/exchanges/poloniex/poloniex_websocket.go @@ -56,16 +56,17 @@ var ( // WsConnect initiates a websocket connection func (p *Poloniex) WsConnect() error { + ctx := context.TODO() if !p.Websocket.IsEnabled() || !p.IsEnabled() { return websocket.ErrWebsocketNotEnabled } var dialer gws.Dialer - err := p.Websocket.Conn.Dial(&dialer, http.Header{}) + err := p.Websocket.Conn.Dial(ctx, &dialer, http.Header{}) if err != nil { return err } - err = p.loadCurrencyDetails(context.TODO()) + err = p.loadCurrencyDetails(ctx) if err != nil { return err } @@ -573,19 +574,21 @@ func (p *Poloniex) GenerateDefaultSubscriptions() (subscription.List, error) { // Subscribe sends a websocket message to receive data from the channel func (p *Poloniex) Subscribe(subs subscription.List) error { - return p.manageSubs(subs, wsSubscribeOp) + ctx := context.TODO() + return p.manageSubs(ctx, subs, wsSubscribeOp) } // Unsubscribe sends a websocket message to stop receiving data from the channel func (p *Poloniex) Unsubscribe(subs subscription.List) error { - return p.manageSubs(subs, wsUnsubscribeOp) + ctx := context.TODO() + return p.manageSubs(ctx, subs, wsUnsubscribeOp) } -func (p *Poloniex) manageSubs(subs subscription.List, op wsOp) error { +func (p *Poloniex) manageSubs(ctx context.Context, subs subscription.List, op wsOp) error { var creds *account.Credentials if p.IsWebsocketAuthenticationSupported() { var err error - creds, err = p.GetCredentials(context.TODO()) + creds, err = p.GetCredentials(ctx) if err != nil { return err } @@ -595,7 +598,7 @@ func (p *Poloniex) manageSubs(subs subscription.List, op wsOp) error { for _, s := range subs { var err error if creds != nil && strings.EqualFold(strconv.FormatInt(wsAccountNotificationID, 10), s.Channel) { - err = p.wsSendAuthorisedCommand(creds.Secret, creds.Key, op) + err = p.wsSendAuthorisedCommand(ctx, creds.Secret, creds.Key, op) } else { req := wsCommand{Command: op} if strings.EqualFold(strconv.FormatInt(wsTickerDataID, 10), s.Channel) { @@ -606,7 +609,7 @@ func (p *Poloniex) manageSubs(subs subscription.List, op wsOp) error { } req.Channel = s.Pairs[0].String() } - err = p.Websocket.Conn.SendJSONMessage(context.TODO(), request.Unset, req) + err = p.Websocket.Conn.SendJSONMessage(ctx, request.Unset, req) } if err == nil { if op == wsSubscribeOp { @@ -622,7 +625,7 @@ func (p *Poloniex) manageSubs(subs subscription.List, op wsOp) error { return errs } -func (p *Poloniex) wsSendAuthorisedCommand(secret, key string, op wsOp) error { +func (p *Poloniex) wsSendAuthorisedCommand(ctx context.Context, secret, key string, op wsOp) error { nonce := fmt.Sprintf("nonce=%v", time.Now().UnixNano()) hmac, err := crypto.GetHMAC(crypto.HashSHA512, []byte(nonce), []byte(secret)) if err != nil { @@ -635,7 +638,7 @@ func (p *Poloniex) wsSendAuthorisedCommand(secret, key string, op wsOp) error { Key: key, Payload: nonce, } - return p.Websocket.Conn.SendJSONMessage(context.TODO(), request.Unset, req) + return p.Websocket.Conn.SendJSONMessage(ctx, request.Unset, req) } func (p *Poloniex) processAccountMarginPosition(notification []any) error { diff --git a/internal/testing/exchange/exchange.go b/internal/testing/exchange/exchange.go index 2506f831..27ce4e49 100644 --- a/internal/testing/exchange/exchange.go +++ b/internal/testing/exchange/exchange.go @@ -2,6 +2,7 @@ package exchange import ( "bufio" + "context" "fmt" "log" "net/http" @@ -124,7 +125,7 @@ type FixtureError struct { } // FixtureToDataHandler squirts the contents of a file to a reader function (probably e.wsHandleData) and asserts no errors are returned -func FixtureToDataHandler(tb testing.TB, fixturePath string, reader func([]byte) error) { +func FixtureToDataHandler(tb testing.TB, fixturePath string, reader func(context.Context, []byte) error) { tb.Helper() for _, e := range FixtureToDataHandlerWithErrors(tb, fixturePath, reader) { @@ -134,7 +135,7 @@ func FixtureToDataHandler(tb testing.TB, fixturePath string, reader func([]byte) // FixtureToDataHandlerWithErrors squirts the contents of a file to a reader function (probably e.wsHandleData) and returns handler errors // Any errors setting up the fixture will fail tests -func FixtureToDataHandlerWithErrors(tb testing.TB, fixturePath string, reader func([]byte) error) []FixtureError { +func FixtureToDataHandlerWithErrors(tb testing.TB, fixturePath string, reader func(context.Context, []byte) error) []FixtureError { tb.Helper() fixture, err := os.Open(fixturePath) @@ -147,7 +148,7 @@ func FixtureToDataHandlerWithErrors(tb testing.TB, fixturePath string, reader fu s := bufio.NewScanner(fixture) for s.Scan() { msg := s.Bytes() - if err := reader(msg); err != nil { + if err := reader(tb.Context(), msg); err != nil { errs = append(errs, FixtureError{ Err: err, Msg: msg,