diff --git a/CoinEx.Net.UnitTests/CoinEx.Net.UnitTests.csproj b/CoinEx.Net.UnitTests/CoinEx.Net.UnitTests.csproj index 6328bde..5b2a89a 100644 --- a/CoinEx.Net.UnitTests/CoinEx.Net.UnitTests.csproj +++ b/CoinEx.Net.UnitTests/CoinEx.Net.UnitTests.csproj @@ -8,10 +8,10 @@ - - - - + + + + diff --git a/CoinEx.Net.UnitTests/CoinExClientTests.cs b/CoinEx.Net.UnitTests/CoinExClientTests.cs index 00a2e68..124b906 100644 --- a/CoinEx.Net.UnitTests/CoinExClientTests.cs +++ b/CoinEx.Net.UnitTests/CoinExClientTests.cs @@ -19,93 +19,51 @@ using CoinEx.Net.Clients.SpotApi; using CoinEx.Net.ExtensionMethods; using CryptoExchange.Net.Objects.Sockets; +using NUnit.Framework.Legacy; namespace CoinEx.Net.UnitTests { [TestFixture] public class CoinExClientTests { - //[Test] - //public async Task GetKlines_Should_RespondWithKlines() - //{ - // // arrange - // CoinExKline[] expected = new CoinExKline[] { - // new CoinExKline(), - // new CoinExKline(), - // }; - // var objects = TestHelpers.PrepareClient(() => Construct(), CreateRequest(expected)); - - // // act - // var result = await objects.Client.GetKlinesAsync("ETHBTC", KlineInterval.FiveMinute); - - // // assert - // Assert.AreEqual(true, result.Success); - // TestHelpers.PublicInstancePropertiesEqual(expected[0], result.Data.ToList()[0]); - // TestHelpers.PublicInstancePropertiesEqual(expected[1], result.Data.ToList()[1]); - //} - - //[Test] - //public async Task ReceivingCoinExError_Should_ReturnCoinExErrorAndNotSuccess() - //{ - // // arrange - // var response = JsonConvert.SerializeObject(new CoinExApiResult() { Code = 101, Data = new object(), Message = "Some error" }); - // var objects = TestHelpers.PrepareClient(() => Construct(), response); - - // // act - // var result = await objects.Client.GetSymbolsAsync(); - - // // assert - // Assert.IsFalse(result.Success); - // Assert.IsNotNull(result.Error); - // Assert.IsTrue(result.Error.ToString().Contains("Some error")); - //} - - //[Test] - //public async Task ReceivingHttpError_Should_ReturnErrorAndNotSuccess() - //{ - // // arrange - // var objects = TestHelpers.PrepareClient(() => Construct(), "Error request", HttpStatusCode.BadRequest); - - // // act - // var result = await objects.Client.GetSymbolsAsync(); - - // // assert - // Assert.IsFalse(result.Success); - // Assert.IsNotNull(result.Error); - // Assert.IsTrue(result.Error.ToString().Contains("Error request")); - //} - - //[Test] - //public async Task AuthenticatedRequests_Should_HaveAuthenticationHeader() - //{ - // // arrange - // var objects = TestHelpers.PrepareClient(() => Construct(new CoinExClientOptions() - // { - // ApiCredentials = new ApiCredentials("test", "test") - // }), CreateRequest("{}")); - - // // act - // var result = await objects.Client.GetBalancesAsync(); - - // // assert - // objects.Request.Verify(r => r.AddHeader("Authorization", It.IsAny())); - //} - - //[Test] - //public async Task PostRequests_Should_HaveContentBody() - //{ - // // arrange - // var objects = TestHelpers.PrepareClient(() => Construct(new CoinExClientOptions() - // { - // ApiCredentials = new ApiCredentials("test", "test") - // }), CreateRequest("{}")); - - // // act - // var result = await objects.Client.PlaceOrderAsync("BTCETH", OrderType.Limit, OrderSide.Buy, 1, 1); - - // // assert - // objects.Request.Verify(r => r.SetContent(It.IsAny(), It.IsAny())); - //} + + [TestCase()] + public async Task ReceivingError_Should_ReturnErrorAndNotSuccess() + { + // arrange + var client = TestHelpers.CreateClient(); + var resultObj = new CoinExApiResult() + { + Code = 400001, + Message = "Error occured" + }; + + TestHelpers.SetResponse((CoinExRestClient)client, JsonConvert.SerializeObject(resultObj)); + + // act + var result = await client.SpotApi.ExchangeData.GetAssetsAsync(); + + // assert + ClassicAssert.IsFalse(result.Success); + ClassicAssert.IsNotNull(result.Error); + Assert.That(result.Error!.Code == 400001); + Assert.That(result.Error.Message == "Error occured"); + } + + [TestCase()] + public async Task ReceivingHttpErrorWithNoJson_Should_ReturnErrorAndNotSuccess() + { + // arrange + var client = TestHelpers.CreateClient(); + TestHelpers.SetResponse((CoinExRestClient)client, "", System.Net.HttpStatusCode.BadRequest); + + // act + var result = await client.SpotApi.ExchangeData.GetAssetsAsync(); + + // assert + ClassicAssert.IsFalse(result.Success); + ClassicAssert.IsNotNull(result.Error); + } [Test] public void ProvidingApiCredentials_Should_SaveApiCredentials() @@ -115,7 +73,7 @@ public void ProvidingApiCredentials_Should_SaveApiCredentials() var authProvider = new CoinExAuthenticationProvider(new ApiCredentials("TestKey", "TestSecret"), null); // assert - Assert.AreEqual(authProvider.GetApiKey(), "TestKey"); + Assert.That(authProvider.GetApiKey() == "TestKey"); } [Test] @@ -130,7 +88,7 @@ public void SigningString_Should_GiveCorrectSignResult(string input, string outp var sign = authProvider.Sign(input); // assert - Assert.AreEqual(sign, output); + Assert.That(sign == output); } [TestCase("BTCUSDT", true)] @@ -163,7 +121,7 @@ public void CheckRestInterfaces() foreach (var method in implementation.GetMethods().Where(m => m.ReturnType.IsAssignableTo(typeof(Task)))) { var interfaceMethod = clientInterface.GetMethod(method.Name, method.GetParameters().Select(p => p.ParameterType).ToArray()); - Assert.NotNull(interfaceMethod, $"Missing interface for method {method.Name} in {implementation.Name} implementing interface {clientInterface.Name}"); + ClassicAssert.NotNull(interfaceMethod, $"Missing interface for method {method.Name} in {implementation.Name} implementing interface {clientInterface.Name}"); methods++; } Debug.WriteLine($"{clientInterface.Name} {methods} methods validated"); @@ -183,7 +141,7 @@ public void CheckSocketInterfaces() foreach (var method in implementation.GetMethods().Where(m => m.ReturnType.IsAssignableTo(typeof(Task>)))) { var interfaceMethod = clientInterface.GetMethod(method.Name, method.GetParameters().Select(p => p.ParameterType).ToArray()); - Assert.NotNull(interfaceMethod, $"Missing interface for method {method.Name} in {implementation.Name} implementing interface {clientInterface.Name}"); + ClassicAssert.NotNull(interfaceMethod, $"Missing interface for method {method.Name} in {implementation.Name} implementing interface {clientInterface.Name}"); methods++; } Debug.WriteLine($"{clientInterface.Name} {methods} methods validated"); diff --git a/CoinEx.Net.UnitTests/CoinExSocketClientTests.cs b/CoinEx.Net.UnitTests/CoinExSocketClientTests.cs index 84bc754..9249b13 100644 --- a/CoinEx.Net.UnitTests/CoinExSocketClientTests.cs +++ b/CoinEx.Net.UnitTests/CoinExSocketClientTests.cs @@ -33,8 +33,8 @@ // subTask.Wait(5000); // // Assert -// Assert.IsTrue(subTask.IsCompleted); -// Assert.IsTrue(subTask.Result.Success); +// Assert.That(subTask.IsCompleted); +// Assert.That(subTask.Result.Success); // } // [Test] @@ -56,7 +56,7 @@ // subTask.Wait(); // // Assert -// Assert.IsFalse(subTask.Result.Success); +// ClassicAssert.IsFalse(subTask.Result.Success); // } // [Test] @@ -93,8 +93,8 @@ // InvokeSubUpdate(client, "state.update", receive); // // Assert -// Assert.IsTrue(subTask.Result.Success); -// Assert.IsTrue(actual != null); +// Assert.That(subTask.Result.Success); +// Assert.That(actual != null); // TestHelpers.PublicInstancePropertiesEqual(expected[0], actual[0]); // TestHelpers.PublicInstancePropertiesEqual(expected[1], actual[1]); // } @@ -129,8 +129,8 @@ // InvokeSubUpdate(client, "deals.update", "ETHBTC", expected ); // // Assert -// Assert.IsTrue(subTask.Result.Success); -// Assert.IsTrue(actual != null); +// Assert.That(subTask.Result.Success); +// Assert.That(actual != null); // TestHelpers.PublicInstancePropertiesEqual(expected, actual); // } @@ -163,8 +163,8 @@ // InvokeSubUpdate(client, "deals.update", "ETHBTC", expected); // // Assert -// Assert.IsTrue(subTask.Result.Success); -// Assert.IsTrue(actual != null); +// Assert.That(subTask.Result.Success); +// Assert.That(actual != null); // TestHelpers.PublicInstancePropertiesEqual(expected, actual); // } @@ -199,8 +199,8 @@ // // Assert -// Assert.IsTrue(subTask.Result.Success); -// Assert.IsTrue(actual != null); +// Assert.That(subTask.Result.Success); +// Assert.That(actual != null); // TestHelpers.PublicInstancePropertiesEqual(expected, actual); // } @@ -234,8 +234,8 @@ // InvokeSubUpdate(client, "kline.update", expected); // // Assert -// Assert.IsTrue(subTask.Result.Success); -// Assert.IsTrue(actual != null); +// Assert.That(subTask.Result.Success); +// Assert.That(actual != null); // TestHelpers.PublicInstancePropertiesEqual(expected, actual); // } @@ -278,8 +278,8 @@ // InvokeSubUpdate(client, "asset.update", receive); // // Assert -// Assert.IsTrue(subTask.Result.Success); -// Assert.IsTrue(actual != null); +// Assert.That(subTask.Result.Success); +// Assert.That(actual != null); // TestHelpers.PublicInstancePropertiesEqual(expected, actual); // } @@ -313,8 +313,8 @@ // InvokeSubUpdate(client, "order.update", 1, expected); // // Assert -// Assert.IsTrue(subTask.Result.Success); -// Assert.IsTrue(actual != null); +// Assert.That(subTask.Result.Success); +// Assert.That(actual != null); // TestHelpers.PublicInstancePropertiesEqual(expected, actual); // } @@ -346,7 +346,7 @@ // //TestHelpers.CloseWebsocket(client); // //// Assert -// //Assert.IsTrue(conWait.Result); +// //Assert.That(conWait.Result); // } // [Test] diff --git a/CoinEx.Net.UnitTests/JsonTests.cs b/CoinEx.Net.UnitTests/JsonTests.cs index db6749c..6e1a0e9 100644 --- a/CoinEx.Net.UnitTests/JsonTests.cs +++ b/CoinEx.Net.UnitTests/JsonTests.cs @@ -1,6 +1,5 @@ using CoinEx.Net.Interfaces; using CoinEx.Net.Objects; -using CoinEx.Net.Testing; using NUnit.Framework; using System.Collections.Generic; using System.Threading.Tasks; diff --git a/CoinEx.Net.UnitTests/JsonToObjectComparer.cs b/CoinEx.Net.UnitTests/JsonToObjectComparer.cs index f7715a4..af02e03 100644 --- a/CoinEx.Net.UnitTests/JsonToObjectComparer.cs +++ b/CoinEx.Net.UnitTests/JsonToObjectComparer.cs @@ -1,9 +1,10 @@ -using CoinEx.Net.Testing; -using CryptoExchange.Net.Converters; +using CryptoExchange.Net.Converters; +using CryptoExchange.Net.Converters.JsonNet; using CryptoExchange.Net.Objects; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using NUnit.Framework; +using NUnit.Framework.Legacy; using System; using System.Collections; using System.Collections.Generic; @@ -84,7 +85,7 @@ public async Task ProcessSubject( var result = (CallResult)await TestHelpers.InvokeAsync(method, getSubject(client), input.ToArray()); // asset - Assert.Null(result.Error, method.Name); + ClassicAssert.Null(result.Error, method.Name); var resultProp = result.GetType().GetProperty("Data", BindingFlags.Public | BindingFlags.Instance); if (resultProp == null) @@ -226,10 +227,8 @@ private static void CheckObject(string method, JProperty prop, object obj, Dicti // Property has a value var property = resultProperties.SingleOrDefault(p => p.Item2?.PropertyName == prop.Name).p; - if (property is null) - property = resultProperties.SingleOrDefault(p => p.p.Name == prop.Name).p; - if (property is null) - property = resultProperties.SingleOrDefault(p => p.p.Name.ToUpperInvariant() == prop.Name.ToUpperInvariant()).p; + property ??= resultProperties.SingleOrDefault(p => p.p.Name == prop.Name).p; + property ??= resultProperties.SingleOrDefault(p => p.p.Name.ToUpperInvariant() == prop.Name.ToUpperInvariant()).p; if (property is null) { @@ -341,7 +340,9 @@ private static void CheckPropertyValue(string method, JToken propValue, object p { if (info.GetCustomAttribute(true) == null && info.GetCustomAttribute(true)?.ItemConverterType == null) + { CheckValues(method, propertyName, (JValue)propValue, propertyValue); + } } } } @@ -380,7 +381,9 @@ private static void CheckValues(string method, string property, JValue jsonValue // timestamp, hard to check.. } else if (jsonValue.Value().ToLowerInvariant() != objectValue.ToString().ToLowerInvariant()) + { throw new Exception($"{method}: {property} not equal: {jsonValue.Value()} vs {objectValue.ToString()}"); + } } else if (jsonValue.Type == JTokenType.Integer) { diff --git a/CoinEx.Net.UnitTests/TestHelpers.cs b/CoinEx.Net.UnitTests/TestHelpers.cs index db3d44f..a6a9f27 100644 --- a/CoinEx.Net.UnitTests/TestHelpers.cs +++ b/CoinEx.Net.UnitTests/TestHelpers.cs @@ -17,7 +17,7 @@ using CoinEx.Net.Clients; using CoinEx.Net.Objects.Options; -namespace CoinEx.Net.Testing +namespace CoinEx.Net.UnitTests { public class TestHelpers { @@ -128,7 +128,7 @@ public static object GetTestValue(Type type, int i) return (decimal?)(i / 100m); if (type == typeof(int)) - return i+1; + return i + 1; if (type == typeof(int?)) return (int?)i; @@ -165,7 +165,7 @@ public static object GetTestValue(Type type, int i) return result; } - if (type.IsGenericType && (type.GetGenericTypeDefinition() == typeof(List<>))) + if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(List<>)) { var result = (IList)Activator.CreateInstance(type)!; result.Add(GetTestValue(type.GetGenericArguments()[0], 0)); diff --git a/CoinEx.Net/Clients/CoinExRestClient.cs b/CoinEx.Net/Clients/CoinExRestClient.cs index 2258e51..aa45c98 100644 --- a/CoinEx.Net/Clients/CoinExRestClient.cs +++ b/CoinEx.Net/Clients/CoinExRestClient.cs @@ -1,5 +1,4 @@ -using CryptoExchange.Net; -using CoinEx.Net.Interfaces.Clients; +using CoinEx.Net.Interfaces.Clients; using CoinEx.Net.Interfaces.Clients.SpotApi; using CoinEx.Net.Clients.SpotApi; using CryptoExchange.Net.Authentication; @@ -7,6 +6,7 @@ using System.Net.Http; using System; using CoinEx.Net.Objects.Options; +using CryptoExchange.Net.Clients; namespace CoinEx.Net.Clients { diff --git a/CoinEx.Net/Clients/CoinExSocketClient.cs b/CoinEx.Net/Clients/CoinExSocketClient.cs index afed842..da2cdde 100644 --- a/CoinEx.Net/Clients/CoinExSocketClient.cs +++ b/CoinEx.Net/Clients/CoinExSocketClient.cs @@ -1,11 +1,11 @@ -using CryptoExchange.Net; -using CoinEx.Net.Interfaces.Clients; +using CoinEx.Net.Interfaces.Clients; using CoinEx.Net.Interfaces.Clients.SpotApi; using CoinEx.Net.Clients.SpotApi; using CryptoExchange.Net.Authentication; using Microsoft.Extensions.Logging; using System; using CoinEx.Net.Objects.Options; +using CryptoExchange.Net.Clients; namespace CoinEx.Net.Clients { diff --git a/CoinEx.Net/Clients/SpotApi/CoinExRestClientSpotApi.cs b/CoinEx.Net/Clients/SpotApi/CoinExRestClientSpotApi.cs index adb79e1..3c792db 100644 --- a/CoinEx.Net/Clients/SpotApi/CoinExRestClientSpotApi.cs +++ b/CoinEx.Net/Clients/SpotApi/CoinExRestClientSpotApi.cs @@ -17,6 +17,9 @@ using Newtonsoft.Json.Linq; using Microsoft.Extensions.Logging; using CoinEx.Net.Objects.Options; +using CryptoExchange.Net.Interfaces; +using CryptoExchange.Net.Converters.MessageParsing; +using CryptoExchange.Net.Clients; namespace CoinEx.Net.Clients.SpotApi { @@ -59,7 +62,6 @@ internal CoinExRestClientSpotApi(ILogger logger, HttpClient? httpClient, CoinExR ExchangeData = new CoinExRestClientSpotApiExchangeData(this); Trading = new CoinExRestClientSpotApiTrading(this); - manualParseError = true; ParameterPositions[HttpMethod.Delete] = HttpMethodParameterPosition.InUri; _brokerId = !string.IsNullOrEmpty(options.BrokerId) ? options.BrokerId! : "147866029"; @@ -74,12 +76,40 @@ protected override AuthenticationProvider CreateAuthenticationProvider(ApiCreden #region methods #region private internal async Task> Execute(Uri uri, HttpMethod method, CancellationToken ct, Dictionary? parameters = null, bool signed = false) where T : class - => GetResult(await SendRequestAsync>(uri, method, ct, parameters, signed).ConfigureAwait(false)); + { + var result = await SendRequestAsync>(uri, method, ct, parameters, signed).ConfigureAwait(false); + if (!result) + return result.As(default); + + if (result.Data.Code != 0) + return result.AsError(new ServerError(result.Data.Code, result.Data.Message!)); + + return result.As(result.Data.Data); + } + internal async Task Execute(Uri uri, HttpMethod method, CancellationToken ct, Dictionary? parameters = null, bool signed = false) - => GetResult(await SendRequestAsync>(uri, method, ct, parameters, signed).ConfigureAwait(false)); + { + var result = await SendRequestAsync(uri, method, ct, parameters, signed).ConfigureAwait(false); + if (!result) + return result.AsDataless(); + + if (result.Data.Code != 0) + return result.AsDatalessError(new ServerError(result.Data.Code, result.Data.Message!)); + + return result.AsDataless(); + } internal async Task>> ExecutePaged(Uri uri, HttpMethod method, CancellationToken ct, Dictionary? parameters = null, bool signed = false) where T : class - => GetResult(await SendRequestAsync>>(uri, method, ct, parameters, signed).ConfigureAwait(false)); + { + var result = await SendRequestAsync>>(uri, method, ct, parameters, signed).ConfigureAwait(false); + if (!result) + return result.As>(default); + + if (result.Data.Code != 0) + return result.AsError>(new ServerError(result.Data.Code, result.Data.Message!)); + + return result.As(result.Data.Data); + } internal Uri GetUrl(string endpoint) { @@ -405,52 +435,21 @@ private static KlineInterval GetKlineIntervalFromTimespan(TimeSpan timeSpan) } #endregion - - /// - protected override Task TryParseErrorAsync(JToken data) - { - if (data["code"] != null && data["message"] != null) - { - if (data["code"]!.Value() != 0) - { - if (data["code"] == null || data["message"] == null) - return Task.FromResult((ServerError?)new ServerError(data.ToString())); - - return Task.FromResult((ServerError?)new ServerError((int)data["code"]!, (string)data["message"]!)); - } - } - - return Task.FromResult((ServerError?)null); - } - /// - protected override Error ParseErrorResponse(int httpStatusCode, IEnumerable>> responseHeaders, string data) + protected override Error ParseErrorResponse(int httpStatusCode, IEnumerable>> responseHeaders, IMessageAccessor accessor) { - var errorData = ValidateJson(data); - if (!errorData) - return new ServerError(data); + if (!accessor.IsJson) + return new ServerError(accessor.GetOriginalString()); - if (errorData.Data["code"] == null || errorData.Data["message"] == null) - return new ServerError(errorData.Data.ToString()); + var code = accessor.GetValue(MessagePath.Get().Property("code")); + var msg = accessor.GetValue(MessagePath.Get().Property("message")); + if (msg == null) + return new ServerError(accessor.GetOriginalString()); - return new ServerError((int)errorData.Data["code"]!, (string)errorData.Data["message"]!); - } + if (code == null) + return new ServerError(msg); - - private static WebCallResult GetResult(WebCallResult> result) where T : class - { - if (result.Error != null || result.Data == null) - return result.AsError(result.Error ?? new UnknownError("No data received")); - - return result.As(result.Data.Data); - } - - private static WebCallResult GetResult(WebCallResult> result) - { - if (result.Error != null || result.Data == null) - return result.AsDatalessError(result.Error ?? new UnknownError("No data received")); - - return result.AsDataless(); + return new ServerError(code.Value, msg); } /// diff --git a/CoinEx.Net/Clients/SpotApi/CoinExSocketClientSpotApi.cs b/CoinEx.Net/Clients/SpotApi/CoinExSocketClientSpotApi.cs index 779abe8..29d1132 100644 --- a/CoinEx.Net/Clients/SpotApi/CoinExSocketClientSpotApi.cs +++ b/CoinEx.Net/Clients/SpotApi/CoinExSocketClientSpotApi.cs @@ -16,8 +16,6 @@ using CoinEx.Net.Objects.Models.Socket; using CoinEx.Net.Interfaces.Clients.SpotApi; using CoinEx.Net.Objects.Options; -using CryptoExchange.Net.Sockets.MessageParsing.Interfaces; -using CryptoExchange.Net.Sockets.MessageParsing; using CryptoExchange.Net.Objects.Sockets; using CoinEx.Net.Objects.Sockets.Queries; using CryptoExchange.Net.Converters; @@ -28,6 +26,9 @@ using CoinEx.Net.Objects.Sockets.Subscriptions.State; using CoinEx.Net.Objects.Sockets.Subscriptions.Orders; using CoinEx.Net.ExtensionMethods; +using CryptoExchange.Net.Interfaces; +using CryptoExchange.Net.Converters.MessageParsing; +using CryptoExchange.Net.Clients; namespace CoinEx.Net.Clients.SpotApi { diff --git a/CoinEx.Net/CoinEx.Net.csproj b/CoinEx.Net/CoinEx.Net.csproj index ddd005c..c3dcf69 100644 --- a/CoinEx.Net/CoinEx.Net.csproj +++ b/CoinEx.Net/CoinEx.Net.csproj @@ -1,15 +1,15 @@ - + netstandard2.0;netstandard2.1 - 8.0 + 10.0 enable CoinEx.Net JKorf - 6.1.1 - 6.1.1 - 6.1.1 + 6.2.0 + 6.2.0 + 6.2.0 CoinEx.Net is a client library for accessing the CoinEx REST and Websocket API. All data is mapped to readable models and enum values. Additional features include an implementation for maintaining a client side order book, easy integration with other exchange client libraries and more. false CoinEx;CoinEx.Net;CoinEx Client;CoinEx API;CryptoCurrency;CryptoCurrency Exchange @@ -44,12 +44,12 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/CoinEx.Net/CoinEx.Net.xml b/CoinEx.Net/CoinEx.Net.xml index 04d53ee..25340d9 100644 --- a/CoinEx.Net/CoinEx.Net.xml +++ b/CoinEx.Net/CoinEx.Net.xml @@ -106,10 +106,7 @@ - - - - + @@ -225,7 +222,7 @@ - + diff --git a/CoinEx.Net/CoinExAuthenticationProvider.cs b/CoinEx.Net/CoinExAuthenticationProvider.cs index d5ddf3d..a0749fa 100644 --- a/CoinEx.Net/CoinExAuthenticationProvider.cs +++ b/CoinEx.Net/CoinExAuthenticationProvider.cs @@ -7,6 +7,7 @@ using CryptoExchange.Net.Interfaces; using CoinEx.Net.Objects.Internal; using System.Linq; +using CryptoExchange.Net.Clients; namespace CoinEx.Net { @@ -25,7 +26,7 @@ public CoinExAuthenticationProvider(ApiCredentials credentials, INonceProvider? _nonceProvider = nonceProvider ?? new CoinExNonceProvider(); } - public override void AuthenticateRequest(RestApiClient apiClient, Uri uri, HttpMethod method, Dictionary providedParameters, bool auth, ArrayParametersSerialization arraySerialization, HttpMethodParameterPosition parameterPosition, out SortedDictionary uriParameters, out SortedDictionary bodyParameters, out Dictionary headers) + public override void AuthenticateRequest(RestApiClient apiClient, Uri uri, HttpMethod method, Dictionary providedParameters, bool auth, ArrayParametersSerialization arraySerialization, HttpMethodParameterPosition parameterPosition, RequestBodyFormat bodyFormat, out SortedDictionary uriParameters, out SortedDictionary bodyParameters, out Dictionary headers) { uriParameters = parameterPosition == HttpMethodParameterPosition.InUri ? new SortedDictionary(providedParameters) : new SortedDictionary(); bodyParameters = parameterPosition == HttpMethodParameterPosition.InBody ? new SortedDictionary(providedParameters) : new SortedDictionary(); diff --git a/CoinEx.Net/Objects/Internal/CoinExApiResult.cs b/CoinEx.Net/Objects/Internal/CoinExApiResult.cs index 039d981..26f91da 100644 --- a/CoinEx.Net/Objects/Internal/CoinExApiResult.cs +++ b/CoinEx.Net/Objects/Internal/CoinExApiResult.cs @@ -1,9 +1,13 @@ namespace CoinEx.Net.Objects.Internal { - internal class CoinExApiResult + internal class CoinExApiResult { public string? Message { get; set; } public int Code { get; set; } + } + + internal class CoinExApiResult : CoinExApiResult + { public T Data { get; set; } = default!; } } diff --git a/CoinEx.Net/Objects/Sockets/Queries/CoinExQuery.cs b/CoinEx.Net/Objects/Sockets/Queries/CoinExQuery.cs index e050ea2..54ccdf9 100644 --- a/CoinEx.Net/Objects/Sockets/Queries/CoinExQuery.cs +++ b/CoinEx.Net/Objects/Sockets/Queries/CoinExQuery.cs @@ -21,12 +21,12 @@ public CoinExQuery(string method, IEnumerable parameters, bool authentic ListenerIdentifiers = new HashSet() { ((CoinExSocketRequest)Request).Id.ToString() }; } - public override Task>> HandleMessageAsync(SocketConnection connection, DataEvent> message) + public override CallResult> HandleMessage(SocketConnection connection, DataEvent> message) { if (message.Data.Error != null) - return Task.FromResult(new CallResult>(new ServerError(message.Data.Error.Code, message.Data.Error.Message))); + return new CallResult>(new ServerError(message.Data.Error.Code, message.Data.Error.Message)); - return Task.FromResult(new CallResult>(message.Data, message.OriginalData, null)); + return new CallResult>(message.Data, message.OriginalData, null); } } } diff --git a/CoinEx.Net/Objects/Sockets/Subscriptions/Balance/CoinExBalanceSubscription.cs b/CoinEx.Net/Objects/Sockets/Subscriptions/Balance/CoinExBalanceSubscription.cs index 7804de9..b193a1d 100644 --- a/CoinEx.Net/Objects/Sockets/Subscriptions/Balance/CoinExBalanceSubscription.cs +++ b/CoinEx.Net/Objects/Sockets/Subscriptions/Balance/CoinExBalanceSubscription.cs @@ -1,9 +1,9 @@ using CoinEx.Net.Objects.Models; using CoinEx.Net.Objects.Sockets.Queries; +using CryptoExchange.Net.Interfaces; using CryptoExchange.Net.Objects; using CryptoExchange.Net.Objects.Sockets; using CryptoExchange.Net.Sockets; -using CryptoExchange.Net.Sockets.MessageParsing.Interfaces; using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; @@ -24,14 +24,14 @@ public CoinExBalanceSubscription(ILogger logger, Action { "asset.update" }; } - public override Task DoHandleMessageAsync(SocketConnection connection, DataEvent message) + public override CallResult DoHandleMessage(SocketConnection connection, DataEvent message) { var data = (CoinExSocketUpdate)message.Data; foreach (var item in data.Data.Balances) item.Value.Asset = item.Key; _handler.Invoke(message.As(data.Data.Balances.Values.AsEnumerable(), null, SocketUpdateType.Update)); - return Task.FromResult(new CallResult(null)); + return new CallResult(null); } public override Type? GetMessageType(IMessageAccessor message) => typeof(CoinExSocketUpdate); diff --git a/CoinEx.Net/Objects/Sockets/Subscriptions/Deals/CoinExDealsSubscription.cs b/CoinEx.Net/Objects/Sockets/Subscriptions/Deals/CoinExDealsSubscription.cs index d33f6c3..4f2de77 100644 --- a/CoinEx.Net/Objects/Sockets/Subscriptions/Deals/CoinExDealsSubscription.cs +++ b/CoinEx.Net/Objects/Sockets/Subscriptions/Deals/CoinExDealsSubscription.cs @@ -1,10 +1,10 @@ using CoinEx.Net.Objects.Models.Socket; using CoinEx.Net.Objects.Sockets.Queries; using CoinEx.Net.Objects.Sockets.Subscriptions.Balance; +using CryptoExchange.Net.Interfaces; using CryptoExchange.Net.Objects; using CryptoExchange.Net.Objects.Sockets; using CryptoExchange.Net.Sockets; -using CryptoExchange.Net.Sockets.MessageParsing.Interfaces; using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; @@ -29,11 +29,11 @@ public CoinExDealsSubscription(ILogger logger, string? symbol, IEnumerable DoHandleMessageAsync(SocketConnection connection, DataEvent message) + public override CallResult DoHandleMessage(SocketConnection connection, DataEvent message) { var data = (CoinExSocketUpdate)message.Data; _handler.Invoke(message.As(data.Data.Trades, _symbol, ConnectionInvocations == 1 ? SocketUpdateType.Snapshot : SocketUpdateType.Update)); - return Task.FromResult(new CallResult(null)); + return new CallResult(null); } public override Type? GetMessageType(IMessageAccessor message) => typeof(CoinExSocketUpdate); diff --git a/CoinEx.Net/Objects/Sockets/Subscriptions/Depth/CoinExDepthSubscription.cs b/CoinEx.Net/Objects/Sockets/Subscriptions/Depth/CoinExDepthSubscription.cs index cf33425..f0130a0 100644 --- a/CoinEx.Net/Objects/Sockets/Subscriptions/Depth/CoinExDepthSubscription.cs +++ b/CoinEx.Net/Objects/Sockets/Subscriptions/Depth/CoinExDepthSubscription.cs @@ -1,9 +1,9 @@ using CoinEx.Net.Objects.Models.Socket; using CoinEx.Net.Objects.Sockets.Queries; +using CryptoExchange.Net.Interfaces; using CryptoExchange.Net.Objects; using CryptoExchange.Net.Objects.Sockets; using CryptoExchange.Net.Sockets; -using CryptoExchange.Net.Sockets.MessageParsing.Interfaces; using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; @@ -27,11 +27,11 @@ public CoinExDepthSubscription(ILogger logger, string? symbol, IEnumerable { "depth.update" + symbol }; } - public override Task DoHandleMessageAsync(SocketConnection connection, DataEvent message) + public override CallResult DoHandleMessage(SocketConnection connection, DataEvent message) { var data = (CoinExSocketUpdate)message.Data; _handler.Invoke(message.As(data.Data.Book, _symbol, data.Data.Snapshot ? SocketUpdateType.Snapshot : SocketUpdateType.Update)); - return Task.FromResult(new CallResult(null)); + return new CallResult(null); } public override Type? GetMessageType(IMessageAccessor message) => typeof(CoinExSocketUpdate); diff --git a/CoinEx.Net/Objects/Sockets/Subscriptions/Orders/CoinExOrderSubscription.cs b/CoinEx.Net/Objects/Sockets/Subscriptions/Orders/CoinExOrderSubscription.cs index ce127c9..d938120 100644 --- a/CoinEx.Net/Objects/Sockets/Subscriptions/Orders/CoinExOrderSubscription.cs +++ b/CoinEx.Net/Objects/Sockets/Subscriptions/Orders/CoinExOrderSubscription.cs @@ -1,9 +1,9 @@ using CoinEx.Net.Objects.Models.Socket; using CoinEx.Net.Objects.Sockets.Queries; +using CryptoExchange.Net.Interfaces; using CryptoExchange.Net.Objects; using CryptoExchange.Net.Objects.Sockets; using CryptoExchange.Net.Sockets; -using CryptoExchange.Net.Sockets.MessageParsing.Interfaces; using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; @@ -26,7 +26,7 @@ public CoinExOrderSubscription(ILogger logger, IEnumerable symbols, Acti ListenerIdentifiers = new HashSet { "order.update" }; } - public override Task DoHandleMessageAsync(SocketConnection connection, DataEvent message) + public override CallResult DoHandleMessage(SocketConnection connection, DataEvent message) { var data = (CoinExSocketUpdate)message.Data; _handler.Invoke(message.As(new CoinExSocketOrderUpdate @@ -34,7 +34,7 @@ public override Task DoHandleMessageAsync(SocketConnection connectio UpdateType = data.Data.UpdateType, Order = data.Data.Order }, data.Data.Order.Symbol, SocketUpdateType.Update)); - return Task.FromResult(new CallResult(null)); + return new CallResult(null); } public override Type? GetMessageType(IMessageAccessor message) => typeof(CoinExSocketUpdate); diff --git a/CoinEx.Net/Objects/Sockets/Subscriptions/Orders/CoinExOrderUpdate.cs b/CoinEx.Net/Objects/Sockets/Subscriptions/Orders/CoinExOrderUpdate.cs index c962fd3..fb08040 100644 --- a/CoinEx.Net/Objects/Sockets/Subscriptions/Orders/CoinExOrderUpdate.cs +++ b/CoinEx.Net/Objects/Sockets/Subscriptions/Orders/CoinExOrderUpdate.cs @@ -3,6 +3,7 @@ using CoinEx.Net.Objects.Models.Socket; using CryptoExchange.Net.Attributes; using CryptoExchange.Net.Converters; +using CryptoExchange.Net.Converters.JsonNet; using Newtonsoft.Json; namespace CoinEx.Net.Objects.Sockets.Subscriptions.Orders diff --git a/CoinEx.Net/Objects/Sockets/Subscriptions/State/CoinExStateSubscription.cs b/CoinEx.Net/Objects/Sockets/Subscriptions/State/CoinExStateSubscription.cs index 405cda8..f06eb27 100644 --- a/CoinEx.Net/Objects/Sockets/Subscriptions/State/CoinExStateSubscription.cs +++ b/CoinEx.Net/Objects/Sockets/Subscriptions/State/CoinExStateSubscription.cs @@ -1,9 +1,9 @@ using CoinEx.Net.Objects.Models.Socket; using CoinEx.Net.Objects.Sockets.Queries; +using CryptoExchange.Net.Interfaces; using CryptoExchange.Net.Objects; using CryptoExchange.Net.Objects.Sockets; using CryptoExchange.Net.Sockets; -using CryptoExchange.Net.Sockets.MessageParsing.Interfaces; using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; @@ -28,7 +28,7 @@ public CoinExStateSubscription(ILogger logger, string? symbol, IEnumerable { "state.update" }; } - public override Task DoHandleMessageAsync(SocketConnection connection, DataEvent message) + public override CallResult DoHandleMessage(SocketConnection connection, DataEvent message) { var data = (CoinExSocketUpdate>>)message.Data; foreach (var item in data.Data.First()) @@ -37,7 +37,7 @@ public override Task DoHandleMessageAsync(SocketConnection connectio var relevant = data.Data.First().Where(d => _symbol == null || d.Key == _symbol).Select(d => d.Value); _handler.Invoke(message.As(relevant, _symbol, SocketUpdateType.Update)); - return Task.FromResult(new CallResult(null)); + return new CallResult(null); } public override Type? GetMessageType(IMessageAccessor message) => typeof(CoinExSocketUpdate>>); diff --git a/CoinEx.Net/Usings.cs b/CoinEx.Net/Usings.cs new file mode 100644 index 0000000..7ef0a6f --- /dev/null +++ b/CoinEx.Net/Usings.cs @@ -0,0 +1 @@ +global using CryptoExchange.Net.Converters.JsonNet; \ No newline at end of file diff --git a/README.md b/README.md index e52e69a..62cc3b9 100644 --- a/README.md +++ b/README.md @@ -95,6 +95,10 @@ Make a one time donation in a crypto currency of your choice. If you prefer to d Alternatively, sponsor me on Github using [Github Sponsors](https://github.com/sponsors/JKorf). ## Release notes +* Version 6.2.0 - 16 Mar 2024 + * Updated CryptoExchange.Net to 7.1.0, see https://github.com/JKorf/CryptoExchange.Net?tab=readme-ov-file#release-notes for release notes + * Updated unit test package dependencies and updated tests accordingly + * Version 6.1.1 - 26 Feb 2024 * Fixed order subscription with symbol parameters