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:
parent
de0916920f
commit
8cb3420520
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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)}});
|
||||||
|
@ -78,7 +78,7 @@ namespace CryptoExchange.Net.Converters
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = default(T);
|
result = default;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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>
|
||||||
|
@ -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>();
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
93
CryptoExchange.Net/Interfaces/ISymbolOrderBook.cs
Normal file
93
CryptoExchange.Net/Interfaces/ISymbolOrderBook.cs
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
namespace CryptoExchange.Net.OrderBook
|
namespace CryptoExchange.Net.Interfaces
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Interface for order book entries
|
/// Interface for order book entries
|
@ -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.
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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>
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
namespace CryptoExchange.Net.OrderBook
|
using CryptoExchange.Net.Interfaces;
|
||||||
|
|
||||||
|
namespace CryptoExchange.Net.OrderBook
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Order book entry
|
/// Order book entry
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using CryptoExchange.Net.Objects;
|
using CryptoExchange.Net.Interfaces;
|
||||||
|
using CryptoExchange.Net.Objects;
|
||||||
|
|
||||||
namespace CryptoExchange.Net.OrderBook
|
namespace CryptoExchange.Net.OrderBook
|
||||||
{
|
{
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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)
|
||||||
|
@ -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";
|
||||||
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user