mirror of
https://github.com/JKorf/CryptoExchange.Net
synced 2025-06-09 00:46:19 +00:00
Merge branch 'master' of https://github.com/EricGarnier/CryptoExchange.Net
This commit is contained in:
commit
9deae358ac
1
.github/FUNDING.yml
vendored
Normal file
1
.github/FUNDING.yml
vendored
Normal file
@ -0,0 +1 @@
|
||||
github: JKorf
|
20
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
20
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**To Reproduce**
|
||||
What endpoints and subscriptions are called.
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Debug logging**
|
||||
Add debug logging related to the issue. Enable Debug logging in the client options by settings LogVerbosity to Debug.
|
@ -113,7 +113,7 @@ namespace CryptoExchange.Net.UnitTests
|
||||
|
||||
|
||||
// assert
|
||||
Assert.IsTrue(client.BaseAddress == "http://test.address.com");
|
||||
Assert.IsTrue(client.BaseAddress == "http://test.address.com/");
|
||||
Assert.IsTrue(client.RateLimiters.Count() == 1);
|
||||
Assert.IsTrue(client.RateLimitBehaviour == RateLimitingBehaviour.Fail);
|
||||
Assert.IsTrue(client.RequestTimeout == TimeSpan.FromMinutes(1));
|
||||
|
@ -25,7 +25,7 @@ namespace CryptoExchange.Net.UnitTests
|
||||
|
||||
|
||||
//assert
|
||||
Assert.IsTrue(client.BaseAddress == "http://test.address.com");
|
||||
Assert.IsTrue(client.BaseAddress == "http://test.address.com/");
|
||||
Assert.IsTrue(client.ReconnectInterval.TotalSeconds == 6);
|
||||
}
|
||||
|
||||
|
@ -9,11 +9,11 @@ namespace CryptoExchange.Net.UnitTests
|
||||
{
|
||||
public class TestBaseClient: BaseClient
|
||||
{
|
||||
public TestBaseClient(): base(new RestClientOptions("http://testurl.url"), null)
|
||||
public TestBaseClient(): base("Test", new RestClientOptions("http://testurl.url"), null)
|
||||
{
|
||||
}
|
||||
|
||||
public TestBaseClient(RestClientOptions exchangeOptions) : base(exchangeOptions, exchangeOptions.ApiCredentials == null ? null : new TestAuthProvider(exchangeOptions.ApiCredentials))
|
||||
public TestBaseClient(RestClientOptions exchangeOptions) : base("Test", exchangeOptions, exchangeOptions.ApiCredentials == null ? null : new TestAuthProvider(exchangeOptions.ApiCredentials))
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -16,12 +16,12 @@ namespace CryptoExchange.Net.UnitTests.TestImplementations
|
||||
{
|
||||
public class TestRestClient: RestClient
|
||||
{
|
||||
public TestRestClient() : base(new RestClientOptions("http://testurl.url"), null)
|
||||
public TestRestClient() : base("Test", new RestClientOptions("http://testurl.url"), null)
|
||||
{
|
||||
RequestFactory = new Mock<IRequestFactory>().Object;
|
||||
}
|
||||
|
||||
public TestRestClient(RestClientOptions exchangeOptions) : base(exchangeOptions, exchangeOptions.ApiCredentials == null ? null : new TestAuthProvider(exchangeOptions.ApiCredentials))
|
||||
public TestRestClient(RestClientOptions exchangeOptions) : base("Test", exchangeOptions, exchangeOptions.ApiCredentials == null ? null : new TestAuthProvider(exchangeOptions.ApiCredentials))
|
||||
{
|
||||
RequestFactory = new Mock<IRequestFactory>().Object;
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ namespace CryptoExchange.Net.UnitTests.TestImplementations
|
||||
{
|
||||
}
|
||||
|
||||
public TestSocketClient(SocketClientOptions exchangeOptions) : base(exchangeOptions, exchangeOptions.ApiCredentials == null ? null : new TestAuthProvider(exchangeOptions.ApiCredentials))
|
||||
public TestSocketClient(SocketClientOptions exchangeOptions) : base("test", exchangeOptions, exchangeOptions.ApiCredentials == null ? null : new TestAuthProvider(exchangeOptions.ApiCredentials))
|
||||
{
|
||||
SocketFactory = new Mock<IWebsocketFactory>().Object;
|
||||
Mock.Get(SocketFactory).Setup(f => f.CreateWebsocket(It.IsAny<Log>(), It.IsAny<string>())).Returns(new TestSocket());
|
||||
|
@ -80,7 +80,7 @@ namespace CryptoExchange.Net.Authentication
|
||||
/// <param name="identifierSecret">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'.</param>
|
||||
public ApiCredentials(Stream inputStream, string? identifierKey = null, string? identifierSecret = null)
|
||||
{
|
||||
using var reader = new StreamReader(inputStream, Encoding.ASCII, false, 512, true);
|
||||
using var reader = new StreamReader(inputStream, Encoding.UTF8, false, 512, true);
|
||||
|
||||
var stringData = reader.ReadToEnd();
|
||||
var jsonData = stringData.ToJToken();
|
||||
@ -109,7 +109,7 @@ namespace CryptoExchange.Net.Authentication
|
||||
{
|
||||
if (data[key] == null)
|
||||
return null;
|
||||
return (string) data[key];
|
||||
return (string) data[key]!;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -25,6 +25,10 @@ namespace CryptoExchange.Net
|
||||
/// </summary>
|
||||
public string BaseAddress { get; }
|
||||
/// <summary>
|
||||
/// The name of the client
|
||||
/// </summary>
|
||||
public string ClientName { get; }
|
||||
/// <summary>
|
||||
/// The log object
|
||||
/// </summary>
|
||||
protected internal Log log;
|
||||
@ -64,15 +68,17 @@ namespace CryptoExchange.Net
|
||||
/// <summary>
|
||||
/// ctor
|
||||
/// </summary>
|
||||
/// <param name="clientName"></param>
|
||||
/// <param name="options"></param>
|
||||
/// <param name="authenticationProvider"></param>
|
||||
protected BaseClient(ClientOptions options, AuthenticationProvider? authenticationProvider)
|
||||
protected BaseClient(string clientName, ClientOptions options, AuthenticationProvider? authenticationProvider)
|
||||
{
|
||||
log = new Log();
|
||||
log = new Log(clientName);
|
||||
authProvider = authenticationProvider;
|
||||
log.UpdateWriters(options.LogWriters);
|
||||
log.Level = options.LogVerbosity;
|
||||
|
||||
ClientName = clientName;
|
||||
BaseAddress = options.BaseAddress;
|
||||
apiProxy = options.Proxy;
|
||||
|
||||
@ -101,7 +107,7 @@ namespace CryptoExchange.Net
|
||||
{
|
||||
var info = "Empty data object received";
|
||||
log.Write(LogVerbosity.Error, info);
|
||||
return new CallResult<JToken>(null, new DeserializeError(info));
|
||||
return new CallResult<JToken>(null, new DeserializeError(info, data));
|
||||
}
|
||||
|
||||
try
|
||||
@ -110,18 +116,18 @@ namespace CryptoExchange.Net
|
||||
}
|
||||
catch (JsonReaderException jre)
|
||||
{
|
||||
var info = $"Deserialize JsonReaderException: {jre.Message}, Path: {jre.Path}, LineNumber: {jre.LineNumber}, LinePosition: {jre.LinePosition}. Data: {data}";
|
||||
return new CallResult<JToken>(null, new DeserializeError(info));
|
||||
var info = $"Deserialize JsonReaderException: {jre.Message}, Path: {jre.Path}, LineNumber: {jre.LineNumber}, LinePosition: {jre.LinePosition}";
|
||||
return new CallResult<JToken>(null, new DeserializeError(info, data));
|
||||
}
|
||||
catch (JsonSerializationException jse)
|
||||
{
|
||||
var info = $"Deserialize JsonSerializationException: {jse.Message}. Data: {data}";
|
||||
return new CallResult<JToken>(null, new DeserializeError(info));
|
||||
var info = $"Deserialize JsonSerializationException: {jse.Message}";
|
||||
return new CallResult<JToken>(null, new DeserializeError(info, data));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var info = $"Deserialize Unknown Exception: {(ex.InnerException?.Message ?? ex.Message)}. Data: {data}";
|
||||
return new CallResult<JToken>(null, new DeserializeError(info));
|
||||
var info = $"Deserialize Unknown Exception: {(ex.InnerException?.Message ?? ex.Message)}";
|
||||
return new CallResult<JToken>(null, new DeserializeError(info, data));
|
||||
}
|
||||
}
|
||||
|
||||
@ -186,21 +192,21 @@ namespace CryptoExchange.Net
|
||||
}
|
||||
catch (JsonReaderException jre)
|
||||
{
|
||||
var info = $"{(requestId != null ? $"[{requestId}] " : "")}Deserialize JsonReaderException: {jre.Message}, Path: {jre.Path}, LineNumber: {jre.LineNumber}, LinePosition: {jre.LinePosition}. Received data: {obj}";
|
||||
var info = $"{(requestId != null ? $"[{requestId}] " : "")}Deserialize JsonReaderException: {jre.Message}, Path: {jre.Path}, LineNumber: {jre.LineNumber}, LinePosition: {jre.LinePosition}";
|
||||
log.Write(LogVerbosity.Error, info);
|
||||
return new CallResult<T>(default, new DeserializeError(info));
|
||||
return new CallResult<T>(default, new DeserializeError(info, obj));
|
||||
}
|
||||
catch (JsonSerializationException jse)
|
||||
{
|
||||
var info = $"{(requestId != null ? $"[{requestId}] " : "")}Deserialize JsonSerializationException: {jse.Message}. Received data: {obj}";
|
||||
var info = $"{(requestId != null ? $"[{requestId}] " : "")}Deserialize JsonSerializationException: {jse.Message}";
|
||||
log.Write(LogVerbosity.Error, info);
|
||||
return new CallResult<T>(default, new DeserializeError(info));
|
||||
return new CallResult<T>(default, new DeserializeError(info, obj));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var info = $"{(requestId != null ? $"[{requestId}] " : "")}Deserialize Unknown Exception: {(ex.InnerException?.Message ?? ex.Message)}. Received data: {obj}";
|
||||
var info = $"{(requestId != null ? $"[{requestId}] " : "")}Deserialize Unknown Exception: {(ex.InnerException?.Message ?? ex.Message)}";
|
||||
log.Write(LogVerbosity.Error, info);
|
||||
return new CallResult<T>(default, new DeserializeError(info));
|
||||
return new CallResult<T>(default, new DeserializeError(info, obj));
|
||||
}
|
||||
}
|
||||
|
||||
@ -211,7 +217,7 @@ namespace CryptoExchange.Net
|
||||
/// <param name="stream">The stream to deserialize</param>
|
||||
/// <param name="serializer">A specific serializer to use</param>
|
||||
/// <param name="requestId">Id of the request</param>
|
||||
/// <param name="elapsedMilliseconds">Milliseconds reponse time</param>
|
||||
/// <param name="elapsedMilliseconds">Milliseconds response time</param>
|
||||
/// <returns></returns>
|
||||
protected async Task<CallResult<T>> Deserialize<T>(Stream stream, JsonSerializer? serializer = null, int? requestId = null, long? elapsedMilliseconds = null)
|
||||
{
|
||||
@ -237,7 +243,7 @@ namespace CryptoExchange.Net
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
var data = await ReadStream(stream).ConfigureAwait(false);
|
||||
log.Write(LogVerbosity.Error, $"{(requestId != null ? $"[{requestId}] " : "")}Deserialize JsonReaderException: {jre.Message}, Path: {jre.Path}, LineNumber: {jre.LineNumber}, LinePosition: {jre.LinePosition}, data: {data}");
|
||||
return new CallResult<T>(default, new DeserializeError(data));
|
||||
return new CallResult<T>(default, new DeserializeError($"Deserialize JsonReaderException: {jre.Message}, Path: {jre.Path}, LineNumber: {jre.LineNumber}, LinePosition: {jre.LinePosition}", data));
|
||||
}
|
||||
catch (JsonSerializationException jse)
|
||||
{
|
||||
@ -245,7 +251,7 @@ namespace CryptoExchange.Net
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
var data = await ReadStream(stream).ConfigureAwait(false);
|
||||
log.Write(LogVerbosity.Error, $"{(requestId != null ? $"[{requestId}] " : "")}Deserialize JsonSerializationException: {jse.Message}, data: {data}");
|
||||
return new CallResult<T>(default, new DeserializeError(data));
|
||||
return new CallResult<T>(default, new DeserializeError($"Deserialize JsonSerializationException: {jse.Message}", data));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@ -253,7 +259,7 @@ namespace CryptoExchange.Net
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
var data = await ReadStream(stream).ConfigureAwait(false);
|
||||
log.Write(LogVerbosity.Error, $"{(requestId != null ? $"[{requestId}] " : "")}Deserialize Unknown Exception: {(ex.InnerException?.Message ?? ex.Message)}, data: {data}");
|
||||
return new CallResult<T>(default, new DeserializeError(data));
|
||||
return new CallResult<T>(default, new DeserializeError($"Deserialize Unknown Exception: {(ex.InnerException?.Message ?? ex.Message)}", data));
|
||||
}
|
||||
}
|
||||
|
||||
@ -291,7 +297,8 @@ namespace CryptoExchange.Net
|
||||
if (ignore != null)
|
||||
continue;
|
||||
|
||||
properties.Add(attr == null ? prop.Name : ((JsonPropertyAttribute)attr).PropertyName);
|
||||
var propertyName = ((JsonPropertyAttribute?) attr)?.PropertyName;
|
||||
properties.Add(propertyName ?? prop.Name);
|
||||
}
|
||||
foreach (var token in obj)
|
||||
{
|
||||
@ -313,12 +320,12 @@ namespace CryptoExchange.Net
|
||||
properties.Remove(d);
|
||||
|
||||
var propType = GetProperty(d, props)?.PropertyType;
|
||||
if (propType == null)
|
||||
if (propType == null || token.Value == null)
|
||||
continue;
|
||||
if (!IsSimple(propType) && propType != typeof(DateTime))
|
||||
{
|
||||
if (propType.IsArray && token.Value.HasValues && ((JArray)token.Value).Any() && ((JArray)token.Value)[0] is JObject)
|
||||
CheckObject(propType.GetElementType(), (JObject)token.Value[0], requestId);
|
||||
CheckObject(propType.GetElementType()!, (JObject)token.Value[0]!, requestId);
|
||||
else if (token.Value is JObject o)
|
||||
CheckObject(propType, o, requestId);
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ namespace CryptoExchange.Net.Converters
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override object? ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
|
||||
public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer)
|
||||
{
|
||||
if (objectType == typeof(JToken))
|
||||
return JToken.Load(reader);
|
||||
@ -115,8 +115,11 @@ namespace CryptoExchange.Net.Converters
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
|
||||
public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer)
|
||||
{
|
||||
if (value == null)
|
||||
return;
|
||||
|
||||
writer.WriteStartArray();
|
||||
var props = value.GetType().GetProperties();
|
||||
var ordered = props.OrderBy(p => p.GetCustomAttribute<ArrayPropertyAttribute>()?.Index);
|
||||
|
@ -28,9 +28,9 @@ namespace CryptoExchange.Net.Converters
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
|
||||
public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer)
|
||||
{
|
||||
var stringValue = GetValue((T) value);
|
||||
var stringValue = value == null? null: GetValue((T) value);
|
||||
if (quotes)
|
||||
writer.WriteValue(stringValue);
|
||||
else
|
||||
@ -38,7 +38,7 @@ namespace CryptoExchange.Net.Converters
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override object? ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
|
||||
public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer)
|
||||
{
|
||||
if (reader.Value == null)
|
||||
return null;
|
||||
|
@ -15,7 +15,7 @@ namespace CryptoExchange.Net.Converters
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override object? ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
|
||||
public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer)
|
||||
{
|
||||
if (reader.Value == null)
|
||||
return null;
|
||||
@ -25,9 +25,12 @@ namespace CryptoExchange.Net.Converters
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
|
||||
public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer)
|
||||
{
|
||||
writer.WriteValue((long)Math.Round(((DateTime)value - new DateTime(1970, 1, 1)).TotalMilliseconds));
|
||||
if(value == null)
|
||||
writer.WriteValue((DateTime?)null);
|
||||
else
|
||||
writer.WriteValue((long)Math.Round(((DateTime)value - new DateTime(1970, 1, 1)).TotalMilliseconds));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ namespace CryptoExchange.Net.Converters
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override object? ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
|
||||
public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer)
|
||||
{
|
||||
if (reader.Value == null)
|
||||
return null;
|
||||
@ -27,9 +27,9 @@ namespace CryptoExchange.Net.Converters
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
|
||||
public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer)
|
||||
{
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ namespace CryptoExchange.Net.Converters
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override object? ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
|
||||
public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer)
|
||||
{
|
||||
if (reader.Value == null)
|
||||
return null;
|
||||
@ -29,9 +29,12 @@ namespace CryptoExchange.Net.Converters
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
|
||||
public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer)
|
||||
{
|
||||
writer.WriteValue((long)Math.Round(((DateTime)value - new DateTime(1970, 1, 1)).TotalSeconds));
|
||||
if (value == null)
|
||||
writer.WriteValue((DateTime?)null);
|
||||
else
|
||||
writer.WriteValue((long)Math.Round(((DateTime)value! - new DateTime(1970, 1, 1)).TotalSeconds));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -9,20 +9,20 @@ namespace CryptoExchange.Net.Converters
|
||||
public class UTCDateTimeConverter: JsonConverter
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
|
||||
public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer)
|
||||
{
|
||||
writer.WriteValue(JsonConvert.SerializeObject(value));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override object? ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
|
||||
public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer)
|
||||
{
|
||||
if (reader.Value == null)
|
||||
return null;
|
||||
|
||||
DateTime value;
|
||||
if (reader.Value is string s)
|
||||
value = (DateTime)JsonConvert.DeserializeObject(s);
|
||||
value = (DateTime)JsonConvert.DeserializeObject(s)!;
|
||||
else
|
||||
value = (DateTime) reader.Value;
|
||||
|
||||
|
@ -6,12 +6,13 @@
|
||||
<PackageId>CryptoExchange.Net</PackageId>
|
||||
<Authors>JKorf</Authors>
|
||||
<Description>A base package for implementing cryptocurrency exchange API's</Description>
|
||||
<PackageVersion>3.0.14</PackageVersion>
|
||||
<PackageVersion>3.3.0</PackageVersion>
|
||||
<AssemblyVersion>3.3.0</AssemblyVersion>
|
||||
<PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
|
||||
<PackageProjectUrl>https://github.com/JKorf/CryptoExchange.Net</PackageProjectUrl>
|
||||
<NeutralLanguage>en</NeutralLanguage>
|
||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||
<PackageReleaseNotes>3.0.14 - Updated exception message logging</PackageReleaseNotes>
|
||||
<PackageReleaseNotes>3.3.0 - Added client name, Added common interfaces, Fixed api key plain text storing in RateLimitterApiKey</PackageReleaseNotes>
|
||||
<Nullable>enable</Nullable>
|
||||
<LangVersion>8.0</LangVersion>
|
||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||
@ -20,7 +21,7 @@
|
||||
<DocumentationFile>CryptoExchange.Net.xml</DocumentationFile>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.1" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
||||
<PackageReference Include="WebSocket4Net" Version="0.15.2" />
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -209,6 +209,11 @@
|
||||
The address of the client
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:CryptoExchange.Net.BaseClient.ClientName">
|
||||
<summary>
|
||||
The name of the client
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:CryptoExchange.Net.BaseClient.log">
|
||||
<summary>
|
||||
The log object
|
||||
@ -244,10 +249,11 @@
|
||||
Last is used
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:CryptoExchange.Net.BaseClient.#ctor(CryptoExchange.Net.Objects.ClientOptions,CryptoExchange.Net.Authentication.AuthenticationProvider)">
|
||||
<member name="M:CryptoExchange.Net.BaseClient.#ctor(System.String,CryptoExchange.Net.Objects.ClientOptions,CryptoExchange.Net.Authentication.AuthenticationProvider)">
|
||||
<summary>
|
||||
ctor
|
||||
</summary>
|
||||
<param name="clientName"></param>
|
||||
<param name="options"></param>
|
||||
<param name="authenticationProvider"></param>
|
||||
</member>
|
||||
@ -294,7 +300,7 @@
|
||||
<param name="stream">The stream to deserialize</param>
|
||||
<param name="serializer">A specific serializer to use</param>
|
||||
<param name="requestId">Id of the request</param>
|
||||
<param name="elapsedMilliseconds">Milliseconds reponse time</param>
|
||||
<param name="elapsedMilliseconds">Milliseconds response time</param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:CryptoExchange.Net.BaseClient.NextId">
|
||||
@ -435,6 +441,318 @@
|
||||
<member name="M:CryptoExchange.Net.Converters.UTCDateTimeConverter.CanConvert(System.Type)">
|
||||
<inheritdoc />
|
||||
</member>
|
||||
<member name="T:CryptoExchange.Net.ExchangeInterfaces.ICommonTrade">
|
||||
<summary>
|
||||
Common trade
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:CryptoExchange.Net.ExchangeInterfaces.ICommonTrade.CommonId">
|
||||
<summary>
|
||||
Id of the trade
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:CryptoExchange.Net.ExchangeInterfaces.ICommonTrade.CommonPrice">
|
||||
<summary>
|
||||
Price of the trade
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:CryptoExchange.Net.ExchangeInterfaces.ICommonTrade.CommonQuantity">
|
||||
<summary>
|
||||
Quantity of the trade
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:CryptoExchange.Net.ExchangeInterfaces.ICommonTrade.CommonFee">
|
||||
<summary>
|
||||
Fee paid for the trade
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:CryptoExchange.Net.ExchangeInterfaces.ICommonTrade.CommonFeeAsset">
|
||||
<summary>
|
||||
The asset fee was paid in
|
||||
</summary>
|
||||
</member>
|
||||
<member name="T:CryptoExchange.Net.ExchangeInterfaces.IExchangeClient">
|
||||
<summary>
|
||||
Shared interface for exchange wrappers based on the CryptoExchange.Net package
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:CryptoExchange.Net.ExchangeInterfaces.IExchangeClient.GetSymbolName(System.String,System.String)">
|
||||
<summary>
|
||||
Get the symbol name based on a base and quote asset
|
||||
</summary>
|
||||
<param name="baseAsset"></param>
|
||||
<param name="quoteAsset"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:CryptoExchange.Net.ExchangeInterfaces.IExchangeClient.GetSymbolsAsync">
|
||||
<summary>
|
||||
Get a list of symbols for the exchange
|
||||
</summary>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:CryptoExchange.Net.ExchangeInterfaces.IExchangeClient.GetTickersAsync">
|
||||
<summary>
|
||||
Get a list of tickers for the exchange
|
||||
</summary>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:CryptoExchange.Net.ExchangeInterfaces.IExchangeClient.GetKlinesAsync(System.String,System.TimeSpan)">
|
||||
<summary>
|
||||
Get a list of candles for a given symbol on the exchange
|
||||
</summary>
|
||||
<param name="symbol">The symbol to retrieve the candles for</param>
|
||||
<param name="timespan">The timespan to retrieve the candles for. The supported value are dependent on the exchange</param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:CryptoExchange.Net.ExchangeInterfaces.IExchangeClient.GetOrderBookAsync(System.String)">
|
||||
<summary>
|
||||
Get the order book for a symbol
|
||||
</summary>
|
||||
<param name="symbol">The symbol to get the book for</param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:CryptoExchange.Net.ExchangeInterfaces.IExchangeClient.GetRecentTradesAsync(System.String)">
|
||||
<summary>
|
||||
The recent trades for a symbol
|
||||
</summary>
|
||||
<param name="symbol">The symbol to get the trades for</param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:CryptoExchange.Net.ExchangeInterfaces.IExchangeClient.PlaceOrderAsync(System.String,CryptoExchange.Net.ExchangeInterfaces.IExchangeClient.OrderSide,CryptoExchange.Net.ExchangeInterfaces.IExchangeClient.OrderType,System.Decimal,System.Nullable{System.Decimal},System.String)">
|
||||
<summary>
|
||||
Place an order
|
||||
</summary>
|
||||
<param name="symbol">The symbol the order is for</param>
|
||||
<param name="side">The side of the order</param>
|
||||
<param name="type">The type of the order</param>
|
||||
<param name="quantity">The quantity of the order</param>
|
||||
<param name="price">The price of the order, only for limit orders</param>
|
||||
<param name="accountId">[Optional] The account id to place the order on, required for some exchanges, ignored otherwise</param>
|
||||
<returns>The id of the resulting order</returns>
|
||||
</member>
|
||||
<member name="M:CryptoExchange.Net.ExchangeInterfaces.IExchangeClient.GetOrderAsync(System.String,System.String)">
|
||||
<summary>
|
||||
Get an order by id
|
||||
</summary>
|
||||
<param name="orderId">The id</param>
|
||||
<param name="symbol">[Optional] The symbol the order is on, required for some exchanges, ignored otherwise</param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:CryptoExchange.Net.ExchangeInterfaces.IExchangeClient.GetTradesAsync(System.String,System.String)">
|
||||
<summary>
|
||||
Get trades for an order by id
|
||||
</summary>
|
||||
<param name="orderId">The id</param>
|
||||
<param name="symbol">[Optional] The symbol the order is on, required for some exchanges, ignored otherwise</param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:CryptoExchange.Net.ExchangeInterfaces.IExchangeClient.GetOpenOrdersAsync(System.String)">
|
||||
<summary>
|
||||
Get a list of open orders
|
||||
</summary>
|
||||
<param name="symbol">[Optional] The symbol to get open orders for, required for some exchanges, ignored otherwise</param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:CryptoExchange.Net.ExchangeInterfaces.IExchangeClient.GetClosedOrdersAsync(System.String)">
|
||||
<summary>
|
||||
Get a list of closed orders
|
||||
</summary>
|
||||
<param name="symbol">[Optional] The symbol to get closed orders for, required for some exchanges, ignored otherwise</param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:CryptoExchange.Net.ExchangeInterfaces.IExchangeClient.CancelOrderAsync(System.String,System.String)">
|
||||
<summary>
|
||||
Cancel an order by id
|
||||
</summary>
|
||||
<param name="orderId">The id</param>
|
||||
<param name="symbol">[Optional] The symbol the order is on, required for some exchanges, ignored otherwise</param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="T:CryptoExchange.Net.ExchangeInterfaces.IExchangeClient.OrderType">
|
||||
<summary>
|
||||
Common order id
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:CryptoExchange.Net.ExchangeInterfaces.IExchangeClient.OrderType.Limit">
|
||||
<summary>
|
||||
Limit type
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:CryptoExchange.Net.ExchangeInterfaces.IExchangeClient.OrderType.Market">
|
||||
<summary>
|
||||
Market type
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:CryptoExchange.Net.ExchangeInterfaces.IExchangeClient.OrderType.Other">
|
||||
<summary>
|
||||
Other order type
|
||||
</summary>
|
||||
</member>
|
||||
<member name="T:CryptoExchange.Net.ExchangeInterfaces.IExchangeClient.OrderSide">
|
||||
<summary>
|
||||
Common order side
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:CryptoExchange.Net.ExchangeInterfaces.IExchangeClient.OrderSide.Buy">
|
||||
<summary>
|
||||
Buy order
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:CryptoExchange.Net.ExchangeInterfaces.IExchangeClient.OrderSide.Sell">
|
||||
<summary>
|
||||
Sell order
|
||||
</summary>
|
||||
</member>
|
||||
<member name="T:CryptoExchange.Net.ExchangeInterfaces.ICommonKline">
|
||||
<summary>
|
||||
Common kline
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:CryptoExchange.Net.ExchangeInterfaces.ICommonKline.CommonHigh">
|
||||
<summary>
|
||||
High price for this kline
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:CryptoExchange.Net.ExchangeInterfaces.ICommonKline.CommonLow">
|
||||
<summary>
|
||||
Low price for this kline
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:CryptoExchange.Net.ExchangeInterfaces.ICommonKline.CommonOpen">
|
||||
<summary>
|
||||
Open price for this kline
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:CryptoExchange.Net.ExchangeInterfaces.ICommonKline.CommonClose">
|
||||
<summary>
|
||||
Close price for this kline
|
||||
</summary>
|
||||
</member>
|
||||
<member name="T:CryptoExchange.Net.ExchangeInterfaces.ICommonOrder">
|
||||
<summary>
|
||||
Common order
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:CryptoExchange.Net.ExchangeInterfaces.ICommonOrder.CommonSymbol">
|
||||
<summary>
|
||||
Symbol of the order
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:CryptoExchange.Net.ExchangeInterfaces.ICommonOrder.CommonPrice">
|
||||
<summary>
|
||||
Price of the order
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:CryptoExchange.Net.ExchangeInterfaces.ICommonOrder.CommonQuantity">
|
||||
<summary>
|
||||
Quantity of the order
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:CryptoExchange.Net.ExchangeInterfaces.ICommonOrder.CommonStatus">
|
||||
<summary>
|
||||
Status of the order
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:CryptoExchange.Net.ExchangeInterfaces.ICommonOrder.IsActive">
|
||||
<summary>
|
||||
Whether the order is active
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:CryptoExchange.Net.ExchangeInterfaces.ICommonOrder.CommonSide">
|
||||
<summary>
|
||||
Side of the order
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:CryptoExchange.Net.ExchangeInterfaces.ICommonOrder.CommonType">
|
||||
<summary>
|
||||
Type of the order
|
||||
</summary>
|
||||
</member>
|
||||
<member name="T:CryptoExchange.Net.ExchangeInterfaces.ICommonOrderBook">
|
||||
<summary>
|
||||
Common order book
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:CryptoExchange.Net.ExchangeInterfaces.ICommonOrderBook.CommonBids">
|
||||
<summary>
|
||||
Bids
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:CryptoExchange.Net.ExchangeInterfaces.ICommonOrderBook.CommonAsks">
|
||||
<summary>
|
||||
Asks
|
||||
</summary>
|
||||
</member>
|
||||
<member name="T:CryptoExchange.Net.ExchangeInterfaces.ICommonOrderId">
|
||||
<summary>
|
||||
Common order id
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:CryptoExchange.Net.ExchangeInterfaces.ICommonOrderId.CommonId">
|
||||
<summary>
|
||||
Id of the order
|
||||
</summary>
|
||||
</member>
|
||||
<member name="T:CryptoExchange.Net.ExchangeInterfaces.ICommonRecentTrade">
|
||||
<summary>
|
||||
Recent trade
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:CryptoExchange.Net.ExchangeInterfaces.ICommonRecentTrade.CommonPrice">
|
||||
<summary>
|
||||
Price of the trade
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:CryptoExchange.Net.ExchangeInterfaces.ICommonRecentTrade.CommonQuantity">
|
||||
<summary>
|
||||
Quantity of the trade
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:CryptoExchange.Net.ExchangeInterfaces.ICommonRecentTrade.CommonTradeTime">
|
||||
<summary>
|
||||
Trade time
|
||||
</summary>
|
||||
</member>
|
||||
<member name="T:CryptoExchange.Net.ExchangeInterfaces.ICommonSymbol">
|
||||
<summary>
|
||||
Common symbol
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:CryptoExchange.Net.ExchangeInterfaces.ICommonSymbol.CommonName">
|
||||
<summary>
|
||||
Symbol name
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:CryptoExchange.Net.ExchangeInterfaces.ICommonSymbol.CommonMinimumTradeSize">
|
||||
<summary>
|
||||
Minimum trade size
|
||||
</summary>
|
||||
</member>
|
||||
<member name="T:CryptoExchange.Net.ExchangeInterfaces.ICommonTicker">
|
||||
<summary>
|
||||
Common ticker
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:CryptoExchange.Net.ExchangeInterfaces.ICommonTicker.CommonSymbol">
|
||||
<summary>
|
||||
Symbol name
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:CryptoExchange.Net.ExchangeInterfaces.ICommonTicker.CommonHigh">
|
||||
<summary>
|
||||
High price
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:CryptoExchange.Net.ExchangeInterfaces.ICommonTicker.CommonLow">
|
||||
<summary>
|
||||
Low price
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:CryptoExchange.Net.ExchangeInterfaces.ICommonTicker.CommonVolume">
|
||||
<summary>
|
||||
Volume
|
||||
</summary>
|
||||
</member>
|
||||
<member name="T:CryptoExchange.Net.ExtensionMethods">
|
||||
<summary>
|
||||
Helper methods
|
||||
@ -712,6 +1030,11 @@
|
||||
The base address of the API
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:CryptoExchange.Net.Interfaces.IRestClient.ClientName">
|
||||
<summary>
|
||||
Client name
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:CryptoExchange.Net.Interfaces.IRestClient.AddRateLimiter(CryptoExchange.Net.Interfaces.IRateLimiter)">
|
||||
<summary>
|
||||
Adds a rate limiter to the client. There are 2 choices, the <see cref="T:CryptoExchange.Net.RateLimiter.RateLimiterTotal"/> and the <see cref="T:CryptoExchange.Net.RateLimiter.RateLimiterPerEndpoint"/>.
|
||||
@ -1065,7 +1388,12 @@
|
||||
The verbosity of the logging
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:CryptoExchange.Net.Logging.Log.#ctor">
|
||||
<member name="P:CryptoExchange.Net.Logging.Log.ClientName">
|
||||
<summary>
|
||||
Client name
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:CryptoExchange.Net.Logging.Log.#ctor(System.String)">
|
||||
<summary>
|
||||
ctor
|
||||
</summary>
|
||||
@ -1199,6 +1527,40 @@
|
||||
<param name="y"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="T:CryptoExchange.Net.Objects.CallResult">
|
||||
<summary>
|
||||
The result of an operation
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:CryptoExchange.Net.Objects.CallResult.Error">
|
||||
<summary>
|
||||
An error if the call didn't succeed
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:CryptoExchange.Net.Objects.CallResult.Success">
|
||||
<summary>
|
||||
Whether the call was successful
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:CryptoExchange.Net.Objects.CallResult.#ctor(CryptoExchange.Net.Objects.Error)">
|
||||
<summary>
|
||||
ctor
|
||||
</summary>
|
||||
<param name="error"></param>
|
||||
</member>
|
||||
<member name="M:CryptoExchange.Net.Objects.CallResult.op_Implicit(CryptoExchange.Net.Objects.CallResult)~System.Boolean">
|
||||
<summary>
|
||||
Overwrite bool check so we can use if(callResult) instead of if(callResult.Success)
|
||||
</summary>
|
||||
<param name="obj"></param>
|
||||
</member>
|
||||
<member name="M:CryptoExchange.Net.Objects.CallResult.CreateErrorResult(CryptoExchange.Net.Objects.Error)">
|
||||
<summary>
|
||||
Create an error result
|
||||
</summary>
|
||||
<param name="error"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="T:CryptoExchange.Net.Objects.CallResult`1">
|
||||
<summary>
|
||||
The result of an operation
|
||||
@ -1210,16 +1572,6 @@
|
||||
The data returned by the call
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:CryptoExchange.Net.Objects.CallResult`1.Error">
|
||||
<summary>
|
||||
An error if the call didn't succeed
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:CryptoExchange.Net.Objects.CallResult`1.Success">
|
||||
<summary>
|
||||
Whether the call was successful
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:CryptoExchange.Net.Objects.CallResult`1.#ctor(`0,CryptoExchange.Net.Objects.Error)">
|
||||
<summary>
|
||||
ctor
|
||||
@ -1233,6 +1585,60 @@
|
||||
</summary>
|
||||
<param name="obj"></param>
|
||||
</member>
|
||||
<member name="M:CryptoExchange.Net.Objects.CallResult`1.GetResultOrError(`0@,CryptoExchange.Net.Objects.Error@)">
|
||||
<summary>
|
||||
Whether the call was successful or not. Useful for nullability checking.
|
||||
</summary>
|
||||
<param name="data">The data returned by the call.</param>
|
||||
<param name="error"><see cref="T:CryptoExchange.Net.Objects.Error"/> on failure.</param>
|
||||
<returns><c>true</c> when <see cref="T:CryptoExchange.Net.Objects.CallResult`1"/> succeeded, <c>false</c> otherwise.</returns>
|
||||
</member>
|
||||
<member name="M:CryptoExchange.Net.Objects.CallResult`1.CreateErrorResult(CryptoExchange.Net.Objects.Error)">
|
||||
<summary>
|
||||
Create an error result
|
||||
</summary>
|
||||
<param name="error"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="T:CryptoExchange.Net.Objects.WebCallResult">
|
||||
<summary>
|
||||
The result of a request
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:CryptoExchange.Net.Objects.WebCallResult.ResponseStatusCode">
|
||||
<summary>
|
||||
The status code of the response. Note that a OK status does not always indicate success, check the Success parameter for this.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:CryptoExchange.Net.Objects.WebCallResult.ResponseHeaders">
|
||||
<summary>
|
||||
The response headers
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:CryptoExchange.Net.Objects.WebCallResult.#ctor(System.Nullable{System.Net.HttpStatusCode},System.Collections.Generic.IEnumerable{System.Collections.Generic.KeyValuePair{System.String,System.Collections.Generic.IEnumerable{System.String}}},CryptoExchange.Net.Objects.Error)">
|
||||
<summary>
|
||||
ctor
|
||||
</summary>
|
||||
<param name="code"></param>
|
||||
<param name="responseHeaders"></param>
|
||||
<param name="error"></param>
|
||||
</member>
|
||||
<member name="M:CryptoExchange.Net.Objects.WebCallResult.CreateErrorResult(System.Nullable{System.Net.HttpStatusCode},System.Collections.Generic.IEnumerable{System.Collections.Generic.KeyValuePair{System.String,System.Collections.Generic.IEnumerable{System.String}}},CryptoExchange.Net.Objects.Error)">
|
||||
<summary>
|
||||
Create an error result
|
||||
</summary>
|
||||
<param name="code"></param>
|
||||
<param name="responseHeaders"></param>
|
||||
<param name="error"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:CryptoExchange.Net.Objects.WebCallResult.CreateErrorResult(CryptoExchange.Net.Objects.WebCallResult)">
|
||||
<summary>
|
||||
Create an error result
|
||||
</summary>
|
||||
<param name="result"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="T:CryptoExchange.Net.Objects.WebCallResult`1">
|
||||
<summary>
|
||||
The result of a request
|
||||
@ -1258,11 +1664,18 @@
|
||||
<param name="data"></param>
|
||||
<param name="error"></param>
|
||||
</member>
|
||||
<member name="M:CryptoExchange.Net.Objects.WebCallResult`1.CreateErrorResult(CryptoExchange.Net.Objects.Error)">
|
||||
<member name="M:CryptoExchange.Net.Objects.WebCallResult`1.#ctor(CryptoExchange.Net.Objects.WebCallResult{`0})">
|
||||
<summary>
|
||||
Create an error result
|
||||
Create new based on existing
|
||||
</summary>
|
||||
<param name="error"></param>
|
||||
<param name="callResult"></param>
|
||||
</member>
|
||||
<member name="M:CryptoExchange.Net.Objects.WebCallResult`1.CreateFrom``1(CryptoExchange.Net.Objects.WebCallResult{``0})">
|
||||
<summary>
|
||||
Create from a call result
|
||||
</summary>
|
||||
<typeparam name="Y"></typeparam>
|
||||
<param name="source"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:CryptoExchange.Net.Objects.WebCallResult`1.CreateErrorResult(System.Nullable{System.Net.HttpStatusCode},System.Collections.Generic.IEnumerable{System.Collections.Generic.KeyValuePair{System.String,System.Collections.Generic.IEnumerable{System.String}}},CryptoExchange.Net.Objects.Error)">
|
||||
@ -1401,20 +1814,20 @@
|
||||
</member>
|
||||
<member name="P:CryptoExchange.Net.Objects.Error.Code">
|
||||
<summary>
|
||||
The error code
|
||||
The error code from the server
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:CryptoExchange.Net.Objects.Error.Message">
|
||||
<summary>
|
||||
The message for the error that occured
|
||||
The message for the error that occurred
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:CryptoExchange.Net.Objects.Error.Data">
|
||||
<summary>
|
||||
Optional data for the error
|
||||
The data which caused the error
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:CryptoExchange.Net.Objects.Error.#ctor(System.Int32,System.String,System.Object)">
|
||||
<member name="M:CryptoExchange.Net.Objects.Error.#ctor(System.Nullable{System.Int32},System.String,System.Object)">
|
||||
<summary>
|
||||
ctor
|
||||
</summary>
|
||||
@ -1473,10 +1886,19 @@
|
||||
Web error returned by the server
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:CryptoExchange.Net.Objects.WebError.#ctor(System.Object)">
|
||||
<member name="M:CryptoExchange.Net.Objects.WebError.#ctor(System.String,System.Object)">
|
||||
<summary>
|
||||
ctor
|
||||
</summary>
|
||||
<param name="message"></param>
|
||||
<param name="data"></param>
|
||||
</member>
|
||||
<member name="M:CryptoExchange.Net.Objects.WebError.#ctor(System.Int32,System.String,System.Object)">
|
||||
<summary>
|
||||
ctor
|
||||
</summary>
|
||||
<param name="code"></param>
|
||||
<param name="message"></param>
|
||||
<param name="data"></param>
|
||||
</member>
|
||||
<member name="T:CryptoExchange.Net.Objects.DeserializeError">
|
||||
@ -1484,21 +1906,23 @@
|
||||
Error while deserializing data
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:CryptoExchange.Net.Objects.DeserializeError.#ctor(System.Object)">
|
||||
<member name="M:CryptoExchange.Net.Objects.DeserializeError.#ctor(System.String,System.Object)">
|
||||
<summary>
|
||||
ctor
|
||||
</summary>
|
||||
<param name="data">Deserializing data</param>
|
||||
<param name="message">The error message</param>
|
||||
<param name="data">The data which caused the error</param>
|
||||
</member>
|
||||
<member name="T:CryptoExchange.Net.Objects.UnknownError">
|
||||
<summary>
|
||||
Unknown error
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:CryptoExchange.Net.Objects.UnknownError.#ctor(System.Object)">
|
||||
<member name="M:CryptoExchange.Net.Objects.UnknownError.#ctor(System.String,System.Object)">
|
||||
<summary>
|
||||
ctor
|
||||
</summary>
|
||||
<param name="message">Error message</param>
|
||||
<param name="data">Error data</param>
|
||||
</member>
|
||||
<member name="T:CryptoExchange.Net.Objects.ArgumentError">
|
||||
@ -1992,6 +2416,11 @@
|
||||
<member name="M:CryptoExchange.Net.RateLimiter.RateLimiterAPIKey.LimitRequest(CryptoExchange.Net.RestClient,System.String,CryptoExchange.Net.Objects.RateLimitingBehaviour)">
|
||||
<inheritdoc />
|
||||
</member>
|
||||
<member name="M:CryptoExchange.Net.RateLimiter.RateLimiterAPIKey.Dispose">
|
||||
<summary>
|
||||
Dispose
|
||||
</summary>
|
||||
</member>
|
||||
<member name="T:CryptoExchange.Net.RateLimiter.RateLimiterPerEndpoint">
|
||||
<summary>
|
||||
Limits the amount of requests per time period to a certain limit, counts the request per endpoint.
|
||||
@ -2184,10 +2613,11 @@
|
||||
Total requests made
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:CryptoExchange.Net.RestClient.#ctor(CryptoExchange.Net.Objects.RestClientOptions,CryptoExchange.Net.Authentication.AuthenticationProvider)">
|
||||
<member name="M:CryptoExchange.Net.RestClient.#ctor(System.String,CryptoExchange.Net.Objects.RestClientOptions,CryptoExchange.Net.Authentication.AuthenticationProvider)">
|
||||
<summary>
|
||||
ctor
|
||||
</summary>
|
||||
<param name="clientName"></param>
|
||||
<param name="exchangeOptions"></param>
|
||||
<param name="authenticationProvider"></param>
|
||||
</member>
|
||||
@ -2348,10 +2778,11 @@
|
||||
If false; data which is a response to a query won't get forwarded to subscriptions as well
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:CryptoExchange.Net.SocketClient.#ctor(CryptoExchange.Net.Objects.SocketClientOptions,CryptoExchange.Net.Authentication.AuthenticationProvider)">
|
||||
<member name="M:CryptoExchange.Net.SocketClient.#ctor(System.String,CryptoExchange.Net.Objects.SocketClientOptions,CryptoExchange.Net.Authentication.AuthenticationProvider)">
|
||||
<summary>
|
||||
Create a socket client
|
||||
</summary>
|
||||
<param name="clientName">Client name</param>
|
||||
<param name="exchangeOptions">Client options</param>
|
||||
<param name="authenticationProvider">Authentication provider</param>
|
||||
</member>
|
||||
|
33
CryptoExchange.Net/ExchangeInterfaces/ICommonTrade.cs
Normal file
33
CryptoExchange.Net/ExchangeInterfaces/ICommonTrade.cs
Normal file
@ -0,0 +1,33 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace CryptoExchange.Net.ExchangeInterfaces
|
||||
{
|
||||
/// <summary>
|
||||
/// Common trade
|
||||
/// </summary>
|
||||
public interface ICommonTrade
|
||||
{
|
||||
/// <summary>
|
||||
/// Id of the trade
|
||||
/// </summary>
|
||||
public string CommonId { get; }
|
||||
/// <summary>
|
||||
/// Price of the trade
|
||||
/// </summary>
|
||||
public decimal CommonPrice { get; }
|
||||
/// <summary>
|
||||
/// Quantity of the trade
|
||||
/// </summary>
|
||||
public decimal CommonQuantity { get; }
|
||||
/// <summary>
|
||||
/// Fee paid for the trade
|
||||
/// </summary>
|
||||
public decimal CommonFee { get; }
|
||||
/// <summary>
|
||||
/// The asset fee was paid in
|
||||
/// </summary>
|
||||
public string? CommonFeeAsset { get; }
|
||||
}
|
||||
}
|
133
CryptoExchange.Net/ExchangeInterfaces/IExchangeClient.cs
Normal file
133
CryptoExchange.Net/ExchangeInterfaces/IExchangeClient.cs
Normal file
@ -0,0 +1,133 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using CryptoExchange.Net.Objects;
|
||||
|
||||
namespace CryptoExchange.Net.ExchangeInterfaces
|
||||
{
|
||||
/// <summary>
|
||||
/// Shared interface for exchange wrappers based on the CryptoExchange.Net package
|
||||
/// </summary>
|
||||
public interface IExchangeClient
|
||||
{
|
||||
/// <summary>
|
||||
/// Get the symbol name based on a base and quote asset
|
||||
/// </summary>
|
||||
/// <param name="baseAsset"></param>
|
||||
/// <param name="quoteAsset"></param>
|
||||
/// <returns></returns>
|
||||
string GetSymbolName(string baseAsset, string quoteAsset);
|
||||
|
||||
/// <summary>
|
||||
/// Get a list of symbols for the exchange
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
Task<WebCallResult<IEnumerable<ICommonSymbol>>> GetSymbolsAsync();
|
||||
|
||||
/// <summary>
|
||||
/// Get a list of tickers for the exchange
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
Task<WebCallResult<IEnumerable<ICommonTicker>>> GetTickersAsync();
|
||||
|
||||
/// <summary>
|
||||
/// Get a list of candles for a given symbol on the exchange
|
||||
/// </summary>
|
||||
/// <param name="symbol">The symbol to retrieve the candles for</param>
|
||||
/// <param name="timespan">The timespan to retrieve the candles for. The supported value are dependent on the exchange</param>
|
||||
/// <returns></returns>
|
||||
Task<WebCallResult<IEnumerable<ICommonKline>>> GetKlinesAsync(string symbol, TimeSpan timespan);
|
||||
/// <summary>
|
||||
/// Get the order book for a symbol
|
||||
/// </summary>
|
||||
/// <param name="symbol">The symbol to get the book for</param>
|
||||
/// <returns></returns>
|
||||
Task<WebCallResult<ICommonOrderBook>> GetOrderBookAsync(string symbol);
|
||||
/// <summary>
|
||||
/// The recent trades for a symbol
|
||||
/// </summary>
|
||||
/// <param name="symbol">The symbol to get the trades for</param>
|
||||
/// <returns></returns>
|
||||
Task<WebCallResult<IEnumerable<ICommonRecentTrade>>> GetRecentTradesAsync(string symbol);
|
||||
|
||||
/// <summary>
|
||||
/// Place an order
|
||||
/// </summary>
|
||||
/// <param name="symbol">The symbol the order is for</param>
|
||||
/// <param name="side">The side of the order</param>
|
||||
/// <param name="type">The type of the order</param>
|
||||
/// <param name="quantity">The quantity of the order</param>
|
||||
/// <param name="price">The price of the order, only for limit orders</param>
|
||||
/// <param name="accountId">[Optional] The account id to place the order on, required for some exchanges, ignored otherwise</param>
|
||||
/// <returns>The id of the resulting order</returns>
|
||||
Task<WebCallResult<ICommonOrderId>> PlaceOrderAsync(string symbol, OrderSide side, OrderType type, decimal quantity, decimal? price = null, string? accountId = null);
|
||||
/// <summary>
|
||||
/// Get an order by id
|
||||
/// </summary>
|
||||
/// <param name="orderId">The id</param>
|
||||
/// <param name="symbol">[Optional] The symbol the order is on, required for some exchanges, ignored otherwise</param>
|
||||
/// <returns></returns>
|
||||
Task<WebCallResult<ICommonOrder>> GetOrderAsync(string orderId, string? symbol = null);
|
||||
/// <summary>
|
||||
/// Get trades for an order by id
|
||||
/// </summary>
|
||||
/// <param name="orderId">The id</param>
|
||||
/// <param name="symbol">[Optional] The symbol the order is on, required for some exchanges, ignored otherwise</param>
|
||||
/// <returns></returns>
|
||||
Task<WebCallResult<IEnumerable<ICommonTrade>>> GetTradesAsync(string orderId, string? symbol = null);
|
||||
/// <summary>
|
||||
/// Get a list of open orders
|
||||
/// </summary>
|
||||
/// <param name="symbol">[Optional] The symbol to get open orders for, required for some exchanges, ignored otherwise</param>
|
||||
/// <returns></returns>
|
||||
Task<WebCallResult<IEnumerable<ICommonOrder>>> GetOpenOrdersAsync(string? symbol);
|
||||
|
||||
/// <summary>
|
||||
/// Get a list of closed orders
|
||||
/// </summary>
|
||||
/// <param name="symbol">[Optional] The symbol to get closed orders for, required for some exchanges, ignored otherwise</param>
|
||||
/// <returns></returns>
|
||||
Task<WebCallResult<IEnumerable<ICommonOrder>>> GetClosedOrdersAsync(string? symbol);
|
||||
/// <summary>
|
||||
/// Cancel an order by id
|
||||
/// </summary>
|
||||
/// <param name="orderId">The id</param>
|
||||
/// <param name="symbol">[Optional] The symbol the order is on, required for some exchanges, ignored otherwise</param>
|
||||
/// <returns></returns>
|
||||
Task<WebCallResult<ICommonOrderId>> CancelOrderAsync(string orderId, string? symbol);
|
||||
|
||||
/// <summary>
|
||||
/// Common order id
|
||||
/// </summary>
|
||||
public enum OrderType
|
||||
{
|
||||
/// <summary>
|
||||
/// Limit type
|
||||
/// </summary>
|
||||
Limit,
|
||||
/// <summary>
|
||||
/// Market type
|
||||
/// </summary>
|
||||
Market,
|
||||
/// <summary>
|
||||
/// Other order type
|
||||
/// </summary>
|
||||
Other
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Common order side
|
||||
/// </summary>
|
||||
public enum OrderSide
|
||||
{
|
||||
/// <summary>
|
||||
/// Buy order
|
||||
/// </summary>
|
||||
Buy,
|
||||
/// <summary>
|
||||
/// Sell order
|
||||
/// </summary>
|
||||
Sell
|
||||
}
|
||||
}
|
||||
}
|
29
CryptoExchange.Net/ExchangeInterfaces/IKline.cs
Normal file
29
CryptoExchange.Net/ExchangeInterfaces/IKline.cs
Normal file
@ -0,0 +1,29 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace CryptoExchange.Net.ExchangeInterfaces
|
||||
{
|
||||
/// <summary>
|
||||
/// Common kline
|
||||
/// </summary>
|
||||
public interface ICommonKline
|
||||
{
|
||||
/// <summary>
|
||||
/// High price for this kline
|
||||
/// </summary>
|
||||
decimal CommonHigh { get; }
|
||||
/// <summary>
|
||||
/// Low price for this kline
|
||||
/// </summary>
|
||||
decimal CommonLow { get; }
|
||||
/// <summary>
|
||||
/// Open price for this kline
|
||||
/// </summary>
|
||||
decimal CommonOpen { get; }
|
||||
/// <summary>
|
||||
/// Close price for this kline
|
||||
/// </summary>
|
||||
decimal CommonClose { get; }
|
||||
}
|
||||
}
|
41
CryptoExchange.Net/ExchangeInterfaces/IOrder.cs
Normal file
41
CryptoExchange.Net/ExchangeInterfaces/IOrder.cs
Normal file
@ -0,0 +1,41 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace CryptoExchange.Net.ExchangeInterfaces
|
||||
{
|
||||
/// <summary>
|
||||
/// Common order
|
||||
/// </summary>
|
||||
public interface ICommonOrder: ICommonOrderId
|
||||
{
|
||||
/// <summary>
|
||||
/// Symbol of the order
|
||||
/// </summary>
|
||||
public string CommonSymbol { get; }
|
||||
/// <summary>
|
||||
/// Price of the order
|
||||
/// </summary>
|
||||
public decimal CommonPrice { get; }
|
||||
/// <summary>
|
||||
/// Quantity of the order
|
||||
/// </summary>
|
||||
public decimal CommonQuantity { get; }
|
||||
/// <summary>
|
||||
/// Status of the order
|
||||
/// </summary>
|
||||
public string CommonStatus { get; }
|
||||
/// <summary>
|
||||
/// Whether the order is active
|
||||
/// </summary>
|
||||
public bool IsActive { get; }
|
||||
/// <summary>
|
||||
/// Side of the order
|
||||
/// </summary>
|
||||
public IExchangeClient.OrderSide CommonSide { get; }
|
||||
/// <summary>
|
||||
/// Type of the order
|
||||
/// </summary>
|
||||
public IExchangeClient.OrderType CommonType { get; }
|
||||
}
|
||||
}
|
22
CryptoExchange.Net/ExchangeInterfaces/IOrderBook.cs
Normal file
22
CryptoExchange.Net/ExchangeInterfaces/IOrderBook.cs
Normal file
@ -0,0 +1,22 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using CryptoExchange.Net.Interfaces;
|
||||
|
||||
namespace CryptoExchange.Net.ExchangeInterfaces
|
||||
{
|
||||
/// <summary>
|
||||
/// Common order book
|
||||
/// </summary>
|
||||
public interface ICommonOrderBook
|
||||
{
|
||||
/// <summary>
|
||||
/// Bids
|
||||
/// </summary>
|
||||
IEnumerable<ISymbolOrderBookEntry> CommonBids { get; }
|
||||
/// <summary>
|
||||
/// Asks
|
||||
/// </summary>
|
||||
IEnumerable<ISymbolOrderBookEntry> CommonAsks { get; }
|
||||
}
|
||||
}
|
17
CryptoExchange.Net/ExchangeInterfaces/IPlacedOrder.cs
Normal file
17
CryptoExchange.Net/ExchangeInterfaces/IPlacedOrder.cs
Normal file
@ -0,0 +1,17 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace CryptoExchange.Net.ExchangeInterfaces
|
||||
{
|
||||
/// <summary>
|
||||
/// Common order id
|
||||
/// </summary>
|
||||
public interface ICommonOrderId
|
||||
{
|
||||
/// <summary>
|
||||
/// Id of the order
|
||||
/// </summary>
|
||||
public string CommonId { get; }
|
||||
}
|
||||
}
|
25
CryptoExchange.Net/ExchangeInterfaces/IRecentTrade.cs
Normal file
25
CryptoExchange.Net/ExchangeInterfaces/IRecentTrade.cs
Normal file
@ -0,0 +1,25 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace CryptoExchange.Net.ExchangeInterfaces
|
||||
{
|
||||
/// <summary>
|
||||
/// Recent trade
|
||||
/// </summary>
|
||||
public interface ICommonRecentTrade
|
||||
{
|
||||
/// <summary>
|
||||
/// Price of the trade
|
||||
/// </summary>
|
||||
decimal CommonPrice { get; }
|
||||
/// <summary>
|
||||
/// Quantity of the trade
|
||||
/// </summary>
|
||||
decimal CommonQuantity { get; }
|
||||
/// <summary>
|
||||
/// Trade time
|
||||
/// </summary>
|
||||
DateTime CommonTradeTime { get; }
|
||||
}
|
||||
}
|
21
CryptoExchange.Net/ExchangeInterfaces/ISymbol.cs
Normal file
21
CryptoExchange.Net/ExchangeInterfaces/ISymbol.cs
Normal file
@ -0,0 +1,21 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace CryptoExchange.Net.ExchangeInterfaces
|
||||
{
|
||||
/// <summary>
|
||||
/// Common symbol
|
||||
/// </summary>
|
||||
public interface ICommonSymbol
|
||||
{
|
||||
/// <summary>
|
||||
/// Symbol name
|
||||
/// </summary>
|
||||
public string CommonName { get; }
|
||||
/// <summary>
|
||||
/// Minimum trade size
|
||||
/// </summary>
|
||||
public decimal CommonMinimumTradeSize { get; }
|
||||
}
|
||||
}
|
29
CryptoExchange.Net/ExchangeInterfaces/ITicker.cs
Normal file
29
CryptoExchange.Net/ExchangeInterfaces/ITicker.cs
Normal file
@ -0,0 +1,29 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace CryptoExchange.Net.ExchangeInterfaces
|
||||
{
|
||||
/// <summary>
|
||||
/// Common ticker
|
||||
/// </summary>
|
||||
public interface ICommonTicker
|
||||
{
|
||||
/// <summary>
|
||||
/// Symbol name
|
||||
/// </summary>
|
||||
public string CommonSymbol { get; }
|
||||
/// <summary>
|
||||
/// High price
|
||||
/// </summary>
|
||||
public decimal CommonHigh { get; }
|
||||
/// <summary>
|
||||
/// Low price
|
||||
/// </summary>
|
||||
public decimal CommonLow { get; }
|
||||
/// <summary>
|
||||
/// Volume
|
||||
/// </summary>
|
||||
public decimal CommonVolume { get; }
|
||||
}
|
||||
}
|
@ -225,7 +225,7 @@ namespace CryptoExchange.Net
|
||||
{
|
||||
if (!allowedValues.Contains(value))
|
||||
throw new ArgumentException(
|
||||
$"{value} not allowed for parameter {argumentName}, allowed values: {string.Join(", ", allowedValues)}");
|
||||
$"{value} not allowed for parameter {argumentName}, allowed values: {string.Join(", ", allowedValues)}", argumentName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -239,7 +239,7 @@ namespace CryptoExchange.Net
|
||||
{
|
||||
if (value < minValue || value > maxValue)
|
||||
throw new ArgumentException(
|
||||
$"{value} not allowed for parameter {argumentName}, min: {minValue}, max: {maxValue}");
|
||||
$"{value} not allowed for parameter {argumentName}, min: {minValue}, max: {maxValue}", argumentName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -250,7 +250,7 @@ namespace CryptoExchange.Net
|
||||
public static void ValidateNotNull(this string value, string argumentName)
|
||||
{
|
||||
if (string.IsNullOrEmpty(value))
|
||||
throw new ArgumentException($"No value provided for parameter {argumentName}");
|
||||
throw new ArgumentException($"No value provided for parameter {argumentName}", argumentName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -261,7 +261,7 @@ namespace CryptoExchange.Net
|
||||
public static void ValidateNotNull(this object value, string argumentName)
|
||||
{
|
||||
if (value == null)
|
||||
throw new ArgumentException($"No value provided for parameter {argumentName}");
|
||||
throw new ArgumentException($"No value provided for parameter {argumentName}", argumentName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -272,7 +272,7 @@ namespace CryptoExchange.Net
|
||||
public static void ValidateNotNull<T>(this IEnumerable<T> value, string argumentName)
|
||||
{
|
||||
if (value == null || !value.Any())
|
||||
throw new ArgumentException($"No values provided for parameter {argumentName}");
|
||||
throw new ArgumentException($"No values provided for parameter {argumentName}", argumentName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -37,6 +37,11 @@ namespace CryptoExchange.Net.Interfaces
|
||||
/// </summary>
|
||||
string BaseAddress { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Client name
|
||||
/// </summary>
|
||||
string ClientName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Adds a rate limiter to the client. There are 2 choices, the <see cref="RateLimiterTotal"/> and the <see cref="RateLimiterPerEndpoint"/>.
|
||||
/// </summary>
|
||||
|
@ -17,11 +17,17 @@ namespace CryptoExchange.Net.Logging
|
||||
/// </summary>
|
||||
public LogVerbosity Level { get; set; } = LogVerbosity.Info;
|
||||
|
||||
/// <summary>
|
||||
/// Client name
|
||||
/// </summary>
|
||||
public string ClientName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// ctor
|
||||
/// </summary>
|
||||
public Log()
|
||||
public Log(string clientName)
|
||||
{
|
||||
ClientName = clientName;
|
||||
writers = new List<TextWriter>();
|
||||
}
|
||||
|
||||
@ -44,7 +50,7 @@ namespace CryptoExchange.Net.Logging
|
||||
if ((int)logType < (int)Level)
|
||||
return;
|
||||
|
||||
var logMessage = $"{DateTime.Now:yyyy/MM/dd HH:mm:ss:fff} | {logType} | {message}";
|
||||
var logMessage = $"{DateTime.Now:yyyy/MM/dd HH:mm:ss:fff} | {ClientName.PadRight(10)} | {logType} | {message}";
|
||||
foreach (var writer in writers.ToList())
|
||||
{
|
||||
try
|
||||
|
@ -7,13 +7,8 @@ namespace CryptoExchange.Net.Objects
|
||||
/// <summary>
|
||||
/// The result of an operation
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
public class CallResult<T>
|
||||
public class CallResult
|
||||
{
|
||||
/// <summary>
|
||||
/// The data returned by the call
|
||||
/// </summary>
|
||||
public T Data { get; internal set; }
|
||||
/// <summary>
|
||||
/// An error if the call didn't succeed
|
||||
/// </summary>
|
||||
@ -23,15 +18,56 @@ namespace CryptoExchange.Net.Objects
|
||||
/// </summary>
|
||||
public bool Success => Error == null;
|
||||
|
||||
/// <summary>
|
||||
/// ctor
|
||||
/// </summary>
|
||||
/// <param name="error"></param>
|
||||
public CallResult(Error? error)
|
||||
{
|
||||
Error = error;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overwrite bool check so we can use if(callResult) instead of if(callResult.Success)
|
||||
/// </summary>
|
||||
/// <param name="obj"></param>
|
||||
public static implicit operator bool(CallResult obj)
|
||||
{
|
||||
return obj?.Success == true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create an error result
|
||||
/// </summary>
|
||||
/// <param name="error"></param>
|
||||
/// <returns></returns>
|
||||
public static WebCallResult CreateErrorResult(Error error)
|
||||
{
|
||||
return new WebCallResult(null, null, error);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The result of an operation
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
public class CallResult<T>: CallResult
|
||||
{
|
||||
/// <summary>
|
||||
/// The data returned by the call
|
||||
/// </summary>
|
||||
public T Data { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// ctor
|
||||
/// </summary>
|
||||
/// <param name="data"></param>
|
||||
/// <param name="error"></param>
|
||||
public CallResult([AllowNull]T data, Error? error)
|
||||
public CallResult([AllowNull]T data, Error? error): base(error)
|
||||
{
|
||||
#pragma warning disable 8601
|
||||
Data = data;
|
||||
Error = error;
|
||||
#pragma warning disable 8601
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -42,6 +78,92 @@ namespace CryptoExchange.Net.Objects
|
||||
{
|
||||
return obj?.Success == true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Whether the call was successful or not. Useful for nullability checking.
|
||||
/// </summary>
|
||||
/// <param name="data">The data returned by the call.</param>
|
||||
/// <param name="error"><see cref="Error"/> on failure.</param>
|
||||
/// <returns><c>true</c> when <see cref="CallResult{T}"/> succeeded, <c>false</c> otherwise.</returns>
|
||||
public bool GetResultOrError([MaybeNullWhen(false)] out T data, [NotNullWhen(false)] out Error? error)
|
||||
{
|
||||
if (Success)
|
||||
{
|
||||
data = Data!;
|
||||
error = null;
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
data = default;
|
||||
error = Error!;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create an error result
|
||||
/// </summary>
|
||||
/// <param name="error"></param>
|
||||
/// <returns></returns>
|
||||
public new static WebCallResult<T> CreateErrorResult(Error error)
|
||||
{
|
||||
return new WebCallResult<T>(null, null, default, error);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The result of a request
|
||||
/// </summary>
|
||||
public class WebCallResult : CallResult
|
||||
{
|
||||
/// <summary>
|
||||
/// The status code of the response. Note that a OK status does not always indicate success, check the Success parameter for this.
|
||||
/// </summary>
|
||||
public HttpStatusCode? ResponseStatusCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The response headers
|
||||
/// </summary>
|
||||
public IEnumerable<KeyValuePair<string, IEnumerable<string>>>? ResponseHeaders { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// ctor
|
||||
/// </summary>
|
||||
/// <param name="code"></param>
|
||||
/// <param name="responseHeaders"></param>
|
||||
/// <param name="error"></param>
|
||||
public WebCallResult(
|
||||
HttpStatusCode? code,
|
||||
IEnumerable<KeyValuePair<string, IEnumerable<string>>>? responseHeaders, Error? error) : base(error)
|
||||
{
|
||||
ResponseHeaders = responseHeaders;
|
||||
ResponseStatusCode = code;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create an error result
|
||||
/// </summary>
|
||||
/// <param name="code"></param>
|
||||
/// <param name="responseHeaders"></param>
|
||||
/// <param name="error"></param>
|
||||
/// <returns></returns>
|
||||
public static WebCallResult CreateErrorResult(HttpStatusCode? code, IEnumerable<KeyValuePair<string, IEnumerable<string>>>? responseHeaders, Error error)
|
||||
{
|
||||
return new WebCallResult(code, responseHeaders, error);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create an error result
|
||||
/// </summary>
|
||||
/// <param name="result"></param>
|
||||
/// <returns></returns>
|
||||
public static WebCallResult CreateErrorResult(WebCallResult result)
|
||||
{
|
||||
return new WebCallResult(result.ResponseStatusCode, result.ResponseHeaders, result.Error);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -71,18 +193,29 @@ namespace CryptoExchange.Net.Objects
|
||||
HttpStatusCode? code,
|
||||
IEnumerable<KeyValuePair<string, IEnumerable<string>>>? responseHeaders, [AllowNull] T data, Error? error): base(data, error)
|
||||
{
|
||||
ResponseHeaders = responseHeaders;
|
||||
ResponseStatusCode = code;
|
||||
ResponseHeaders = responseHeaders;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create an error result
|
||||
/// Create new based on existing
|
||||
/// </summary>
|
||||
/// <param name="error"></param>
|
||||
/// <returns></returns>
|
||||
public static WebCallResult<T> CreateErrorResult(Error error)
|
||||
/// <param name="callResult"></param>
|
||||
public WebCallResult(WebCallResult<T> callResult): base(callResult.Data, callResult.Error)
|
||||
{
|
||||
return new WebCallResult<T>(null, null, default!, error);
|
||||
ResponseHeaders = callResult.ResponseHeaders;
|
||||
ResponseStatusCode = callResult.ResponseStatusCode;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create from a call result
|
||||
/// </summary>
|
||||
/// <typeparam name="Y"></typeparam>
|
||||
/// <param name="source"></param>
|
||||
/// <returns></returns>
|
||||
public static WebCallResult<T> CreateFrom<Y>(WebCallResult<Y> source) where Y : T
|
||||
{
|
||||
return new WebCallResult<T>(source.ResponseStatusCode, source.ResponseHeaders, (T)source.Data, source.Error);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -94,7 +227,7 @@ namespace CryptoExchange.Net.Objects
|
||||
/// <returns></returns>
|
||||
public static WebCallResult<T> CreateErrorResult(HttpStatusCode? code, IEnumerable<KeyValuePair<string, IEnumerable<string>>>? responseHeaders, Error error)
|
||||
{
|
||||
return new WebCallResult<T>(code, responseHeaders, default!, error);
|
||||
return new WebCallResult<T>(code, responseHeaders, default, error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,16 +6,17 @@
|
||||
public abstract class Error
|
||||
{
|
||||
/// <summary>
|
||||
/// The error code
|
||||
/// The error code from the server
|
||||
/// </summary>
|
||||
public int Code { get; set; }
|
||||
public int? Code { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The message for the error that occured
|
||||
/// The message for the error that occurred
|
||||
/// </summary>
|
||||
public string Message { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Optional data for the error
|
||||
/// The data which caused the error
|
||||
/// </summary>
|
||||
public object? Data { get; set; }
|
||||
|
||||
@ -25,7 +26,7 @@
|
||||
/// <param name="code"></param>
|
||||
/// <param name="message"></param>
|
||||
/// <param name="data"></param>
|
||||
protected Error(int code, string message, object? data)
|
||||
protected Error(int? code, string message, object? data)
|
||||
{
|
||||
Code = code;
|
||||
Message = message;
|
||||
@ -50,7 +51,7 @@
|
||||
/// <summary>
|
||||
/// ctor
|
||||
/// </summary>
|
||||
public CantConnectError() : base(1, "Can't connect to the server", null) { }
|
||||
public CantConnectError() : base(null, "Can't connect to the server", null) { }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -61,7 +62,7 @@
|
||||
/// <summary>
|
||||
/// ctor
|
||||
/// </summary>
|
||||
public NoApiCredentialsError() : base(2, "No credentials provided for private endpoint", null) { }
|
||||
public NoApiCredentialsError() : base(null, "No credentials provided for private endpoint", null) { }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -74,7 +75,7 @@
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
/// <param name="data"></param>
|
||||
public ServerError(string message, object? data = null) : base(3, "Server error: " + message, data) { }
|
||||
public ServerError(string message, object? data = null) : base(null, message, data) { }
|
||||
|
||||
/// <summary>
|
||||
/// ctor
|
||||
@ -95,8 +96,17 @@
|
||||
/// <summary>
|
||||
/// ctor
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
/// <param name="data"></param>
|
||||
public WebError(object? data) : base(4, "Web error", data) { }
|
||||
public WebError(string message, object? data = null) : base(null, message, data) { }
|
||||
|
||||
/// <summary>
|
||||
/// ctor
|
||||
/// </summary>
|
||||
/// <param name="code"></param>
|
||||
/// <param name="message"></param>
|
||||
/// <param name="data"></param>
|
||||
public WebError(int code, string message, object? data = null) : base(code, message, data) { }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -107,8 +117,9 @@
|
||||
/// <summary>
|
||||
/// ctor
|
||||
/// </summary>
|
||||
/// <param name="data">Deserializing data</param>
|
||||
public DeserializeError(object? data) : base(5, "Error deserializing data", data) { }
|
||||
/// <param name="message">The error message</param>
|
||||
/// <param name="data">The data which caused the error</param>
|
||||
public DeserializeError(string message, object? data) : base(null, message, data) { }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -119,8 +130,9 @@
|
||||
/// <summary>
|
||||
/// ctor
|
||||
/// </summary>
|
||||
/// <param name="message">Error message</param>
|
||||
/// <param name="data">Error data</param>
|
||||
public UnknownError(object? data = null) : base(6, "Unknown error occured", data) { }
|
||||
public UnknownError(string message, object? data = null) : base(null, message, data) { }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -132,7 +144,7 @@
|
||||
/// ctor
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
public ArgumentError(string message) : base(7, "Invalid parameter: " + message, null) { }
|
||||
public ArgumentError(string message) : base(null, "Invalid parameter: " + message, null) { }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -144,7 +156,7 @@
|
||||
/// ctor
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
public RateLimitError(string message) : base(8, "Rate limit exceeded: " + message, null) { }
|
||||
public RateLimitError(string message) : base(null, "Rate limit exceeded: " + message, null) { }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -155,6 +167,6 @@
|
||||
/// <summary>
|
||||
/// ctor
|
||||
/// </summary>
|
||||
public CancellationRequestedError() : base(9, "Cancellation requested", null) { }
|
||||
public CancellationRequestedError() : base(null, "Cancellation requested", null) { }
|
||||
}
|
||||
}
|
||||
|
@ -76,10 +76,22 @@ namespace CryptoExchange.Net.Objects
|
||||
/// </summary>
|
||||
public class ClientOptions : BaseOptions
|
||||
{
|
||||
private string _baseAddress;
|
||||
|
||||
/// <summary>
|
||||
/// The base address of the client
|
||||
/// </summary>
|
||||
public string BaseAddress { get; set; }
|
||||
public string BaseAddress
|
||||
{
|
||||
get => _baseAddress;
|
||||
set
|
||||
{
|
||||
var newValue = value;
|
||||
if (!newValue.EndsWith("/"))
|
||||
newValue += "/";
|
||||
_baseAddress = newValue;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The api credentials
|
||||
@ -89,7 +101,7 @@ namespace CryptoExchange.Net.Objects
|
||||
/// <summary>
|
||||
/// Should check objects for missing properties based on the model and the received JSON
|
||||
/// </summary>
|
||||
public bool ShouldCheckObjects { get; set; } = true;
|
||||
public bool ShouldCheckObjects { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// Proxy to use
|
||||
@ -100,7 +112,9 @@ namespace CryptoExchange.Net.Objects
|
||||
/// ctor
|
||||
/// </summary>
|
||||
/// <param name="baseAddress"></param>
|
||||
#pragma warning disable 8618
|
||||
public ClientOptions(string baseAddress)
|
||||
#pragma warning restore 8618
|
||||
{
|
||||
BaseAddress = baseAddress;
|
||||
}
|
||||
|
@ -39,8 +39,8 @@ namespace CryptoExchange.Net.OrderBook
|
||||
private readonly bool strictLevels;
|
||||
|
||||
private Task? _processTask;
|
||||
private AutoResetEvent _queueEvent;
|
||||
private ConcurrentQueue<object> _processQueue;
|
||||
private readonly AutoResetEvent _queueEvent;
|
||||
private readonly ConcurrentQueue<object> _processQueue;
|
||||
|
||||
/// <summary>
|
||||
/// Order book implementation id
|
||||
@ -208,7 +208,7 @@ namespace CryptoExchange.Net.OrderBook
|
||||
asks = new SortedList<decimal, ISymbolOrderBookEntry>();
|
||||
bids = new SortedList<decimal, ISymbolOrderBookEntry>(new DescComparer<decimal>());
|
||||
|
||||
log = new Log { Level = options.LogVerbosity };
|
||||
log = new Log(options.OrderBookName) { Level = options.LogVerbosity };
|
||||
var writers = options.LogWriters ?? new List<TextWriter> { new DebugTextWriter() };
|
||||
log.UpdateWriters(writers.ToList());
|
||||
}
|
||||
@ -377,7 +377,7 @@ namespace CryptoExchange.Net.OrderBook
|
||||
FirstUpdateId = item.StartUpdateId,
|
||||
LastUpdateId = item.EndUpdateId,
|
||||
});
|
||||
log.Write(LogVerbosity.Debug, $"{Id} order book {Symbol} update buffered #{item.StartUpdateId}-#{item.EndUpdateId} [{Asks.Count()} asks, {Bids.Count()} bids]");
|
||||
log.Write(LogVerbosity.Debug, $"{Id} order book {Symbol} update buffered #{item.StartUpdateId}-#{item.EndUpdateId} [{item.Asks.Count()} asks, {item.Bids.Count()} bids]");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1,6 +1,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using CryptoExchange.Net.Interfaces;
|
||||
using CryptoExchange.Net.Objects;
|
||||
@ -10,10 +12,11 @@ namespace CryptoExchange.Net.RateLimiter
|
||||
/// <summary>
|
||||
/// Limits the amount of requests per time period to a certain limit, counts the request per API key.
|
||||
/// </summary>
|
||||
public class RateLimiterAPIKey: IRateLimiter
|
||||
public class RateLimiterAPIKey: IRateLimiter, IDisposable
|
||||
{
|
||||
internal Dictionary<string, RateLimitObject> history = new Dictionary<string, RateLimitObject>();
|
||||
|
||||
private readonly SHA256 encryptor;
|
||||
private readonly int limitPerKey;
|
||||
private readonly TimeSpan perTimePeriod;
|
||||
private readonly object historyLock = new object();
|
||||
@ -26,6 +29,7 @@ namespace CryptoExchange.Net.RateLimiter
|
||||
public RateLimiterAPIKey(int limitPerApiKey, TimeSpan perTimePeriod)
|
||||
{
|
||||
limitPerKey = limitPerApiKey;
|
||||
encryptor = SHA256.Create();
|
||||
this.perTimePeriod = perTimePeriod;
|
||||
}
|
||||
|
||||
@ -35,7 +39,14 @@ namespace CryptoExchange.Net.RateLimiter
|
||||
if(client.authProvider?.Credentials?.Key == null)
|
||||
return new CallResult<double>(0, null);
|
||||
|
||||
var key = client.authProvider.Credentials.Key.GetString();
|
||||
var keyBytes = encryptor.ComputeHash(Encoding.UTF8.GetBytes(client.authProvider.Credentials.Key.GetString()));
|
||||
StringBuilder builder = new StringBuilder();
|
||||
for (int i = 0; i < keyBytes.Length; i++)
|
||||
{
|
||||
builder.Append(keyBytes[i].ToString("x2"));
|
||||
}
|
||||
|
||||
var key = builder.ToString();
|
||||
|
||||
int waitTime;
|
||||
RateLimitObject rlo;
|
||||
@ -69,5 +80,13 @@ namespace CryptoExchange.Net.RateLimiter
|
||||
|
||||
return new CallResult<double>(waitTime, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Dispose
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
encryptor.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -76,9 +76,10 @@ namespace CryptoExchange.Net
|
||||
/// <summary>
|
||||
/// ctor
|
||||
/// </summary>
|
||||
/// <param name="clientName"></param>
|
||||
/// <param name="exchangeOptions"></param>
|
||||
/// <param name="authenticationProvider"></param>
|
||||
protected RestClient(RestClientOptions exchangeOptions, AuthenticationProvider? authenticationProvider) : base(exchangeOptions, authenticationProvider)
|
||||
protected RestClient(string clientName, RestClientOptions exchangeOptions, AuthenticationProvider? authenticationProvider) : base(clientName, exchangeOptions, authenticationProvider)
|
||||
{
|
||||
if (exchangeOptions == null)
|
||||
throw new ArgumentNullException(nameof(exchangeOptions));
|
||||
@ -232,7 +233,7 @@ namespace CryptoExchange.Net
|
||||
|
||||
var parseResult = ValidateJson(data);
|
||||
if (!parseResult.Success)
|
||||
return WebCallResult<T>.CreateErrorResult(response.StatusCode, response.ResponseHeaders, new ServerError(data));
|
||||
return WebCallResult<T>.CreateErrorResult(response.StatusCode, response.ResponseHeaders, parseResult.Error!);
|
||||
var error = await TryParseError(parseResult.Data);
|
||||
if (error != null)
|
||||
return WebCallResult<T>.CreateErrorResult(response.StatusCode, response.ResponseHeaders, error);
|
||||
@ -257,7 +258,10 @@ namespace CryptoExchange.Net
|
||||
responseStream.Close();
|
||||
response.Close();
|
||||
var parseResult = ValidateJson(data);
|
||||
return new WebCallResult<T>(statusCode, headers, default, parseResult.Success ? ParseErrorResponse(parseResult.Data) : new ServerError(data));
|
||||
var error = parseResult.Success ? ParseErrorResponse(parseResult.Data) : parseResult.Error!;
|
||||
if(error.Code == null || error.Code == 0)
|
||||
error.Code = (int)response.StatusCode;
|
||||
return new WebCallResult<T>(statusCode, headers, default, error);
|
||||
}
|
||||
}
|
||||
catch (HttpRequestException requestException)
|
||||
|
@ -83,9 +83,10 @@ namespace CryptoExchange.Net
|
||||
/// <summary>
|
||||
/// Create a socket client
|
||||
/// </summary>
|
||||
/// <param name="clientName">Client name</param>
|
||||
/// <param name="exchangeOptions">Client options</param>
|
||||
/// <param name="authenticationProvider">Authentication provider</param>
|
||||
protected SocketClient(SocketClientOptions exchangeOptions, AuthenticationProvider? authenticationProvider): base(exchangeOptions, authenticationProvider)
|
||||
protected SocketClient(string clientName, SocketClientOptions exchangeOptions, AuthenticationProvider? authenticationProvider): base(clientName, exchangeOptions, authenticationProvider)
|
||||
{
|
||||
if (exchangeOptions == null)
|
||||
throw new ArgumentNullException(nameof(exchangeOptions));
|
||||
@ -294,7 +295,7 @@ namespace CryptoExchange.Net
|
||||
|
||||
var connectResult = await ConnectSocket(socket).ConfigureAwait(false);
|
||||
if (!connectResult)
|
||||
return new CallResult<bool>(false, new CantConnectError());
|
||||
return new CallResult<bool>(false, connectResult.Error);
|
||||
|
||||
if (!authenticated || socket.Authenticated)
|
||||
return new CallResult<bool>(true, null);
|
||||
@ -427,7 +428,8 @@ namespace CryptoExchange.Net
|
||||
/// <returns></returns>
|
||||
protected virtual SocketConnection GetWebsocket(string address, bool authenticated)
|
||||
{
|
||||
var socketResult = sockets.Where(s => s.Value.Socket.Url == address && (s.Value.Authenticated == authenticated || !authenticated) && s.Value.Connected).OrderBy(s => s.Value.HandlerCount).FirstOrDefault();
|
||||
var socketResult = sockets.Where(s => s.Value.Socket.Url.TrimEnd('/') == address.TrimEnd('/')
|
||||
&& (s.Value.Authenticated == authenticated || !authenticated) && s.Value.Connected).OrderBy(s => s.Value.HandlerCount).FirstOrDefault();
|
||||
var result = socketResult.Equals(default(KeyValuePair<int, SocketConnection>)) ? null : socketResult.Value;
|
||||
if (result != null)
|
||||
{
|
||||
|
25
README.md
25
README.md
@ -61,6 +61,10 @@ Implementations from third parties
|
||||
<br />
|
||||
<a href="https://github.com/ridicoulous/Bitmex.Net">Bitmex</a>
|
||||
</td>
|
||||
<td><a href="https://github.com/intelligences/HitBTC.Net"><img src="https://github.com/intelligences/HitBTC.Net/blob/master/src/HitBTC.Net/Icon/icon.png?raw=true"></a>
|
||||
<br />
|
||||
<a href="https://github.com/intelligences/HitBTC.Net">HitBTC</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
@ -199,6 +203,27 @@ The order book will automatically reconnect when the connection is lost and resy
|
||||
To stop synchronizing an order book use the `Stop` method.
|
||||
|
||||
## Release notes
|
||||
* Version 3.3.0 - 10 dec 2020
|
||||
* Added client name
|
||||
* Added common interfaces
|
||||
* Fixed api key plain text storing in RateLimitterApiKey
|
||||
|
||||
* Version 3.2.1 - 19 nov 2020
|
||||
* Fixed error code parsing
|
||||
|
||||
* Version 3.2.0 - 19 nov 2020
|
||||
* Fix for multiple socket subscriptions re-using the same socket connection
|
||||
* Updated errors
|
||||
|
||||
* Version 3.1.0 - 08 Oct 2020
|
||||
* Added CallResult without type parameter for calls which don't return data
|
||||
* Added GetErrorOrResult method on CallResult to support proper nullability checking
|
||||
* Fix for reading credentials from file
|
||||
* Fix for setting custom base addresses in clients
|
||||
|
||||
* Version 3.0.15 - 06 Oct 2020
|
||||
* Changed default ShouldCheckObjects to false to prevent spam in logging
|
||||
|
||||
* Version 3.0.14 - 24 Aug 2020
|
||||
* Updated exception message logging
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user