mirror of
https://github.com/JKorf/CryptoExchange.Net
synced 2025-06-09 08:56:13 +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
|
||||||
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.RateLimiters.Count() == 1);
|
||||||
Assert.IsTrue(client.RateLimitBehaviour == RateLimitingBehaviour.Fail);
|
Assert.IsTrue(client.RateLimitBehaviour == RateLimitingBehaviour.Fail);
|
||||||
Assert.IsTrue(client.RequestTimeout == TimeSpan.FromMinutes(1));
|
Assert.IsTrue(client.RequestTimeout == TimeSpan.FromMinutes(1));
|
||||||
|
@ -25,7 +25,7 @@ namespace CryptoExchange.Net.UnitTests
|
|||||||
|
|
||||||
|
|
||||||
//assert
|
//assert
|
||||||
Assert.IsTrue(client.BaseAddress == "http://test.address.com");
|
Assert.IsTrue(client.BaseAddress == "http://test.address.com/");
|
||||||
Assert.IsTrue(client.ReconnectInterval.TotalSeconds == 6);
|
Assert.IsTrue(client.ReconnectInterval.TotalSeconds == 6);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,11 +9,11 @@ namespace CryptoExchange.Net.UnitTests
|
|||||||
{
|
{
|
||||||
public class TestBaseClient: BaseClient
|
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 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;
|
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;
|
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;
|
SocketFactory = new Mock<IWebsocketFactory>().Object;
|
||||||
Mock.Get(SocketFactory).Setup(f => f.CreateWebsocket(It.IsAny<Log>(), It.IsAny<string>())).Returns(new TestSocket());
|
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>
|
/// <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)
|
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 stringData = reader.ReadToEnd();
|
||||||
var jsonData = stringData.ToJToken();
|
var jsonData = stringData.ToJToken();
|
||||||
@ -109,7 +109,7 @@ namespace CryptoExchange.Net.Authentication
|
|||||||
{
|
{
|
||||||
if (data[key] == null)
|
if (data[key] == null)
|
||||||
return null;
|
return null;
|
||||||
return (string) data[key];
|
return (string) data[key]!;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -25,6 +25,10 @@ namespace CryptoExchange.Net
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public string BaseAddress { get; }
|
public string BaseAddress { get; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
/// The name of the client
|
||||||
|
/// </summary>
|
||||||
|
public string ClientName { get; }
|
||||||
|
/// <summary>
|
||||||
/// The log object
|
/// The log object
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected internal Log log;
|
protected internal Log log;
|
||||||
@ -64,15 +68,17 @@ namespace CryptoExchange.Net
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// ctor
|
/// ctor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <param name="clientName"></param>
|
||||||
/// <param name="options"></param>
|
/// <param name="options"></param>
|
||||||
/// <param name="authenticationProvider"></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;
|
authProvider = authenticationProvider;
|
||||||
log.UpdateWriters(options.LogWriters);
|
log.UpdateWriters(options.LogWriters);
|
||||||
log.Level = options.LogVerbosity;
|
log.Level = options.LogVerbosity;
|
||||||
|
|
||||||
|
ClientName = clientName;
|
||||||
BaseAddress = options.BaseAddress;
|
BaseAddress = options.BaseAddress;
|
||||||
apiProxy = options.Proxy;
|
apiProxy = options.Proxy;
|
||||||
|
|
||||||
@ -101,7 +107,7 @@ namespace CryptoExchange.Net
|
|||||||
{
|
{
|
||||||
var info = "Empty data object received";
|
var info = "Empty data object received";
|
||||||
log.Write(LogVerbosity.Error, info);
|
log.Write(LogVerbosity.Error, info);
|
||||||
return new CallResult<JToken>(null, new DeserializeError(info));
|
return new CallResult<JToken>(null, new DeserializeError(info, data));
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
@ -110,18 +116,18 @@ namespace CryptoExchange.Net
|
|||||||
}
|
}
|
||||||
catch (JsonReaderException jre)
|
catch (JsonReaderException jre)
|
||||||
{
|
{
|
||||||
var info = $"Deserialize JsonReaderException: {jre.Message}, Path: {jre.Path}, LineNumber: {jre.LineNumber}, LinePosition: {jre.LinePosition}. Data: {data}";
|
var info = $"Deserialize JsonReaderException: {jre.Message}, Path: {jre.Path}, LineNumber: {jre.LineNumber}, LinePosition: {jre.LinePosition}";
|
||||||
return new CallResult<JToken>(null, new DeserializeError(info));
|
return new CallResult<JToken>(null, new DeserializeError(info, data));
|
||||||
}
|
}
|
||||||
catch (JsonSerializationException jse)
|
catch (JsonSerializationException jse)
|
||||||
{
|
{
|
||||||
var info = $"Deserialize JsonSerializationException: {jse.Message}. Data: {data}";
|
var info = $"Deserialize JsonSerializationException: {jse.Message}";
|
||||||
return new CallResult<JToken>(null, new DeserializeError(info));
|
return new CallResult<JToken>(null, new DeserializeError(info, data));
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
var info = $"Deserialize Unknown Exception: {(ex.InnerException?.Message ?? ex.Message)}. Data: {data}";
|
var info = $"Deserialize Unknown Exception: {(ex.InnerException?.Message ?? ex.Message)}";
|
||||||
return new CallResult<JToken>(null, new DeserializeError(info));
|
return new CallResult<JToken>(null, new DeserializeError(info, data));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -186,21 +192,21 @@ namespace CryptoExchange.Net
|
|||||||
}
|
}
|
||||||
catch (JsonReaderException jre)
|
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);
|
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)
|
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);
|
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)
|
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);
|
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="stream">The stream to deserialize</param>
|
||||||
/// <param name="serializer">A specific serializer to use</param>
|
/// <param name="serializer">A specific serializer to use</param>
|
||||||
/// <param name="requestId">Id of the request</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>
|
/// <returns></returns>
|
||||||
protected async Task<CallResult<T>> Deserialize<T>(Stream stream, JsonSerializer? serializer = null, int? requestId = null, long? elapsedMilliseconds = null)
|
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);
|
stream.Seek(0, SeekOrigin.Begin);
|
||||||
var data = await ReadStream(stream).ConfigureAwait(false);
|
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}");
|
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)
|
catch (JsonSerializationException jse)
|
||||||
{
|
{
|
||||||
@ -245,7 +251,7 @@ namespace CryptoExchange.Net
|
|||||||
stream.Seek(0, SeekOrigin.Begin);
|
stream.Seek(0, SeekOrigin.Begin);
|
||||||
var data = await ReadStream(stream).ConfigureAwait(false);
|
var data = await ReadStream(stream).ConfigureAwait(false);
|
||||||
log.Write(LogVerbosity.Error, $"{(requestId != null ? $"[{requestId}] " : "")}Deserialize JsonSerializationException: {jse.Message}, data: {data}");
|
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)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@ -253,7 +259,7 @@ namespace CryptoExchange.Net
|
|||||||
stream.Seek(0, SeekOrigin.Begin);
|
stream.Seek(0, SeekOrigin.Begin);
|
||||||
var data = await ReadStream(stream).ConfigureAwait(false);
|
var data = await ReadStream(stream).ConfigureAwait(false);
|
||||||
log.Write(LogVerbosity.Error, $"{(requestId != null ? $"[{requestId}] " : "")}Deserialize Unknown Exception: {(ex.InnerException?.Message ?? ex.Message)}, data: {data}");
|
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)
|
if (ignore != null)
|
||||||
continue;
|
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)
|
foreach (var token in obj)
|
||||||
{
|
{
|
||||||
@ -313,12 +320,12 @@ namespace CryptoExchange.Net
|
|||||||
properties.Remove(d);
|
properties.Remove(d);
|
||||||
|
|
||||||
var propType = GetProperty(d, props)?.PropertyType;
|
var propType = GetProperty(d, props)?.PropertyType;
|
||||||
if (propType == null)
|
if (propType == null || token.Value == null)
|
||||||
continue;
|
continue;
|
||||||
if (!IsSimple(propType) && propType != typeof(DateTime))
|
if (!IsSimple(propType) && propType != typeof(DateTime))
|
||||||
{
|
{
|
||||||
if (propType.IsArray && token.Value.HasValues && ((JArray)token.Value).Any() && ((JArray)token.Value)[0] is JObject)
|
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)
|
else if (token.Value is JObject o)
|
||||||
CheckObject(propType, o, requestId);
|
CheckObject(propType, o, requestId);
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,7 @@ namespace CryptoExchange.Net.Converters
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <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))
|
if (objectType == typeof(JToken))
|
||||||
return JToken.Load(reader);
|
return JToken.Load(reader);
|
||||||
@ -115,8 +115,11 @@ namespace CryptoExchange.Net.Converters
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
|
public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer)
|
||||||
{
|
{
|
||||||
|
if (value == null)
|
||||||
|
return;
|
||||||
|
|
||||||
writer.WriteStartArray();
|
writer.WriteStartArray();
|
||||||
var props = value.GetType().GetProperties();
|
var props = value.GetType().GetProperties();
|
||||||
var ordered = props.OrderBy(p => p.GetCustomAttribute<ArrayPropertyAttribute>()?.Index);
|
var ordered = props.OrderBy(p => p.GetCustomAttribute<ArrayPropertyAttribute>()?.Index);
|
||||||
|
@ -28,9 +28,9 @@ namespace CryptoExchange.Net.Converters
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
|
public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer)
|
||||||
{
|
{
|
||||||
var stringValue = GetValue((T) value);
|
var stringValue = value == null? null: GetValue((T) value);
|
||||||
if (quotes)
|
if (quotes)
|
||||||
writer.WriteValue(stringValue);
|
writer.WriteValue(stringValue);
|
||||||
else
|
else
|
||||||
@ -38,7 +38,7 @@ namespace CryptoExchange.Net.Converters
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <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)
|
if (reader.Value == null)
|
||||||
return null;
|
return null;
|
||||||
|
@ -15,7 +15,7 @@ namespace CryptoExchange.Net.Converters
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <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)
|
if (reader.Value == null)
|
||||||
return null;
|
return null;
|
||||||
@ -25,8 +25,11 @@ namespace CryptoExchange.Net.Converters
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
|
public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer)
|
||||||
{
|
{
|
||||||
|
if(value == null)
|
||||||
|
writer.WriteValue((DateTime?)null);
|
||||||
|
else
|
||||||
writer.WriteValue((long)Math.Round(((DateTime)value - new DateTime(1970, 1, 1)).TotalMilliseconds));
|
writer.WriteValue((long)Math.Round(((DateTime)value - new DateTime(1970, 1, 1)).TotalMilliseconds));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ namespace CryptoExchange.Net.Converters
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <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)
|
if (reader.Value == null)
|
||||||
return null;
|
return null;
|
||||||
@ -27,9 +27,9 @@ namespace CryptoExchange.Net.Converters
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
|
public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer)
|
||||||
{
|
{
|
||||||
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 />
|
/// <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)
|
if (reader.Value == null)
|
||||||
return null;
|
return null;
|
||||||
@ -29,9 +29,12 @@ namespace CryptoExchange.Net.Converters
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
|
public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer)
|
||||||
{
|
{
|
||||||
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
|
public class UTCDateTimeConverter: JsonConverter
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <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));
|
writer.WriteValue(JsonConvert.SerializeObject(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <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)
|
if (reader.Value == null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
DateTime value;
|
DateTime value;
|
||||||
if (reader.Value is string s)
|
if (reader.Value is string s)
|
||||||
value = (DateTime)JsonConvert.DeserializeObject(s);
|
value = (DateTime)JsonConvert.DeserializeObject(s)!;
|
||||||
else
|
else
|
||||||
value = (DateTime) reader.Value;
|
value = (DateTime) reader.Value;
|
||||||
|
|
||||||
|
@ -6,12 +6,13 @@
|
|||||||
<PackageId>CryptoExchange.Net</PackageId>
|
<PackageId>CryptoExchange.Net</PackageId>
|
||||||
<Authors>JKorf</Authors>
|
<Authors>JKorf</Authors>
|
||||||
<Description>A base package for implementing cryptocurrency exchange API's</Description>
|
<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>
|
<PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
|
||||||
<PackageProjectUrl>https://github.com/JKorf/CryptoExchange.Net</PackageProjectUrl>
|
<PackageProjectUrl>https://github.com/JKorf/CryptoExchange.Net</PackageProjectUrl>
|
||||||
<NeutralLanguage>en</NeutralLanguage>
|
<NeutralLanguage>en</NeutralLanguage>
|
||||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
<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>
|
<Nullable>enable</Nullable>
|
||||||
<LangVersion>8.0</LangVersion>
|
<LangVersion>8.0</LangVersion>
|
||||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||||
@ -20,7 +21,7 @@
|
|||||||
<DocumentationFile>CryptoExchange.Net.xml</DocumentationFile>
|
<DocumentationFile>CryptoExchange.Net.xml</DocumentationFile>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.1" />
|
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
||||||
<PackageReference Include="WebSocket4Net" Version="0.15.2" />
|
<PackageReference Include="WebSocket4Net" Version="0.15.2" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
@ -209,6 +209,11 @@
|
|||||||
The address of the client
|
The address of the client
|
||||||
</summary>
|
</summary>
|
||||||
</member>
|
</member>
|
||||||
|
<member name="P:CryptoExchange.Net.BaseClient.ClientName">
|
||||||
|
<summary>
|
||||||
|
The name of the client
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
<member name="F:CryptoExchange.Net.BaseClient.log">
|
<member name="F:CryptoExchange.Net.BaseClient.log">
|
||||||
<summary>
|
<summary>
|
||||||
The log object
|
The log object
|
||||||
@ -244,10 +249,11 @@
|
|||||||
Last is used
|
Last is used
|
||||||
</summary>
|
</summary>
|
||||||
</member>
|
</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>
|
<summary>
|
||||||
ctor
|
ctor
|
||||||
</summary>
|
</summary>
|
||||||
|
<param name="clientName"></param>
|
||||||
<param name="options"></param>
|
<param name="options"></param>
|
||||||
<param name="authenticationProvider"></param>
|
<param name="authenticationProvider"></param>
|
||||||
</member>
|
</member>
|
||||||
@ -294,7 +300,7 @@
|
|||||||
<param name="stream">The stream to deserialize</param>
|
<param name="stream">The stream to deserialize</param>
|
||||||
<param name="serializer">A specific serializer to use</param>
|
<param name="serializer">A specific serializer to use</param>
|
||||||
<param name="requestId">Id of the request</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>
|
<returns></returns>
|
||||||
</member>
|
</member>
|
||||||
<member name="M:CryptoExchange.Net.BaseClient.NextId">
|
<member name="M:CryptoExchange.Net.BaseClient.NextId">
|
||||||
@ -435,6 +441,318 @@
|
|||||||
<member name="M:CryptoExchange.Net.Converters.UTCDateTimeConverter.CanConvert(System.Type)">
|
<member name="M:CryptoExchange.Net.Converters.UTCDateTimeConverter.CanConvert(System.Type)">
|
||||||
<inheritdoc />
|
<inheritdoc />
|
||||||
</member>
|
</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">
|
<member name="T:CryptoExchange.Net.ExtensionMethods">
|
||||||
<summary>
|
<summary>
|
||||||
Helper methods
|
Helper methods
|
||||||
@ -712,6 +1030,11 @@
|
|||||||
The base address of the API
|
The base address of the API
|
||||||
</summary>
|
</summary>
|
||||||
</member>
|
</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)">
|
<member name="M:CryptoExchange.Net.Interfaces.IRestClient.AddRateLimiter(CryptoExchange.Net.Interfaces.IRateLimiter)">
|
||||||
<summary>
|
<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"/>.
|
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
|
The verbosity of the logging
|
||||||
</summary>
|
</summary>
|
||||||
</member>
|
</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>
|
<summary>
|
||||||
ctor
|
ctor
|
||||||
</summary>
|
</summary>
|
||||||
@ -1199,6 +1527,40 @@
|
|||||||
<param name="y"></param>
|
<param name="y"></param>
|
||||||
<returns></returns>
|
<returns></returns>
|
||||||
</member>
|
</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">
|
<member name="T:CryptoExchange.Net.Objects.CallResult`1">
|
||||||
<summary>
|
<summary>
|
||||||
The result of an operation
|
The result of an operation
|
||||||
@ -1210,16 +1572,6 @@
|
|||||||
The data returned by the call
|
The data returned by the call
|
||||||
</summary>
|
</summary>
|
||||||
</member>
|
</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)">
|
<member name="M:CryptoExchange.Net.Objects.CallResult`1.#ctor(`0,CryptoExchange.Net.Objects.Error)">
|
||||||
<summary>
|
<summary>
|
||||||
ctor
|
ctor
|
||||||
@ -1233,6 +1585,60 @@
|
|||||||
</summary>
|
</summary>
|
||||||
<param name="obj"></param>
|
<param name="obj"></param>
|
||||||
</member>
|
</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">
|
<member name="T:CryptoExchange.Net.Objects.WebCallResult`1">
|
||||||
<summary>
|
<summary>
|
||||||
The result of a request
|
The result of a request
|
||||||
@ -1258,11 +1664,18 @@
|
|||||||
<param name="data"></param>
|
<param name="data"></param>
|
||||||
<param name="error"></param>
|
<param name="error"></param>
|
||||||
</member>
|
</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>
|
<summary>
|
||||||
Create an error result
|
Create new based on existing
|
||||||
</summary>
|
</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>
|
<returns></returns>
|
||||||
</member>
|
</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)">
|
<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>
|
||||||
<member name="P:CryptoExchange.Net.Objects.Error.Code">
|
<member name="P:CryptoExchange.Net.Objects.Error.Code">
|
||||||
<summary>
|
<summary>
|
||||||
The error code
|
The error code from the server
|
||||||
</summary>
|
</summary>
|
||||||
</member>
|
</member>
|
||||||
<member name="P:CryptoExchange.Net.Objects.Error.Message">
|
<member name="P:CryptoExchange.Net.Objects.Error.Message">
|
||||||
<summary>
|
<summary>
|
||||||
The message for the error that occured
|
The message for the error that occurred
|
||||||
</summary>
|
</summary>
|
||||||
</member>
|
</member>
|
||||||
<member name="P:CryptoExchange.Net.Objects.Error.Data">
|
<member name="P:CryptoExchange.Net.Objects.Error.Data">
|
||||||
<summary>
|
<summary>
|
||||||
Optional data for the error
|
The data which caused the error
|
||||||
</summary>
|
</summary>
|
||||||
</member>
|
</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>
|
<summary>
|
||||||
ctor
|
ctor
|
||||||
</summary>
|
</summary>
|
||||||
@ -1473,10 +1886,19 @@
|
|||||||
Web error returned by the server
|
Web error returned by the server
|
||||||
</summary>
|
</summary>
|
||||||
</member>
|
</member>
|
||||||
<member name="M:CryptoExchange.Net.Objects.WebError.#ctor(System.Object)">
|
<member name="M:CryptoExchange.Net.Objects.WebError.#ctor(System.String,System.Object)">
|
||||||
<summary>
|
<summary>
|
||||||
ctor
|
ctor
|
||||||
</summary>
|
</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>
|
<param name="data"></param>
|
||||||
</member>
|
</member>
|
||||||
<member name="T:CryptoExchange.Net.Objects.DeserializeError">
|
<member name="T:CryptoExchange.Net.Objects.DeserializeError">
|
||||||
@ -1484,21 +1906,23 @@
|
|||||||
Error while deserializing data
|
Error while deserializing data
|
||||||
</summary>
|
</summary>
|
||||||
</member>
|
</member>
|
||||||
<member name="M:CryptoExchange.Net.Objects.DeserializeError.#ctor(System.Object)">
|
<member name="M:CryptoExchange.Net.Objects.DeserializeError.#ctor(System.String,System.Object)">
|
||||||
<summary>
|
<summary>
|
||||||
ctor
|
ctor
|
||||||
</summary>
|
</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>
|
||||||
<member name="T:CryptoExchange.Net.Objects.UnknownError">
|
<member name="T:CryptoExchange.Net.Objects.UnknownError">
|
||||||
<summary>
|
<summary>
|
||||||
Unknown error
|
Unknown error
|
||||||
</summary>
|
</summary>
|
||||||
</member>
|
</member>
|
||||||
<member name="M:CryptoExchange.Net.Objects.UnknownError.#ctor(System.Object)">
|
<member name="M:CryptoExchange.Net.Objects.UnknownError.#ctor(System.String,System.Object)">
|
||||||
<summary>
|
<summary>
|
||||||
ctor
|
ctor
|
||||||
</summary>
|
</summary>
|
||||||
|
<param name="message">Error message</param>
|
||||||
<param name="data">Error data</param>
|
<param name="data">Error data</param>
|
||||||
</member>
|
</member>
|
||||||
<member name="T:CryptoExchange.Net.Objects.ArgumentError">
|
<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)">
|
<member name="M:CryptoExchange.Net.RateLimiter.RateLimiterAPIKey.LimitRequest(CryptoExchange.Net.RestClient,System.String,CryptoExchange.Net.Objects.RateLimitingBehaviour)">
|
||||||
<inheritdoc />
|
<inheritdoc />
|
||||||
</member>
|
</member>
|
||||||
|
<member name="M:CryptoExchange.Net.RateLimiter.RateLimiterAPIKey.Dispose">
|
||||||
|
<summary>
|
||||||
|
Dispose
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
<member name="T:CryptoExchange.Net.RateLimiter.RateLimiterPerEndpoint">
|
<member name="T:CryptoExchange.Net.RateLimiter.RateLimiterPerEndpoint">
|
||||||
<summary>
|
<summary>
|
||||||
Limits the amount of requests per time period to a certain limit, counts the request per endpoint.
|
Limits the amount of requests per time period to a certain limit, counts the request per endpoint.
|
||||||
@ -2184,10 +2613,11 @@
|
|||||||
Total requests made
|
Total requests made
|
||||||
</summary>
|
</summary>
|
||||||
</member>
|
</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>
|
<summary>
|
||||||
ctor
|
ctor
|
||||||
</summary>
|
</summary>
|
||||||
|
<param name="clientName"></param>
|
||||||
<param name="exchangeOptions"></param>
|
<param name="exchangeOptions"></param>
|
||||||
<param name="authenticationProvider"></param>
|
<param name="authenticationProvider"></param>
|
||||||
</member>
|
</member>
|
||||||
@ -2348,10 +2778,11 @@
|
|||||||
If false; data which is a response to a query won't get forwarded to subscriptions as well
|
If false; data which is a response to a query won't get forwarded to subscriptions as well
|
||||||
</summary>
|
</summary>
|
||||||
</member>
|
</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>
|
<summary>
|
||||||
Create a socket client
|
Create a socket client
|
||||||
</summary>
|
</summary>
|
||||||
|
<param name="clientName">Client name</param>
|
||||||
<param name="exchangeOptions">Client options</param>
|
<param name="exchangeOptions">Client options</param>
|
||||||
<param name="authenticationProvider">Authentication provider</param>
|
<param name="authenticationProvider">Authentication provider</param>
|
||||||
</member>
|
</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))
|
if (!allowedValues.Contains(value))
|
||||||
throw new ArgumentException(
|
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>
|
/// <summary>
|
||||||
@ -239,7 +239,7 @@ namespace CryptoExchange.Net
|
|||||||
{
|
{
|
||||||
if (value < minValue || value > maxValue)
|
if (value < minValue || value > maxValue)
|
||||||
throw new ArgumentException(
|
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>
|
/// <summary>
|
||||||
@ -250,7 +250,7 @@ namespace CryptoExchange.Net
|
|||||||
public static void ValidateNotNull(this string value, string argumentName)
|
public static void ValidateNotNull(this string value, string argumentName)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(value))
|
if (string.IsNullOrEmpty(value))
|
||||||
throw new ArgumentException($"No value provided for parameter {argumentName}");
|
throw new ArgumentException($"No value provided for parameter {argumentName}", argumentName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -261,7 +261,7 @@ namespace CryptoExchange.Net
|
|||||||
public static void ValidateNotNull(this object value, string argumentName)
|
public static void ValidateNotNull(this object value, string argumentName)
|
||||||
{
|
{
|
||||||
if (value == null)
|
if (value == null)
|
||||||
throw new ArgumentException($"No value provided for parameter {argumentName}");
|
throw new ArgumentException($"No value provided for parameter {argumentName}", argumentName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -272,7 +272,7 @@ namespace CryptoExchange.Net
|
|||||||
public static void ValidateNotNull<T>(this IEnumerable<T> value, string argumentName)
|
public static void ValidateNotNull<T>(this IEnumerable<T> value, string argumentName)
|
||||||
{
|
{
|
||||||
if (value == null || !value.Any())
|
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>
|
/// </summary>
|
||||||
string BaseAddress { get; }
|
string BaseAddress { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Client name
|
||||||
|
/// </summary>
|
||||||
|
string ClientName { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adds a rate limiter to the client. There are 2 choices, the <see cref="RateLimiterTotal"/> and the <see cref="RateLimiterPerEndpoint"/>.
|
/// Adds a rate limiter to the client. There are 2 choices, the <see cref="RateLimiterTotal"/> and the <see cref="RateLimiterPerEndpoint"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -17,11 +17,17 @@ namespace CryptoExchange.Net.Logging
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public LogVerbosity Level { get; set; } = LogVerbosity.Info;
|
public LogVerbosity Level { get; set; } = LogVerbosity.Info;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Client name
|
||||||
|
/// </summary>
|
||||||
|
public string ClientName { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ctor
|
/// ctor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Log()
|
public Log(string clientName)
|
||||||
{
|
{
|
||||||
|
ClientName = clientName;
|
||||||
writers = new List<TextWriter>();
|
writers = new List<TextWriter>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -44,7 +50,7 @@ namespace CryptoExchange.Net.Logging
|
|||||||
if ((int)logType < (int)Level)
|
if ((int)logType < (int)Level)
|
||||||
return;
|
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())
|
foreach (var writer in writers.ToList())
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
@ -7,13 +7,8 @@ namespace CryptoExchange.Net.Objects
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The result of an operation
|
/// The result of an operation
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="T"></typeparam>
|
public class CallResult
|
||||||
public class CallResult<T>
|
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// The data returned by the call
|
|
||||||
/// </summary>
|
|
||||||
public T Data { get; internal set; }
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// An error if the call didn't succeed
|
/// An error if the call didn't succeed
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -23,15 +18,56 @@ namespace CryptoExchange.Net.Objects
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public bool Success => Error == null;
|
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>
|
/// <summary>
|
||||||
/// ctor
|
/// ctor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="data"></param>
|
/// <param name="data"></param>
|
||||||
/// <param name="error"></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;
|
Data = data;
|
||||||
Error = error;
|
#pragma warning disable 8601
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -42,6 +78,92 @@ namespace CryptoExchange.Net.Objects
|
|||||||
{
|
{
|
||||||
return obj?.Success == true;
|
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>
|
/// <summary>
|
||||||
@ -71,18 +193,29 @@ namespace CryptoExchange.Net.Objects
|
|||||||
HttpStatusCode? code,
|
HttpStatusCode? code,
|
||||||
IEnumerable<KeyValuePair<string, IEnumerable<string>>>? responseHeaders, [AllowNull] T data, Error? error): base(data, error)
|
IEnumerable<KeyValuePair<string, IEnumerable<string>>>? responseHeaders, [AllowNull] T data, Error? error): base(data, error)
|
||||||
{
|
{
|
||||||
ResponseHeaders = responseHeaders;
|
|
||||||
ResponseStatusCode = code;
|
ResponseStatusCode = code;
|
||||||
|
ResponseHeaders = responseHeaders;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create an error result
|
/// Create new based on existing
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="error"></param>
|
/// <param name="callResult"></param>
|
||||||
/// <returns></returns>
|
public WebCallResult(WebCallResult<T> callResult): base(callResult.Data, callResult.Error)
|
||||||
public static WebCallResult<T> CreateErrorResult(Error 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>
|
/// <summary>
|
||||||
@ -94,7 +227,7 @@ namespace CryptoExchange.Net.Objects
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static WebCallResult<T> CreateErrorResult(HttpStatusCode? code, IEnumerable<KeyValuePair<string, IEnumerable<string>>>? responseHeaders, Error error)
|
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
|
public abstract class Error
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The error code
|
/// The error code from the server
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int Code { get; set; }
|
public int? Code { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The message for the error that occured
|
/// The message for the error that occurred
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Message { get; set; }
|
public string Message { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Optional data for the error
|
/// The data which caused the error
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public object? Data { get; set; }
|
public object? Data { get; set; }
|
||||||
|
|
||||||
@ -25,7 +26,7 @@
|
|||||||
/// <param name="code"></param>
|
/// <param name="code"></param>
|
||||||
/// <param name="message"></param>
|
/// <param name="message"></param>
|
||||||
/// <param name="data"></param>
|
/// <param name="data"></param>
|
||||||
protected Error(int code, string message, object? data)
|
protected Error(int? code, string message, object? data)
|
||||||
{
|
{
|
||||||
Code = code;
|
Code = code;
|
||||||
Message = message;
|
Message = message;
|
||||||
@ -50,7 +51,7 @@
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// ctor
|
/// ctor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public CantConnectError() : base(1, "Can't connect to the server", null) { }
|
public CantConnectError() : base(null, "Can't connect to the server", null) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -61,7 +62,7 @@
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// ctor
|
/// ctor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public NoApiCredentialsError() : base(2, "No credentials provided for private endpoint", null) { }
|
public NoApiCredentialsError() : base(null, "No credentials provided for private endpoint", null) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -74,7 +75,7 @@
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="message"></param>
|
/// <param name="message"></param>
|
||||||
/// <param name="data"></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>
|
/// <summary>
|
||||||
/// ctor
|
/// ctor
|
||||||
@ -95,8 +96,17 @@
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// ctor
|
/// ctor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <param name="message"></param>
|
||||||
/// <param name="data"></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>
|
/// <summary>
|
||||||
@ -107,8 +117,9 @@
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// ctor
|
/// ctor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="data">Deserializing data</param>
|
/// <param name="message">The error message</param>
|
||||||
public DeserializeError(object? data) : base(5, "Error deserializing data", data) { }
|
/// <param name="data">The data which caused the error</param>
|
||||||
|
public DeserializeError(string message, object? data) : base(null, message, data) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -119,8 +130,9 @@
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// ctor
|
/// ctor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <param name="message">Error message</param>
|
||||||
/// <param name="data">Error data</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>
|
/// <summary>
|
||||||
@ -132,7 +144,7 @@
|
|||||||
/// ctor
|
/// ctor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="message"></param>
|
/// <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>
|
/// <summary>
|
||||||
@ -144,7 +156,7 @@
|
|||||||
/// ctor
|
/// ctor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="message"></param>
|
/// <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>
|
/// <summary>
|
||||||
@ -155,6 +167,6 @@
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// ctor
|
/// ctor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public CancellationRequestedError() : base(9, "Cancellation requested", null) { }
|
public CancellationRequestedError() : base(null, "Cancellation requested", null) { }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -76,10 +76,22 @@ namespace CryptoExchange.Net.Objects
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class ClientOptions : BaseOptions
|
public class ClientOptions : BaseOptions
|
||||||
{
|
{
|
||||||
|
private string _baseAddress;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The base address of the client
|
/// The base address of the client
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string BaseAddress { get; set; }
|
public string BaseAddress
|
||||||
|
{
|
||||||
|
get => _baseAddress;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
var newValue = value;
|
||||||
|
if (!newValue.EndsWith("/"))
|
||||||
|
newValue += "/";
|
||||||
|
_baseAddress = newValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The api credentials
|
/// The api credentials
|
||||||
@ -89,7 +101,7 @@ namespace CryptoExchange.Net.Objects
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Should check objects for missing properties based on the model and the received JSON
|
/// Should check objects for missing properties based on the model and the received JSON
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool ShouldCheckObjects { get; set; } = true;
|
public bool ShouldCheckObjects { get; set; } = false;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Proxy to use
|
/// Proxy to use
|
||||||
@ -100,7 +112,9 @@ namespace CryptoExchange.Net.Objects
|
|||||||
/// ctor
|
/// ctor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="baseAddress"></param>
|
/// <param name="baseAddress"></param>
|
||||||
|
#pragma warning disable 8618
|
||||||
public ClientOptions(string baseAddress)
|
public ClientOptions(string baseAddress)
|
||||||
|
#pragma warning restore 8618
|
||||||
{
|
{
|
||||||
BaseAddress = baseAddress;
|
BaseAddress = baseAddress;
|
||||||
}
|
}
|
||||||
|
@ -39,8 +39,8 @@ namespace CryptoExchange.Net.OrderBook
|
|||||||
private readonly bool strictLevels;
|
private readonly bool strictLevels;
|
||||||
|
|
||||||
private Task? _processTask;
|
private Task? _processTask;
|
||||||
private AutoResetEvent _queueEvent;
|
private readonly AutoResetEvent _queueEvent;
|
||||||
private ConcurrentQueue<object> _processQueue;
|
private readonly ConcurrentQueue<object> _processQueue;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Order book implementation id
|
/// Order book implementation id
|
||||||
@ -208,7 +208,7 @@ namespace CryptoExchange.Net.OrderBook
|
|||||||
asks = new SortedList<decimal, ISymbolOrderBookEntry>();
|
asks = new SortedList<decimal, ISymbolOrderBookEntry>();
|
||||||
bids = new SortedList<decimal, ISymbolOrderBookEntry>(new DescComparer<decimal>());
|
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() };
|
var writers = options.LogWriters ?? new List<TextWriter> { new DebugTextWriter() };
|
||||||
log.UpdateWriters(writers.ToList());
|
log.UpdateWriters(writers.ToList());
|
||||||
}
|
}
|
||||||
@ -377,7 +377,7 @@ namespace CryptoExchange.Net.OrderBook
|
|||||||
FirstUpdateId = item.StartUpdateId,
|
FirstUpdateId = item.StartUpdateId,
|
||||||
LastUpdateId = item.EndUpdateId,
|
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
|
else
|
||||||
{
|
{
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using CryptoExchange.Net.Interfaces;
|
using CryptoExchange.Net.Interfaces;
|
||||||
using CryptoExchange.Net.Objects;
|
using CryptoExchange.Net.Objects;
|
||||||
@ -10,10 +12,11 @@ namespace CryptoExchange.Net.RateLimiter
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Limits the amount of requests per time period to a certain limit, counts the request per API key.
|
/// Limits the amount of requests per time period to a certain limit, counts the request per API key.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class RateLimiterAPIKey: IRateLimiter
|
public class RateLimiterAPIKey: IRateLimiter, IDisposable
|
||||||
{
|
{
|
||||||
internal Dictionary<string, RateLimitObject> history = new Dictionary<string, RateLimitObject>();
|
internal Dictionary<string, RateLimitObject> history = new Dictionary<string, RateLimitObject>();
|
||||||
|
|
||||||
|
private readonly SHA256 encryptor;
|
||||||
private readonly int limitPerKey;
|
private readonly int limitPerKey;
|
||||||
private readonly TimeSpan perTimePeriod;
|
private readonly TimeSpan perTimePeriod;
|
||||||
private readonly object historyLock = new object();
|
private readonly object historyLock = new object();
|
||||||
@ -26,6 +29,7 @@ namespace CryptoExchange.Net.RateLimiter
|
|||||||
public RateLimiterAPIKey(int limitPerApiKey, TimeSpan perTimePeriod)
|
public RateLimiterAPIKey(int limitPerApiKey, TimeSpan perTimePeriod)
|
||||||
{
|
{
|
||||||
limitPerKey = limitPerApiKey;
|
limitPerKey = limitPerApiKey;
|
||||||
|
encryptor = SHA256.Create();
|
||||||
this.perTimePeriod = perTimePeriod;
|
this.perTimePeriod = perTimePeriod;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -35,7 +39,14 @@ namespace CryptoExchange.Net.RateLimiter
|
|||||||
if(client.authProvider?.Credentials?.Key == null)
|
if(client.authProvider?.Credentials?.Key == null)
|
||||||
return new CallResult<double>(0, 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;
|
int waitTime;
|
||||||
RateLimitObject rlo;
|
RateLimitObject rlo;
|
||||||
@ -69,5 +80,13 @@ namespace CryptoExchange.Net.RateLimiter
|
|||||||
|
|
||||||
return new CallResult<double>(waitTime, null);
|
return new CallResult<double>(waitTime, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Dispose
|
||||||
|
/// </summary>
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
encryptor.Dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -76,9 +76,10 @@ namespace CryptoExchange.Net
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// ctor
|
/// ctor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <param name="clientName"></param>
|
||||||
/// <param name="exchangeOptions"></param>
|
/// <param name="exchangeOptions"></param>
|
||||||
/// <param name="authenticationProvider"></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)
|
if (exchangeOptions == null)
|
||||||
throw new ArgumentNullException(nameof(exchangeOptions));
|
throw new ArgumentNullException(nameof(exchangeOptions));
|
||||||
@ -232,7 +233,7 @@ namespace CryptoExchange.Net
|
|||||||
|
|
||||||
var parseResult = ValidateJson(data);
|
var parseResult = ValidateJson(data);
|
||||||
if (!parseResult.Success)
|
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);
|
var error = await TryParseError(parseResult.Data);
|
||||||
if (error != null)
|
if (error != null)
|
||||||
return WebCallResult<T>.CreateErrorResult(response.StatusCode, response.ResponseHeaders, error);
|
return WebCallResult<T>.CreateErrorResult(response.StatusCode, response.ResponseHeaders, error);
|
||||||
@ -257,7 +258,10 @@ namespace CryptoExchange.Net
|
|||||||
responseStream.Close();
|
responseStream.Close();
|
||||||
response.Close();
|
response.Close();
|
||||||
var parseResult = ValidateJson(data);
|
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)
|
catch (HttpRequestException requestException)
|
||||||
|
@ -83,9 +83,10 @@ namespace CryptoExchange.Net
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a socket client
|
/// Create a socket client
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <param name="clientName">Client name</param>
|
||||||
/// <param name="exchangeOptions">Client options</param>
|
/// <param name="exchangeOptions">Client options</param>
|
||||||
/// <param name="authenticationProvider">Authentication provider</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)
|
if (exchangeOptions == null)
|
||||||
throw new ArgumentNullException(nameof(exchangeOptions));
|
throw new ArgumentNullException(nameof(exchangeOptions));
|
||||||
@ -294,7 +295,7 @@ namespace CryptoExchange.Net
|
|||||||
|
|
||||||
var connectResult = await ConnectSocket(socket).ConfigureAwait(false);
|
var connectResult = await ConnectSocket(socket).ConfigureAwait(false);
|
||||||
if (!connectResult)
|
if (!connectResult)
|
||||||
return new CallResult<bool>(false, new CantConnectError());
|
return new CallResult<bool>(false, connectResult.Error);
|
||||||
|
|
||||||
if (!authenticated || socket.Authenticated)
|
if (!authenticated || socket.Authenticated)
|
||||||
return new CallResult<bool>(true, null);
|
return new CallResult<bool>(true, null);
|
||||||
@ -427,7 +428,8 @@ namespace CryptoExchange.Net
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
protected virtual SocketConnection GetWebsocket(string address, bool authenticated)
|
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;
|
var result = socketResult.Equals(default(KeyValuePair<int, SocketConnection>)) ? null : socketResult.Value;
|
||||||
if (result != null)
|
if (result != null)
|
||||||
{
|
{
|
||||||
|
25
README.md
25
README.md
@ -61,6 +61,10 @@ Implementations from third parties
|
|||||||
<br />
|
<br />
|
||||||
<a href="https://github.com/ridicoulous/Bitmex.Net">Bitmex</a>
|
<a href="https://github.com/ridicoulous/Bitmex.Net">Bitmex</a>
|
||||||
</td>
|
</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>
|
</tr>
|
||||||
</table>
|
</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.
|
To stop synchronizing an order book use the `Stop` method.
|
||||||
|
|
||||||
## Release notes
|
## 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
|
* Version 3.0.14 - 24 Aug 2020
|
||||||
* Updated exception message logging
|
* Updated exception message logging
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user