1
0
mirror of https://github.com/JKorf/CryptoExchange.Net synced 2026-02-16 14:13:46 +00:00

Compare commits

...

3 Commits

Author SHA1 Message Date
JKorf
23efb3f432 Update SymbolOrderBook.cs 2025-12-08 21:47:38 +01:00
Jkorf
dedb17b166 wip 2025-12-08 16:11:46 +01:00
Jkorf
be9e2ac7e4 wip 2025-12-08 11:30:16 +01:00
201 changed files with 274 additions and 674 deletions

View File

@ -4,7 +4,6 @@ using NUnit.Framework.Legacy;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CryptoExchange.Net.UnitTests

View File

@ -1,11 +1,5 @@
using CryptoExchange.Net.Authentication;
using CryptoExchange.Net.Objects;
using CryptoExchange.Net.UnitTests.TestImplementations;
using Microsoft.Extensions.Logging;
using NUnit.Framework;
using NUnit.Framework;
using NUnit.Framework.Legacy;
using System;
using System.Collections.Generic;
namespace CryptoExchange.Net.UnitTests
{

View File

@ -4,11 +4,8 @@ using NUnit.Framework;
using NUnit.Framework.Legacy;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
namespace CryptoExchange.Net.UnitTests
{
@ -115,7 +112,7 @@ namespace CryptoExchange.Net.UnitTests
var result = new WebCallResult<TestObjectResult>(
System.Net.HttpStatusCode.OK,
HttpVersion.Version11,
new KeyValuePair<string, string[]>[0],
new HttpResponseMessage().Headers,
TimeSpan.FromSeconds(1),
null,
"{}",
@ -123,7 +120,7 @@ namespace CryptoExchange.Net.UnitTests
"https://test.com/api",
null,
HttpMethod.Get,
new KeyValuePair<string, string[]>[0],
new HttpRequestMessage().Headers,
ResultDataSource.Server,
new TestObjectResult(),
null);
@ -146,7 +143,7 @@ namespace CryptoExchange.Net.UnitTests
var result = new WebCallResult<TestObjectResult>(
System.Net.HttpStatusCode.OK,
HttpVersion.Version11,
new KeyValuePair<string, string[]>[0],
new HttpResponseMessage().Headers,
TimeSpan.FromSeconds(1),
null,
"{}",
@ -154,7 +151,7 @@ namespace CryptoExchange.Net.UnitTests
"https://test.com/api",
null,
HttpMethod.Get,
new KeyValuePair<string, string[]>[0],
new HttpRequestMessage().Headers,
ResultDataSource.Server,
new TestObjectResult(),
null);

View File

@ -1,7 +1,5 @@
using CryptoExchange.Net.Objects;
using NUnit.Framework;
using NUnit.Framework.Legacy;
using System.Diagnostics;
using System.Globalization;
namespace CryptoExchange.Net.UnitTests

View File

@ -1,15 +1,8 @@
using CryptoExchange.Net.Authentication;
using CryptoExchange.Net.Objects;
using CryptoExchange.Net.Objects.Options;
using CryptoExchange.Net.UnitTests.TestImplementations;
using Microsoft.Extensions.Logging;
using NUnit.Framework;
using NUnit.Framework.Legacy;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CryptoExchange.Net.UnitTests
{

View File

@ -9,7 +9,6 @@ using System.Threading.Tasks;
using System.Threading;
using NUnit.Framework.Legacy;
using CryptoExchange.Net.RateLimiting;
using System.Net;
using CryptoExchange.Net.RateLimiting.Guards;
using CryptoExchange.Net.RateLimiting.Filters;
using CryptoExchange.Net.RateLimiting.Interfaces;

View File

@ -4,9 +4,7 @@ using System.Text.Json;
using NUnit.Framework;
using System;
using System.Text.Json.Serialization;
using NUnit.Framework.Legacy;
using CryptoExchange.Net.Converters;
using CryptoExchange.Net.Testing.Comparers;
using CryptoExchange.Net.SharedApis;
namespace CryptoExchange.Net.UnitTests

View File

@ -2,8 +2,8 @@
using CryptoExchange.Net.Objects.Errors;
using CryptoExchange.Net.Objects.Sockets;
using CryptoExchange.Net.Sockets;
using CryptoExchange.Net.Sockets.Default;
using System;
using System.Collections.Generic;
using System.Text.Json.Serialization;
namespace CryptoExchange.Net.UnitTests.TestImplementations.Sockets
@ -37,14 +37,14 @@ namespace CryptoExchange.Net.UnitTests.TestImplementations.Sockets
MessageMatcher = MessageMatcher.Create<SubResponse>(request + "-" + channel, HandleMessage);
}
public CallResult<SubResponse> HandleMessage(SocketConnection connection, DataEvent<SubResponse> message)
public CallResult<SubResponse> HandleMessage(SocketConnection connection, DateTime time, string? originalData, SubResponse message)
{
if (!message.Data.Status.Equals("confirmed", StringComparison.OrdinalIgnoreCase))
if (!message.Status.Equals("confirmed", StringComparison.OrdinalIgnoreCase))
{
return new CallResult<SubResponse>(new ServerError(ErrorInfo.Unknown with { Message = message.Data.Status }));
return new CallResult<SubResponse>(new ServerError(ErrorInfo.Unknown with { Message = message.Status }));
}
return message.ToCallResult();
return new CallResult<SubResponse>(message, originalData, null);
}
}
}

View File

@ -1,9 +1,4 @@
using CryptoExchange.Net.Sockets;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CryptoExchange.Net.UnitTests.TestImplementations.Sockets
{

View File

@ -1,13 +1,9 @@
using CryptoExchange.Net.Interfaces;
using CryptoExchange.Net.Objects;
using CryptoExchange.Net.Objects;
using CryptoExchange.Net.Objects.Sockets;
using CryptoExchange.Net.Sockets;
using CryptoExchange.Net.Sockets.Default;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CryptoExchange.Net.UnitTests.TestImplementations.Sockets
{

View File

@ -1,12 +1,10 @@
using CryptoExchange.Net.Interfaces;
using CryptoExchange.Net.Objects;
using CryptoExchange.Net.Objects;
using CryptoExchange.Net.Objects.Sockets;
using CryptoExchange.Net.Sockets;
using CryptoExchange.Net.Sockets.Default;
using Microsoft.Extensions.Logging;
using Moq;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace CryptoExchange.Net.UnitTests.TestImplementations.Sockets
{

View File

@ -1,19 +1,16 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Net.Http;
using System.Text;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
using CryptoExchange.Net.Authentication;
using CryptoExchange.Net.Clients;
using CryptoExchange.Net.Converters.MessageParsing.DynamicConverters;
using CryptoExchange.Net.Converters.SystemTextJson;
using CryptoExchange.Net.Interfaces;
using CryptoExchange.Net.Objects;
using CryptoExchange.Net.Objects.Errors;
using CryptoExchange.Net.Objects.Options;
using CryptoExchange.Net.SharedApis;
using CryptoExchange.Net.UnitTests.TestImplementations;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
@ -46,6 +43,8 @@ namespace CryptoExchange.Net.UnitTests
public class TestSubClient : RestApiClient
{
protected override IRestMessageHandler MessageHandler => throw new NotImplementedException();
public TestSubClient(RestExchangeOptions<TestEnvironment> options, RestApiOptions apiOptions) : base(new TraceLogger(), null, "https://localhost:123", options, apiOptions)
{
}

View File

@ -13,13 +13,13 @@ using CryptoExchange.Net.Authentication;
using System.Collections.Generic;
using Microsoft.Extensions.Logging;
using CryptoExchange.Net.Clients;
using CryptoExchange.Net.SharedApis;
using Microsoft.Extensions.Options;
using System.Linq;
using CryptoExchange.Net.Converters.SystemTextJson;
using System.Text.Json.Serialization;
using CryptoExchange.Net.Objects.Errors;
using System.Net.Http.Headers;
using CryptoExchange.Net.SharedApis;
using CryptoExchange.Net.Converters.MessageParsing.DynamicConverters;
namespace CryptoExchange.Net.UnitTests.TestImplementations
{
@ -52,13 +52,13 @@ namespace CryptoExchange.Net.UnitTests.TestImplementations
response.Setup(c => c.IsSuccessStatusCode).Returns(true);
response.Setup(c => c.GetResponseStreamAsync()).Returns(Task.FromResult((Stream)responseStream));
var headers = new Dictionary<string, string[]>();
var headers = new HttpRequestMessage().Headers;
var request = new Mock<IRequest>();
request.Setup(c => c.Uri).Returns(new Uri("http://www.test.com"));
request.Setup(c => c.GetResponseAsync(It.IsAny<CancellationToken>())).Returns(Task.FromResult(response.Object));
request.Setup(c => c.SetContent(It.IsAny<string>(), It.IsAny<string>())).Callback(new Action<string, string>((content, type) => { request.Setup(r => r.Content).Returns(content); }));
request.Setup(c => c.AddHeader(It.IsAny<string>(), It.IsAny<string>())).Callback<string, string>((key, val) => headers.Add(key, new string[] { val }));
request.Setup(c => c.GetHeaders()).Returns(() => headers.ToArray());
request.Setup(c => c.GetHeaders()).Returns(() => headers);
var factory = Mock.Get(Api1.RequestFactory);
factory.Setup(c => c.Create(It.IsAny<Version>(), It.IsAny<HttpMethod>(), It.IsAny<Uri>(), It.IsAny<int>()))
@ -132,6 +132,8 @@ namespace CryptoExchange.Net.UnitTests.TestImplementations
public class TestRestApi1Client : RestApiClient
{
protected override IRestMessageHandler MessageHandler { get; } = new TestRestMessageHandler();
public TestRestApi1Client(TestClientOptions options) : base(new TraceLogger(), null, "https://localhost:123", options, options.Api1Options)
{
RequestFactory = new Mock<IRequestFactory>().Object;
@ -179,6 +181,8 @@ namespace CryptoExchange.Net.UnitTests.TestImplementations
public class TestRestApi2Client : RestApiClient
{
protected override IRestMessageHandler MessageHandler { get; } = new TestRestMessageHandler();
public TestRestApi2Client(TestClientOptions options) : base(new TraceLogger(), null, "https://localhost:123", options, options.Api2Options)
{
RequestFactory = new Mock<IRequestFactory>().Object;

View File

@ -0,0 +1,26 @@
using CryptoExchange.Net.Converters.MessageParsing.DynamicConverters;
using CryptoExchange.Net.Converters.SystemTextJson.MessageHandlers;
using CryptoExchange.Net.Objects;
using CryptoExchange.Net.Objects.Errors;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
namespace CryptoExchange.Net.UnitTests.TestImplementations
{
internal class TestRestMessageHandler : JsonRestMessageHandler
{
public override JsonSerializerOptions Options => new JsonSerializerOptions();
public override ValueTask<Error> ParseErrorResponse(int httpStatusCode, HttpResponseHeaders responseHeaders, Stream responseStream)
{
return new ValueTask<Error>(new ServerError(ErrorInfo.Unknown));
}
}
}

View File

@ -1,10 +1,6 @@
using CryptoExchange.Net.UnitTests.TestImplementations;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
namespace CryptoExchange.Net.UnitTests
{

View File

@ -5,7 +5,6 @@ using CryptoExchange.Net.Objects;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Net.Http;
using System.Security.Cryptography;
using System.Text;

View File

@ -1,8 +1,6 @@
using System;
using System.Collections.Generic;
using CryptoExchange.Net.Authentication;
using CryptoExchange.Net.Interfaces;
using CryptoExchange.Net.Objects;
using CryptoExchange.Net.Interfaces.Clients;
using CryptoExchange.Net.Objects.Errors;
using CryptoExchange.Net.Objects.Options;
using CryptoExchange.Net.SharedApis;

View File

@ -1,7 +1,6 @@
using CryptoExchange.Net.Authentication;
using CryptoExchange.Net.Objects.Options;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using System;
using System.Collections.Generic;
using System.Threading;

View File

@ -1,5 +1,5 @@
using System.Linq;
using CryptoExchange.Net.Interfaces;
using CryptoExchange.Net.Interfaces.Clients;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;

View File

@ -1,4 +1,4 @@
using CryptoExchange.Net.Interfaces;
using CryptoExchange.Net.Interfaces.Clients;
using CryptoExchange.Net.Logging.Extensions;
using CryptoExchange.Net.Objects.Options;
using CryptoExchange.Net.Objects.Sockets;
@ -9,7 +9,6 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
namespace CryptoExchange.Net.Clients
{

View File

@ -1,8 +1,5 @@
using CryptoExchange.Net.Interfaces;
using Microsoft.Extensions.DependencyInjection;
using CryptoExchange.Net.Interfaces.Clients;
using System;
using System.Collections.Generic;
using System.Linq;
namespace CryptoExchange.Net.Clients
{

View File

@ -1,4 +1,4 @@
using CryptoExchange.Net.Interfaces;
using CryptoExchange.Net.Interfaces.Clients;
using System;
namespace CryptoExchange.Net.Clients

View File

@ -1,6 +1,7 @@
using CryptoExchange.Net.Caching;
using CryptoExchange.Net.Converters.MessageParsing.DynamicConverters;
using CryptoExchange.Net.Interfaces;
using CryptoExchange.Net.Interfaces.Clients;
using CryptoExchange.Net.Logging.Extensions;
using CryptoExchange.Net.Objects;
using CryptoExchange.Net.Objects.Errors;
@ -18,7 +19,6 @@ using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;

View File

@ -1,5 +1,6 @@
using CryptoExchange.Net.Converters.MessageParsing.DynamicConverters;
using CryptoExchange.Net.Interfaces;
using CryptoExchange.Net.Interfaces.Clients;
using CryptoExchange.Net.Logging.Extensions;
using CryptoExchange.Net.Objects;
using CryptoExchange.Net.Objects.Errors;
@ -8,7 +9,11 @@ using CryptoExchange.Net.Objects.Sockets;
using CryptoExchange.Net.RateLimiting;
using CryptoExchange.Net.RateLimiting.Interfaces;
using CryptoExchange.Net.Sockets;
using CryptoExchange.Net.Sockets.Default;
using CryptoExchange.Net.Sockets.Default.Interfaces;
using CryptoExchange.Net.Sockets.HighPerf;
using CryptoExchange.Net.Sockets.HighPerf.Interfaces;
using CryptoExchange.Net.Sockets.Interfaces;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Concurrent;
@ -29,16 +34,18 @@ namespace CryptoExchange.Net.Clients
#region Fields
/// <inheritdoc/>
public IWebsocketFactory SocketFactory { get; set; } = new WebsocketFactory();
/// <inheritdoc/>
public IHighPerfConnectionFactory? HighPerfConnectionFactory { get; set; }
/// <summary>
/// List of socket connections currently connecting/connected
/// </summary>
protected internal ConcurrentDictionary<int, SocketConnection> socketConnections = new();
protected internal ConcurrentDictionary<int, SocketConnection> _socketConnections = new();
/// <summary>
/// List of HighPerf socket connections currently connecting/connected
/// </summary>
protected internal ConcurrentDictionary<int, HighPerfSocketConnection> highPerfSocketConnections = new();
protected internal ConcurrentDictionary<int, HighPerfSocketConnection> _highPerfSocketConnections = new();
/// <summary>
/// Semaphore used while creating sockets
@ -100,25 +107,25 @@ namespace CryptoExchange.Net.Clients
{
get
{
if (socketConnections.IsEmpty)
if (_socketConnections.IsEmpty)
return 0;
return socketConnections.Sum(s => s.Value.IncomingKbps);
return _socketConnections.Sum(s => s.Value.IncomingKbps);
}
}
/// <inheritdoc />
public int CurrentConnections => socketConnections.Count;
public int CurrentConnections => _socketConnections.Count;
/// <inheritdoc />
public int CurrentSubscriptions
{
get
{
if (socketConnections.IsEmpty)
if (_socketConnections.IsEmpty)
return 0;
return socketConnections.Sum(s => s.Value.UserSubscriptionCount);
return _socketConnections.Sum(s => s.Value.UserSubscriptionCount);
}
}
@ -569,7 +576,7 @@ namespace CryptoExchange.Net.Clients
protected void AddSystemSubscription(SystemSubscription systemSubscription)
{
systemSubscriptions.Add(systemSubscription);
foreach (var connection in socketConnections.Values)
foreach (var connection in _socketConnections.Values)
connection.AddSubscription(systemSubscription);
}
@ -615,7 +622,7 @@ namespace CryptoExchange.Net.Clients
/// <returns></returns>
protected virtual async Task<CallResult<SocketConnection>> GetSocketConnection(string address, bool authenticated, bool dedicatedRequestConnection, CancellationToken ct, string? topic = null)
{
var socketQuery = socketConnections.Where(s => s.Value.Tag.TrimEnd('/') == address.TrimEnd('/')
var socketQuery = _socketConnections.Where(s => s.Value.Tag.TrimEnd('/') == address.TrimEnd('/')
&& s.Value.ApiClient.GetType() == GetType()
&& (AllowTopicsOnTheSameConnection || !s.Value.Topics.Contains(topic)))
.Select(x => x.Value)
@ -668,7 +675,7 @@ namespace CryptoExchange.Net.Clients
if (connection != null)
{
if (connection.UserSubscriptionCount < ClientOptions.SocketSubscriptionsCombineTarget
|| (socketConnections.Count >= (ApiOptions.MaxSocketConnections ?? ClientOptions.MaxSocketConnections) && socketConnections.All(s => s.Value.UserSubscriptionCount >= ClientOptions.SocketSubscriptionsCombineTarget)))
|| (_socketConnections.Count >= (ApiOptions.MaxSocketConnections ?? ClientOptions.MaxSocketConnections) && _socketConnections.All(s => s.Value.UserSubscriptionCount >= ClientOptions.SocketSubscriptionsCombineTarget)))
{
// Use existing socket if it has less than target connections OR it has the least connections and we can't make new
return new CallResult<SocketConnection>(connection);
@ -720,27 +727,6 @@ namespace CryptoExchange.Net.Clients
IHighPerfConnectionFactory connectionFactory,
CancellationToken ct)
{
var socketQuery = highPerfSocketConnections.Where(s => s.Value.Tag.TrimEnd('/') == address.TrimEnd('/')
&& s.Value.ApiClient.GetType() == GetType()
&& s.Value.UpdateType == typeof(TUpdateType))
.Select(x => x.Value)
.ToList();
socketQuery = socketQuery.Where(s => (s.Status == SocketStatus.None || s.Status == SocketStatus.Connected)
&& s.Connected).ToList();
var connection = socketQuery.OrderBy(s => s.UserSubscriptionCount).FirstOrDefault();
if (connection != null)
{
if (connection.UserSubscriptionCount < ClientOptions.SocketSubscriptionsCombineTarget
|| (socketConnections.Count >= (ApiOptions.MaxSocketConnections ?? ClientOptions.MaxSocketConnections) && socketConnections.All(s => s.Value.UserSubscriptionCount >= ClientOptions.SocketSubscriptionsCombineTarget)))
{
// Use existing socket if it has less than target connections OR it has the least connections and we can't make new
return new CallResult<HighPerfSocketConnection<TUpdateType>>((HighPerfSocketConnection<TUpdateType>)connection);
}
}
var connectionAddress = await GetConnectionUrlAsync(address, false).ConfigureAwait(false);
if (!connectionAddress)
{
@ -794,9 +780,9 @@ namespace CryptoExchange.Net.Clients
if (connectResult)
{
if (socketConnection is SocketConnection sc)
socketConnections.TryAdd(socketConnection.SocketId, sc);
_socketConnections.TryAdd(socketConnection.SocketId, sc);
else if (socketConnection is HighPerfSocketConnection hsc)
highPerfSocketConnections.TryAdd(socketConnection.SocketId, hsc);
_highPerfSocketConnections.TryAdd(socketConnection.SocketId, hsc);
return connectResult;
}
@ -832,7 +818,7 @@ namespace CryptoExchange.Net.Clients
{
Subscription? subscription = null;
SocketConnection? connection = null;
foreach (var socket in socketConnections.Values.ToList())
foreach (var socket in _socketConnections.Values.ToList())
{
subscription = socket.GetSubscription(subscriptionId);
if (subscription != null)
@ -870,14 +856,14 @@ namespace CryptoExchange.Net.Clients
/// <returns></returns>
public virtual async Task UnsubscribeAllAsync()
{
var sum = socketConnections.Sum(s => s.Value.UserSubscriptionCount);
var sum = _socketConnections.Sum(s => s.Value.UserSubscriptionCount);
if (sum == 0)
return;
_logger.UnsubscribingAll(socketConnections.Sum(s => s.Value.UserSubscriptionCount));
_logger.UnsubscribingAll(_socketConnections.Sum(s => s.Value.UserSubscriptionCount));
var tasks = new List<Task>();
{
var socketList = socketConnections.Values;
var socketList = _socketConnections.Values;
foreach (var connection in socketList)
{
foreach(var subscription in connection.Subscriptions.Where(x => x.UserSubscription))
@ -894,10 +880,10 @@ namespace CryptoExchange.Net.Clients
/// <returns></returns>
public virtual async Task ReconnectAsync()
{
_logger.ReconnectingAllConnections(socketConnections.Count);
_logger.ReconnectingAllConnections(_socketConnections.Count);
var tasks = new List<Task>();
{
var socketList = socketConnections.Values;
var socketList = _socketConnections.Values;
foreach (var sub in socketList)
tasks.Add(sub.TriggerReconnectAsync());
}
@ -929,7 +915,7 @@ namespace CryptoExchange.Net.Clients
base.SetOptions(options);
if ((!previousProxyIsSet && options.Proxy == null)
|| socketConnections.IsEmpty)
|| _socketConnections.IsEmpty)
{
return;
}
@ -937,7 +923,7 @@ namespace CryptoExchange.Net.Clients
_logger.LogInformation("Reconnecting websockets to apply proxy");
// Update proxy, also triggers reconnect
foreach (var connection in socketConnections)
foreach (var connection in _socketConnections)
_ = connection.Value.UpdateProxy(options.Proxy);
}
@ -957,14 +943,14 @@ namespace CryptoExchange.Net.Clients
public SocketApiClientState GetState(bool includeSubDetails = true)
{
var connectionStates = new List<SocketConnectionState>();
foreach (var socketIdAndConnection in socketConnections)
foreach (var socketIdAndConnection in _socketConnections)
{
SocketConnection connection = socketIdAndConnection.Value;
SocketConnectionState connectionState = connection.GetState(includeSubDetails);
connectionStates.Add(connectionState);
}
return new SocketApiClientState(socketConnections.Count, CurrentSubscriptions, IncomingKbps, connectionStates);
return new SocketApiClientState(_socketConnections.Count, CurrentSubscriptions, IncomingKbps, connectionStates);
}
/// <summary>
@ -1026,7 +1012,7 @@ namespace CryptoExchange.Net.Clients
_disposing = true;
var tasks = new List<Task>();
{
var socketList = socketConnections.Values.Where(x => x.UserSubscriptionCount > 0 || x.Connected);
var socketList = _socketConnections.Values.Where(x => x.UserSubscriptionCount > 0 || x.Connected);
if (socketList.Any())
_logger.DisposingSocketClient();

View File

@ -1,7 +1,5 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Text;
using System.Text.Json.Serialization;
namespace CryptoExchange.Net.Converters

View File

@ -1,9 +1,6 @@
using CryptoExchange.Net.Objects;
using System;
using System.Collections.Generic;
using System.IO;
using System.Net.Http.Headers;
using System.Net.WebSockets;
using System.Threading;
using System.Threading.Tasks;

View File

@ -1,6 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace CryptoExchange.Net.Converters.MessageParsing.DynamicConverters
{

View File

@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace CryptoExchange.Net.Converters.MessageParsing.DynamicConverters
namespace CryptoExchange.Net.Converters.MessageParsing.DynamicConverters
{
internal class MessageEvalutorFieldReference
{

View File

@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace CryptoExchange.Net.Converters.MessageParsing.DynamicConverters
{

View File

@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace CryptoExchange.Net.Converters.MessageParsing.DynamicConverters
namespace CryptoExchange.Net.Converters.MessageParsing.DynamicConverters
{
/// <summary>
/// Search result value

View File

@ -1,15 +1,12 @@
using System;
using System.Collections.Concurrent;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Text.Json.Serialization;
using System.Text.Json;
using CryptoExchange.Net.Attributes;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Threading;
using System.Diagnostics;
namespace CryptoExchange.Net.Converters.SystemTextJson
{

View File

@ -1,6 +1,5 @@
using Microsoft.Extensions.Logging;
using System;
using System.Diagnostics;
using System.Runtime.Serialization;
using System.Text.Json;
using System.Text.Json.Serialization;

View File

@ -1,8 +1,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;

View File

@ -1,6 +1,5 @@
using Microsoft.Extensions.Logging;
using System;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Text.Json;

View File

@ -1,5 +1,4 @@
using System;
using System.Globalization;
using System.Text.Json;
using System.Text.Json.Serialization;

View File

@ -1,10 +1,8 @@
using CryptoExchange.Net.Attributes;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Reflection;

View File

@ -1,5 +1,4 @@
using System;
using System.Globalization;
using System.Text.Json;
using System.Text.Json.Serialization;

View File

@ -1,22 +1,16 @@
using CryptoExchange.Net.Converters.MessageParsing.DynamicConverters;
using CryptoExchange.Net.Interfaces;
using CryptoExchange.Net.Objects;
using CryptoExchange.Net.Objects.Errors;
using CryptoExchange.Net.Objects.Options;
using CryptoExchange.Net.Requests;
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
namespace CryptoExchange.Net.Converters.SystemTextJson.MessageConverters
namespace CryptoExchange.Net.Converters.SystemTextJson.MessageHandlers
{
/// <summary>
/// JSON REST message handler

View File

@ -7,7 +7,7 @@ using System.Net.WebSockets;
using System.Text;
using System.Text.Json;
namespace CryptoExchange.Net.Converters.SystemTextJson
namespace CryptoExchange.Net.Converters.SystemTextJson.MessageHandlers
{
/// <summary>
/// JSON WebSocket message handler, sequentially read the JSON and looks for specific predefined fields to identify the message
@ -87,7 +87,7 @@ namespace CryptoExchange.Net.Converters.SystemTextJson
x.Field is ArrayFieldReference arrayFieldRef
&& arrayFieldRef.ArrayIndex == arrayField.ArrayIndex
&& arrayFieldRef.Depth == arrayField.Depth
&& (arrayFieldRef.Constraint == null && arrayField.Constraint == null)).ToList();
&& arrayFieldRef.Constraint == null && arrayField.Constraint == null).ToList();
}
else if (field is PropertyFieldReference propField)
{
@ -95,7 +95,7 @@ namespace CryptoExchange.Net.Converters.SystemTextJson
x.Field is PropertyFieldReference propFieldRef
&& propFieldRef.PropertyName.SequenceEqual(propField.PropertyName)
&& propFieldRef.Depth == propField.Depth
&& (propFieldRef.Constraint == null && propFieldRef.Constraint == null)).ToList();
&& propFieldRef.Constraint == null && propFieldRef.Constraint == null).ToList();
}
foreach(var sameSearchField in existingSameSearchField)
@ -118,7 +118,7 @@ namespace CryptoExchange.Net.Converters.SystemTextJson
_searchFields.Add(new MessageEvalutorFieldReference(field)
{
SkipReading = evaluator.TypeIdentifierCallback == null && field.Constraint == null,
ForceEvaluator = !existingSameSearchField.Any() ? (evaluator.ForceIfFound ? evaluator : null) : null,
ForceEvaluator = !existingSameSearchField.Any() ? evaluator.ForceIfFound ? evaluator : null : null,
OverlappingField = overlapping.Any()
});
@ -243,10 +243,8 @@ namespace CryptoExchange.Net.Converters.SystemTextJson
if (readArrayValues)
{
if (reader.TokenType != JsonTokenType.StartArray)
{
// error
return null;
}
var sb = new StringBuilder();
reader.Read();// Read start array

View File

@ -3,7 +3,7 @@ using System;
using System.Net.WebSockets;
using System.Text.Json;
namespace CryptoExchange.Net.Converters.SystemTextJson
namespace CryptoExchange.Net.Converters.SystemTextJson.MessageHandlers
{
/// <summary>
/// JSON WebSocket message handler, reads the json data info a JsonDocument after which the data can be inspected to identify the message

View File

@ -1,6 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Text.Json.Serialization.Metadata;
using System.Text.Json;
using System.Text.Json.Serialization;

View File

@ -1,6 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace CryptoExchange.Net.Converters.SystemTextJson
{

View File

@ -1,7 +1,5 @@
using CryptoExchange.Net.SharedApis;
using System;
using System.Collections.Generic;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;

View File

@ -1,7 +1,5 @@
using CryptoExchange.Net.SharedApis;
using System;
using System.Collections.Generic;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;

View File

@ -2,7 +2,6 @@
using CryptoExchange.Net.Interfaces;
using CryptoExchange.Net.Objects;
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Text;

View File

@ -1,8 +1,6 @@
using CryptoExchange.Net.Interfaces;
using System.Diagnostics.CodeAnalysis;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Text.Json.Serialization.Metadata;
namespace CryptoExchange.Net.Converters.SystemTextJson
{

View File

@ -1,7 +1,6 @@
using CryptoExchange.Net.Objects;
using CryptoExchange.Net.Objects.Sockets;
using CryptoExchange.Net.SharedApis;
using CryptoExchange.Net.Sockets;
using System;
using System.Collections.Generic;
using System.Globalization;

View File

@ -3,7 +3,6 @@ using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace CryptoExchange.Net
{

View File

@ -1,10 +1,9 @@
using CryptoExchange.Net.Authentication;
using CryptoExchange.Net.Objects;
using CryptoExchange.Net.Objects.Options;
using CryptoExchange.Net.SharedApis;
using System;
namespace CryptoExchange.Net.Interfaces
namespace CryptoExchange.Net.Interfaces.Clients
{
/// <summary>
/// Base api client

View File

@ -1,6 +1,6 @@
using System;
namespace CryptoExchange.Net.Interfaces
namespace CryptoExchange.Net.Interfaces.Clients
{
/// <summary>
/// Client for accessing REST API's for different exchanges

View File

@ -1,6 +1,6 @@
using System;
namespace CryptoExchange.Net.Interfaces
namespace CryptoExchange.Net.Interfaces.Clients
{
/// <summary>
/// Client for accessing Websocket API's for different exchanges

View File

@ -1,4 +1,4 @@
namespace CryptoExchange.Net.Interfaces
namespace CryptoExchange.Net.Interfaces.Clients
{
/// <summary>
/// Base rest API client

View File

@ -1,7 +1,7 @@
using System;
using CryptoExchange.Net.Objects.Options;
namespace CryptoExchange.Net.Interfaces
namespace CryptoExchange.Net.Interfaces.Clients
{
/// <summary>
/// Base class for rest API implementations

View File

@ -1,9 +1,11 @@
using CryptoExchange.Net.Objects;
using CryptoExchange.Net.Objects.Options;
using CryptoExchange.Net.Objects.Sockets;
using CryptoExchange.Net.Sockets.Default.Interfaces;
using CryptoExchange.Net.Sockets.HighPerf.Interfaces;
using System.Threading.Tasks;
namespace CryptoExchange.Net.Interfaces
namespace CryptoExchange.Net.Interfaces.Clients
{
/// <summary>
/// Socket API client
@ -27,6 +29,10 @@ namespace CryptoExchange.Net.Interfaces
/// </summary>
IWebsocketFactory SocketFactory { get; set; }
/// <summary>
/// High performance websocket factory
/// </summary>
IHighPerfConnectionFactory? HighPerfConnectionFactory { get; set; }
/// <summary>
/// Current client options
/// </summary>
SocketExchangeOptions ClientOptions { get; }

View File

@ -3,7 +3,7 @@ using System.Threading.Tasks;
using CryptoExchange.Net.Objects.Options;
using CryptoExchange.Net.Objects.Sockets;
namespace CryptoExchange.Net.Interfaces
namespace CryptoExchange.Net.Interfaces.Clients
{
/// <summary>
/// Base class for socket API implementations

View File

@ -1,7 +1,6 @@
using CryptoExchange.Net.Converters.MessageParsing;
using CryptoExchange.Net.Objects;
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Threading.Tasks;

View File

@ -1,6 +1,4 @@
using System.Diagnostics.CodeAnalysis;
namespace CryptoExchange.Net.Interfaces
namespace CryptoExchange.Net.Interfaces
{
/// <summary>
/// Serializer interface

View File

@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading;

View File

@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Http.Headers;

View File

@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using CryptoExchange.Net.Objects;

View File

@ -2,11 +2,8 @@
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
namespace CryptoExchange.Net
{
@ -71,7 +68,7 @@ namespace CryptoExchange.Net
{
var reservedLength = brokerId.Length + ClientOrderIdSeparator.Length;
if ((clientOrderId?.Length + reservedLength) > maxLength)
if (clientOrderId?.Length + reservedLength > maxLength)
return clientOrderId!;
if (!string.IsNullOrEmpty(clientOrderId))
@ -157,43 +154,5 @@ namespace CryptoExchange.Net
return httpHandler;
#endif
}
/// <summary>
/// Waits for all of the ValueTasks to complete
/// </summary>
public static async ValueTask WhenAll(IReadOnlyList<ValueTask> tasks)
{
if (tasks.Count == 0)
return;
List<Task>? toAwait = null;
int completedTasks = 0;
for (int i = 0; i < tasks.Count; i++)
{
if (!tasks[i].IsCompletedSuccessfully)
{
toAwait ??= new();
toAwait.Add(tasks[i].AsTask());
}
else
{
completedTasks++;
}
}
if (completedTasks != tasks.Count)
await Task.WhenAll(toAwait!).ConfigureAwait(false);
}
/// <summary>
/// Waits for all of the ValueTasks to complete
/// </summary>
public static ValueTask WhenAll(IEnumerable<ValueTask> tasks)
{
return WhenAll(tasks.ToList());
}
}
}

View File

@ -1,6 +1,6 @@
using System;
using System.Net.WebSockets;
using CryptoExchange.Net.Sockets;
using CryptoExchange.Net.Sockets.Default;
using Microsoft.Extensions.Logging;
namespace CryptoExchange.Net.Logging.Extensions

View File

@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace CryptoExchange.Net.Objects
namespace CryptoExchange.Net.Objects
{
/// <summary>
/// An alias used by the exchange for an asset commonly known by another name

View File

@ -1,7 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace CryptoExchange.Net.Objects
{

View File

@ -1,6 +1,5 @@
using CryptoExchange.Net.SharedApis;
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Net;
using System.Net.Http;

View File

@ -1,6 +1,4 @@
using CryptoExchange.Net.Attributes;
namespace CryptoExchange.Net.Objects
namespace CryptoExchange.Net.Objects
{
/// <summary>
/// What to do when a request would exceed the rate limit

View File

@ -79,7 +79,20 @@ namespace CryptoExchange.Net.Objects
/// <returns></returns>
public override string ToString()
{
return ErrorCode != null ? $"[{GetType().Name}.{ErrorType}] {ErrorCode}: {Message ?? ErrorDescription}" : $"[{GetType().Name}.{ErrorType}] {Message ?? ErrorDescription}";
return Code != null
? $"[{GetType().Name}.{ErrorType}] {Code}: {GetErrorDescription()}"
: $"[{GetType().Name}.{ErrorType}] {GetErrorDescription()}";
}
private string GetErrorDescription()
{
if (!string.IsNullOrEmpty(Message))
return Message!;
if (ErrorDescription != "Unknown error" || Exception == null)
return ErrorDescription!;
return Exception.Message;
}
}

View File

@ -1,6 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace CryptoExchange.Net.Objects.Errors
{

View File

@ -1,6 +1,4 @@
using System;
namespace CryptoExchange.Net.Objects.Errors
namespace CryptoExchange.Net.Objects.Errors
{
/// <summary>
/// Error info

View File

@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace CryptoExchange.Net.Objects.Errors
{

View File

@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace CryptoExchange.Net.Objects.Errors
namespace CryptoExchange.Net.Objects.Errors
{
/// <summary>
/// Type of error

View File

@ -1,7 +1,5 @@
using CryptoExchange.Net.Authentication;
using System;
using System.Net;
using System.Net.Http;
namespace CryptoExchange.Net.Objects.Options
{

View File

@ -1,7 +1,5 @@
using CryptoExchange.Net.Authentication;
using System;
using System.Collections.Generic;
using System.Text;
namespace CryptoExchange.Net.Objects.Options
{

View File

@ -1,11 +1,10 @@
using CryptoExchange.Net.Objects;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging;
using System;
using System.Threading;
using System.Threading.Channels;
using System.Threading.Tasks;
namespace CryptoExchange.Net.Sockets
namespace CryptoExchange.Net.Objects
{
/// <summary>

View File

@ -1,4 +1,4 @@
using CryptoExchange.Net.Sockets;
using CryptoExchange.Net.Sockets.HighPerf;
using System;
using System.Collections.Generic;
using System.Linq;

View File

@ -1,4 +1,4 @@
using CryptoExchange.Net.Sockets;
using CryptoExchange.Net.Sockets.Default;
using System;
using System.Collections.Generic;
using System.Linq;

View File

@ -1,7 +1,6 @@
using CryptoExchange.Net.RateLimiting.Interfaces;
using System;
using System.Collections.Generic;
using System.IO.Pipelines;
using System.Text;
namespace CryptoExchange.Net.Objects.Sockets

View File

@ -1,6 +1,5 @@
using CryptoExchange.Net.Interfaces;
using System;
using System.Collections.Generic;
namespace CryptoExchange.Net.OrderBook
{

View File

@ -1,6 +1,5 @@
using CryptoExchange.Net.Interfaces;
using System;
using System.Collections.Generic;
namespace CryptoExchange.Net.OrderBook
{

View File

@ -477,15 +477,13 @@ namespace CryptoExchange.Net.OrderBook
/// </summary>
protected void CheckProcessBuffer()
{
var pbList = _processBuffer.ToList();
if (pbList.Count > 0)
_logger.OrderBookProcessingBufferedUpdates(Api, Symbol, pbList.Count);
if (_processBuffer.Count > 0)
_logger.OrderBookProcessingBufferedUpdates(Api, Symbol, _processBuffer.Count);
foreach (var bufferEntry in pbList)
{
foreach (var bufferEntry in _processBuffer)
ProcessRangeUpdates(bufferEntry.FirstUpdateId, bufferEntry.LastUpdateId, bufferEntry.Bids, bufferEntry.Asks);
_processBuffer.Remove(bufferEntry);
}
_processBuffer.Clear();
}
/// <summary>
@ -731,7 +729,9 @@ namespace CryptoExchange.Net.OrderBook
LastUpdateId = item.EndUpdateId,
});
_logger.OrderBookUpdateBuffered(Api, Symbol, item.StartUpdateId, item.EndUpdateId, item.Asks.Length, item.Bids.Length);
if (_logger.IsEnabled(LogLevel.Trace))
_logger.OrderBookUpdateBuffered(Api, Symbol, item.StartUpdateId, item.EndUpdateId, item.Asks.Length, item.Bids.Length);
}
else
{
@ -844,7 +844,8 @@ namespace CryptoExchange.Net.OrderBook
LastSequenceNumber = lastUpdateId;
_logger.OrderBookProcessedMessage(Api, Symbol, firstUpdateId, lastUpdateId);
if (_logger.IsEnabled(LogLevel.Trace))
_logger.OrderBookProcessedMessage(Api, Symbol, firstUpdateId, lastUpdateId);
}
}

View File

@ -1,5 +1,4 @@
using CryptoExchange.Net.Objects;
using System;
using System;
namespace CryptoExchange.Net.RateLimiting
{

View File

@ -1,6 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;

View File

@ -1,5 +1,4 @@
using System;
using System.Net;
using System.Net.Http;
using CryptoExchange.Net.Interfaces;
using CryptoExchange.Net.Objects;

View File

@ -1,7 +1,5 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;

View File

@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace CryptoExchange.Net.SharedApis
namespace CryptoExchange.Net.SharedApis
{
/// <summary>
/// Account type

View File

@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace CryptoExchange.Net.SharedApis
namespace CryptoExchange.Net.SharedApis
{
/// <summary>
/// Type of ticker

View File

@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace CryptoExchange.Net.SharedApis
namespace CryptoExchange.Net.SharedApis
{
/// <summary>
/// Take Profit / Stop Loss side

View File

@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace CryptoExchange.Net.SharedApis
namespace CryptoExchange.Net.SharedApis
{
/// <summary>
/// The order direction when order trigger parameters are reached

View File

@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace CryptoExchange.Net.SharedApis
namespace CryptoExchange.Net.SharedApis
{
/// <summary>
/// Trigger order status

View File

@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace CryptoExchange.Net.SharedApis
namespace CryptoExchange.Net.SharedApis
{
/// <summary>
/// Price direction for trigger order

View File

@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace CryptoExchange.Net.SharedApis
namespace CryptoExchange.Net.SharedApis
{
/// <summary>
/// Price direction for trigger order

View File

@ -1,5 +1,4 @@
using CryptoExchange.Net.Objects;
using System;
using System;
namespace CryptoExchange.Net.SharedApis
{

View File

@ -1,5 +1,4 @@
using System.Collections.Generic;
using System.Threading;
using System.Threading;
using System.Threading.Tasks;
namespace CryptoExchange.Net.SharedApis

View File

@ -1,7 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using System.Threading.Tasks;
using System.Threading;
namespace CryptoExchange.Net.SharedApis

View File

@ -1,5 +1,4 @@
using System.Collections.Generic;
using System.Threading;
using System.Threading;
using System.Threading.Tasks;
namespace CryptoExchange.Net.SharedApis

View File

@ -1,5 +1,4 @@
using System.Collections.Generic;
using System.Threading;
using System.Threading;
using System.Threading.Tasks;
namespace CryptoExchange.Net.SharedApis

View File

@ -1,5 +1,4 @@
using System.Collections.Generic;
using System.Threading;
using System.Threading;
using System.Threading.Tasks;
namespace CryptoExchange.Net.SharedApis

View File

@ -1,7 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using System.Threading.Tasks;
using System.Threading;
namespace CryptoExchange.Net.SharedApis

View File

@ -1,7 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Threading;
using System.Threading.Tasks;
namespace CryptoExchange.Net.SharedApis

View File

@ -1,5 +1,4 @@
using System.Collections.Generic;
using System.Threading;
using System.Threading;
using System.Threading.Tasks;
namespace CryptoExchange.Net.SharedApis

Some files were not shown because too many files have changed in this diff Show More