diff --git a/exchanges/btcmarkets/btcmarkets_test.go b/exchanges/btcmarkets/btcmarkets_test.go index 59734a77..704141a1 100644 --- a/exchanges/btcmarkets/btcmarkets_test.go +++ b/exchanges/btcmarkets/btcmarkets_test.go @@ -20,6 +20,7 @@ import ( "github.com/thrasher-corp/gocryptotrader/exchanges/orderbook" "github.com/thrasher-corp/gocryptotrader/exchanges/sharedtestvalues" "github.com/thrasher-corp/gocryptotrader/exchanges/subscription" + "github.com/thrasher-corp/gocryptotrader/exchanges/trade" testexch "github.com/thrasher-corp/gocryptotrader/internal/testing/exchange" testsubs "github.com/thrasher-corp/gocryptotrader/internal/testing/subscriptions" ) @@ -542,18 +543,53 @@ func TestWsTicker(t *testing.T) { } } -func TestWsTrade(t *testing.T) { - pressXToJSON := []byte(` { "marketId": "BTC-AUD", - "timestamp": "2019-04-08T20:54:27.632Z", - "tradeId": 3153171493, - "price": "7370.11", - "volume": "0.10901605", - "side": "Ask", - "messageType": "trade" - }`) - err := b.wsHandleData(pressXToJSON) - if err != nil { - t.Error(err) +func TestWSTrade(t *testing.T) { + t.Parallel() + + b := new(BTCMarkets) //nolint:govet // Intentional shadow to avoid future copy/paste mistakes + require.NoError(t, testexch.Setup(b), "Test instance Setup must not error") + fErrs := testexch.FixtureToDataHandlerWithErrors(t, "testdata/wsAllTrades.json", b.wsHandleData) + require.Equal(t, 2, len(fErrs), "Must get correct number of errors from wsHandleData") + assert.ErrorIs(t, fErrs[0].Err, order.ErrSideIsInvalid, "Side.UnmarshalJSON errors should propagate correctly") + assert.ErrorContains(t, fErrs[0].Err, "WRONG", "Side.UnmarshalJSON errors should propagate correctly") + assert.ErrorIs(t, fErrs[1].Err, order.ErrSideIsInvalid, "wsHandleData errors should propagate correctly") + assert.ErrorContains(t, fErrs[1].Err, "ANY", "wsHandleData errors should propagate correctly") + close(b.Websocket.DataHandler) + + exp := []trade.Data{ + { + Exchange: b.Name, + CurrencyPair: currency.NewPairWithDelimiter("BTC", "AUD", currency.DashDelimiter), + Timestamp: time.Date(2025, 3, 13, 8, 27, 55, 691000000, time.UTC), + Price: 131200.34, + Amount: 0.00151228, + Side: order.Buy, + TID: "7006384466", + AssetType: asset.Spot, + }, + { + Exchange: b.Name, + CurrencyPair: currency.NewPairWithDelimiter("BTC", "AUD", currency.DashDelimiter), + Timestamp: time.Date(2025, 3, 13, 8, 28, 2, 273000000, time.UTC), + Price: 131065.01, + Amount: 0.05, + Side: order.Sell, + TID: "7006384467", + AssetType: asset.Spot, + }, + } + require.Len(t, b.Websocket.DataHandler, 2, "Must see correct number of trades") + + for resp := range b.Websocket.DataHandler { + switch v := resp.(type) { + case trade.Data: + i := 1 - len(b.Websocket.DataHandler) + require.Equalf(t, exp[i], v, "Trade[%d] must be correct", i) + case error: + t.Error(v) + default: + t.Errorf("Unexpected type in DataHandler: %T(%s)", v, v) + } } } diff --git a/exchanges/btcmarkets/btcmarkets_types.go b/exchanges/btcmarkets/btcmarkets_types.go index 162e0ca3..eb2af1e6 100644 --- a/exchanges/btcmarkets/btcmarkets_types.go +++ b/exchanges/btcmarkets/btcmarkets_types.go @@ -4,6 +4,7 @@ import ( "time" "github.com/thrasher-corp/gocryptotrader/currency" + "github.com/thrasher-corp/gocryptotrader/exchanges/order" "github.com/thrasher-corp/gocryptotrader/exchanges/orderbook" ) @@ -373,13 +374,13 @@ type WsTick struct { // WsTrade message received for trade data type WsTrade struct { - Currency string `json:"marketId"` - Timestamp time.Time `json:"timestamp"` - TradeID int64 `json:"tradeId"` - Price float64 `json:"price,string"` - Volume float64 `json:"volume,string"` - Side string `json:"side"` - MessageType string `json:"messageType"` + Currency string `json:"marketId"` + Timestamp time.Time `json:"timestamp"` + TradeID int64 `json:"tradeId"` + Price float64 `json:"price,string"` + Volume float64 `json:"volume,string"` + Side order.Side `json:"side"` + MessageType string `json:"messageType"` } // WsOrderbook message received for orderbook data diff --git a/exchanges/btcmarkets/btcmarkets_websocket.go b/exchanges/btcmarkets/btcmarkets_websocket.go index 1e7c02fe..37c70df3 100644 --- a/exchanges/btcmarkets/btcmarkets_websocket.go +++ b/exchanges/btcmarkets/btcmarkets_websocket.go @@ -185,9 +185,12 @@ func (b *BTCMarkets) wsHandleData(respRaw []byte) error { } return nil case tradeEndPoint: - if !b.IsSaveTradeDataEnabled() { + tradeFeed := b.IsTradeFeedEnabled() + saveTradeData := b.IsSaveTradeDataEnabled() + if !saveTradeData && !tradeFeed { return nil } + var t WsTrade err := json.Unmarshal(respRaw, &t) if err != nil { @@ -200,11 +203,16 @@ func (b *BTCMarkets) wsHandleData(respRaw []byte) error { } side := order.Buy - if t.Side == "Ask" { + switch { + case t.Side.IsLong(): + // Nothing to do + case t.Side.IsShort(): side = order.Sell + default: + return fmt.Errorf("%w: `%s`", order.ErrSideIsInvalid, t.Side) } - return trade.AddTradesToBuffer(trade.Data{ + td := trade.Data{ Timestamp: t.Timestamp, CurrencyPair: p, AssetType: asset.Spot, @@ -213,7 +221,14 @@ func (b *BTCMarkets) wsHandleData(respRaw []byte) error { Amount: t.Volume, Side: side, TID: strconv.FormatInt(t.TradeID, 10), - }) + } + + if tradeFeed { + b.Websocket.DataHandler <- td + } + if saveTradeData { + return trade.AddTradesToBuffer(td) + } case tick: var tick WsTick err := json.Unmarshal(respRaw, &tick) diff --git a/exchanges/btcmarkets/testdata/wsAllTrades.json b/exchanges/btcmarkets/testdata/wsAllTrades.json new file mode 100644 index 00000000..3d29abf0 --- /dev/null +++ b/exchanges/btcmarkets/testdata/wsAllTrades.json @@ -0,0 +1,4 @@ +{"marketId":"BTC-AUD","timestamp":"2025-03-13T08:27:55.691Z","tradeId":7006384466,"price":"131200.34","volume":"0.00151228","messageType":"trade","side":"Bid"} +{"marketId":"BTC-AUD","timestamp":"2025-03-13T08:28:02.273Z","tradeId":7006384467,"price":"131065.01","volume":"0.05","messageType":"trade","side":"Ask"} +{"marketId":"BTC-AUD","timestamp":"2025-03-13T08:28:02.274Z","tradeId":7006384468,"price":"131065.02","volume":"0.06","messageType":"trade","side":"Wrong"} +{"marketId":"BTC-AUD","timestamp":"2025-03-13T08:28:02.274Z","tradeId":7006384469,"price":"131065.02","volume":"0.06","messageType":"trade","side":"Any"} \ No newline at end of file diff --git a/testdata/configtest.json b/testdata/configtest.json index d3d77a5f..13f9f074 100644 --- a/testdata/configtest.json +++ b/testdata/configtest.json @@ -297,7 +297,9 @@ }, "enabled": { "autoPairUpdates": true, - "websocketAPI": false + "websocketAPI": false, + "saveTradeData": false, + "tradeFeed": true } }, "bankAccounts": [