diff --git a/.github/notification_pr.workflow b/.github/notification_pr.workflow deleted file mode 100644 index 85ff3ba..0000000 --- a/.github/notification_pr.workflow +++ /dev/null @@ -1,10 +0,0 @@ -workflow "Notify about PR" { - on = "pull_request" - resolves = ["GitHub Action for Slack"] -} - -action "GitHub Action for Slack" { - uses = "Ilshidur/action-slack@305f56a15c09f84b6b4a86e83bff1c41c6b69c63" - secrets = ["SLACK_WEBHOOK"] - args = "A new PR has been created in Bitfinex websocket repo" -} diff --git a/.github/workflows/dotnet-core-branches.yml b/.github/workflows/dotnet-core-branches.yml new file mode 100644 index 0000000..b6225df --- /dev/null +++ b/.github/workflows/dotnet-core-branches.yml @@ -0,0 +1,23 @@ +name: .NET Core (branch) + +on: + pull_request: + branches: [ master ] + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: Setup .NET Core + uses: actions/setup-dotnet@v1 + with: + dotnet-version: 8.x + - name: Install dependencies + run: dotnet restore + - name: Build + run: dotnet build --configuration Release --no-restore + - name: Test + run: dotnet test --no-restore --verbosity normal diff --git a/.github/workflows/dotnet-core.yml b/.github/workflows/dotnet-core.yml new file mode 100644 index 0000000..60f60f9 --- /dev/null +++ b/.github/workflows/dotnet-core.yml @@ -0,0 +1,37 @@ +name: .NET Core + +on: + push: + branches: [ master ] + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: Setup .NET Core + uses: actions/setup-dotnet@v1 + with: + dotnet-version: 8.x + + - name: Install dependencies + run: dotnet restore + - name: Build + run: dotnet build --configuration Release --no-restore + - name: Test + run: dotnet test --no-restore --logger "trx;LogFileName=tests.trx" + - name: Test Report + uses: dorny/test-reporter@v1 + if: success() || failure() # run this step even if previous step failed + with: + name: tests + path: '**/*.trx' + reporter: dotnet-trx + - name: Pack library project + run: dotnet pack src/Bitfinex.Client.Websocket/Bitfinex.Client.Websocket.csproj --no-build --configuration Release --include-symbols -p:SymbolPackageFormat=snupkg -o . + - name: Publish library (NuGet) + run: dotnet nuget push *.nupkg --api-key ${{secrets.NUGET_API_KEY}} --source "https://api.nuget.org/v3/index.json" --skip-duplicate + #- name: Publish library (Github) + # run: dotnet nuget push *.nupkg --api-key ${{secrets.PUBLISH_TO_GITHUB_TOKEN}} --source "https://nuget.pkg.github.com/marfusios/index.json" --skip-duplicate diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 249f491..0000000 --- a/.travis.yml +++ /dev/null @@ -1,19 +0,0 @@ -language: csharp -dotnet: 6.0 -os: linux -dist: xenial -mono: none -sudo: required - -install: -before_script: -script: -- dotnet build -c Release -- dotnet test test/Bitfinex.Client.Websocket.Tests -c Release -deploy: - provider: script - skip_cleanup: true - script: - - cd src/Bitfinex.Client.Websocket && dotnet pack /p:PackageVersion=4.1.$TRAVIS_BUILD_NUMBER -c Release && cd bin/Release && dotnet nuget push **/*.4.1.$TRAVIS_BUILD_NUMBER.nupkg -k $NUGET_API_KEY -s https://api.nuget.org/v3/index.json - on: - branch: master \ No newline at end of file diff --git a/Bitfinex.Client.Websocket.sln b/Bitfinex.Client.Websocket.sln index 4a4cece..a3a137a 100644 --- a/Bitfinex.Client.Websocket.sln +++ b/Bitfinex.Client.Websocket.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.29806.167 +# Visual Studio Version 17 +VisualStudioVersion = 17.8.34601.278 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{360B18BD-653A-4824-9261-C88167EEBAD2}" EndProject @@ -19,8 +19,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bitfinex.Client.Websocket.S EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{6D0FCFA1-4C4C-4BBD-83CC-22C8E464E338}" ProjectSection(SolutionItems) = preProject - .travis.yml = .travis.yml bitfinex_logo.png = bitfinex_logo.png + .github\workflows\dotnet-core-branches.yml = .github\workflows\dotnet-core-branches.yml + .github\workflows\dotnet-core.yml = .github\workflows\dotnet-core.yml LICENSE = LICENSE README.md = README.md EndProjectSection diff --git a/Directory.Build.props b/Directory.Build.props new file mode 100644 index 0000000..9185158 --- /dev/null +++ b/Directory.Build.props @@ -0,0 +1,9 @@ + + + + + + 4.1.0 + + + diff --git a/README.md b/README.md index 2676edb..9b1bcb6 100644 --- a/README.md +++ b/README.md @@ -346,8 +346,3 @@ Due to the large amount of questions about integration of this library into a de ### Available for help I do consulting, please don't hesitate to contact me if you have a custom solution you would like me to implement ([web](http://mkotas.cz/), ) - -Donations gratefully accepted. -* [![Donate with Bitcoin](https://en.cryptobadges.io/badge/small/1HfxKZhvm68qK3gE8bJAdDBWkcZ2AFs9pw)](https://en.cryptobadges.io/donate/1HfxKZhvm68qK3gE8bJAdDBWkcZ2AFs9pw) -* [![Donate with Litecoin](https://en.cryptobadges.io/badge/small/LftdENE8DTbLpV6RZLKLdzYzVU82E6dz4W)](https://en.cryptobadges.io/donate/LftdENE8DTbLpV6RZLKLdzYzVU82E6dz4W) -* [![Donate with Ethereum](https://en.cryptobadges.io/badge/small/0xb9637c56b307f24372cdcebd208c0679d4e48a47)](https://en.cryptobadges.io/donate/0xb9637c56b307f24372cdcebd208c0679d4e48a47) diff --git a/src/Bitfinex.Client.Websocket/Bitfinex.Client.Websocket.csproj b/src/Bitfinex.Client.Websocket/Bitfinex.Client.Websocket.csproj index 974106d..bd6b1c3 100644 --- a/src/Bitfinex.Client.Websocket/Bitfinex.Client.Websocket.csproj +++ b/src/Bitfinex.Client.Websocket/Bitfinex.Client.Websocket.csproj @@ -1,37 +1,38 @@  - - netstandard2.0;netstandard2.1;net5;net6 - Bitfinex.Client.Websocket - 4.0.0 - Mariusz Kotas - Client for Bitfinex and Ethfinex websocket API version 2.0 - false - - Copyright 2021 Mariusz Kotas. All rights reserved. - Bitfinex Ethfinex websockets websocket client cryptocurrency exchange bitcoin - https://github.com/Marfusios/bitfinex-client-websocket/blob/master/LICENSE - https://github.com/Marfusios/bitfinex-client-websocket - http://blog.bitfinex.com/wp-content/uploads/2016/05/bfx-stacked.png - https://github.com/Marfusios/bitfinex-client-websocket - Git - true - true - 4.0.0.0 - 4.0.0.0 + + netstandard2.1;net6;net7;net8 + Bitfinex.Client.Websocket + Mariusz Kotas + Client for Bitfinex and Ethfinex websocket API version 2.0 + false + Enhancements + Copyright 2024 Mariusz Kotas. All rights reserved. + Bitfinex Ethfinex websockets websocket client cryptocurrency exchange bitcoin + MIT + https://github.com/Marfusios/bitfinex-client-websocket + http://blog.bitfinex.com/wp-content/uploads/2016/05/bfx-stacked.png + icon.png + https://github.com/Marfusios/bitfinex-client-websocket + README.md + Git + true + true - true - snupkg - + true + snupkg + enable + - - - all - runtime; build; native; contentfiles; analyzers - - - - - + + + + + + + + + + diff --git a/src/Bitfinex.Client.Websocket/Client/BitfinexAuthenticatedHandler.cs b/src/Bitfinex.Client.Websocket/Client/BitfinexAuthenticatedHandler.cs index 802137e..1156963 100644 --- a/src/Bitfinex.Client.Websocket/Client/BitfinexAuthenticatedHandler.cs +++ b/src/Bitfinex.Client.Websocket/Client/BitfinexAuthenticatedHandler.cs @@ -1,5 +1,4 @@ using System.Linq; -using Bitfinex.Client.Websocket.Logging; using Bitfinex.Client.Websocket.Responses.Balance; using Bitfinex.Client.Websocket.Responses.Configurations; using Bitfinex.Client.Websocket.Responses.Notifications; @@ -9,18 +8,20 @@ using Bitfinex.Client.Websocket.Responses.Trades; using Bitfinex.Client.Websocket.Responses.TradesPrivate; using Bitfinex.Client.Websocket.Responses.Wallets; +using Microsoft.Extensions.Logging; using Newtonsoft.Json.Linq; namespace Bitfinex.Client.Websocket.Client { internal class BitfinexAuthenticatedHandler { - private static readonly ILog Log = LogProvider.GetCurrentClassLogger(); + private readonly ILogger _logger; private readonly BitfinexClientStreams _streams; - public BitfinexAuthenticatedHandler(BitfinexClientStreams streams, BitfinexChannelList channelIdToHandler) + public BitfinexAuthenticatedHandler(BitfinexClientStreams streams, BitfinexChannelList channelIdToHandler, ILogger logger) { _streams = streams; + _logger = logger; channelIdToHandler[0] = HandleAccountInfo; } @@ -35,17 +36,17 @@ internal void HandleAccountInfo(JToken token, ConfigurationState config) var itemsCount = token?.Count(); if (token == null || itemsCount < 2) { - Log.Warn($"Invalid message format, too low items"); + _logger.LogWarning(L("Invalid message format, too low items")); return; } var secondItem = token[1]; - if (secondItem.Type != JTokenType.String) + if (secondItem?.Type != JTokenType.String) { - Log.Warn(L("Invalid message format, second param is not string")); + _logger.LogWarning(L("Invalid message format, second param is not string")); return; } - var msgType = (string)secondItem; + var msgType = (string?)secondItem; if (msgType == "hb") { // heartbeat, ignore @@ -54,7 +55,7 @@ internal void HandleAccountInfo(JToken token, ConfigurationState config) if (itemsCount < 3) { - Log.Warn(L("Invalid message format, too low items")); + _logger.LogWarning(L("Invalid message format, too low items")); return; } @@ -109,9 +110,9 @@ internal void HandleAccountInfo(JToken token, ConfigurationState config) case "miu": MarginInfo.Handle(token, _streams.MarginInfoSubject); break; - //default: - // Log.Warning($"Missing private handler for '{msgType}'. Data: {token}"); - // break; + //default: + // Log.Warning($"Missing private handler for '{msgType}'. Data: {token}"); + // break; } } } diff --git a/src/Bitfinex.Client.Websocket/Client/BitfinexPublicHandler.cs b/src/Bitfinex.Client.Websocket/Client/BitfinexPublicHandler.cs index 15e7ce1..13b141c 100644 --- a/src/Bitfinex.Client.Websocket/Client/BitfinexPublicHandler.cs +++ b/src/Bitfinex.Client.Websocket/Client/BitfinexPublicHandler.cs @@ -1,5 +1,4 @@ using System; -using Bitfinex.Client.Websocket.Logging; using Bitfinex.Client.Websocket.Messages; using Bitfinex.Client.Websocket.Responses; using Bitfinex.Client.Websocket.Responses.Books; @@ -14,8 +13,6 @@ namespace Bitfinex.Client.Websocket.Client { internal class BitfinexPublicHandler { - private static readonly ILog Log = LogProvider.GetCurrentClassLogger(); - private readonly BitfinexClientStreams _streams; private readonly BitfinexChannelList _channelIdToHandler; @@ -52,14 +49,17 @@ public void OnObjectMessage(string msg) case MessageType.Unsubscribed: UnsubscribedResponse.Handle(msg, _streams.UnsubscriptionSubject); break; - //default: - // Log.Warning($"Missing handler for public stream, data: '{msg}'"); - // break; + //default: + // Log.Warning($"Missing handler for public stream, data: '{msg}'"); + // break; } } - private void OnSubscription(SubscribedResponse response) + private void OnSubscription(SubscribedResponse? response) { + if (response == null) + return; + _streams.SubscriptionSubject.OnNext(response); var channelId = response.ChanId; @@ -71,32 +71,32 @@ private void OnSubscription(SubscribedResponse response) switch (response.Channel) { case "ticker": - _channelIdToHandler[channelId] = (data, config) => + _channelIdToHandler[channelId] = (data, config) => Ticker.Handle(data, response, config, _streams.TickerSubject); break; case "trades": //if pair is null means that is funding if (response.Pair == null) { - _channelIdToHandler[channelId] = (data, config) => + _channelIdToHandler[channelId] = (data, config) => Funding.Handle(data, response, config, _streams.FundingsSubject); } else { - _channelIdToHandler[channelId] = (data, config) => + _channelIdToHandler[channelId] = (data, config) => Trade.Handle(data, response, config, _streams.TradesSubject, _streams.TradesSnapshotSubject); } break; case "candles": - _channelIdToHandler[channelId] = (data, config) => + _channelIdToHandler[channelId] = (data, config) => Candles.Handle(data, response, _streams.CandlesSubject); break; case "book": - if("R0".Equals(response.Prec, StringComparison.OrdinalIgnoreCase)) - _channelIdToHandler[channelId] = (data, config) => + if ("R0".Equals(response.Prec, StringComparison.OrdinalIgnoreCase)) + _channelIdToHandler[channelId] = (data, config) => RawBook.Handle(data, response, config, _streams.RawBookSubject, _streams.RawBookSnapshotSubject, _streams.BookChecksumSubject); else - _channelIdToHandler[channelId] = (data, config) => + _channelIdToHandler[channelId] = (data, config) => Book.Handle(data, response, config, _streams.BookSubject, _streams.BookSnapshotSubject, _streams.BookChecksumSubject); break; case "status": @@ -113,9 +113,9 @@ private void OnSubscription(SubscribedResponse response) } break; - //default: - // Log.Warning($"Missing subscription handler '{response.Channel}'"); - // break; + //default: + // Log.Warning($"Missing subscription handler '{response.Channel}'"); + // break; } } diff --git a/src/Bitfinex.Client.Websocket/Client/BitfinexSerialization.cs b/src/Bitfinex.Client.Websocket/Client/BitfinexSerialization.cs index e56cd67..2c6b0e0 100644 --- a/src/Bitfinex.Client.Websocket/Client/BitfinexSerialization.cs +++ b/src/Bitfinex.Client.Websocket/Client/BitfinexSerialization.cs @@ -5,7 +5,7 @@ namespace Bitfinex.Client.Websocket.Client { internal static class BitfinexSerialization { - public static T Deserialize(string msg) + public static T? Deserialize(string msg) where T : class { return JsonConvert.DeserializeObject(msg, BitfinexJsonSerializer.Settings); } diff --git a/src/Bitfinex.Client.Websocket/Client/BitfinexWebsocketClient.cs b/src/Bitfinex.Client.Websocket/Client/BitfinexWebsocketClient.cs index e1a10b4..c9e43ef 100644 --- a/src/Bitfinex.Client.Websocket/Client/BitfinexWebsocketClient.cs +++ b/src/Bitfinex.Client.Websocket/Client/BitfinexWebsocketClient.cs @@ -1,13 +1,13 @@ using System; using System.Linq; -using System.Threading.Tasks; using Bitfinex.Client.Websocket.Communicator; using Bitfinex.Client.Websocket.Json; -using Bitfinex.Client.Websocket.Logging; using Bitfinex.Client.Websocket.Requests; using Bitfinex.Client.Websocket.Requests.Configurations; using Bitfinex.Client.Websocket.Responses.Configurations; using Bitfinex.Client.Websocket.Validations; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Websocket.Client; @@ -21,8 +21,7 @@ namespace Bitfinex.Client.Websocket.Client /// public class BitfinexWebsocketClient : IDisposable { - private static readonly ILog Log = LogProvider.GetCurrentClassLogger(); - + private readonly ILogger _logger; private readonly IBitfinexCommunicator _communicator; private readonly IDisposable _messageReceivedSubscription; private readonly IDisposable _configurationSubscription; @@ -33,15 +32,16 @@ public class BitfinexWebsocketClient : IDisposable private readonly BitfinexPublicHandler _publicHandler; /// - public BitfinexWebsocketClient(IBitfinexCommunicator communicator) + public BitfinexWebsocketClient(IBitfinexCommunicator communicator, ILogger? logger = null) { BfxValidations.ValidateInput(communicator, nameof(communicator)); _communicator = communicator; + _logger = logger ?? NullLogger.Instance; _messageReceivedSubscription = _communicator.MessageReceived.Subscribe(HandleMessage); _configurationSubscription = Streams.ConfigurationSubject.Subscribe(HandleConfiguration); - _authenticatedHandler = new BitfinexAuthenticatedHandler(Streams, _channelIdToHandler); + _authenticatedHandler = new BitfinexAuthenticatedHandler(Streams, _channelIdToHandler, _logger); _publicHandler = new BitfinexPublicHandler(Streams, _channelIdToHandler); } @@ -80,7 +80,7 @@ public void Send(T request) } catch (Exception e) { - Log.Error(e, L($"Exception while sending message '{request}'. Error: {e.Message}")); + _logger.LogError(e, L("Exception while sending message '{request}'. Error: {error}"), request, e.Message); throw; } } @@ -117,7 +117,7 @@ private void HandleConfiguration(ConfigurationResponse response) } catch (Exception e) { - Log.Error(e, L("Exception while received configuration")); + _logger.LogError(e, L("Exception while received configuration, error: {error}"), e.Message); } } @@ -141,7 +141,7 @@ private void HandleMessage(ResponseMessage message) } catch (Exception e) { - Log.Error(e, L("Exception while receiving message")); + _logger.LogError(e, L("Exception while receiving message, error: {error}"), e.Message); } } @@ -150,7 +150,7 @@ private void OnArrayMessage(string msg) var parsed = BitfinexSerialization.Deserialize(msg); if (parsed.Count() < 2) { - Log.Warn(L("Invalid message format, too low items")); + _logger.LogWarning(L("Invalid message format, too low items")); return; } @@ -158,7 +158,7 @@ private void OnArrayMessage(string msg) if (!_channelIdToHandler.ContainsKey(channelId)) { - Log.Debug($"Unrecognized channel id '{channelId}', ignoring.."); + _logger.LogDebug("Unrecognized channel id '{channelId}', ignoring..", channelId); return; } diff --git a/src/Bitfinex.Client.Websocket/Files/BitfinexFileCommunicator.cs b/src/Bitfinex.Client.Websocket/Files/BitfinexFileCommunicator.cs index 2aa5dfe..c74aa87 100644 --- a/src/Bitfinex.Client.Websocket/Files/BitfinexFileCommunicator.cs +++ b/src/Bitfinex.Client.Websocket/Files/BitfinexFileCommunicator.cs @@ -7,7 +7,6 @@ using System.Threading.Tasks; using Bitfinex.Client.Websocket.Communicator; using Websocket.Client; -using Websocket.Client.Models; namespace Bitfinex.Client.Websocket.Files { @@ -24,6 +23,7 @@ public class BitfinexFileCommunicator : IBitfinexCommunicator public TimeSpan? ReconnectTimeout { get; set; } = TimeSpan.FromSeconds(60); public TimeSpan? ErrorReconnectTimeout { get; set; } = TimeSpan.FromSeconds(60); + public TimeSpan? LostReconnectTimeout { get; set; } = TimeSpan.FromSeconds(60); public string Name { get; set; } public bool IsStarted { get; private set; } public bool IsRunning { get; private set; } @@ -39,7 +39,7 @@ public class BitfinexFileCommunicator : IBitfinexCommunicator public virtual void Dispose() { - + } public virtual Task Start() @@ -64,16 +64,19 @@ public Task StopOrFail(WebSocketCloseStatus status, string statusDescripti return Task.FromResult(true); } - public virtual void Send(string message) + public virtual bool Send(string message) { + return true; } - public void Send(byte[] message) + public bool Send(byte[] message) { + return true; } - public void Send(ArraySegment message) + public bool Send(ArraySegment message) { + return true; } public virtual Task SendInstant(string message) @@ -86,6 +89,16 @@ public Task SendInstant(byte[] message) return Task.CompletedTask; } + public bool SendAsText(byte[] message) + { + return true; + } + + public bool SendAsText(ArraySegment message) + { + return true; + } + public Task Reconnect() { return Task.CompletedTask; @@ -107,7 +120,7 @@ private void StartStreaming() { if (FileNames == null) throw new InvalidOperationException("FileNames are not set, provide at least one path to historical data"); - if(string.IsNullOrEmpty(Delimiter)) + if (string.IsNullOrEmpty(Delimiter)) throw new InvalidOperationException("Delimiter is not set (separator between messages in the file)"); foreach (var fileName in FileNames) @@ -126,19 +139,19 @@ private void StartStreaming() } } - + private static string ReadByDelimeter(StreamReader sr, string delimiter) { var line = new StringBuilder(); int matchIndex = 0; while (sr.Peek() > 0) - { + { var nextChar = (char)sr.Read(); line.Append(nextChar); if (nextChar == delimiter[matchIndex]) { - if(matchIndex == delimiter.Length - 1) + if (matchIndex == delimiter.Length - 1) { return line.ToString().Substring(0, line.Length - delimiter.Length); } diff --git a/src/Bitfinex.Client.Websocket/Responses/AuthenticationResponse.cs b/src/Bitfinex.Client.Websocket/Responses/AuthenticationResponse.cs index 80350d6..0ff222f 100644 --- a/src/Bitfinex.Client.Websocket/Responses/AuthenticationResponse.cs +++ b/src/Bitfinex.Client.Websocket/Responses/AuthenticationResponse.cs @@ -1,17 +1,12 @@ using System.Reactive.Subjects; using Bitfinex.Client.Websocket.Client; -using Bitfinex.Client.Websocket.Logging; using Bitfinex.Client.Websocket.Messages; using Newtonsoft.Json; -using static Bitfinex.Client.Websocket.Client.BitfinexLogger; - namespace Bitfinex.Client.Websocket.Responses { public class AuthenticationResponse : MessageBase { - private static readonly ILog Log = LogProvider.GetCurrentClassLogger(); - public string Status { get; set; } public int ChanId { get; set; } public int UserId { get; set; } @@ -21,16 +16,15 @@ public class AuthenticationResponse : MessageBase /// /// Returns true if authentication succeed /// - [JsonIgnore] + [JsonIgnore] public bool IsAuthenticated => Status == "OK"; internal static void Handle(string msg, Subject subject) { var response = BitfinexSerialization.Deserialize(msg); -; if (!response.IsAuthenticated) - Log.Warn(L("Authentication failed. Code: " + response.Code)); - subject.OnNext(response); + if (response != null) + subject.OnNext(response); } } } diff --git a/src/Bitfinex.Client.Websocket/Responses/Balance/BalanceInfo.cs b/src/Bitfinex.Client.Websocket/Responses/Balance/BalanceInfo.cs index 2fd6261..e555cde 100644 --- a/src/Bitfinex.Client.Websocket/Responses/Balance/BalanceInfo.cs +++ b/src/Bitfinex.Client.Websocket/Responses/Balance/BalanceInfo.cs @@ -1,6 +1,5 @@ using System.Diagnostics; using System.Reactive.Subjects; -using Bitfinex.Client.Websocket.Logging; using Newtonsoft.Json; using Newtonsoft.Json.Linq; @@ -13,8 +12,6 @@ namespace Bitfinex.Client.Websocket.Responses.Balance [JsonConverter(typeof(BalanceInfoConverter))] public class BalanceInfo { - private static readonly ILog Log = LogProvider.GetCurrentClassLogger(); - /// /// Total Assets Under Management /// @@ -28,19 +25,14 @@ public class BalanceInfo internal static void Handle(JToken token, Subject subject) { var data = token[2]; - if (data.Type != JTokenType.Array) + if (data?.Type != JTokenType.Array) { - Log.Warn(L("BalanceInfo - Invalid message format, third param not array")); return; } var parsed = data.ToObject(); - subject.OnNext(parsed); - } - - private static string L(string msg) - { - return $"[BFX BALANCE INFO HANDLER] {msg}"; + if (parsed != null) + subject.OnNext(parsed); } } } \ No newline at end of file diff --git a/src/Bitfinex.Client.Websocket/Responses/ErrorResponse.cs b/src/Bitfinex.Client.Websocket/Responses/ErrorResponse.cs index 2ab092a..ec3a025 100644 --- a/src/Bitfinex.Client.Websocket/Responses/ErrorResponse.cs +++ b/src/Bitfinex.Client.Websocket/Responses/ErrorResponse.cs @@ -1,16 +1,11 @@ using System.Reactive.Subjects; using Bitfinex.Client.Websocket.Client; -using Bitfinex.Client.Websocket.Logging; using Bitfinex.Client.Websocket.Messages; -using static Bitfinex.Client.Websocket.Client.BitfinexLogger; - namespace Bitfinex.Client.Websocket.Responses { public class ErrorResponse : MessageBase { - private static readonly ILog Log = LogProvider.GetCurrentClassLogger(); - public string Code { get; set; } public string Msg { get; set; } @@ -18,8 +13,8 @@ public class ErrorResponse : MessageBase internal static void Handle(string msg, Subject subject) { var error = BitfinexSerialization.Deserialize(msg); - Log.Error(L($"Error received - message: {error.Msg}, code: {error.Code}")); - subject.OnNext(error); + if (error != null) + subject.OnNext(error); } } } diff --git a/src/Bitfinex.Client.Websocket/Responses/Margin/MarginInfo.cs b/src/Bitfinex.Client.Websocket/Responses/Margin/MarginInfo.cs index 2ca7ec3..8e9792a 100644 --- a/src/Bitfinex.Client.Websocket/Responses/Margin/MarginInfo.cs +++ b/src/Bitfinex.Client.Websocket/Responses/Margin/MarginInfo.cs @@ -1,6 +1,5 @@ using System.Diagnostics; using System.Reactive.Subjects; -using Bitfinex.Client.Websocket.Logging; using Newtonsoft.Json; using Newtonsoft.Json.Linq; @@ -13,8 +12,6 @@ namespace Bitfinex.Client.Websocket.Responses.Margin [JsonConverter(typeof(MarginInfoConverter))] public class MarginInfo { - private static readonly ILog Log = LogProvider.GetCurrentClassLogger(); - /// /// User Profit and Loss (P/L) /// @@ -43,9 +40,8 @@ public class MarginInfo internal static void Handle(JToken token, Subject subject) { var data = token[2]; - if (data.Type != JTokenType.Array) + if (data?.Type != JTokenType.Array) { - Log.Warn(L("MarginInfo - Invalid message format, third param not array")); return; } diff --git a/src/Bitfinex.Client.Websocket/Responses/Notifications/Notification.cs b/src/Bitfinex.Client.Websocket/Responses/Notifications/Notification.cs index 0439153..b01cc20 100644 --- a/src/Bitfinex.Client.Websocket/Responses/Notifications/Notification.cs +++ b/src/Bitfinex.Client.Websocket/Responses/Notifications/Notification.cs @@ -1,7 +1,6 @@ using System; using System.Diagnostics; using System.Reactive.Subjects; -using Bitfinex.Client.Websocket.Logging; using Newtonsoft.Json; using Newtonsoft.Json.Linq; @@ -14,8 +13,6 @@ namespace Bitfinex.Client.Websocket.Responses.Notifications [JsonConverter(typeof(NotificationConverter))] public class Notification { - private static readonly ILog Log = LogProvider.GetCurrentClassLogger(); - /// /// Timestamp of the update /// @@ -55,19 +52,14 @@ public class Notification internal static void Handle(JToken token, Subject subject) { var data = token[2]; - if (data.Type != JTokenType.Array) + if (data?.Type != JTokenType.Array) { - Log.Warn(L("Notification - Invalid message format, third param not array")); return; } var parsed = data.ToObject(); - subject.OnNext(parsed); - } - - private static string L(string msg) - { - return $"[BFX NOTIFICATION HANDLER] {msg}"; + if (parsed != null) + subject.OnNext(parsed); } } } \ No newline at end of file diff --git a/src/Bitfinex.Client.Websocket/Responses/Notifications/NotificationConverter.cs b/src/Bitfinex.Client.Websocket/Responses/Notifications/NotificationConverter.cs index 451b033..497af60 100644 --- a/src/Bitfinex.Client.Websocket/Responses/Notifications/NotificationConverter.cs +++ b/src/Bitfinex.Client.Websocket/Responses/Notifications/NotificationConverter.cs @@ -1,5 +1,4 @@ using System; -using Bitfinex.Client.Websocket.Logging; using Bitfinex.Client.Websocket.Utils; using Newtonsoft.Json; using Newtonsoft.Json.Linq; @@ -8,8 +7,6 @@ namespace Bitfinex.Client.Websocket.Responses.Notifications { class NotificationConverter : JsonConverter { - private static readonly ILog Log = LogProvider.GetCurrentClassLogger(); - public override bool CanConvert(Type objectType) { return objectType == typeof(Notification); @@ -33,12 +30,12 @@ private Notification JArrayToNotification(JArray array) { return new Notification { - Mts = BitfinexTime.ConvertToTime((long) array[0]), - Type = ParseNotificationType((string) array[1]), - MessageId = (long?) array[2], + Mts = BitfinexTime.ConvertToTime((long)array[0]), + Type = ParseNotificationType((string)array[1]), + MessageId = (long?)array[2], NotifyInfo = array[4].ToString(), - Code = (long?) array[5], - Status = (string) array[6], + Code = (long?)array[5], + Status = (string)array[6], Text = array[7].ToString(), }; } @@ -76,7 +73,6 @@ private static NotificationType ParseNotificationType(string type) return NotificationType.DepositComplete; } - Log.Warn("Can't parse NotificationType, input: " + safe); return NotificationType.Undefined; } } diff --git a/src/Bitfinex.Client.Websocket/Responses/Orders/Order.cs b/src/Bitfinex.Client.Websocket/Responses/Orders/Order.cs index 538d1c1..4c69f66 100644 --- a/src/Bitfinex.Client.Websocket/Responses/Orders/Order.cs +++ b/src/Bitfinex.Client.Websocket/Responses/Orders/Order.cs @@ -1,7 +1,6 @@ using System; using System.Diagnostics; using System.Reactive.Subjects; -using Bitfinex.Client.Websocket.Logging; using Bitfinex.Client.Websocket.Utils; using Newtonsoft.Json; using Newtonsoft.Json.Linq; @@ -15,8 +14,6 @@ namespace Bitfinex.Client.Websocket.Responses.Orders [JsonConverter(typeof(OrderConverter))] public class Order { - private static readonly ILog Log = LogProvider.GetCurrentClassLogger(); - /// /// Order ID /// @@ -165,33 +162,26 @@ public class Order internal static void Handle(JToken token, Subject subject) { var data = token[2]; - if (data.Type != JTokenType.Array) + if (data?.Type != JTokenType.Array) { - Log.Warn(L("Orders - Invalid message format, third param not array")); return; } var parsed = data.ToObject(); - subject.OnNext(parsed); + if (parsed != null) subject.OnNext(parsed); } internal static void Handle(JToken token, Subject subject) { var data = token[2]; - if (data.Type != JTokenType.Array) + if (data?.Type != JTokenType.Array) { - Log.Warn(L("Order info - Invalid message format, third param not array")); return; } var parsed = data.ToObject(); - subject.OnNext(parsed); - } - - private static string L(string msg) - { - return $"[BFX ORDER HANDLER] {msg}"; + if (parsed != null) subject.OnNext(parsed); } } } diff --git a/src/Bitfinex.Client.Websocket/Responses/Orders/OrderConverter.cs b/src/Bitfinex.Client.Websocket/Responses/Orders/OrderConverter.cs index 7d873da..58a3185 100644 --- a/src/Bitfinex.Client.Websocket/Responses/Orders/OrderConverter.cs +++ b/src/Bitfinex.Client.Websocket/Responses/Orders/OrderConverter.cs @@ -1,6 +1,5 @@ using System; using Bitfinex.Client.Websocket.Exceptions; -using Bitfinex.Client.Websocket.Logging; using Bitfinex.Client.Websocket.Utils; using Newtonsoft.Json; using Newtonsoft.Json.Linq; @@ -9,8 +8,6 @@ namespace Bitfinex.Client.Websocket.Responses.Orders { internal class OrderConverter : JsonConverter { - private static readonly ILog Log = LogProvider.GetCurrentClassLogger(); - public override bool CanConvert(Type objectType) { return objectType == typeof(Order); @@ -103,7 +100,6 @@ public static OrderStatus ParseStatus(string status) return OrderStatus.PartiallyFilled; } - Log.Warn("Can't parse OrderStatus, input: " + safe); return OrderStatus.Undefined; } @@ -151,7 +147,6 @@ public static OrderType ParseType(string type) case var s when s.StartsWith("exchange fok"): return OrderType.ExchangeFok; } - Log.Warn("Can't parse OrderType, input: " + safe); return OrderType.Undefined; } diff --git a/src/Bitfinex.Client.Websocket/Responses/Positions/Position.cs b/src/Bitfinex.Client.Websocket/Responses/Positions/Position.cs index de83b90..d703ecc 100644 --- a/src/Bitfinex.Client.Websocket/Responses/Positions/Position.cs +++ b/src/Bitfinex.Client.Websocket/Responses/Positions/Position.cs @@ -1,6 +1,6 @@ -using System.Diagnostics; +using System; +using System.Diagnostics; using System.Reactive.Subjects; -using Bitfinex.Client.Websocket.Logging; using Bitfinex.Client.Websocket.Responses.Configurations; using Bitfinex.Client.Websocket.Utils; using Newtonsoft.Json; @@ -15,8 +15,6 @@ namespace Bitfinex.Client.Websocket.Responses.Positions [JsonConverter(typeof(PositionConverter))] public class Position : ResponseBase { - private static readonly ILog Log = LogProvider.GetCurrentClassLogger(); - /// /// Pair (tBTCUSD, etc). /// @@ -85,13 +83,12 @@ public class Position : ResponseBase internal static void Handle(JToken token, ConfigurationState config, Subject subject) { var data = token[2]; - if (data.Type != JTokenType.Array) + if (data?.Type != JTokenType.Array) { - Log.Warn(L("Positions - Invalid message format, third param not array")); return; } - var parsed = data.ToObject(); + var parsed = data.ToObject() ?? Array.Empty(); foreach (var position in parsed) { SetGlobalData(position, config, token, 2, true); @@ -102,20 +99,17 @@ internal static void Handle(JToken token, ConfigurationState config, Subject subject) { var data = token[2]; - if (data.Type != JTokenType.Array) + if (data?.Type != JTokenType.Array) { - Log.Warn(L("Position - Invalid message format, third param not array")); return; } var position = data.ToObject(); - SetGlobalData(position, config, token, 2, true); - subject.OnNext(position); - } - - private static string L(string msg) - { - return $"[BFX POSITION HANDLER] {msg}"; + if (position != null) + { + SetGlobalData(position, config, token, 2, true); + subject.OnNext(position); + } } } } diff --git a/src/Bitfinex.Client.Websocket/Responses/Positions/PositionConverter.cs b/src/Bitfinex.Client.Websocket/Responses/Positions/PositionConverter.cs index 9f02aa1..0dc95e5 100644 --- a/src/Bitfinex.Client.Websocket/Responses/Positions/PositionConverter.cs +++ b/src/Bitfinex.Client.Websocket/Responses/Positions/PositionConverter.cs @@ -1,5 +1,4 @@ using System; -using Bitfinex.Client.Websocket.Logging; using Newtonsoft.Json; using Newtonsoft.Json.Linq; @@ -7,8 +6,6 @@ namespace Bitfinex.Client.Websocket.Responses.Positions { internal class PositionConverter : JsonConverter { - private static readonly ILog Log = LogProvider.GetCurrentClassLogger(); - public override bool CanConvert(Type objectType) { return objectType == typeof(Position); @@ -58,7 +55,6 @@ public static PositionStatus ParseStatus(string status) case var s when s.Contains("closed"): return PositionStatus.Closed; } - Log.Warn("Can't parse PositionStatus, input: " + safe); return PositionStatus.Undefined; } @@ -73,7 +69,6 @@ public static MarginFundingType ParseFundingType(int? type) case 1: return MarginFundingType.Term; } - Log.Warn("Can't parse MarginFundingType, input: " + type); return MarginFundingType.Undefined; } } diff --git a/src/Bitfinex.Client.Websocket/Responses/ResponseBase.cs b/src/Bitfinex.Client.Websocket/Responses/ResponseBase.cs index 4e53860..c3820df 100644 --- a/src/Bitfinex.Client.Websocket/Responses/ResponseBase.cs +++ b/src/Bitfinex.Client.Websocket/Responses/ResponseBase.cs @@ -1,5 +1,4 @@ using System; -using Bitfinex.Client.Websocket.Logging; using Bitfinex.Client.Websocket.Responses.Configurations; using Bitfinex.Client.Websocket.Utils; using Newtonsoft.Json.Linq; @@ -11,8 +10,6 @@ namespace Bitfinex.Client.Websocket.Responses /// public class ResponseBase { - private static readonly ILog Log = LogProvider.GetCurrentClassLogger(); - /// /// Unique channel id for this type of response. /// @@ -69,7 +66,7 @@ internal static void SetGlobalData(ResponseBase response, ConfigurationState con } catch (Exception e) { - Log.Warn($"[BFX response] Failed to parse global data (timestamp, sequence). Error: {e.Message}"); + Console.WriteLine($"[BFX response] Failed to parse global data (timestamp, sequence). Error: {e.Message}"); } } } diff --git a/src/Bitfinex.Client.Websocket/Responses/TradesPrivate/PrivateTrade.cs b/src/Bitfinex.Client.Websocket/Responses/TradesPrivate/PrivateTrade.cs index b6c8f24..55d0151 100644 --- a/src/Bitfinex.Client.Websocket/Responses/TradesPrivate/PrivateTrade.cs +++ b/src/Bitfinex.Client.Websocket/Responses/TradesPrivate/PrivateTrade.cs @@ -1,6 +1,5 @@ using System; using System.Reactive.Subjects; -using Bitfinex.Client.Websocket.Logging; using Bitfinex.Client.Websocket.Responses.Configurations; using Bitfinex.Client.Websocket.Responses.Orders; using Bitfinex.Client.Websocket.Responses.Trades; @@ -16,8 +15,6 @@ namespace Bitfinex.Client.Websocket.Responses.TradesPrivate [JsonConverter(typeof(PrivateTradeConverter))] public class PrivateTrade : ResponseBase { - private static readonly ILog Log = LogProvider.GetCurrentClassLogger(); - /// /// Trade id /// @@ -89,22 +86,18 @@ public class PrivateTrade : ResponseBase internal static void Handle(JToken token, ConfigurationState config, Subject subject, TradeType type) { var data = token[2]; - if (data.Type != JTokenType.Array) + if (data?.Type != JTokenType.Array) { - Log.Warn(L("Private trade info - Invalid message format, third param not array")); return; } var trade = data.ToObject(); - trade.Type = type; - SetGlobalData(trade, config, token, 2, true); - - subject.OnNext(trade); - } - - private static string L(string msg) - { - return $"[BFX PRIVATE TRADE HANDLER] {msg}"; + if (trade != null) + { + trade.Type = type; + SetGlobalData(trade, config, token, 2, true); + subject.OnNext(trade); + } } } } diff --git a/src/Bitfinex.Client.Websocket/Responses/Wallets/Wallet.cs b/src/Bitfinex.Client.Websocket/Responses/Wallets/Wallet.cs index 59f0820..770500b 100644 --- a/src/Bitfinex.Client.Websocket/Responses/Wallets/Wallet.cs +++ b/src/Bitfinex.Client.Websocket/Responses/Wallets/Wallet.cs @@ -1,7 +1,6 @@ using System.Diagnostics; using System.Linq; using System.Reactive.Subjects; -using Bitfinex.Client.Websocket.Logging; using Newtonsoft.Json; using Newtonsoft.Json.Linq; @@ -14,8 +13,6 @@ namespace Bitfinex.Client.Websocket.Responses.Wallets [JsonConverter(typeof(WalletConverter))] public class Wallet { - private static readonly ILog Log = LogProvider.GetCurrentClassLogger(); - /// /// Wallet name (exchange, margin, funding) /// @@ -42,37 +39,34 @@ public class Wallet /// public double? BalanceAvailable { get; set; } - + internal static void Handle(JToken token, Subject subject, Subject subjectMultiple) { var data = token[2]; - if (data.Type != JTokenType.Array) + if (data?.Type != JTokenType.Array) { - Log.Warn(L("Wallets - Invalid message format, third param not array")); return; } var parsed = data.ToObject(); - subjectMultiple.OnNext(parsed); - parsed.ToList().ForEach(subject.OnNext); + if (parsed != null) + { + subjectMultiple.OnNext(parsed); + parsed.ToList().ForEach(subject.OnNext); + } } internal static void Handle(JToken token, Subject subject) { var data = token[2]; - if (data.Type != JTokenType.Array) + if (data?.Type != JTokenType.Array) { - Log.Warn(L("Wallet update - Invalid message format, third param not array")); return; } var parsed = data.ToObject(); - subject.OnNext(parsed); - } - - private static string L(string msg) - { - return $"[BFX WALLET HANDLER] {msg}"; + if (parsed != null) + subject.OnNext(parsed); } } } diff --git a/src/Bitfinex.Client.Websocket/Responses/Wallets/WalletConverter.cs b/src/Bitfinex.Client.Websocket/Responses/Wallets/WalletConverter.cs index 6d8dedc..518fc07 100644 --- a/src/Bitfinex.Client.Websocket/Responses/Wallets/WalletConverter.cs +++ b/src/Bitfinex.Client.Websocket/Responses/Wallets/WalletConverter.cs @@ -1,5 +1,4 @@ using System; -using Bitfinex.Client.Websocket.Logging; using Newtonsoft.Json; using Newtonsoft.Json.Linq; @@ -7,8 +6,6 @@ namespace Bitfinex.Client.Websocket.Responses.Wallets { class WalletConverter : JsonConverter { - private static readonly ILog Log = LogProvider.GetCurrentClassLogger(); - public override bool CanConvert(Type objectType) { return objectType == typeof(Wallet); @@ -57,7 +54,6 @@ public static WalletType ParseWalletType(string type) case var s when s.StartsWith("funding"): return WalletType.Funding; } - Log.Warn("Can't parse WalletType, input: " + safe); return WalletType.Undefined; } } diff --git a/src/Bitfinex.Client.Websocket/Websockets/BitfinexWebsocketCommunicator.cs b/src/Bitfinex.Client.Websocket/Websockets/BitfinexWebsocketCommunicator.cs index 4b43015..87c1e43 100644 --- a/src/Bitfinex.Client.Websocket/Websockets/BitfinexWebsocketCommunicator.cs +++ b/src/Bitfinex.Client.Websocket/Websockets/BitfinexWebsocketCommunicator.cs @@ -1,6 +1,7 @@ using System; using System.Net.WebSockets; using Bitfinex.Client.Websocket.Communicator; +using Microsoft.Extensions.Logging; using Websocket.Client; namespace Bitfinex.Client.Websocket.Websockets @@ -9,9 +10,15 @@ namespace Bitfinex.Client.Websocket.Websockets public class BitfinexWebsocketCommunicator : WebsocketClient, IBitfinexCommunicator { /// - public BitfinexWebsocketCommunicator(Uri url, Func clientFactory = null) + public BitfinexWebsocketCommunicator(Uri url, Func? clientFactory = null) : base(url, clientFactory) { } + + /// + public BitfinexWebsocketCommunicator(Uri url, ILogger logger, Func? clientFactory = null) + : base(url, logger, clientFactory) + { + } } } diff --git a/src/Bitfinex.Client.Websocket/icon.png b/src/Bitfinex.Client.Websocket/icon.png new file mode 100644 index 0000000..6a2dae5 Binary files /dev/null and b/src/Bitfinex.Client.Websocket/icon.png differ diff --git a/test/Bitfinex.Client.Websocket.Tests/Bitfinex.Client.Websocket.Tests.csproj b/test/Bitfinex.Client.Websocket.Tests/Bitfinex.Client.Websocket.Tests.csproj index 7d46416..3258c64 100644 --- a/test/Bitfinex.Client.Websocket.Tests/Bitfinex.Client.Websocket.Tests.csproj +++ b/test/Bitfinex.Client.Websocket.Tests/Bitfinex.Client.Websocket.Tests.csproj @@ -1,23 +1,23 @@ - - net6 + + net8 - false - + false + - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + - - - + + + diff --git a/test_integration/Bitfinex.Client.Websocket.Sample/Bitfinex.Client.Websocket.Sample.csproj b/test_integration/Bitfinex.Client.Websocket.Sample/Bitfinex.Client.Websocket.Sample.csproj index 1845a03..a10a53e 100644 --- a/test_integration/Bitfinex.Client.Websocket.Sample/Bitfinex.Client.Websocket.Sample.csproj +++ b/test_integration/Bitfinex.Client.Websocket.Sample/Bitfinex.Client.Websocket.Sample.csproj @@ -1,15 +1,15 @@ - + - - Exe - net6 - + + Exe + net8 + - - - - - - + + + + + + diff --git a/test_integration/Bitfinex.Client.Websocket.Sample/Program.cs b/test_integration/Bitfinex.Client.Websocket.Sample/Program.cs index 2abf958..730dc06 100644 --- a/test_integration/Bitfinex.Client.Websocket.Sample/Program.cs +++ b/test_integration/Bitfinex.Client.Websocket.Sample/Program.cs @@ -14,21 +14,23 @@ using Bitfinex.Client.Websocket.Responses.Trades; using Bitfinex.Client.Websocket.Utils; using Bitfinex.Client.Websocket.Websockets; +using Microsoft.Extensions.Logging; using Serilog; using Serilog.Events; +using Serilog.Extensions.Logging; namespace Bitfinex.Client.Websocket.Sample { class Program { - private static readonly ManualResetEvent ExitEvent = new ManualResetEvent(false); + private static readonly ManualResetEvent ExitEvent = new(false); - private static readonly string API_KEY = "your_api_key"; - private static readonly string API_SECRET = ""; + private const string ApiKey = "your_api_key"; + private const string ApiSecret = ""; static void Main(string[] args) { - InitLogging(); + var logger = InitLogging(); AppDomain.CurrentDomain.ProcessExit += CurrentDomainOnProcessExit; AssemblyLoadContext.Default.Unloading += DefaultOnUnloading; @@ -45,18 +47,18 @@ static void Main(string[] args) var url = BitfinexValues.ApiWebsocketUrl; - using (var communicator = new BitfinexWebsocketCommunicator(url)) + using (var communicator = new BitfinexWebsocketCommunicator(url, logger.CreateLogger())) { communicator.Name = "Bitfinex-1"; communicator.ReconnectTimeout = TimeSpan.FromSeconds(30); communicator.ReconnectionHappened.Subscribe(info => - Log.Information($"Reconnection happened, type: {info.Type}")); + Log.Information("Reconnection happened, type: {type}", info.Type)); - using (var client = new BitfinexWebsocketClient(communicator)) + using (var client = new BitfinexWebsocketClient(communicator, logger.CreateLogger())) { client.Streams.InfoStream.Subscribe(info => { - Log.Information($"Info received version: {info.Version}, reconnection happened, resubscribing to streams"); + Log.Information("Info received version: {version}, reconnection happened, resubscribing to streams", info.Version); SendSubscriptionRequests(client).Wait(); }); @@ -77,12 +79,12 @@ static void Main(string[] args) private static async Task SendSubscriptionRequests(BitfinexWebsocketClient client) { //client.Send(new ConfigurationRequest(ConfigurationFlag.Timestamp | ConfigurationFlag.Sequencing)); - client.Send(new PingRequest() {Cid = 123456}); + client.Send(new PingRequest() { Cid = 123456 }); //client.Send(new TickerSubscribeRequest("BTC/USD")); //client.Send(new TickerSubscribeRequest("ETH/USD")); - //client.Send(new TradesSubscribeRequest("BTC/USD")); + client.Send(new TradesSubscribeRequest("BTC/USD")); //client.Send(new TradesSubscribeRequest("NEC/ETH")); // Nectar coin from ETHFINEX //client.Send(new FundingsSubscribeRequest("BTC")); //client.Send(new FundingsSubscribeRequest("USD")); @@ -96,16 +98,16 @@ private static async Task SendSubscriptionRequests(BitfinexWebsocketClient clien //client.Send(new BookSubscribeRequest("fUSD", BitfinexPrecision.P0, BitfinexFrequency.Realtime)); - client.Send(new RawBookSubscribeRequest("BTCUSD", "100")); + //client.Send(new RawBookSubscribeRequest("BTCUSD", "100")); //client.Send(new RawBookSubscribeRequest("fUSD", "25")); //client.Send(new RawBookSubscribeRequest("fBTC", "25")); //client.Send(new StatusSubscribeRequest("liq:global")); //client.Send(new StatusSubscribeRequest("deriv:tBTCF0:USTF0")); - if (!string.IsNullOrWhiteSpace(API_SECRET)) + if (!string.IsNullOrWhiteSpace(ApiSecret)) { - client.Authenticate(API_KEY, API_SECRET); + client.Authenticate(ApiKey, ApiSecret); #pragma warning disable 4014 Task.Run(async () => @@ -161,10 +163,10 @@ private static void SubscribeToStreams(BitfinexWebsocketClient client) Log.Information($"Configuration happened {x.Status}, flags: {x.Flags}, server timestamp enabled: {client.Configuration.IsTimestampEnabled}")); client.Streams.PongStream.Subscribe(pong => Log.Information($"Pong received! Id: {pong.Cid}")); - + client.Streams.TickerStream.Subscribe(ticker => Log.Information($"{ticker.ServerSequence} {ticker.Pair} - last price: {ticker.LastPrice}, bid: {ticker.Bid}, ask: {ticker.Ask}, {ShowServerTimestamp(client, ticker)}")); - + client.Streams.TradesSnapshotStream.Subscribe(trades => { foreach (var x in trades) @@ -176,7 +178,7 @@ private static void SubscribeToStreams(BitfinexWebsocketClient client) client.Streams.TradesStream.Where(x => x.Type == TradeType.Executed).Subscribe(x => Log.Information($"{x.ServerSequence} Trade {x.Pair} executed. Time: {x.Mts:mm:ss.fff}, Amount: {x.Amount}, Price: {x.Price}, {ShowServerTimestamp(client, x)}")); - + client.Streams.FundingStream.Where(x => x.Type == FundingType.Executed).Subscribe(x => Log.Information($"Funding, Symbol {x.Symbol} executed. Time: {x.Mts:mm:ss.fff}, Amount: {x.Amount}, Rate: {x.Rate}, Period: {x.Period}")); @@ -193,14 +195,14 @@ private static void SubscribeToStreams(BitfinexWebsocketClient client) Log.Information( book.Period <= 0 ? $"{book.ServerSequence} Book | channel: {book.ChanId} pair: {book.Pair}, price: {book.Price}, amount {book.Amount}, count: {book.Count}, {ShowServerTimestamp(client, book)}" : - $"{book.ServerSequence} Book | channel: {book.ChanId} sym: {book.Symbol}, rate: {book.Rate*100}% (p.a. {(book.Rate*100*365):F}%), period: {book.Period} amount {book.Amount}, count: {book.Count}, {ShowServerTimestamp(client, book)}")); + $"{book.ServerSequence} Book | channel: {book.ChanId} sym: {book.Symbol}, rate: {book.Rate * 100}% (p.a. {(book.Rate * 100 * 365):F}%), period: {book.Period} amount {book.Amount}, count: {book.Count}, {ShowServerTimestamp(client, book)}")); client.Streams.RawBookStream.Subscribe(book => { Log.Information( book.OrderId > 0 ? $"{book.ServerSequence} RawBook | channel: {book.ChanId} pair: {book.Pair}, order: {book.OrderId}, price: {book.Price}, amount {book.Amount} {ShowServerTimestamp(client, book)}" - : $"{book.ServerSequence} RawBook | channel: {book.ChanId} sym: {book.Symbol}, offer: {book.OfferId}, period: {book.Period} days, rate {book.Rate*100}% (p.a. {(book.Rate*100*365):F}%) {ShowServerTimestamp(client, book)}"); + : $"{book.ServerSequence} RawBook | channel: {book.ChanId} sym: {book.Symbol}, offer: {book.OfferId}, period: {book.Period} days, rate {book.Rate * 100}% (p.a. {(book.Rate * 100 * 365):F}%) {ShowServerTimestamp(client, book)}"); }); @@ -248,7 +250,7 @@ private static void SubscribeToStreams(BitfinexWebsocketClient client) // Flags = OrderFlag.PostOnly //}); }); - + client.Streams.OrderUpdatedStream.Subscribe(info => Log.Information($"Order #{info.Cid} group: {info.Gid} updated: {info.Pair} - {info.Type} - {info.Amount} @ {info.Price} | {info.OrderStatus}")); @@ -256,7 +258,7 @@ private static void SubscribeToStreams(BitfinexWebsocketClient client) client.Streams.OrderCanceledStream.Subscribe(info => Log.Information($"Order #{info.Cid} group: {info.Gid} {info.OrderStatus}: {info.Pair} - {info.Type} - {info.Amount} @ {info.Price}")); - client.Streams.PrivateTradeStream.Subscribe(trade => + client.Streams.PrivateTradeStream.Subscribe(trade => Log.Information($"Private trade {trade.Pair} executed. Time: {trade.MtsCreate:mm:ss.fff}, Amount: {trade.ExecAmount}, Price: {trade.ExecPrice}, " + $"Fee: {trade.Fee} {trade.FeeCurrency}, type: {trade.OrderType}, " + $"{ShowServerSequence(client, trade)}, {ShowServerTimestamp(client, trade)}")); @@ -290,7 +292,7 @@ private static void SubscribeToStreams(BitfinexWebsocketClient client) client.Streams.NotificationStream.Subscribe(notification => Log.Information( $"Notification: {notification.Text} code: {notification.Code}, status: {notification.Status}, type : {notification.Type}")); - + client.Streams.BalanceInfoStream.Subscribe(info => Log.Information($"Balance, total: {info.TotalAum}, net: {info.NetAum}")); @@ -324,28 +326,30 @@ private static void SubscribeToStreams(BitfinexWebsocketClient client) private static string ShowServerTimestamp(BitfinexWebsocketClient client, ResponseBase response) { - if(!client.Configuration.IsTimestampEnabled) + if (!client.Configuration.IsTimestampEnabled) return string.Empty; return $"server timestamp: {response.ServerTimestamp:mm:ss.fff}"; } private static string ShowServerSequence(BitfinexWebsocketClient client, ResponseBase response) { - if(!client.Configuration.IsSequencingEnabled) + if (!client.Configuration.IsSequencingEnabled) return string.Empty; return $"sequence: {response.ServerSequence} / {response.ServerPrivateSequence}"; } - private static void InitLogging() + private static SerilogLoggerFactory InitLogging() { var executingDir = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location); var logPath = Path.Combine(executingDir, "logs", "verbose.log"); - Log.Logger = new LoggerConfiguration() + var logger = new LoggerConfiguration() .MinimumLevel.Verbose() .WriteTo.File(logPath, rollingInterval: RollingInterval.Day) - .WriteTo.ColoredConsole(LogEventLevel.Debug, outputTemplate: + .WriteTo.Console(LogEventLevel.Debug, outputTemplate: "[{Timestamp:HH:mm:ss.fff} {Level:u3}] {Message:lj}{NewLine}{Exception}") .CreateLogger(); + Log.Logger = logger; + return new SerilogLoggerFactory(logger); } private static void CurrentDomainOnProcessExit(object sender, EventArgs eventArgs) diff --git a/test_integration/Bitfinex.Client.Websocket.Tests.Integration/Bitfinex.Client.Websocket.Tests.Integration.csproj b/test_integration/Bitfinex.Client.Websocket.Tests.Integration/Bitfinex.Client.Websocket.Tests.Integration.csproj index 4ebc46e..b0a6f30 100644 --- a/test_integration/Bitfinex.Client.Websocket.Tests.Integration/Bitfinex.Client.Websocket.Tests.Integration.csproj +++ b/test_integration/Bitfinex.Client.Websocket.Tests.Integration/Bitfinex.Client.Websocket.Tests.Integration.csproj @@ -1,30 +1,30 @@  - - net6 + + net8 - false - + false + - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + - - - + + + - - - PreserveNewest - - + + + PreserveNewest + +