1
0
mirror of https://github.com/JKorf/CryptoExchange.Net synced 2025-06-12 02:16:23 +00:00

Cleanup/Fixed Resharper comments

This commit is contained in:
Jan Korf 2019-09-05 11:00:57 +02:00
parent de0916920f
commit 8cb3420520
22 changed files with 315 additions and 136 deletions

View File

@ -14,12 +14,12 @@ namespace CryptoExchange.Net.Authentication
/// <summary> /// <summary>
/// The api key to authenticate requests /// The api key to authenticate requests
/// </summary> /// </summary>
public SecureString Key { get; private set; } public SecureString Key { get; }
/// <summary> /// <summary>
/// The api secret to authenticate requests /// The api secret to authenticate requests
/// </summary> /// </summary>
public SecureString Secret { get; private set; } public SecureString Secret { get; }
/// <summary> /// <summary>
/// The private key to authenticate requests /// The private key to authenticate requests

View File

@ -140,7 +140,7 @@ namespace CryptoExchange.Net
protected CallResult<T> Deserialize<T>(string data, bool checkObject = true, JsonSerializer serializer = null) protected CallResult<T> Deserialize<T>(string data, bool checkObject = true, JsonSerializer serializer = null)
{ {
var tokenResult = ValidateJson(data); var tokenResult = ValidateJson(data);
return !tokenResult.Success ? new CallResult<T>(default(T), tokenResult.Error) : Deserialize<T>(tokenResult.Data, checkObject, serializer); return !tokenResult.Success ? new CallResult<T>(default, tokenResult.Error) : Deserialize<T>(tokenResult.Data, checkObject, serializer);
} }
/// <summary> /// <summary>
@ -184,19 +184,19 @@ namespace CryptoExchange.Net
{ {
var info = $"Deserialize JsonReaderException: {jre.Message}, Path: {jre.Path}, LineNumber: {jre.LineNumber}, LinePosition: {jre.LinePosition}. Received data: {obj}"; var info = $"Deserialize JsonReaderException: {jre.Message}, Path: {jre.Path}, LineNumber: {jre.LineNumber}, LinePosition: {jre.LinePosition}. Received data: {obj}";
log.Write(LogVerbosity.Error, info); log.Write(LogVerbosity.Error, info);
return new CallResult<T>(default(T), new DeserializeError(info)); return new CallResult<T>(default, new DeserializeError(info));
} }
catch (JsonSerializationException jse) catch (JsonSerializationException jse)
{ {
var info = $"Deserialize JsonSerializationException: {jse.Message}. Received data: {obj}"; var info = $"Deserialize JsonSerializationException: {jse.Message}. Received data: {obj}";
log.Write(LogVerbosity.Error, info); log.Write(LogVerbosity.Error, info);
return new CallResult<T>(default(T), new DeserializeError(info)); return new CallResult<T>(default, new DeserializeError(info));
} }
catch (Exception ex) catch (Exception ex)
{ {
var info = $"Deserialize Unknown Exception: {ex.Message}. Received data: {obj}"; var info = $"Deserialize Unknown Exception: {ex.Message}. Received data: {obj}";
log.Write(LogVerbosity.Error, info); log.Write(LogVerbosity.Error, info);
return new CallResult<T>(default(T), new DeserializeError(info)); return new CallResult<T>(default, new DeserializeError(info));
} }
} }
@ -277,7 +277,7 @@ namespace CryptoExchange.Net
var attr = prop.GetCustomAttributes(typeof(JsonPropertyAttribute), false).FirstOrDefault(); var attr = prop.GetCustomAttributes(typeof(JsonPropertyAttribute), false).FirstOrDefault();
if (attr == null) if (attr == null)
{ {
if (String.Equals(prop.Name, name, StringComparison.CurrentCultureIgnoreCase)) if (string.Equals(prop.Name, name, StringComparison.CurrentCultureIgnoreCase))
return prop; return prop;
} }
else else

View File

@ -76,7 +76,7 @@ namespace CryptoExchange.Net.Converters
var converterAttribute = (JsonConverterAttribute)property.GetCustomAttribute(typeof(JsonConverterAttribute)) ?? (JsonConverterAttribute)property.PropertyType.GetCustomAttribute(typeof(JsonConverterAttribute)); var converterAttribute = (JsonConverterAttribute)property.GetCustomAttribute(typeof(JsonConverterAttribute)) ?? (JsonConverterAttribute)property.PropertyType.GetCustomAttribute(typeof(JsonConverterAttribute));
var conversionAttribute = (JsonConversionAttribute)property.GetCustomAttribute(typeof(JsonConversionAttribute)) ?? (JsonConversionAttribute)property.PropertyType.GetCustomAttribute(typeof(JsonConversionAttribute)); var conversionAttribute = (JsonConversionAttribute)property.GetCustomAttribute(typeof(JsonConversionAttribute)) ?? (JsonConversionAttribute)property.PropertyType.GetCustomAttribute(typeof(JsonConversionAttribute));
object value = null; object value;
if (converterAttribute != null) if (converterAttribute != null)
{ {
value = arr[attribute.Index].ToObject(property.PropertyType, new JsonSerializer {Converters = {(JsonConverter) Activator.CreateInstance(converterAttribute.ConverterType)}}); value = arr[attribute.Index].ToObject(property.PropertyType, new JsonSerializer {Converters = {(JsonConverter) Activator.CreateInstance(converterAttribute.ConverterType)}});

View File

@ -78,7 +78,7 @@ namespace CryptoExchange.Net.Converters
return true; return true;
} }
result = default(T); result = default;
return false; return false;
} }

View File

@ -8,6 +8,8 @@ namespace CryptoExchange.Net.Converters
/// </summary> /// </summary>
public class TimestampNanoSecondsConverter : JsonConverter public class TimestampNanoSecondsConverter : JsonConverter
{ {
private const decimal ticksPerNanosecond = TimeSpan.TicksPerMillisecond / 1000m / 1000;
/// <inheritdoc /> /// <inheritdoc />
public override bool CanConvert(Type objectType) public override bool CanConvert(Type objectType)
{ {
@ -20,7 +22,6 @@ namespace CryptoExchange.Net.Converters
if (reader.Value == null) if (reader.Value == null)
return null; return null;
var ticksPerNanosecond = (TimeSpan.TicksPerMillisecond / 1000m / 1000);
var nanoSeconds = long.Parse(reader.Value.ToString()); var nanoSeconds = long.Parse(reader.Value.ToString());
return new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddTicks((long)Math.Round(nanoSeconds * ticksPerNanosecond)); return new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddTicks((long)Math.Round(nanoSeconds * ticksPerNanosecond));
} }
@ -28,7 +29,6 @@ namespace CryptoExchange.Net.Converters
/// <inheritdoc /> /// <inheritdoc />
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{ {
var ticksPerNanosecond = (TimeSpan.TicksPerMillisecond / 1000m / 1000);
writer.WriteValue((long)Math.Round(((DateTime)value - new DateTime(1970, 1, 1)).Ticks / ticksPerNanosecond)); writer.WriteValue((long)Math.Round(((DateTime)value - new DateTime(1970, 1, 1)).Ticks / ticksPerNanosecond));
} }
} }

View File

@ -469,7 +469,7 @@
</member> </member>
<member name="M:CryptoExchange.Net.ExtensionMethods.ToIEnumerable(System.Net.WebHeaderCollection)"> <member name="M:CryptoExchange.Net.ExtensionMethods.ToIEnumerable(System.Net.WebHeaderCollection)">
<summary> <summary>
Header collection to inenumerable Header collection to IEnumerable
</summary> </summary>
<param name="headers"></param> <param name="headers"></param>
<returns></returns> <returns></returns>
@ -709,6 +709,110 @@
</summary> </summary>
<returns></returns> <returns></returns>
</member> </member>
<member name="T:CryptoExchange.Net.Interfaces.ISymbolOrderBook">
<summary>
Interface for order book
</summary>
</member>
<member name="P:CryptoExchange.Net.Interfaces.ISymbolOrderBook.Status">
<summary>
The status of the order book. Order book is up to date when the status is `Synced`
</summary>
</member>
<member name="P:CryptoExchange.Net.Interfaces.ISymbolOrderBook.LastSequenceNumber">
<summary>
Last update identifier
</summary>
</member>
<member name="P:CryptoExchange.Net.Interfaces.ISymbolOrderBook.Symbol">
<summary>
The symbol of the order book
</summary>
</member>
<member name="E:CryptoExchange.Net.Interfaces.ISymbolOrderBook.OnStatusChange">
<summary>
Event when the state changes
</summary>
</member>
<member name="E:CryptoExchange.Net.Interfaces.ISymbolOrderBook.OnOrderBookUpdate">
<summary>
Event when order book was updated. Be careful! It can generate a lot of events at high-liquidity markets
</summary>
</member>
<member name="P:CryptoExchange.Net.Interfaces.ISymbolOrderBook.LastOrderBookUpdate">
<summary>
Timestamp of the last update
</summary>
</member>
<member name="P:CryptoExchange.Net.Interfaces.ISymbolOrderBook.AskCount">
<summary>
The number of asks in the book
</summary>
</member>
<member name="P:CryptoExchange.Net.Interfaces.ISymbolOrderBook.BidCount">
<summary>
The number of bids in the book
</summary>
</member>
<member name="P:CryptoExchange.Net.Interfaces.ISymbolOrderBook.Asks">
<summary>
The list of asks
</summary>
</member>
<member name="P:CryptoExchange.Net.Interfaces.ISymbolOrderBook.Bids">
<summary>
The list of bids
</summary>
</member>
<member name="P:CryptoExchange.Net.Interfaces.ISymbolOrderBook.BestBid">
<summary>
The best bid currently in the order book
</summary>
</member>
<member name="P:CryptoExchange.Net.Interfaces.ISymbolOrderBook.BestAsk">
<summary>
The best ask currently in the order book
</summary>
</member>
<member name="M:CryptoExchange.Net.Interfaces.ISymbolOrderBook.Start">
<summary>
Start connecting and synchronizing the order book
</summary>
<returns></returns>
</member>
<member name="M:CryptoExchange.Net.Interfaces.ISymbolOrderBook.StartAsync">
<summary>
Start connecting and synchronizing the order book
</summary>
<returns></returns>
</member>
<member name="M:CryptoExchange.Net.Interfaces.ISymbolOrderBook.Stop">
<summary>
Stop syncing the order book
</summary>
<returns></returns>
</member>
<member name="M:CryptoExchange.Net.Interfaces.ISymbolOrderBook.StopAsync">
<summary>
Stop syncing the order book
</summary>
<returns></returns>
</member>
<member name="T:CryptoExchange.Net.Interfaces.ISymbolOrderBookEntry">
<summary>
Interface for order book entries
</summary>
</member>
<member name="P:CryptoExchange.Net.Interfaces.ISymbolOrderBookEntry.Quantity">
<summary>
The quantity of the entry
</summary>
</member>
<member name="P:CryptoExchange.Net.Interfaces.ISymbolOrderBookEntry.Price">
<summary>
The price of the entry
</summary>
</member>
<member name="T:CryptoExchange.Net.Interfaces.IWebsocket"> <member name="T:CryptoExchange.Net.Interfaces.IWebsocket">
<summary> <summary>
Interface for websocket interaction Interface for websocket interaction
@ -1445,21 +1549,6 @@
<typeparam name="T"></typeparam> <typeparam name="T"></typeparam>
<returns></returns> <returns></returns>
</member> </member>
<member name="T:CryptoExchange.Net.OrderBook.ISymbolOrderBookEntry">
<summary>
Interface for order book entries
</summary>
</member>
<member name="P:CryptoExchange.Net.OrderBook.ISymbolOrderBookEntry.Quantity">
<summary>
The quantity of the entry
</summary>
</member>
<member name="P:CryptoExchange.Net.OrderBook.ISymbolOrderBookEntry.Price">
<summary>
The price of the entry
</summary>
</member>
<member name="T:CryptoExchange.Net.OrderBook.OrderBookEntry"> <member name="T:CryptoExchange.Net.OrderBook.OrderBookEntry">
<summary> <summary>
Order book entry Order book entry
@ -1522,7 +1611,7 @@
The type The type
</summary> </summary>
</member> </member>
<member name="M:CryptoExchange.Net.OrderBook.ProcessEntry.#ctor(CryptoExchange.Net.Objects.OrderBookEntryType,CryptoExchange.Net.OrderBook.ISymbolOrderBookEntry)"> <member name="M:CryptoExchange.Net.OrderBook.ProcessEntry.#ctor(CryptoExchange.Net.Objects.OrderBookEntryType,CryptoExchange.Net.Interfaces.ISymbolOrderBookEntry)">
<summary> <summary>
ctor ctor
</summary> </summary>
@ -1576,12 +1665,12 @@
</member> </member>
<member name="E:CryptoExchange.Net.OrderBook.SymbolOrderBook.OnOrderBookUpdate"> <member name="E:CryptoExchange.Net.OrderBook.SymbolOrderBook.OnOrderBookUpdate">
<summary> <summary>
Event when orderbook was updated. Be careful! It can generate a lot of events at high-liquidity markets Event when order book was updated. Be careful! It can generate a lot of events at high-liquidity markets
</summary> </summary>
</member> </member>
<member name="F:CryptoExchange.Net.OrderBook.SymbolOrderBook.LastOrderBookUpdate"> <member name="P:CryptoExchange.Net.OrderBook.SymbolOrderBook.LastOrderBookUpdate">
<summary> <summary>
Should be useful for low-liquidity order-books to monitor market activity Timestamp of the last update
</summary> </summary>
</member> </member>
<member name="P:CryptoExchange.Net.OrderBook.SymbolOrderBook.AskCount"> <member name="P:CryptoExchange.Net.OrderBook.SymbolOrderBook.AskCount">
@ -1662,7 +1751,7 @@
</summary> </summary>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:CryptoExchange.Net.OrderBook.SymbolOrderBook.SetInitialOrderBook(System.Int64,System.Collections.Generic.IEnumerable{CryptoExchange.Net.OrderBook.ISymbolOrderBookEntry},System.Collections.Generic.IEnumerable{CryptoExchange.Net.OrderBook.ISymbolOrderBookEntry})"> <member name="M:CryptoExchange.Net.OrderBook.SymbolOrderBook.SetInitialOrderBook(System.Int64,System.Collections.Generic.IEnumerable{CryptoExchange.Net.Interfaces.ISymbolOrderBookEntry},System.Collections.Generic.IEnumerable{CryptoExchange.Net.Interfaces.ISymbolOrderBookEntry})">
<summary> <summary>
Set the initial data for the order book Set the initial data for the order book
</summary> </summary>
@ -1683,7 +1772,7 @@
Check and empty the process buffer; see what entries to update the book with Check and empty the process buffer; see what entries to update the book with
</summary> </summary>
</member> </member>
<member name="M:CryptoExchange.Net.OrderBook.SymbolOrderBook.ProcessUpdate(CryptoExchange.Net.Objects.OrderBookEntryType,CryptoExchange.Net.OrderBook.ISymbolOrderBookEntry)"> <member name="M:CryptoExchange.Net.OrderBook.SymbolOrderBook.ProcessUpdate(CryptoExchange.Net.Objects.OrderBookEntryType,CryptoExchange.Net.Interfaces.ISymbolOrderBookEntry)">
<summary> <summary>
Update order book with an entry Update order book with an entry
</summary> </summary>
@ -1789,7 +1878,7 @@
</member> </member>
<member name="M:CryptoExchange.Net.Requests.Request.#ctor(System.Net.WebRequest)"> <member name="M:CryptoExchange.Net.Requests.Request.#ctor(System.Net.WebRequest)">
<summary> <summary>
Create request object for webrequest Create request object for web request
</summary> </summary>
<param name="request"></param> <param name="request"></param>
</member> </member>
@ -2126,7 +2215,7 @@
<summary> <summary>
Query for data Query for data
</summary> </summary>
<typeparam name="T">Exepected result type</typeparam> <typeparam name="T">Expected result type</typeparam>
<param name="request">The request to send</param> <param name="request">The request to send</param>
<param name="authenticated">Whether the socket should be authenticated</param> <param name="authenticated">Whether the socket should be authenticated</param>
<returns></returns> <returns></returns>

View File

@ -127,7 +127,7 @@ namespace CryptoExchange.Net
} }
/// <summary> /// <summary>
/// Header collection to inenumerable /// Header collection to IEnumerable
/// </summary> /// </summary>
/// <param name="headers"></param> /// <param name="headers"></param>
/// <returns></returns> /// <returns></returns>
@ -153,7 +153,7 @@ namespace CryptoExchange.Net
public static async Task<bool> WaitOneAsync(this WaitHandle handle, int millisecondsTimeout, CancellationToken cancellationToken) public static async Task<bool> WaitOneAsync(this WaitHandle handle, int millisecondsTimeout, CancellationToken cancellationToken)
{ {
RegisteredWaitHandle registeredHandle = null; RegisteredWaitHandle registeredHandle = null;
CancellationTokenRegistration tokenRegistration = default(CancellationTokenRegistration); CancellationTokenRegistration tokenRegistration = default;
try try
{ {
var tcs = new TaskCompletionSource<bool>(); var tcs = new TaskCompletionSource<bool>();

View File

@ -1,7 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using CryptoExchange.Net.Interfaces;
using CryptoExchange.Net.Objects; using CryptoExchange.Net.Objects;
using CryptoExchange.Net.RateLimiter; using CryptoExchange.Net.RateLimiter;

View File

@ -0,0 +1,93 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using CryptoExchange.Net.Objects;
namespace CryptoExchange.Net.Interfaces
{
/// <summary>
/// Interface for order book
/// </summary>
public interface ISymbolOrderBook
{
/// <summary>
/// The status of the order book. Order book is up to date when the status is `Synced`
/// </summary>
OrderBookStatus Status { get; set; }
/// <summary>
/// Last update identifier
/// </summary>
long LastSequenceNumber { get; }
/// <summary>
/// The symbol of the order book
/// </summary>
string Symbol { get; }
/// <summary>
/// Event when the state changes
/// </summary>
event Action<OrderBookStatus, OrderBookStatus> OnStatusChange;
/// <summary>
/// Event when order book was updated. Be careful! It can generate a lot of events at high-liquidity markets
/// </summary>
event Action OnOrderBookUpdate;
/// <summary>
/// Timestamp of the last update
/// </summary>
DateTime LastOrderBookUpdate { get; }
/// <summary>
/// The number of asks in the book
/// </summary>
int AskCount { get; }
/// <summary>
/// The number of bids in the book
/// </summary>
int BidCount { get; }
/// <summary>
/// The list of asks
/// </summary>
IEnumerable<ISymbolOrderBookEntry> Asks { get; }
/// <summary>
/// The list of bids
/// </summary>
IEnumerable<ISymbolOrderBookEntry> Bids { get; }
/// <summary>
/// The best bid currently in the order book
/// </summary>
ISymbolOrderBookEntry BestBid { get; }
/// <summary>
/// The best ask currently in the order book
/// </summary>
ISymbolOrderBookEntry BestAsk { get; }
/// <summary>
/// Start connecting and synchronizing the order book
/// </summary>
/// <returns></returns>
CallResult<bool> Start();
/// <summary>
/// Start connecting and synchronizing the order book
/// </summary>
/// <returns></returns>
Task<CallResult<bool>> StartAsync();
/// <summary>
/// Stop syncing the order book
/// </summary>
/// <returns></returns>
void Stop();
/// <summary>
/// Stop syncing the order book
/// </summary>
/// <returns></returns>
Task StopAsync();
}
}

View File

@ -1,4 +1,4 @@
namespace CryptoExchange.Net.OrderBook namespace CryptoExchange.Net.Interfaces
{ {
/// <summary> /// <summary>
/// Interface for order book entries /// Interface for order book entries

View File

@ -21,8 +21,8 @@ namespace CryptoExchange.Net.Objects
// If one is null and the other isn't, then the // If one is null and the other isn't, then the
// one that is null is "lesser". // one that is null is "lesser".
if (x == null && y != null) return -1; if (x == null) return -1;
if (x != null && y == null) return 1; if (y == null) return 1;
// Both arrays are non-null. Find the shorter // Both arrays are non-null. Find the shorter
// of the two lengths. // of the two lengths.

View File

@ -71,7 +71,7 @@ namespace CryptoExchange.Net.Objects
/// <returns></returns> /// <returns></returns>
public static WebCallResult<T> CreateErrorResult(Error error) public static WebCallResult<T> CreateErrorResult(Error error)
{ {
return new WebCallResult<T>(null, null, default(T), error); return new WebCallResult<T>(null, null, default, error);
} }
/// <summary> /// <summary>
@ -83,7 +83,7 @@ namespace CryptoExchange.Net.Objects
/// <returns></returns> /// <returns></returns>
public static WebCallResult<T> CreateErrorResult(HttpStatusCode? code, IEnumerable<Tuple<string, string>> responseHeaders, Error error) public static WebCallResult<T> CreateErrorResult(HttpStatusCode? code, IEnumerable<Tuple<string, string>> responseHeaders, Error error)
{ {
return new WebCallResult<T>(code, responseHeaders, default(T), error); return new WebCallResult<T>(code, responseHeaders, default, error);
} }
} }
} }

View File

@ -65,7 +65,7 @@
/// <summary> /// <summary>
/// Data synced, order book is up to date /// Data synced, order book is up to date
/// </summary> /// </summary>
Synced, Synced
} }
/// <summary> /// <summary>

View File

@ -1,4 +1,6 @@
namespace CryptoExchange.Net.OrderBook using CryptoExchange.Net.Interfaces;
namespace CryptoExchange.Net.OrderBook
{ {
/// <summary> /// <summary>
/// Order book entry /// Order book entry

View File

@ -1,4 +1,5 @@
using CryptoExchange.Net.Objects; using CryptoExchange.Net.Interfaces;
using CryptoExchange.Net.Objects;
namespace CryptoExchange.Net.OrderBook namespace CryptoExchange.Net.OrderBook
{ {

View File

@ -4,6 +4,7 @@ using System.Globalization;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using CryptoExchange.Net.Interfaces;
using CryptoExchange.Net.Logging; using CryptoExchange.Net.Logging;
using CryptoExchange.Net.Objects; using CryptoExchange.Net.Objects;
using CryptoExchange.Net.Sockets; using CryptoExchange.Net.Sockets;
@ -13,7 +14,7 @@ namespace CryptoExchange.Net.OrderBook
/// <summary> /// <summary>
/// Base for order book implementations /// Base for order book implementations
/// </summary> /// </summary>
public abstract class SymbolOrderBook : IDisposable public abstract class SymbolOrderBook : ISymbolOrderBook, IDisposable
{ {
/// <summary> /// <summary>
/// The process buffer, used while syncing /// The process buffer, used while syncing
@ -23,12 +24,12 @@ namespace CryptoExchange.Net.OrderBook
/// <summary> /// <summary>
/// The ask list /// The ask list
/// </summary> /// </summary>
protected SortedList<decimal, OrderBookEntry> asks; protected SortedList<decimal, ISymbolOrderBookEntry> asks;
/// <summary> /// <summary>
/// The bid list /// The bid list
/// </summary> /// </summary>
protected SortedList<decimal, OrderBookEntry> bids; protected SortedList<decimal, ISymbolOrderBookEntry> bids;
private OrderBookStatus status; private OrderBookStatus status;
private UpdateSubscription subscription; private UpdateSubscription subscription;
private readonly bool sequencesAreConsecutive; private readonly bool sequencesAreConsecutive;
@ -72,13 +73,13 @@ namespace CryptoExchange.Net.OrderBook
/// </summary> /// </summary>
public event Action<OrderBookStatus, OrderBookStatus> OnStatusChange; public event Action<OrderBookStatus, OrderBookStatus> OnStatusChange;
/// <summary> /// <summary>
/// Event when orderbook was updated. Be careful! It can generate a lot of events at high-liquidity markets /// Event when order book was updated. Be careful! It can generate a lot of events at high-liquidity markets
/// </summary> /// </summary>
public event Action OnOrderBookUpdate; public event Action OnOrderBookUpdate;
/// <summary> /// <summary>
/// Should be useful for low-liquidity order-books to monitor market activity /// Timestamp of the last update
/// </summary> /// </summary>
public DateTime LastOrderBookUpdate; public DateTime LastOrderBookUpdate { get; private set; }
/// <summary> /// <summary>
/// The number of asks in the book /// The number of asks in the book
@ -150,8 +151,8 @@ namespace CryptoExchange.Net.OrderBook
Symbol = symbol; Symbol = symbol;
Status = OrderBookStatus.Disconnected; Status = OrderBookStatus.Disconnected;
asks = new SortedList<decimal, OrderBookEntry>(); asks = new SortedList<decimal, ISymbolOrderBookEntry>();
bids = new SortedList<decimal, OrderBookEntry>(new DescComparer<decimal>()); bids = new SortedList<decimal, ISymbolOrderBookEntry>(new DescComparer<decimal>());
log = new Log { Level = options.LogVerbosity }; log = new Log { Level = options.LogVerbosity };
var writers = options.LogWriters ?? new List<TextWriter> { new DebugTextWriter() }; var writers = options.LogWriters ?? new List<TextWriter> { new DebugTextWriter() };
@ -177,7 +178,7 @@ namespace CryptoExchange.Net.OrderBook
subscription = startResult.Data; subscription = startResult.Data;
subscription.ConnectionLost += Reset; subscription.ConnectionLost += Reset;
subscription.ConnectionRestored += (time) => Resync(); subscription.ConnectionRestored += time => Resync();
Status = OrderBookStatus.Synced; Status = OrderBookStatus.Synced;
return new CallResult<bool>(true, null); return new CallResult<bool>(true, null);
} }
@ -194,7 +195,7 @@ namespace CryptoExchange.Net.OrderBook
private void Resync() private void Resync()
{ {
Status = OrderBookStatus.Syncing; Status = OrderBookStatus.Syncing;
bool success = false; var success = false;
while (!success) while (!success)
{ {
if (Status != OrderBookStatus.Syncing) if (Status != OrderBookStatus.Syncing)
@ -289,7 +290,7 @@ namespace CryptoExchange.Net.OrderBook
if (!bookSet) if (!bookSet)
{ {
var entry = new ProcessBufferEntry() var entry = new ProcessBufferEntry
{ {
FirstSequence = firstSequenceNumber, FirstSequence = firstSequenceNumber,
LastSequence = lastSequenceNumber, LastSequence = lastSequenceNumber,
@ -350,25 +351,25 @@ namespace CryptoExchange.Net.OrderBook
var listToChange = type == OrderBookEntryType.Ask ? asks : bids; var listToChange = type == OrderBookEntryType.Ask ? asks : bids;
if (entry.Quantity == 0) if (entry.Quantity == 0)
{ {
var bookEntry = listToChange.SingleOrDefault(i => i.Key == entry.Price); if (!listToChange.ContainsKey(entry.Price))
if (!bookEntry.Equals(default(KeyValuePair<decimal, OrderBookEntry>))) return;
{
listToChange.Remove(entry.Price); listToChange.Remove(entry.Price);
if (type == OrderBookEntryType.Ask) AskCount--; if (type == OrderBookEntryType.Ask) AskCount--;
else BidCount--; else BidCount--;
}
} }
else else
{ {
var bookEntry = listToChange.SingleOrDefault(i => i.Key == entry.Price); if (!listToChange.ContainsKey(entry.Price))
if (bookEntry.Equals(default(KeyValuePair<decimal, OrderBookEntry>)))
{ {
listToChange.Add(entry.Price, new OrderBookEntry(entry.Price, entry.Quantity)); listToChange.Add(entry.Price, new OrderBookEntry(entry.Price, entry.Quantity));
if (type == OrderBookEntryType.Ask) AskCount++; if (type == OrderBookEntryType.Ask) AskCount++;
else BidCount++; else BidCount++;
} }
else else
bookEntry.Value.Quantity = entry.Quantity; {
listToChange[entry.Price].Quantity = entry.Quantity;
}
} }
} }

View File

@ -35,7 +35,7 @@ namespace CryptoExchange.Net.RateLimiter
if(client.authProvider?.Credentials == null) if(client.authProvider?.Credentials == null)
return new CallResult<double>(0, null); return new CallResult<double>(0, null);
string key = client.authProvider.Credentials.Key.GetString(); var key = client.authProvider.Credentials.Key.GetString();
int waitTime; int waitTime;
RateLimitObject rlo; RateLimitObject rlo;

View File

@ -14,7 +14,7 @@ namespace CryptoExchange.Net.Requests
private readonly WebRequest request; private readonly WebRequest request;
/// <summary> /// <summary>
/// Create request object for webrequest /// Create request object for web request
/// </summary> /// </summary>
/// <param name="request"></param> /// <param name="request"></param>
public Request(WebRequest request) public Request(WebRequest request)

View File

@ -126,14 +126,14 @@ namespace CryptoExchange.Net
catch(PingException e) catch(PingException e)
{ {
if (e.InnerException == null) if (e.InnerException == null)
return new CallResult<long>(0, new CantConnectError() {Message = "Ping failed: " + e.Message}); return new CallResult<long>(0, new CantConnectError {Message = "Ping failed: " + e.Message});
if (e.InnerException is SocketException exception) if (e.InnerException is SocketException exception)
return new CallResult<long>(0, new CantConnectError() { Message = "Ping failed: " + exception.SocketErrorCode }); return new CallResult<long>(0, new CantConnectError { Message = "Ping failed: " + exception.SocketErrorCode });
return new CallResult<long>(0, new CantConnectError() { Message = "Ping failed: " + e.InnerException.Message }); return new CallResult<long>(0, new CantConnectError { Message = "Ping failed: " + e.InnerException.Message });
} }
return reply.Status == IPStatus.Success ? new CallResult<long>(reply.RoundtripTime, null) : new CallResult<long>(0, new CantConnectError() { Message = "Ping failed: " + reply.Status }); return reply.Status == IPStatus.Success ? new CallResult<long>(reply.RoundtripTime, null) : new CallResult<long>(0, new CantConnectError { Message = "Ping failed: " + reply.Status });
} }
/// <summary> /// <summary>
@ -280,7 +280,7 @@ namespace CryptoExchange.Net
} }
else if(requestBodyFormat == RequestBodyFormat.FormData) else if(requestBodyFormat == RequestBodyFormat.FormData)
{ {
var formData = HttpUtility.ParseQueryString(String.Empty); var formData = HttpUtility.ParseQueryString(string.Empty);
foreach (var kvp in parameters.OrderBy(p => p.Key)) foreach (var kvp in parameters.OrderBy(p => p.Key))
formData.Add(kvp.Key, kvp.Value.ToString()); formData.Add(kvp.Key, kvp.Value.ToString());
var stringData = formData.ToString(); var stringData = formData.ToString();
@ -320,19 +320,24 @@ namespace CryptoExchange.Net
try try
{ {
using (var reader = new StreamReader(response.GetResponseStream())) var responseStream = response?.GetResponseStream();
if (response != null && responseStream != null)
{ {
returnedData = await reader.ReadToEndAsync().ConfigureAwait(false); using (var reader = new StreamReader(responseStream))
log.Write(LogVerbosity.Warning, "Server returned an error: " + returnedData); {
returnedData = await reader.ReadToEndAsync().ConfigureAwait(false);
log.Write(LogVerbosity.Warning, "Server returned an error: " + returnedData);
}
response.Close();
var jsonResult = ValidateJson(returnedData);
return !jsonResult.Success ? new WebCallResult<string>(statusCode, returnHeaders, null, jsonResult.Error) : new WebCallResult<string>(statusCode, returnHeaders, null, ParseErrorResponse(jsonResult.Data));
} }
response.Close();
var jsonResult = ValidateJson(returnedData);
return !jsonResult.Success ? new WebCallResult<string>(statusCode, returnHeaders, null, jsonResult.Error) : new WebCallResult<string>(statusCode, returnHeaders, null, ParseErrorResponse(jsonResult.Data));
} }
catch (Exception) catch (Exception e)
{ {
log.Write(LogVerbosity.Debug, "Not able to read server response: " + e.Message);
} }
var infoMessage = "No response from server"; var infoMessage = "No response from server";

View File

@ -141,7 +141,7 @@ namespace CryptoExchange.Net
{ {
SocketConnection socket; SocketConnection socket;
SocketSubscription handler; SocketSubscription handler;
bool released = false; var released = false;
await semaphoreSlim.WaitAsync().ConfigureAwait(false); await semaphoreSlim.WaitAsync().ConfigureAwait(false);
try try
{ {
@ -193,13 +193,7 @@ namespace CryptoExchange.Net
protected internal virtual async Task<CallResult<bool>> SubscribeAndWait(SocketConnection socket, object request, SocketSubscription subscription) protected internal virtual async Task<CallResult<bool>> SubscribeAndWait(SocketConnection socket, object request, SocketSubscription subscription)
{ {
CallResult<object> callResult = null; CallResult<object> callResult = null;
await socket.SendAndWait(request, ResponseTimeout, (data) => await socket.SendAndWait(request, ResponseTimeout, data => HandleSubscriptionResponse(socket, subscription, request, data, out callResult)).ConfigureAwait(false);
{
if (!HandleSubscriptionResponse(socket, subscription, request, data, out callResult))
return false;
return true;
}).ConfigureAwait(false);
if (callResult?.Success == true) if (callResult?.Success == true)
subscription.Confirmed = true; subscription.Confirmed = true;
@ -210,7 +204,7 @@ namespace CryptoExchange.Net
/// <summary> /// <summary>
/// Query for data /// Query for data
/// </summary> /// </summary>
/// <typeparam name="T">Exepected result type</typeparam> /// <typeparam name="T">Expected result type</typeparam>
/// <param name="request">The request to send</param> /// <param name="request">The request to send</param>
/// <param name="authenticated">Whether the socket should be authenticated</param> /// <param name="authenticated">Whether the socket should be authenticated</param>
/// <returns></returns> /// <returns></returns>
@ -230,7 +224,7 @@ namespace CryptoExchange.Net
protected virtual async Task<CallResult<T>> Query<T>(string url, object request, bool authenticated) protected virtual async Task<CallResult<T>> Query<T>(string url, object request, bool authenticated)
{ {
SocketConnection socket; SocketConnection socket;
bool released = false; var released = false;
await semaphoreSlim.WaitAsync().ConfigureAwait(false); await semaphoreSlim.WaitAsync().ConfigureAwait(false);
try try
{ {
@ -244,7 +238,7 @@ namespace CryptoExchange.Net
var connectResult = await ConnectIfNeeded(socket, authenticated).ConfigureAwait(false); var connectResult = await ConnectIfNeeded(socket, authenticated).ConfigureAwait(false);
if (!connectResult.Success) if (!connectResult.Success)
return new CallResult<T>(default(T), connectResult.Error); return new CallResult<T>(default, connectResult.Error);
} }
finally finally
{ {
@ -257,7 +251,7 @@ namespace CryptoExchange.Net
if (socket.PausedActivity) if (socket.PausedActivity)
{ {
log.Write(LogVerbosity.Info, "Socket has been paused, can't send query at this moment"); log.Write(LogVerbosity.Info, "Socket has been paused, can't send query at this moment");
return new CallResult<T>(default(T), new ServerError("Socket is paused")); return new CallResult<T>(default, new ServerError("Socket is paused"));
} }
return await QueryAndWait<T>(socket, request).ConfigureAwait(false); return await QueryAndWait<T>(socket, request).ConfigureAwait(false);
@ -272,8 +266,8 @@ namespace CryptoExchange.Net
/// <returns></returns> /// <returns></returns>
protected virtual async Task<CallResult<T>> QueryAndWait<T>(SocketConnection socket, object request) protected virtual async Task<CallResult<T>> QueryAndWait<T>(SocketConnection socket, object request)
{ {
CallResult<T> dataResult = new CallResult<T>(default(T), new ServerError("No response on query received")); var dataResult = new CallResult<T>(default, new ServerError("No response on query received"));
await socket.SendAndWait(request, ResponseTimeout, (data) => await socket.SendAndWait(request, ResponseTimeout, data =>
{ {
if (!HandleQueryResponse<T>(socket, request, data, out var callResult)) if (!HandleQueryResponse<T>(socket, request, data, out var callResult))
return false; return false;
@ -293,28 +287,25 @@ namespace CryptoExchange.Net
/// <returns></returns> /// <returns></returns>
protected virtual async Task<CallResult<bool>> ConnectIfNeeded(SocketConnection socket, bool authenticated) protected virtual async Task<CallResult<bool>> ConnectIfNeeded(SocketConnection socket, bool authenticated)
{ {
if (!socket.Connected) if (socket.Connected)
return new CallResult<bool>(true, null);
var connectResult = await ConnectSocket(socket).ConfigureAwait(false);
if (!connectResult.Success)
return new CallResult<bool>(false, new CantConnectError());
if (!authenticated || socket.Authenticated)
return new CallResult<bool>(true, null);
var result = await AuthenticateSocket(socket).ConfigureAwait(false);
if (!result.Success)
{ {
var connectResult = await ConnectSocket(socket).ConfigureAwait(false); log.Write(LogVerbosity.Warning, "Socket authentication failed");
if (!connectResult.Success) result.Error.Message = "Authentication failed: " + result.Error.Message;
{ return new CallResult<bool>(false, result.Error);
return new CallResult<bool>(false, new CantConnectError());
}
if (authenticated && !socket.Authenticated)
{
var result = await AuthenticateSocket(socket).ConfigureAwait(false);
if (!result.Success)
{
log.Write(LogVerbosity.Warning, "Socket authentication failed");
result.Error.Message = "Authentication failed: " + result.Error.Message;
return new CallResult<bool>(false, result.Error);
}
socket.Authenticated = true;
}
} }
socket.Authenticated = true;
return new CallResult<bool>(true, null); return new CallResult<bool>(true, null);
} }
@ -388,11 +379,11 @@ namespace CryptoExchange.Net
/// <returns></returns> /// <returns></returns>
protected virtual SocketSubscription AddHandler<T>(object request, string identifier, bool userSubscription, SocketConnection connection, Action<T> dataHandler) protected virtual SocketSubscription AddHandler<T>(object request, string identifier, bool userSubscription, SocketConnection connection, Action<T> dataHandler)
{ {
Action<SocketConnection, JToken> internalHandler = (socketWrapper, data) => void InternalHandler(SocketConnection socketWrapper, JToken data)
{ {
if (typeof(T) == typeof(string)) if (typeof(T) == typeof(string))
{ {
dataHandler((T)Convert.ChangeType(data.ToString(), typeof(T))); dataHandler((T) Convert.ChangeType(data.ToString(), typeof(T)));
return; return;
} }
@ -404,11 +395,9 @@ namespace CryptoExchange.Net
} }
dataHandler(desResult.Data); dataHandler(desResult.Data);
}; }
if (request != null) return connection.AddHandler(request ?? identifier, userSubscription, InternalHandler);
return connection.AddHandler(request, userSubscription, internalHandler);
return connection.AddHandler(identifier, userSubscription, internalHandler);
} }
/// <summary> /// <summary>
@ -515,16 +504,16 @@ namespace CryptoExchange.Net
break; break;
var obj = objGetter(socket); var obj = objGetter(socket);
if (obj != null) if (obj == null)
continue;
try
{ {
try socket.Send(obj);
{ }
socket.Send(obj); catch (Exception ex)
} {
catch (Exception ex) log.Write(LogVerbosity.Warning, "Periodic send failed: " + ex);
{
log.Write(LogVerbosity.Warning, "Periodic send failed: " + ex);
}
} }
} }
} }

View File

@ -16,7 +16,7 @@ namespace CryptoExchange.Net.Sockets
/// <summary> /// <summary>
/// Socket implementation /// Socket implementation
/// </summary> /// </summary>
public class BaseSocket: IWebsocket internal class BaseSocket: IWebsocket
{ {
internal static int lastStreamId; internal static int lastStreamId;
private static readonly object streamIdLock = new object(); private static readonly object streamIdLock = new object();
@ -153,7 +153,7 @@ namespace CryptoExchange.Net.Sockets
if (DateTime.UtcNow - LastActionTime > Timeout) if (DateTime.UtcNow - LastActionTime > Timeout)
{ {
log.Write(LogVerbosity.Warning, $"No data received for {Timeout}, reconnecting socket"); log.Write(LogVerbosity.Warning, $"No data received for {Timeout}, reconnecting socket");
Close().ConfigureAwait(false); _ = Close().ConfigureAwait(false);
return; return;
} }
} }
@ -267,7 +267,7 @@ namespace CryptoExchange.Net.Sockets
if (connected) if (connected)
{ {
log?.Write(LogVerbosity.Debug, $"Socket {Id} connected"); log?.Write(LogVerbosity.Debug, $"Socket {Id} connected");
if ((timeoutTask == null || timeoutTask.IsCompleted) && Timeout != default(TimeSpan)) if ((timeoutTask == null || timeoutTask.IsCompleted) && Timeout != default)
timeoutTask = Task.Run(CheckTimeout); timeoutTask = Task.Run(CheckTimeout);
} }
else else

View File

@ -172,7 +172,7 @@ namespace CryptoExchange.Net.Sockets
SocketSubscription currentSubscription = null; SocketSubscription currentSubscription = null;
try try
{ {
bool handled = false; var handled = false;
var sw = Stopwatch.StartNew(); var sw = Stopwatch.StartNew();
lock (handlersLock) lock (handlersLock)
{ {
@ -387,7 +387,7 @@ namespace CryptoExchange.Net.Sockets
if (subscription.Confirmed) if (subscription.Confirmed)
await socketClient.Unsubscribe(this, subscription).ConfigureAwait(false); await socketClient.Unsubscribe(this, subscription).ConfigureAwait(false);
bool shouldCloseWrapper = false; var shouldCloseWrapper = false;
lock (handlersLock) lock (handlersLock)
{ {
handlers.Remove(subscription); handlers.Remove(subscription);