diff --git a/CryptoExchange.Net/Attributes/JsonOptionalPropertyAttribute.cs b/CryptoExchange.Net/Attributes/JsonOptionalPropertyAttribute.cs
index 9c33a6a..c50ff7b 100644
--- a/CryptoExchange.Net/Attributes/JsonOptionalPropertyAttribute.cs
+++ b/CryptoExchange.Net/Attributes/JsonOptionalPropertyAttribute.cs
@@ -2,6 +2,9 @@
namespace CryptoExchange.Net.Attributes
{
+ ///
+ /// Marks property as optional
+ ///
public class JsonOptionalPropertyAttribute : Attribute
{
}
diff --git a/CryptoExchange.Net/Authentication/ApiCredentials.cs b/CryptoExchange.Net/Authentication/ApiCredentials.cs
index f2b71d8..0cadf6f 100644
--- a/CryptoExchange.Net/Authentication/ApiCredentials.cs
+++ b/CryptoExchange.Net/Authentication/ApiCredentials.cs
@@ -6,6 +6,9 @@ using Newtonsoft.Json.Linq;
namespace CryptoExchange.Net.Authentication
{
+ ///
+ /// Api credentials info
+ ///
public class ApiCredentials: IDisposable
{
///
@@ -85,14 +88,14 @@ namespace CryptoExchange.Net.Authentication
inputStream.Seek(0, SeekOrigin.Begin);
}
- protected string TryGetValue(JToken data, string key)
+ private string TryGetValue(JToken data, string key)
{
if (data[key] == null)
return null;
return (string) data[key];
}
- protected SecureString CreateSecureString(string source)
+ private SecureString CreateSecureString(string source)
{
var secureString = new SecureString();
foreach (var c in source)
@@ -101,6 +104,9 @@ namespace CryptoExchange.Net.Authentication
return secureString;
}
+ ///
+ /// Dispose
+ ///
public void Dispose()
{
Key?.Dispose();
diff --git a/CryptoExchange.Net/Authentication/AuthenticationProvider.cs b/CryptoExchange.Net/Authentication/AuthenticationProvider.cs
index deb4e9b..d2a41a0 100644
--- a/CryptoExchange.Net/Authentication/AuthenticationProvider.cs
+++ b/CryptoExchange.Net/Authentication/AuthenticationProvider.cs
@@ -2,35 +2,76 @@
namespace CryptoExchange.Net.Authentication
{
+ ///
+ /// Base class for authentication providers
+ ///
public abstract class AuthenticationProvider
{
+ ///
+ /// The provided credentials
+ ///
public ApiCredentials Credentials { get; }
+ ///
+ /// ctor
+ ///
+ ///
protected AuthenticationProvider(ApiCredentials credentials)
{
Credentials = credentials;
}
+ ///
+ /// Add authentication to the parameter list
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
public virtual Dictionary AddAuthenticationToParameters(string uri, string method, Dictionary parameters, bool signed)
{
return parameters;
}
+ ///
+ /// Add authentication to the header dictionary
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
public virtual Dictionary AddAuthenticationToHeaders(string uri, string method, Dictionary parameters, bool signed)
{
return new Dictionary();
}
+ ///
+ /// Sign a string
+ ///
+ ///
+ ///
public virtual string Sign(string toSign)
{
return toSign;
}
+ ///
+ /// Sign a byte array
+ ///
+ ///
+ ///
public virtual byte[] Sign(byte[] toSign)
{
return toSign;
}
+ ///
+ /// Convert byte array to hex
+ ///
+ ///
+ ///
protected string ByteToString(byte[] buff)
{
var result = "";
diff --git a/CryptoExchange.Net/Authentication/PrivateKey.cs b/CryptoExchange.Net/Authentication/PrivateKey.cs
index 62c20b1..47c4755 100644
--- a/CryptoExchange.Net/Authentication/PrivateKey.cs
+++ b/CryptoExchange.Net/Authentication/PrivateKey.cs
@@ -3,6 +3,9 @@ using System.Security;
namespace CryptoExchange.Net.Authentication
{
+ ///
+ /// Private key info
+ ///
public class PrivateKey : IDisposable
{
///
@@ -87,6 +90,9 @@ namespace CryptoExchange.Net.Authentication
IsEncrypted = false;
}
+ ///
+ /// Dispose
+ ///
public void Dispose()
{
Key?.Dispose();
diff --git a/CryptoExchange.Net/BaseClient.cs b/CryptoExchange.Net/BaseClient.cs
index 7adf435..6d48158 100644
--- a/CryptoExchange.Net/BaseClient.cs
+++ b/CryptoExchange.Net/BaseClient.cs
@@ -12,14 +12,35 @@ using System.Reflection;
namespace CryptoExchange.Net
{
+ ///
+ /// The base for all clients
+ ///
public abstract class BaseClient: IDisposable
{
+ ///
+ /// The address of the client
+ ///
public string BaseAddress { get; private set; }
+ ///
+ /// The log object
+ ///
protected internal Log log;
+ ///
+ /// The api proxy
+ ///
protected ApiProxy apiProxy;
+ ///
+ /// The auth provider
+ ///
protected internal AuthenticationProvider authProvider;
+ ///
+ /// The last used id
+ ///
protected static int lastId;
+ ///
+ /// Lock for id generating
+ ///
protected static object idLock = new object();
private static readonly JsonSerializer defaultSerializer = JsonSerializer.Create(new JsonSerializerSettings
@@ -28,8 +49,16 @@ namespace CryptoExchange.Net
Culture = CultureInfo.InvariantCulture
});
+ ///
+ /// Last is used
+ ///
public static int LastId => lastId;
+ ///
+ /// ctor
+ ///
+ ///
+ ///
protected BaseClient(ClientOptions options, AuthenticationProvider authenticationProvider)
{
log = new Log();
@@ -40,7 +69,7 @@ namespace CryptoExchange.Net
///
/// Configure the client using the provided options
///
- /// Options
+ /// Options
protected void Configure(ClientOptions clientOptions)
{
log.UpdateWriters(clientOptions.LogWriters);
@@ -306,6 +335,9 @@ namespace CryptoExchange.Net
return path;
}
+ ///
+ /// Dispose
+ ///
public virtual void Dispose()
{
authProvider?.Credentials?.Dispose();
diff --git a/CryptoExchange.Net/Converters/ArrayConverter.cs b/CryptoExchange.Net/Converters/ArrayConverter.cs
index dd91b57..62cebc6 100644
--- a/CryptoExchange.Net/Converters/ArrayConverter.cs
+++ b/CryptoExchange.Net/Converters/ArrayConverter.cs
@@ -8,13 +8,18 @@ using Newtonsoft.Json.Linq;
namespace CryptoExchange.Net.Converters
{
+ ///
+ /// Converter for arrays to properties
+ ///
public class ArrayConverter : JsonConverter
{
+ ///
public override bool CanConvert(Type objectType)
{
return true;
}
-
+
+ ///
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (objectType == typeof(JToken))
@@ -95,6 +100,7 @@ namespace CryptoExchange.Net.Converters
return result;
}
+ ///
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
writer.WriteStartArray();
@@ -143,10 +149,20 @@ namespace CryptoExchange.Net.Converters
}
}
+ ///
+ /// Mark property as an index in the array
+ ///
public class ArrayPropertyAttribute: Attribute
{
+ ///
+ /// The index in the array
+ ///
public int Index { get; }
+ ///
+ /// ctor
+ ///
+ ///
public ArrayPropertyAttribute(int index)
{
Index = index;
diff --git a/CryptoExchange.Net/Converters/BaseConverter.cs b/CryptoExchange.Net/Converters/BaseConverter.cs
index 9e47948..47ce489 100644
--- a/CryptoExchange.Net/Converters/BaseConverter.cs
+++ b/CryptoExchange.Net/Converters/BaseConverter.cs
@@ -6,16 +6,28 @@ using Newtonsoft.Json;
namespace CryptoExchange.Net.Converters
{
+ ///
+ /// Base class for enum converters
+ ///
+ /// Type of enum to convert
public abstract class BaseConverter: JsonConverter
{
+ ///
+ /// The enum->string mapping
+ ///
protected abstract List> Mapping { get; }
private readonly bool quotes;
+ ///
+ /// ctor
+ ///
+ ///
protected BaseConverter(bool useQuotes)
{
quotes = useQuotes;
}
+ ///
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var stringValue = GetValue((T) value);
@@ -25,6 +37,7 @@ namespace CryptoExchange.Net.Converters
writer.WriteRawValue(stringValue);
}
+ ///
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.Value == null)
@@ -39,11 +52,17 @@ namespace CryptoExchange.Net.Converters
return result;
}
+ ///
+ /// Convert a string value
+ ///
+ ///
+ ///
public T ReadString(string data)
{
return Mapping.FirstOrDefault(v => v.Value == data).Key;
}
+ ///
public override bool CanConvert(Type objectType)
{
// Check if it is type, or nullable of type
diff --git a/CryptoExchange.Net/Converters/TimestampConverter.cs b/CryptoExchange.Net/Converters/TimestampConverter.cs
index aefed15..6d08a0d 100644
--- a/CryptoExchange.Net/Converters/TimestampConverter.cs
+++ b/CryptoExchange.Net/Converters/TimestampConverter.cs
@@ -3,13 +3,18 @@ using Newtonsoft.Json;
namespace CryptoExchange.Net.Converters
{
+ ///
+ /// converter for milliseconds to datetime
+ ///
public class TimestampConverter : JsonConverter
{
+ ///
public override bool CanConvert(Type objectType)
{
return objectType == typeof(DateTime);
}
+ ///
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.Value == null)
@@ -19,6 +24,7 @@ namespace CryptoExchange.Net.Converters
return new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddMilliseconds(t);
}
+ ///
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
writer.WriteValue((long)Math.Round(((DateTime)value - new DateTime(1970, 1, 1)).TotalMilliseconds));
diff --git a/CryptoExchange.Net/Converters/TimestampNanoSecondsConverter.cs b/CryptoExchange.Net/Converters/TimestampNanoSecondsConverter.cs
index a617131..17a6803 100644
--- a/CryptoExchange.Net/Converters/TimestampNanoSecondsConverter.cs
+++ b/CryptoExchange.Net/Converters/TimestampNanoSecondsConverter.cs
@@ -3,13 +3,18 @@ using Newtonsoft.Json;
namespace CryptoExchange.Net.Converters
{
+ ///
+ /// Converter for nanoseconds to datetime
+ ///
public class TimestampNanoSecondsConverter : JsonConverter
{
+ ///
public override bool CanConvert(Type objectType)
{
return objectType == typeof(DateTime);
}
+ ///
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.Value == null)
@@ -20,6 +25,7 @@ namespace CryptoExchange.Net.Converters
return new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddTicks((long)Math.Round(nanoSeconds * ticksPerNanosecond));
}
+ ///
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var ticksPerNanosecond = (TimeSpan.TicksPerMillisecond / 1000m / 1000);
diff --git a/CryptoExchange.Net/Converters/TimestampSecondsConverter.cs b/CryptoExchange.Net/Converters/TimestampSecondsConverter.cs
index 21f660c..c1dff7e 100644
--- a/CryptoExchange.Net/Converters/TimestampSecondsConverter.cs
+++ b/CryptoExchange.Net/Converters/TimestampSecondsConverter.cs
@@ -4,13 +4,18 @@ using Newtonsoft.Json;
namespace CryptoExchange.Net.Converters
{
+ ///
+ /// Converter for seconds to datetime
+ ///
public class TimestampSecondsConverter : JsonConverter
{
+ ///
public override bool CanConvert(Type objectType)
{
return objectType == typeof(DateTime);
}
+ ///
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.Value is double d)
@@ -20,6 +25,7 @@ namespace CryptoExchange.Net.Converters
return new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(t);
}
+ ///
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
writer.WriteValue((long)Math.Round(((DateTime)value - new DateTime(1970, 1, 1)).TotalSeconds));
diff --git a/CryptoExchange.Net/Converters/UTCDateTimeConverter.cs b/CryptoExchange.Net/Converters/UTCDateTimeConverter.cs
index 270f588..5210ccf 100644
--- a/CryptoExchange.Net/Converters/UTCDateTimeConverter.cs
+++ b/CryptoExchange.Net/Converters/UTCDateTimeConverter.cs
@@ -3,13 +3,18 @@ using Newtonsoft.Json;
namespace CryptoExchange.Net.Converters
{
+ ///
+ /// Converter for utc datetime
+ ///
public class UTCDateTimeConverter: JsonConverter
{
+ ///
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
writer.WriteValue(JsonConvert.SerializeObject(value));
}
+ ///
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.Value == null)
@@ -24,6 +29,7 @@ namespace CryptoExchange.Net.Converters
return DateTime.SpecifyKind(value, DateTimeKind.Utc);
}
+ ///
public override bool CanConvert(Type objectType)
{
return objectType == typeof(DateTime) || objectType == typeof(DateTime?);
diff --git a/CryptoExchange.Net/CryptoExchange.Net.csproj b/CryptoExchange.Net/CryptoExchange.Net.csproj
index 2709772..ecc7a86 100644
--- a/CryptoExchange.Net/CryptoExchange.Net.csproj
+++ b/CryptoExchange.Net/CryptoExchange.Net.csproj
@@ -1,27 +1,23 @@
-
netstandard2.0
-
CryptoExchange.Net
- JKorf
- 2.1.5
- false
+ JKorf
+ 2.1.6
+ false
https://github.com/JKorf/CryptoExchange.Net
- https://github.com/JKorf/CryptoExchange.Net/blob/master/LICENSE
- en
- true
+ https://github.com/JKorf/CryptoExchange.Net/blob/master/LICENSE
+ en
+ true
+ 2.1.6 - Fix for missing subscription events if they are also a request response, added code docs
-
CryptoExchange.Net.xml
-
-
-
+
\ No newline at end of file
diff --git a/CryptoExchange.Net/CryptoExchange.Net.xml b/CryptoExchange.Net/CryptoExchange.Net.xml
index c9b64ab..df25990 100644
--- a/CryptoExchange.Net/CryptoExchange.Net.xml
+++ b/CryptoExchange.Net/CryptoExchange.Net.xml
@@ -4,6 +4,16 @@
CryptoExchange.Net
+
+
+ Marks property as optional
+
+
+
+
+ Api credentials info
+
+
The api key to authenticate requests
@@ -47,6 +57,73 @@
A key to identify the credentials for the API. For example, when set to `binanceKey` the json data should contain a value for the property `binanceKey`. Defaults to 'apiKey'.
A key to identify the credentials for the API. For example, when set to `binanceSecret` the json data should contain a value for the property `binanceSecret`. Defaults to 'apiSecret'.
+
+
+ Dispose
+
+
+
+
+ Base class for authentication providers
+
+
+
+
+ The provided credentials
+
+
+
+
+ ctor
+
+
+
+
+
+ Add authentication to the parameter list
+
+
+
+
+
+
+
+
+
+ Add authentication to the header dictionary
+
+
+
+
+
+
+
+
+
+ Sign a string
+
+
+
+
+
+
+ Sign a byte array
+
+
+
+
+
+
+ Convert byte array to hex
+
+
+
+
+
+
+ Private key info
+
+
The private key
@@ -88,11 +165,63 @@
The private key used for signing
+
+
+ Dispose
+
+
+
+
+ The base for all clients
+
+
+
+
+ The address of the client
+
+
+
+
+ The log object
+
+
+
+
+ The api proxy
+
+
+
+
+ The auth provider
+
+
+
+
+ The last used id
+
+
+
+
+ Lock for id generating
+
+
+
+
+ Last is used
+
+
+
+
+ ctor
+
+
+
+
Configure the client using the provided options
- Options
+ Options
@@ -141,6 +270,167 @@
The values to fill
+
+
+ Dispose
+
+
+
+
+ Converter for arrays to properties
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Mark property as an index in the array
+
+
+
+
+ The index in the array
+
+
+
+
+ ctor
+
+
+
+
+
+ Base class for enum converters
+
+ Type of enum to convert
+
+
+
+ The enum->string mapping
+
+
+
+
+ ctor
+
+
+
+
+
+
+
+
+
+
+
+ Convert a string value
+
+
+
+
+
+
+
+
+
+ converter for milliseconds to datetime
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Converter for nanoseconds to datetime
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Converter for seconds to datetime
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Converter for utc datetime
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Helper methods
+
+
+
+
+ Add a parameter
+
+
+
+
+
+
+
+ Add a parameter
+
+
+
+
+
+
+
+ Add an optional parameter. Not added if value is null
+
+
+
+
+
+
+
+ Add an optional parameter. Not added if value is null
+
+
+
+
+
Create a query string of the specified parameters
@@ -156,6 +446,157 @@
The source secure string
+
+
+ Header collection to inenumerable
+
+
+
+
+
+
+ Wait one async
+
+
+
+
+
+
+
+
+ Wait one async
+
+
+
+
+
+
+
+ String to JToken
+
+
+
+
+
+
+
+ Rate limiter interface
+
+
+
+
+ Limit the request if needed
+
+
+
+
+
+
+
+
+ Request interface
+
+
+
+
+ The uri of the request
+
+
+
+
+ The headers of the request
+
+
+
+
+ The method of the request
+
+
+
+
+ The timeout of the request
+
+
+
+
+ Set a proxy
+
+
+
+
+
+
+
+
+ Content type
+
+
+
+
+ String content
+
+
+
+
+ Accept
+
+
+
+
+ Content length
+
+
+
+
+ Get the request stream
+
+
+
+
+
+ Get the response object
+
+
+
+
+
+ Request factory interface
+
+
+
+
+ Create a request for an uri
+
+
+
+
+
+
+ Response object interface
+
+
+
+
+ The response status code
+
+
+
+
+ Get the response stream
+
+
+
+
+
+ Get the response headers
+
+
+
+
+
+ Close the response
+
+
Base class for rest API implementations
@@ -247,6 +688,246 @@
+
+
+ Interface for websocket interaction
+
+
+
+
+ Websocket closed
+
+
+
+
+ Websocket message received
+
+
+
+
+ Websocket error
+
+
+
+
+ Websocket opened
+
+
+
+
+ Id
+
+
+
+
+ Origin
+
+
+
+
+ Reconnecting
+
+
+
+
+ Handler for byte data
+
+
+
+
+ Handler for string data
+
+
+
+
+ Socket url
+
+
+
+
+ State
+
+
+
+
+ Is closed
+
+
+
+
+ Is open
+
+
+
+
+ Should ping connecting
+
+
+
+
+ Interval of pinging
+
+
+
+
+ Supported ssl protocols
+
+
+
+
+ Timeout
+
+
+
+
+ Connect the socket
+
+
+
+
+
+ Send data
+
+
+
+
+
+ Reset socket
+
+
+
+
+ Close the connecting
+
+
+
+
+
+ Set proxy
+
+
+
+
+
+
+ Websocket factory interface
+
+
+
+
+ Create a websocket for an url
+
+
+
+
+
+
+
+ Create a websocket for an url
+
+
+
+
+
+
+
+
+
+ Default log writer, writes to debug
+
+
+
+
+
+
+
+
+
+
+ Log implementation
+
+
+
+
+ The verbosity of the logging
+
+
+
+
+ ctor
+
+
+
+
+ Set the writers
+
+
+
+
+
+ Write a log entry
+
+
+
+
+
+
+ The log verbosity
+
+
+
+
+ Debug logging
+
+
+
+
+ Info logging
+
+
+
+
+ Warning logging
+
+
+
+
+ Error logging
+
+
+
+
+ None, used for disabling logging
+
+
+
+
+ File writer
+
+
+
+
+
+
+
+ ctor
+
+
+
+
+
+
+
+
+ Dispose
+
+
+
+
+
+ Proxy info
+
+
The host address of the proxy
@@ -284,6 +965,25 @@
The proxy login
The proxy password
+
+
+ Comparer for byte order
+
+
+
+
+ Compare function
+
+
+
+
+
+
+
+ The result of an operation
+
+
+
The data returned by the call
@@ -299,11 +999,179 @@
Whether the call was successful
+
+
+ ctor
+
+
+
+
+
+
+ The result of a request
+
+
+
The status code of the response. Note that a OK status does not always indicate success, check the Success parameter for this.
+
+
+ The response headers
+
+
+
+
+ ctor
+
+
+
+
+
+
+
+
+ Create an error result
+
+
+
+
+
+
+ Create an error result
+
+
+
+
+
+
+
+
+ Constants
+
+
+
+
+ GET Http method
+
+
+
+
+ POST Http method
+
+
+
+
+ DELETE Http method
+
+
+
+
+ PUT Http method
+
+
+
+
+ Json content type header
+
+
+
+
+ Form content type header
+
+
+
+
+ What to do when a request would exceed the rate limit
+
+
+
+
+ Fail the request
+
+
+
+
+ Wait till the request can be send
+
+
+
+
+ Where the post parameters should be added
+
+
+
+
+ Post parameters in body
+
+
+
+
+ Post parameters in url
+
+
+
+
+ The format of the request body
+
+
+
+
+ Form data
+
+
+
+
+ Json
+
+
+
+
+ Status of the order book
+
+
+
+
+ Not connected
+
+
+
+
+ Connecting
+
+
+
+
+ Syncing data
+
+
+
+
+ Data synced, order book is up to date
+
+
+
+
+ Order book entry type
+
+
+
+
+ Ask
+
+
+
+
+ Bid
+
+
+
+
+ Base class for errors
+
+
The error code
@@ -314,6 +1182,112 @@
The message for the error that occured
+
+
+ ctor
+
+
+
+
+
+
+ String representation
+
+
+
+
+
+ Cant reach server error
+
+
+
+
+ ctor
+
+
+
+
+ No api credentials provided while trying to access private endpoint
+
+
+
+
+ ctor
+
+
+
+
+ Error returned by the server
+
+
+
+
+ ctor
+
+
+
+
+
+ ctor
+
+
+
+
+
+
+ Web error returned by the server
+
+
+
+
+ ctor
+
+
+
+
+
+ Error while deserializing data
+
+
+
+
+ ctor
+
+
+
+
+
+ Unknown error
+
+
+
+
+ ctor
+
+
+
+
+
+ An invalid parameter has been provided
+
+
+
+
+ ctor
+
+
+
+
+
+ Rate limit exceeded
+
+
+
+
+ ctor
+
+
+
Base options
@@ -390,6 +1364,13 @@
The time the server has to respond to a request before timing out
+
+
+ Create a copy of the options
+
+
+
+
Base for socket client options
@@ -421,6 +1402,18 @@
Setting this to a higher number increases subscription speed, but having more subscriptions on a single connection will also increase the amount of traffic on that single connection.
+
+
+ Create a copy of the options
+
+
+
+
+
+
+ Interface for order book entries
+
+
The quantity of the entry
@@ -431,11 +1424,100 @@
The price of the entry
+
+
+ Order book entry
+
+
+
+
+ Quantity of the entry
+
+
+
+
+ Price of the entry
+
+
+
+
+ ctor
+
+
+
+
+
+
+ Buffer entry for order book
+
+
+
+
+ The first sequence number of the entries
+
+
+
+
+ The last sequence number of the entries
+
+
+
+
+ List of entries
+
+
+
+
+ ctor
+
+
+
+
+ Process entry for order book
+
+
+
+
+ The entry
+
+
+
+
+ The type
+
+
+
+
+ ctor
+
+
+
+
Base for order book implementations
+
+
+ The process buffer, used while syncing
+
+
+
+
+ The ask list
+
+
+
+
+ The bid list
+
+
+
+
+ The log
+
+
The status of the order book. Order book is up to date when the status is `Synced`
@@ -486,6 +1568,13 @@
The best ask currently in the order book
+
+
+ ctor
+
+
+
+
Start connecting and synchronizing the order book
@@ -510,6 +1599,68 @@
+
+
+ Start the order book
+
+
+
+
+
+ Reset the order book
+
+
+
+
+ Resync the order book
+
+
+
+
+
+ Set the initial data for the order book
+
+ The last update sequence number
+ List of asks
+ List of bids
+
+
+
+ Update the order book with entries
+
+ First sequence number
+ Last sequence number
+ List of entries
+
+
+
+ Check and empty the process buffer; see what entries to update the book with
+
+
+
+
+ Update order book with an entry
+
+ Type of entry
+ The entry
+
+
+
+ Dispose the order book
+
+
+
+
+ String representation of the top 3 entries
+
+
+
+
+
+ String representation of the top x entries
+
+
+
Limits the amount of requests per time period to a certain limit, counts the request per API key.
@@ -522,6 +1673,9 @@
The amount to limit to
The time period over which the limit counts
+
+
+
Limits the amount of requests per time period to a certain limit, counts the request per endpoint.
@@ -534,6 +1688,9 @@
The amount to limit to
The time period over which the limit counts
+
+
+
Limits the amount of requests per time period to a certain limit, counts the total amount of requests.
@@ -546,11 +1703,161 @@
The amount to limit to
The time period over which the limit counts
+
+
+
+
+
+ Rate limiting object
+
+
+
+
+ Lock
+
+
+
+
+ ctor
+
+
+
+
+ Get time to wait for a specific time
+
+
+
+
+
+
+
+
+ Add an executed request time
+
+
+
+
+
+ Request object
+
+
+
+
+ Create request object for webrequest
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ WebRequest factory
+
+
+
+
+
+
+
+ HttpWebResponse response object
+
+
+
+
+
+
+
+ Create response for http web response
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Base rest client
+
+
The factory for creating requests. Used for unit testing
+
+
+ Where to place post parameters
+
+
+
+
+ Request body content type
+
+
+
+
+ Timeout for requests
+
+
+
+
+ Rate limiting behaviour
+
+
+
+
+ List of ratelimitters
+
+
+
+
+ Total requests made
+
+
+
+
+ ctor
+
+
+
+
Configure the client using the provided options
@@ -637,6 +1944,11 @@
The string the request returned
+
+
+ Base for socket client implementations
+
+
The factory for creating sockets. Used for unit testing
@@ -647,6 +1959,10 @@
List of socket connections currently connecting/connected
+
+
+
+
@@ -667,6 +1983,49 @@
+
+
+ Handler for byte data
+
+
+
+
+ Handler for string data
+
+
+
+
+ Generic handlers
+
+
+
+
+ Periodic task
+
+
+
+
+ Periodic task event
+
+
+
+
+ Is disposing
+
+
+
+
+ If true; data which is a response to a query will also be distributed to subscriptions
+ If false; data which is a response to a query won't get forwarded to subscriptions as well
+
+
+
+
+ Create a socket client
+
+ Client options
+ Authentication provider
+
Configure the client using the provided options
@@ -712,11 +2071,21 @@
The subscription the request is for
+
+
+ Query for data
+
+ Exepected result type
+ The request to send
+ Whether the socket should be authenticated
+
+
Query for data
The expected result type
+ The url for the request
The request to send
Whether the socket should be authenticated
@@ -756,7 +2125,7 @@
The socket connection
The request that a response is awaited for
- The message
+ The message
The interpretation (null if message wasn't a response to the request)
True if the message was a response to the subscription request
@@ -864,6 +2233,102 @@
Dispose the client
+
+
+ Socket implementation
+
+
+
+
+ Socket connecting
+
+
+
+
+ Connection lost event
+
+
+
+
+ Connecting restored event
+
+
+
+
+ Connecting closed event
+
+
+
+
+ The amount of handlers
+
+
+
+
+ If connection is authenticated
+
+
+
+
+ If connection is made
+
+
+
+
+ The socket
+
+
+
+
+ If should reconnect upon closing
+
+
+
+
+ Time of disconnecting
+
+
+
+
+ If activity is paused
+
+
+
+
+ New socket connection
+
+ The socket client
+ The socket
+
+
+
+ Add a handler
+
+ The request object
+ If it is a user subscription or a generic handler
+ The data handler
+
+
+
+
+ Add a handler
+
+ The identifier of the handler
+ If it is a user subscription or a generic handler
+ The data handler
+
+
+
+
+
+ Send data
+
+ The data type
+ The object to send
+ The timeout for response
+ The response handler
+
+
Send data to the websocket
@@ -883,11 +2348,74 @@
Handler for a socket closing. Reconnects the socket if needed, or removes it from the active socket list if not
+
+
+ Close the connection
+
+
+
+
+
+ Close the subscriptions
+
+ Subscription to close
+
+
+
+
+ Socket subscription
+
+
+
+
+ Exception event
+
+
Message handlers for this subscription. Should return true if the message is handled and should not be distributed to the other handlers
+
+
+ Request object
+
+
+
+
+ Subscription identifier
+
+
+
+
+ Is user subscription or generic
+
+
+
+
+ If the subscription has been confirmed
+
+
+
+
+ ctor
+
+
+
+
+
+
+
+
+ Invoke the exception event
+
+
+
+
+
+ Subscription
+
+
Event when the connection is lost. The socket will automatically reconnect when possible.
@@ -908,6 +2436,13 @@
The id of the socket
+
+
+ ctor
+
+
+
+
Close the subscription
@@ -920,5 +2455,16 @@
+
+
+ Factory implementation
+
+
+
+
+
+
+
+
diff --git a/CryptoExchange.Net/ExtensionMethods.cs b/CryptoExchange.Net/ExtensionMethods.cs
index b682107..f2485a8 100644
--- a/CryptoExchange.Net/ExtensionMethods.cs
+++ b/CryptoExchange.Net/ExtensionMethods.cs
@@ -13,24 +13,51 @@ using Newtonsoft.Json.Linq;
namespace CryptoExchange.Net
{
+ ///
+ /// Helper methods
+ ///
public static class ExtensionMethods
{
+ ///
+ /// Add a parameter
+ ///
+ ///
+ ///
+ ///
public static void AddParameter(this Dictionary parameters, string key, string value)
{
parameters.Add(key, value);
}
+ ///
+ /// Add a parameter
+ ///
+ ///
+ ///
+ ///
public static void AddParameter(this Dictionary parameters, string key, object value)
{
parameters.Add(key, value);
}
+ ///
+ /// Add an optional parameter. Not added if value is null
+ ///
+ ///
+ ///
+ ///
public static void AddOptionalParameter(this Dictionary parameters, string key, object value)
{
if(value != null)
parameters.Add(key, value);
}
+ ///
+ /// Add an optional parameter. Not added if value is null
+ ///
+ ///
+ ///
+ ///
public static void AddOptionalParameter(this Dictionary parameters, string key, string value)
{
if (value != null)
@@ -90,6 +117,11 @@ namespace CryptoExchange.Net
}
}
+ ///
+ /// Header collection to inenumerable
+ ///
+ ///
+ ///
public static IEnumerable> ToIEnumerable(this WebHeaderCollection headers)
{
if (headers == null)
@@ -102,6 +134,13 @@ namespace CryptoExchange.Net
);
}
+ ///
+ /// Wait one async
+ ///
+ ///
+ ///
+ ///
+ ///
public static async Task WaitOneAsync(this WaitHandle handle, int millisecondsTimeout, CancellationToken cancellationToken)
{
RegisteredWaitHandle registeredHandle = null;
@@ -126,12 +165,24 @@ namespace CryptoExchange.Net
tokenRegistration.Dispose();
}
}
-
+
+ ///
+ /// Wait one async
+ ///
+ ///
+ ///
+ ///
public static Task WaitOneAsync(this WaitHandle handle, TimeSpan timeout)
{
return handle.WaitOneAsync((int)timeout.TotalMilliseconds, CancellationToken.None);
}
+ ///
+ /// String to JToken
+ ///
+ ///
+ ///
+ ///
public static JToken ToJToken(this string stringData, Log log = null)
{
if (string.IsNullOrEmpty(stringData))
diff --git a/CryptoExchange.Net/Interfaces/IRateLimiter.cs b/CryptoExchange.Net/Interfaces/IRateLimiter.cs
index 5220f46..735f3ec 100644
--- a/CryptoExchange.Net/Interfaces/IRateLimiter.cs
+++ b/CryptoExchange.Net/Interfaces/IRateLimiter.cs
@@ -2,8 +2,18 @@
namespace CryptoExchange.Net.Interfaces
{
+ ///
+ /// Rate limiter interface
+ ///
public interface IRateLimiter
{
+ ///
+ /// Limit the request if needed
+ ///
+ ///
+ ///
+ ///
+ ///
CallResult LimitRequest(RestClient client, string url, RateLimitingBehaviour limitBehaviour);
}
}
diff --git a/CryptoExchange.Net/Interfaces/IRequest.cs b/CryptoExchange.Net/Interfaces/IRequest.cs
index 457a42d..6c42ca5 100644
--- a/CryptoExchange.Net/Interfaces/IRequest.cs
+++ b/CryptoExchange.Net/Interfaces/IRequest.cs
@@ -5,20 +5,62 @@ using System.Threading.Tasks;
namespace CryptoExchange.Net.Interfaces
{
+ ///
+ /// Request interface
+ ///
public interface IRequest
{
+ ///
+ /// The uri of the request
+ ///
Uri Uri { get; }
+ ///
+ /// The headers of the request
+ ///
WebHeaderCollection Headers { get; set; }
+ ///
+ /// The method of the request
+ ///
string Method { get; set; }
+ ///
+ /// The timeout of the request
+ ///
TimeSpan Timeout { get; set; }
+ ///
+ /// Set a proxy
+ ///
+ ///
+ ///
+ ///
+ ///
void SetProxy(string host, int port, string login, string password);
+ ///
+ /// Content type
+ ///
string ContentType { get; set; }
+ ///
+ /// String content
+ ///
string Content { get; set; }
+ ///
+ /// Accept
+ ///
string Accept { get; set; }
+ ///
+ /// Content length
+ ///
long ContentLength { get; set; }
+ ///
+ /// Get the request stream
+ ///
+ ///
Task GetRequestStream();
+ ///
+ /// Get the response object
+ ///
+ ///
Task GetResponse();
}
}
diff --git a/CryptoExchange.Net/Interfaces/IRequestFactory.cs b/CryptoExchange.Net/Interfaces/IRequestFactory.cs
index 5acdb4b..193db1d 100644
--- a/CryptoExchange.Net/Interfaces/IRequestFactory.cs
+++ b/CryptoExchange.Net/Interfaces/IRequestFactory.cs
@@ -1,7 +1,15 @@
namespace CryptoExchange.Net.Interfaces
{
+ ///
+ /// Request factory interface
+ ///
public interface IRequestFactory
{
+ ///
+ /// Create a request for an uri
+ ///
+ ///
+ ///
IRequest Create(string uri);
}
}
diff --git a/CryptoExchange.Net/Interfaces/IResponse.cs b/CryptoExchange.Net/Interfaces/IResponse.cs
index 58430ed..cc32604 100644
--- a/CryptoExchange.Net/Interfaces/IResponse.cs
+++ b/CryptoExchange.Net/Interfaces/IResponse.cs
@@ -5,11 +5,28 @@ using System.Net;
namespace CryptoExchange.Net.Interfaces
{
+ ///
+ /// Response object interface
+ ///
public interface IResponse
{
+ ///
+ /// The response status code
+ ///
HttpStatusCode StatusCode { get; }
+ ///
+ /// Get the response stream
+ ///
+ ///
Stream GetResponseStream();
+ ///
+ /// Get the response headers
+ ///
+ ///
IEnumerable> GetResponseHeaders();
+ ///
+ /// Close the response
+ ///
void Close();
}
}
diff --git a/CryptoExchange.Net/Interfaces/IWebsocket.cs b/CryptoExchange.Net/Interfaces/IWebsocket.cs
index ec8db64..6a97da1 100644
--- a/CryptoExchange.Net/Interfaces/IWebsocket.cs
+++ b/CryptoExchange.Net/Interfaces/IWebsocket.cs
@@ -5,30 +5,104 @@ using WebSocket4Net;
namespace CryptoExchange.Net.Interfaces
{
+ ///
+ /// Interface for websocket interaction
+ ///
public interface IWebsocket: IDisposable
{
+ ///
+ /// Websocket closed
+ ///
event Action OnClose;
+ ///
+ /// Websocket message received
+ ///
event Action OnMessage;
+ ///
+ /// Websocket error
+ ///
event Action OnError;
+ ///
+ /// Websocket opened
+ ///
event Action OnOpen;
+ ///
+ /// Id
+ ///
int Id { get; }
+ ///
+ /// Origin
+ ///
string Origin { get; set; }
+ ///
+ /// Reconnecting
+ ///
bool Reconnecting { get; set; }
+ ///
+ /// Handler for byte data
+ ///
Func DataInterpreterBytes { get; set; }
+ ///
+ /// Handler for string data
+ ///
Func DataInterpreterString { get; set; }
+ ///
+ /// Socket url
+ ///
string Url { get; }
+ ///
+ /// State
+ ///
WebSocketState SocketState { get; }
+ ///
+ /// Is closed
+ ///
bool IsClosed { get; }
+ ///
+ /// Is open
+ ///
bool IsOpen { get; }
+ ///
+ /// Should ping connecting
+ ///
bool PingConnection { get; set; }
+ ///
+ /// Interval of pinging
+ ///
TimeSpan PingInterval { get; set; }
+ ///
+ /// Supported ssl protocols
+ ///
SslProtocols SSLProtocols { get; set; }
+ ///
+ /// Timeout
+ ///
TimeSpan Timeout { get; set; }
+ ///
+ /// Connect the socket
+ ///
+ ///
Task Connect();
+ ///
+ /// Send data
+ ///
+ ///
void Send(string data);
+ ///
+ /// Reset socket
+ ///
void Reset();
+ ///
+ /// Close the connecting
+ ///
+ ///
Task Close();
+ ///
+ /// Set proxy
+ ///
+ ///
+ ///
void SetProxy(string host, int port);
}
}
diff --git a/CryptoExchange.Net/Interfaces/IWebsocketFactory.cs b/CryptoExchange.Net/Interfaces/IWebsocketFactory.cs
index e3a45c7..1b0d74f 100644
--- a/CryptoExchange.Net/Interfaces/IWebsocketFactory.cs
+++ b/CryptoExchange.Net/Interfaces/IWebsocketFactory.cs
@@ -3,9 +3,26 @@ using CryptoExchange.Net.Logging;
namespace CryptoExchange.Net.Interfaces
{
+ ///
+ /// Websocket factory interface
+ ///
public interface IWebsocketFactory
{
+ ///
+ /// Create a websocket for an url
+ ///
+ ///
+ ///
+ ///
IWebsocket CreateWebsocket(Log log, string url);
+ ///
+ /// Create a websocket for an url
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
IWebsocket CreateWebsocket(Log log, string url, IDictionary cookies, IDictionary headers);
}
}
diff --git a/CryptoExchange.Net/Logging/DebugTextWriter.cs b/CryptoExchange.Net/Logging/DebugTextWriter.cs
index 9cea25b..3e0bc14 100644
--- a/CryptoExchange.Net/Logging/DebugTextWriter.cs
+++ b/CryptoExchange.Net/Logging/DebugTextWriter.cs
@@ -4,10 +4,15 @@ using System.Text;
namespace CryptoExchange.Net.Logging
{
+ ///
+ /// Default log writer, writes to debug
+ ///
public class DebugTextWriter: TextWriter
{
+ ///
public override Encoding Encoding => Encoding.ASCII;
+ ///
public override void WriteLine(string value)
{
Debug.WriteLine(value);
diff --git a/CryptoExchange.Net/Logging/Log.cs b/CryptoExchange.Net/Logging/Log.cs
index e090c30..9338280 100644
--- a/CryptoExchange.Net/Logging/Log.cs
+++ b/CryptoExchange.Net/Logging/Log.cs
@@ -6,22 +6,39 @@ using System.Linq;
namespace CryptoExchange.Net.Logging
{
+ ///
+ /// Log implementation
+ ///
public class Log
{
private List writers;
-
+ ///
+ /// The verbosity of the logging
+ ///
public LogVerbosity Level { get; set; } = LogVerbosity.Info;
+ ///
+ /// ctor
+ ///
public Log()
{
writers = new List();
}
+ ///
+ /// Set the writers
+ ///
+ ///
public void UpdateWriters(List textWriters)
{
writers = textWriters;
}
+ ///
+ /// Write a log entry
+ ///
+ ///
+ ///
public void Write(LogVerbosity logType, string message)
{
if ((int)logType < (int)Level)
@@ -42,12 +59,30 @@ namespace CryptoExchange.Net.Logging
}
}
+ ///
+ /// The log verbosity
+ ///
public enum LogVerbosity
{
+ ///
+ /// Debug logging
+ ///
Debug,
+ ///
+ /// Info logging
+ ///
Info,
+ ///
+ /// Warning logging
+ ///
Warning,
+ ///
+ /// Error logging
+ ///
Error,
+ ///
+ /// None, used for disabling logging
+ ///
None
}
}
diff --git a/CryptoExchange.Net/Logging/ThreadSafeFileWriter.cs b/CryptoExchange.Net/Logging/ThreadSafeFileWriter.cs
index f5c03d3..5caac53 100644
--- a/CryptoExchange.Net/Logging/ThreadSafeFileWriter.cs
+++ b/CryptoExchange.Net/Logging/ThreadSafeFileWriter.cs
@@ -4,6 +4,9 @@ using System.Text;
namespace CryptoExchange.Net.Logging
{
+ ///
+ /// File writer
+ ///
public class ThreadSafeFileWriter: TextWriter
{
private static readonly object openedFilesLock = new object();
@@ -12,8 +15,13 @@ namespace CryptoExchange.Net.Logging
private StreamWriter logWriter;
private readonly object writeLock;
+ ///
public override Encoding Encoding => Encoding.ASCII;
+ ///
+ /// ctor
+ ///
+ ///
public ThreadSafeFileWriter(string path)
{
logWriter = new StreamWriter(File.Open(path, FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite)) {AutoFlush = true};
@@ -28,12 +36,17 @@ namespace CryptoExchange.Net.Logging
}
}
+ ///
public override void WriteLine(string logMessage)
{
lock(writeLock)
logWriter.WriteLine(logMessage);
}
+ ///
+ /// Dispose
+ ///
+ ///
protected override void Dispose(bool disposing)
{
lock (writeLock)
diff --git a/CryptoExchange.Net/Objects/ApiProxy.cs b/CryptoExchange.Net/Objects/ApiProxy.cs
index 970f5b6..b4db095 100644
--- a/CryptoExchange.Net/Objects/ApiProxy.cs
+++ b/CryptoExchange.Net/Objects/ApiProxy.cs
@@ -2,6 +2,9 @@
namespace CryptoExchange.Net.Objects
{
+ ///
+ /// Proxy info
+ ///
public class ApiProxy
{
///
diff --git a/CryptoExchange.Net/Objects/ByteOrderComparer.cs b/CryptoExchange.Net/Objects/ByteOrderComparer.cs
index 25f026d..29be971 100644
--- a/CryptoExchange.Net/Objects/ByteOrderComparer.cs
+++ b/CryptoExchange.Net/Objects/ByteOrderComparer.cs
@@ -3,8 +3,17 @@ using System.Collections.Generic;
namespace CryptoExchange.Net.Objects
{
+ ///
+ /// Comparer for byte order
+ ///
public class ByteOrderComparer : IComparer
{
+ ///
+ /// Compare function
+ ///
+ ///
+ ///
+ ///
public int Compare(byte[] x, byte[] y)
{
// Shortcuts: If both are null, they are the same.
diff --git a/CryptoExchange.Net/Objects/CallResult.cs b/CryptoExchange.Net/Objects/CallResult.cs
index fbfb5cb..d8c2f59 100644
--- a/CryptoExchange.Net/Objects/CallResult.cs
+++ b/CryptoExchange.Net/Objects/CallResult.cs
@@ -4,6 +4,10 @@ using System.Net;
namespace CryptoExchange.Net.Objects
{
+ ///
+ /// The result of an operation
+ ///
+ ///
public class CallResult
{
///
@@ -19,6 +23,11 @@ namespace CryptoExchange.Net.Objects
///
public bool Success => Error == null;
+ ///
+ /// ctor
+ ///
+ ///
+ ///
public CallResult(T data, Error error)
{
Data = data;
@@ -26,6 +35,10 @@ namespace CryptoExchange.Net.Objects
}
}
+ ///
+ /// The result of a request
+ ///
+ ///
public class WebCallResult: CallResult
{
///
@@ -33,18 +46,41 @@ namespace CryptoExchange.Net.Objects
///
public HttpStatusCode? ResponseStatusCode { get; set; }
+ ///
+ /// The response headers
+ ///
public IEnumerable> ResponseHeaders { get; set; }
+ ///
+ /// ctor
+ ///
+ ///
+ ///
+ ///
+ ///
public WebCallResult(HttpStatusCode? code, IEnumerable> responseHeaders, T data, Error error): base(data, error)
{
ResponseHeaders = responseHeaders;
ResponseStatusCode = code;
}
+ ///
+ /// Create an error result
+ ///
+ ///
+ ///
public static WebCallResult CreateErrorResult(Error error)
{
return new WebCallResult(null, null, default(T), error);
}
+
+ ///
+ /// Create an error result
+ ///
+ ///
+ ///
+ ///
+ ///
public static WebCallResult CreateErrorResult(HttpStatusCode? code, IEnumerable> responseHeaders, Error error)
{
return new WebCallResult(code, responseHeaders, default(T), error);
diff --git a/CryptoExchange.Net/Objects/Constants.cs b/CryptoExchange.Net/Objects/Constants.cs
index 95e3a7f..55112fa 100644
--- a/CryptoExchange.Net/Objects/Constants.cs
+++ b/CryptoExchange.Net/Objects/Constants.cs
@@ -1,13 +1,34 @@
namespace CryptoExchange.Net.Objects
{
+ ///
+ /// Constants
+ ///
public class Constants
{
+ ///
+ /// GET Http method
+ ///
public const string GetMethod = "GET";
+ ///
+ /// POST Http method
+ ///
public const string PostMethod = "POST";
+ ///
+ /// DELETE Http method
+ ///
public const string DeleteMethod = "DELETE";
+ ///
+ /// PUT Http method
+ ///
public const string PutMethod = "PUT";
+ ///
+ /// Json content type header
+ ///
public const string JsonContentHeader = "application/json";
+ ///
+ /// Form content type header
+ ///
public const string FormContentHeader = "application/x-www-form-urlencoded";
}
}
diff --git a/CryptoExchange.Net/Objects/Enums.cs b/CryptoExchange.Net/Objects/Enums.cs
index 53cff06..fc6b630 100644
--- a/CryptoExchange.Net/Objects/Enums.cs
+++ b/CryptoExchange.Net/Objects/Enums.cs
@@ -1,34 +1,85 @@
namespace CryptoExchange.Net.Objects
{
+ ///
+ /// What to do when a request would exceed the rate limit
+ ///
public enum RateLimitingBehaviour
{
+ ///
+ /// Fail the request
+ ///
Fail,
+ ///
+ /// Wait till the request can be send
+ ///
Wait
}
+ ///
+ /// Where the post parameters should be added
+ ///
public enum PostParameters
{
+ ///
+ /// Post parameters in body
+ ///
InBody,
+ ///
+ /// Post parameters in url
+ ///
InUri
}
+ ///
+ /// The format of the request body
+ ///
public enum RequestBodyFormat
{
+ ///
+ /// Form data
+ ///
FormData,
+ ///
+ /// Json
+ ///
Json
}
+ ///
+ /// Status of the order book
+ ///
public enum OrderBookStatus
{
+ ///
+ /// Not connected
+ ///
Disconnected,
+ ///
+ /// Connecting
+ ///
Connecting,
+ ///
+ /// Syncing data
+ ///
Syncing,
+ ///
+ /// Data synced, order book is up to date
+ ///
Synced,
}
+ ///
+ /// Order book entry type
+ ///
public enum OrderBookEntryType
{
+ ///
+ /// Ask
+ ///
Ask,
+ ///
+ /// Bid
+ ///
Bid
}
}
diff --git a/CryptoExchange.Net/Objects/Error.cs b/CryptoExchange.Net/Objects/Error.cs
index f692762..29240b1 100644
--- a/CryptoExchange.Net/Objects/Error.cs
+++ b/CryptoExchange.Net/Objects/Error.cs
@@ -1,5 +1,8 @@
namespace CryptoExchange.Net.Objects
{
+ ///
+ /// Base class for errors
+ ///
public abstract class Error
{
///
@@ -11,59 +14,127 @@
///
public string Message { get; set; }
+ ///
+ /// ctor
+ ///
+ ///
+ ///
protected Error(int code, string message)
{
Code = code;
Message = message;
}
+ ///
+ /// String representation
+ ///
+ ///
public override string ToString()
{
return $"{Code}: {Message}";
}
}
+ ///
+ /// Cant reach server error
+ ///
public class CantConnectError : Error
{
+ ///
+ /// ctor
+ ///
public CantConnectError() : base(1, "Can't connect to the server") { }
}
+ ///
+ /// No api credentials provided while trying to access private endpoint
+ ///
public class NoApiCredentialsError : Error
{
+ ///
+ /// ctor
+ ///
public NoApiCredentialsError() : base(2, "No credentials provided for private endpoint") { }
}
+ ///
+ /// Error returned by the server
+ ///
public class ServerError: Error
{
+ ///
+ /// ctor
+ ///
+ ///
public ServerError(string message) : base(3, "Server error: " + message) { }
+ ///
+ /// ctor
+ ///
+ ///
+ ///
public ServerError(int code, string message) : base(code, message)
{
}
}
+ ///
+ /// Web error returned by the server
+ ///
public class WebError : Error
{
+ ///
+ /// ctor
+ ///
+ ///
public WebError(string message) : base(4, "Web error: " + message) { }
}
+ ///
+ /// Error while deserializing data
+ ///
public class DeserializeError : Error
{
+ ///
+ /// ctor
+ ///
+ ///
public DeserializeError(string message) : base(5, "Error deserializing data: " + message) { }
}
+ ///
+ /// Unknown error
+ ///
public class UnknownError : Error
{
+ ///
+ /// ctor
+ ///
+ ///
public UnknownError(string message) : base(6, "Unknown error occured " + message) { }
}
+ ///
+ /// An invalid parameter has been provided
+ ///
public class ArgumentError : Error
{
+ ///
+ /// ctor
+ ///
+ ///
public ArgumentError(string message) : base(7, "Invalid parameter: " + message) { }
}
+ ///
+ /// Rate limit exceeded
+ ///
public class RateLimitError: Error
{
+ ///
+ /// ctor
+ ///
+ ///
public RateLimitError(string message) : base(8, "Rate limit exceeded: " + message) { }
}
}
diff --git a/CryptoExchange.Net/Objects/Options.cs b/CryptoExchange.Net/Objects/Options.cs
index aae859d..525f1c8 100644
--- a/CryptoExchange.Net/Objects/Options.cs
+++ b/CryptoExchange.Net/Objects/Options.cs
@@ -91,6 +91,11 @@ namespace CryptoExchange.Net.Objects
///
public TimeSpan RequestTimeout { get; set; } = TimeSpan.FromSeconds(30);
+ ///
+ /// Create a copy of the options
+ ///
+ ///
+ ///
public T Copy() where T:RestClientOptions, new()
{
var copy = new T
@@ -141,6 +146,11 @@ namespace CryptoExchange.Net.Objects
///
public int? SocketSubscriptionsCombineTarget { get; set; }
+ ///
+ /// Create a copy of the options
+ ///
+ ///
+ ///
public T Copy() where T : SocketClientOptions, new()
{
var copy = new T
diff --git a/CryptoExchange.Net/OrderBook/ISymbolOrderBookEntry.cs b/CryptoExchange.Net/OrderBook/ISymbolOrderBookEntry.cs
index 9354ad1..b5cb8ce 100644
--- a/CryptoExchange.Net/OrderBook/ISymbolOrderBookEntry.cs
+++ b/CryptoExchange.Net/OrderBook/ISymbolOrderBookEntry.cs
@@ -1,5 +1,8 @@
namespace CryptoExchange.Net.OrderBook
{
+ ///
+ /// Interface for order book entries
+ ///
public interface ISymbolOrderBookEntry
{
///
diff --git a/CryptoExchange.Net/OrderBook/OrderBookEntry.cs b/CryptoExchange.Net/OrderBook/OrderBookEntry.cs
index 606dccd..3faccf2 100644
--- a/CryptoExchange.Net/OrderBook/OrderBookEntry.cs
+++ b/CryptoExchange.Net/OrderBook/OrderBookEntry.cs
@@ -1,10 +1,24 @@
namespace CryptoExchange.Net.OrderBook
{
+ ///
+ /// Order book entry
+ ///
public class OrderBookEntry : ISymbolOrderBookEntry
{
+ ///
+ /// Quantity of the entry
+ ///
public decimal Quantity { get; set; }
+ ///
+ /// Price of the entry
+ ///
public decimal Price { get; set; }
+ ///
+ /// ctor
+ ///
+ ///
+ ///
public OrderBookEntry(decimal price, decimal quantity)
{
Quantity = quantity;
diff --git a/CryptoExchange.Net/OrderBook/ProcessBufferEntry.cs b/CryptoExchange.Net/OrderBook/ProcessBufferEntry.cs
index e6bf3aa..8a48794 100644
--- a/CryptoExchange.Net/OrderBook/ProcessBufferEntry.cs
+++ b/CryptoExchange.Net/OrderBook/ProcessBufferEntry.cs
@@ -2,12 +2,27 @@
namespace CryptoExchange.Net.OrderBook
{
+ ///
+ /// Buffer entry for order book
+ ///
public class ProcessBufferEntry
{
+ ///
+ /// The first sequence number of the entries
+ ///
public long FirstSequence { get; set; }
+ ///
+ /// The last sequence number of the entries
+ ///
public long LastSequence { get; set; }
+ ///
+ /// List of entries
+ ///
public List Entries { get; set; }
+ ///
+ /// ctor
+ ///
public ProcessBufferEntry()
{
Entries = new List();
diff --git a/CryptoExchange.Net/OrderBook/ProcessEntry.cs b/CryptoExchange.Net/OrderBook/ProcessEntry.cs
index 4ddb93f..a59bc5f 100644
--- a/CryptoExchange.Net/OrderBook/ProcessEntry.cs
+++ b/CryptoExchange.Net/OrderBook/ProcessEntry.cs
@@ -2,11 +2,25 @@
namespace CryptoExchange.Net.OrderBook
{
+ ///
+ /// Process entry for order book
+ ///
public class ProcessEntry
{
+ ///
+ /// The entry
+ ///
public ISymbolOrderBookEntry Entry { get; set; }
+ ///
+ /// The type
+ ///
public OrderBookEntryType Type { get; set; }
+ ///
+ /// ctor
+ ///
+ ///
+ ///
public ProcessEntry(OrderBookEntryType type, ISymbolOrderBookEntry entry)
{
Type = type;
diff --git a/CryptoExchange.Net/OrderBook/SymbolOrderBook.cs b/CryptoExchange.Net/OrderBook/SymbolOrderBook.cs
index 9418129..e6c2e29 100644
--- a/CryptoExchange.Net/OrderBook/SymbolOrderBook.cs
+++ b/CryptoExchange.Net/OrderBook/SymbolOrderBook.cs
@@ -15,14 +15,26 @@ namespace CryptoExchange.Net.OrderBook
///
public abstract class SymbolOrderBook: IDisposable
{
+ ///
+ /// The process buffer, used while syncing
+ ///
protected readonly List processBuffer;
private readonly object bookLock = new object();
+ ///
+ /// The ask list
+ ///
protected SortedList asks;
+ ///
+ /// The bid list
+ ///
protected SortedList bids;
private OrderBookStatus status;
private UpdateSubscription subscription;
private readonly bool sequencesAreConsecutive;
private readonly string id;
+ ///
+ /// The log
+ ///
protected Log log;
private bool bookSet;
@@ -116,6 +128,11 @@ namespace CryptoExchange.Net.OrderBook
}
}
+ ///
+ /// ctor
+ ///
+ ///
+ ///
protected SymbolOrderBook(string symbol, OrderBookOptions options)
{
id = options.OrderBookName;
@@ -198,12 +215,29 @@ namespace CryptoExchange.Net.OrderBook
await subscription.Close().ConfigureAwait(false);
}
+ ///
+ /// Start the order book
+ ///
+ ///
protected abstract Task> DoStart();
+ ///
+ /// Reset the order book
+ ///
protected virtual void DoReset() { }
+ ///
+ /// Resync the order book
+ ///
+ ///
protected abstract Task> DoResync();
+ ///
+ /// Set the initial data for the order book
+ ///
+ /// The last update sequence number
+ /// List of asks
+ /// List of bids
protected void SetInitialOrderBook(long orderBookSequenceNumber, IEnumerable askList, IEnumerable bidList)
{
lock (bookLock)
@@ -229,6 +263,12 @@ namespace CryptoExchange.Net.OrderBook
}
}
+ ///
+ /// Update the order book with entries
+ ///
+ /// First sequence number
+ /// Last sequence number
+ /// List of entries
protected void UpdateOrderBook(long firstSequenceNumber, long lastSequenceNumber, List entries)
{
lock (bookLock)
@@ -264,6 +304,9 @@ namespace CryptoExchange.Net.OrderBook
}
}
+ ///
+ /// Check and empty the process buffer; see what entries to update the book with
+ ///
protected void CheckProcessBuffer()
{
foreach (var bufferEntry in processBuffer.OrderBy(b => b.FirstSequence).ToList())
@@ -284,6 +327,11 @@ namespace CryptoExchange.Net.OrderBook
}
}
+ ///
+ /// Update order book with an entry
+ ///
+ /// Type of entry
+ /// The entry
protected virtual void ProcessUpdate(OrderBookEntryType type, ISymbolOrderBookEntry entry)
{
var listToChange = type == OrderBookEntryType.Ask ? asks : bids;
@@ -311,13 +359,24 @@ namespace CryptoExchange.Net.OrderBook
}
}
+ ///
+ /// Dispose the order book
+ ///
public abstract void Dispose();
+ ///
+ /// String representation of the top 3 entries
+ ///
+ ///
public override string ToString()
{
return ToString(3);
}
+ ///
+ /// String representation of the top x entries
+ ///
+ ///
public string ToString(int numberOfEntries)
{
var result = "";
diff --git a/CryptoExchange.Net/RateLimiter/RateLimitObject.cs b/CryptoExchange.Net/RateLimiter/RateLimitObject.cs
index 1618252..34ed08c 100644
--- a/CryptoExchange.Net/RateLimiter/RateLimitObject.cs
+++ b/CryptoExchange.Net/RateLimiter/RateLimitObject.cs
@@ -4,17 +4,33 @@ using System.Linq;
namespace CryptoExchange.Net.RateLimiter
{
+ ///
+ /// Rate limiting object
+ ///
public class RateLimitObject
{
+ ///
+ /// Lock
+ ///
public object LockObject { get; }
private List Times { get; }
+ ///
+ /// ctor
+ ///
public RateLimitObject()
{
LockObject = new object();
Times = new List();
}
+ ///
+ /// Get time to wait for a specific time
+ ///
+ ///
+ ///
+ ///
+ ///
public int GetWaitTime(DateTime time, int limit, TimeSpan perTimePeriod)
{
Times.RemoveAll(d => d < time - perTimePeriod);
@@ -23,6 +39,10 @@ namespace CryptoExchange.Net.RateLimiter
return 0;
}
+ ///
+ /// Add an executed request time
+ ///
+ ///
public void Add(DateTime time)
{
Times.Add(time);
diff --git a/CryptoExchange.Net/RateLimiter/RateLimiterAPIKey.cs b/CryptoExchange.Net/RateLimiter/RateLimiterAPIKey.cs
index b686345..ce8d9e0 100644
--- a/CryptoExchange.Net/RateLimiter/RateLimiterAPIKey.cs
+++ b/CryptoExchange.Net/RateLimiter/RateLimiterAPIKey.cs
@@ -29,7 +29,7 @@ namespace CryptoExchange.Net.RateLimiter
this.perTimePeriod = perTimePeriod;
}
-
+ ///
public CallResult LimitRequest(RestClient client, string url, RateLimitingBehaviour limitBehaviour)
{
if(client.authProvider?.Credentials == null)
diff --git a/CryptoExchange.Net/RateLimiter/RateLimiterPerEndpoint.cs b/CryptoExchange.Net/RateLimiter/RateLimiterPerEndpoint.cs
index e21ea69..fb62900 100644
--- a/CryptoExchange.Net/RateLimiter/RateLimiterPerEndpoint.cs
+++ b/CryptoExchange.Net/RateLimiter/RateLimiterPerEndpoint.cs
@@ -29,6 +29,7 @@ namespace CryptoExchange.Net.RateLimiter
this.perTimePeriod = perTimePeriod;
}
+ ///
public CallResult LimitRequest(RestClient client, string url, RateLimitingBehaviour limitingBehaviour)
{
int waitTime;
diff --git a/CryptoExchange.Net/RateLimiter/RateLimiterTotal.cs b/CryptoExchange.Net/RateLimiter/RateLimiterTotal.cs
index f28beb8..85919e6 100644
--- a/CryptoExchange.Net/RateLimiter/RateLimiterTotal.cs
+++ b/CryptoExchange.Net/RateLimiter/RateLimiterTotal.cs
@@ -30,6 +30,7 @@ namespace CryptoExchange.Net.RateLimiter
this.perTimePeriod = perTimePeriod;
}
+ ///
public CallResult LimitRequest(RestClient client, string url, RateLimitingBehaviour limitBehaviour)
{
var sw = Stopwatch.StartNew();
diff --git a/CryptoExchange.Net/Requests/Request.cs b/CryptoExchange.Net/Requests/Request.cs
index 8b64c4f..5566699 100644
--- a/CryptoExchange.Net/Requests/Request.cs
+++ b/CryptoExchange.Net/Requests/Request.cs
@@ -6,65 +6,84 @@ using CryptoExchange.Net.Interfaces;
namespace CryptoExchange.Net.Requests
{
+ ///
+ /// Request object
+ ///
public class Request : IRequest
{
private readonly WebRequest request;
+ ///
+ /// Create request object for webrequest
+ ///
+ ///
public Request(WebRequest request)
{
this.request = request;
}
+ ///
public WebHeaderCollection Headers
{
get => request.Headers;
set => request.Headers = value;
}
+
+ ///
public string ContentType
{
get => request.ContentType;
set => request.ContentType = value;
}
+ ///
public string Content { get; set; }
+ ///
public string Accept
{
get => ((HttpWebRequest)request).Accept;
set => ((HttpWebRequest)request).Accept = value;
}
+ ///
public long ContentLength
{
get => ((HttpWebRequest)request).ContentLength;
set => ((HttpWebRequest)request).ContentLength = value;
}
+ ///
public string Method
{
get => request.Method;
set => request.Method = value;
}
+ ///
public TimeSpan Timeout
{
get => TimeSpan.FromMilliseconds(request.Timeout);
set => request.Timeout = (int)Math.Round(value.TotalMilliseconds);
}
+ ///
public Uri Uri => request.RequestUri;
+ ///
public void SetProxy(string host, int port, string login, string password)
{
request.Proxy = new WebProxy(host, port);
if(!string.IsNullOrEmpty(login) && !string.IsNullOrEmpty(password)) request.Proxy.Credentials = new NetworkCredential(login, password);
}
+ ///
public async Task GetRequestStream()
{
return await request.GetRequestStreamAsync().ConfigureAwait(false);
}
+ ///
public async Task GetResponse()
{
return new Response((HttpWebResponse)await request.GetResponseAsync().ConfigureAwait(false));
diff --git a/CryptoExchange.Net/Requests/RequestFactory.cs b/CryptoExchange.Net/Requests/RequestFactory.cs
index 4469293..add3f81 100644
--- a/CryptoExchange.Net/Requests/RequestFactory.cs
+++ b/CryptoExchange.Net/Requests/RequestFactory.cs
@@ -3,8 +3,12 @@ using CryptoExchange.Net.Interfaces;
namespace CryptoExchange.Net.Requests
{
+ ///
+ /// WebRequest factory
+ ///
public class RequestFactory : IRequestFactory
{
+ ///
public IRequest Create(string uri)
{
return new Request(WebRequest.Create(uri));
diff --git a/CryptoExchange.Net/Requests/Response.cs b/CryptoExchange.Net/Requests/Response.cs
index 515414f..a5d88a1 100644
--- a/CryptoExchange.Net/Requests/Response.cs
+++ b/CryptoExchange.Net/Requests/Response.cs
@@ -1,33 +1,43 @@
using System;
using System.Collections.Generic;
using System.IO;
-using System.Linq;
using System.Net;
using CryptoExchange.Net.Interfaces;
namespace CryptoExchange.Net.Requests
{
+ ///
+ /// HttpWebResponse response object
+ ///
public class Response : IResponse
{
private readonly HttpWebResponse response;
+ ///
public HttpStatusCode StatusCode => response.StatusCode;
+ ///
+ /// Create response for http web response
+ ///
+ ///
public Response(HttpWebResponse response)
{
this.response = response;
}
+ ///
public Stream GetResponseStream()
{
return response.GetResponseStream();
}
+ ///
public IEnumerable> GetResponseHeaders()
{
return response.Headers.ToIEnumerable();
}
+ ///
public void Close()
{
response.Close();
diff --git a/CryptoExchange.Net/RestClient.cs b/CryptoExchange.Net/RestClient.cs
index 85511c7..844607f 100644
--- a/CryptoExchange.Net/RestClient.cs
+++ b/CryptoExchange.Net/RestClient.cs
@@ -19,6 +19,9 @@ using Newtonsoft.Json.Linq;
namespace CryptoExchange.Net
{
+ ///
+ /// Base rest client
+ ///
public abstract class RestClient: BaseClient, IRestClient
{
///
@@ -27,14 +30,37 @@ namespace CryptoExchange.Net
public IRequestFactory RequestFactory { get; set; } = new RequestFactory();
+ ///
+ /// Where to place post parameters
+ ///
protected PostParameters postParametersPosition = PostParameters.InBody;
+ ///
+ /// Request body content type
+ ///
protected RequestBodyFormat requestBodyFormat = RequestBodyFormat.Json;
+ ///
+ /// Timeout for requests
+ ///
protected TimeSpan RequestTimeout { get; private set; }
+ ///
+ /// Rate limiting behaviour
+ ///
public RateLimitingBehaviour RateLimitBehaviour { get; private set; }
+ ///
+ /// List of ratelimitters
+ ///
public IEnumerable RateLimiters { get; private set; }
+ ///
+ /// Total requests made
+ ///
public int TotalRequestsMade { get; private set; }
+ ///
+ /// ctor
+ ///
+ ///
+ ///
protected RestClient(RestClientOptions exchangeOptions, AuthenticationProvider authenticationProvider): base(exchangeOptions, authenticationProvider)
{
Configure(exchangeOptions);
diff --git a/CryptoExchange.Net/SocketClient.cs b/CryptoExchange.Net/SocketClient.cs
index c06ffd9..cc53894 100644
--- a/CryptoExchange.Net/SocketClient.cs
+++ b/CryptoExchange.Net/SocketClient.cs
@@ -13,6 +13,9 @@ using Newtonsoft.Json.Linq;
namespace CryptoExchange.Net
{
+ ///
+ /// Base for socket client implementations
+ ///
public abstract class SocketClient: BaseClient, ISocketClient
{
#region fields
@@ -25,6 +28,8 @@ namespace CryptoExchange.Net
/// List of socket connections currently connecting/connected
///
protected internal ConcurrentDictionary sockets = new ConcurrentDictionary();
+ ///
+ ///
protected internal readonly SemaphoreSlim semaphoreSlim = new SemaphoreSlim(1);
///
@@ -42,14 +47,43 @@ namespace CryptoExchange.Net
///
public int SocketCombineTarget { get; protected set; }
+ ///
+ /// Handler for byte data
+ ///
protected Func dataInterpreterBytes;
+ ///
+ /// Handler for string data
+ ///
protected Func dataInterpreterString;
+ ///
+ /// Generic handlers
+ ///
protected Dictionary> genericHandlers = new Dictionary>();
+ ///
+ /// Periodic task
+ ///
protected Task periodicTask;
+ ///
+ /// Periodic task event
+ ///
protected AutoResetEvent periodicEvent;
+ ///
+ /// Is disposing
+ ///
protected bool disposing;
+
+ ///
+ /// If true; data which is a response to a query will also be distributed to subscriptions
+ /// If false; data which is a response to a query won't get forwarded to subscriptions as well
+ ///
+ protected internal bool ContinueOnQueryResponse { get; protected set; }
#endregion
+ ///
+ /// Create a socket client
+ ///
+ /// Client options
+ /// Authentication provider
protected SocketClient(SocketClientOptions exchangeOptions, AuthenticationProvider authenticationProvider): base(exchangeOptions, authenticationProvider)
{
Configure(exchangeOptions);
@@ -174,6 +208,13 @@ namespace CryptoExchange.Net
return new CallResult(callResult?.Success ?? false, callResult == null ? new ServerError("No response on subscription request received"): callResult.Error);
}
+ ///
+ /// Query for data
+ ///
+ /// Exepected result type
+ /// The request to send
+ /// Whether the socket should be authenticated
+ ///
protected virtual Task> Query(object request, bool authenticated)
{
return Query(BaseAddress, request, authenticated);
@@ -183,6 +224,7 @@ namespace CryptoExchange.Net
/// Query for data
///
/// The expected result type
+ /// The url for the request
/// The request to send
/// Whether the socket should be authenticated
///
@@ -293,7 +335,7 @@ namespace CryptoExchange.Net
/// The socket connection
///
/// The request that a response is awaited for
- /// The message
+ /// The message
/// The interpretation (null if message wasn't a response to the request)
/// True if the message was a response to the subscription request
protected internal abstract bool HandleSubscriptionResponse(SocketConnection s, SocketSubscription subscription, object request, JToken message, out CallResult