mirror of
https://github.com/JKorf/CryptoExchange.Net.git
synced 2026-10-14 15:11:44 +00:00
Compare commits
21 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 08972d3d63 | |||
| 357809fd0c | |||
| 7629455dec | |||
| 9df960361a | |||
| f215b729ed | |||
| 431ef93611 | |||
| a545efbb45 | |||
| 67bf7d08cb | |||
| 2704693600 | |||
| 1643487e73 | |||
| 1a0101a45f | |||
| 20977e28b7 | |||
| d0f5a8d6cc | |||
| 2fff7a307f | |||
| ca2bf414a7 | |||
| 5f101e3b88 | |||
| 32e74e9bc4 | |||
| d93d6b7a2e | |||
| d0ce2563de | |||
| 407509e9cd | |||
| 3dd68dcad4 |
@@ -0,0 +1,281 @@
|
||||
using CryptoExchange.Net.Objects;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using NUnit.Framework;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace CryptoExchange.Net.UnitTests
|
||||
{
|
||||
[TestFixture]
|
||||
public class RequestCoalescerTests
|
||||
{
|
||||
private static readonly TimeSpan _testTimeout = TimeSpan.FromSeconds(5);
|
||||
|
||||
[Test]
|
||||
public async Task ExecuteAsync_WithIdenticalRequests_ShouldExecuteRequestOnce()
|
||||
{
|
||||
var coalescer = CreateCoalescer();
|
||||
var key = CreateKey();
|
||||
var requestCompletion = CreateCompletionSource<string>();
|
||||
var requestStarted = CreateCompletionSource<bool>();
|
||||
var requestCount = 0;
|
||||
|
||||
async Task<string> ExecuteRequest(CancellationToken cancellationToken)
|
||||
{
|
||||
Interlocked.Increment(ref requestCount);
|
||||
requestStarted.TrySetResult(true);
|
||||
return await requestCompletion.Task;
|
||||
}
|
||||
|
||||
var first = coalescer.ExecuteAsync(key, ExecuteRequest, () => "canceled", CancellationToken.None);
|
||||
await requestStarted.Task.WaitAsync(_testTimeout);
|
||||
var second = coalescer.ExecuteAsync(key, ExecuteRequest, () => "canceled", CancellationToken.None);
|
||||
|
||||
Assert.That(requestCount, Is.EqualTo(1));
|
||||
|
||||
requestCompletion.SetResult("result");
|
||||
|
||||
Assert.That(await first.WaitAsync(_testTimeout), Is.EqualTo("result"));
|
||||
Assert.That(await second.WaitAsync(_testTimeout), Is.EqualTo("result"));
|
||||
Assert.That(requestCount, Is.EqualTo(1));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task ExecuteAsync_WithDifferentKeys_ShouldExecuteEachRequest()
|
||||
{
|
||||
var coalescer = CreateCoalescer();
|
||||
var firstCompletion = CreateCompletionSource<string>();
|
||||
var secondCompletion = CreateCompletionSource<string>();
|
||||
var firstStarted = CreateCompletionSource<bool>();
|
||||
var secondStarted = CreateCompletionSource<bool>();
|
||||
var requestCount = 0;
|
||||
|
||||
var first = coalescer.ExecuteAsync(
|
||||
CreateKey(parameters: "symbol=ETH"),
|
||||
async cancellationToken =>
|
||||
{
|
||||
Interlocked.Increment(ref requestCount);
|
||||
firstStarted.TrySetResult(true);
|
||||
return await firstCompletion.Task;
|
||||
},
|
||||
() => "canceled",
|
||||
CancellationToken.None);
|
||||
|
||||
var second = coalescer.ExecuteAsync(
|
||||
CreateKey(parameters: "symbol=BTC"),
|
||||
async cancellationToken =>
|
||||
{
|
||||
Interlocked.Increment(ref requestCount);
|
||||
secondStarted.TrySetResult(true);
|
||||
return await secondCompletion.Task;
|
||||
},
|
||||
() => "canceled",
|
||||
CancellationToken.None);
|
||||
|
||||
await Task.WhenAll(firstStarted.Task, secondStarted.Task).WaitAsync(_testTimeout);
|
||||
Assert.That(requestCount, Is.EqualTo(2));
|
||||
|
||||
firstCompletion.SetResult("first");
|
||||
secondCompletion.SetResult("second");
|
||||
|
||||
Assert.That(await first.WaitAsync(_testTimeout), Is.EqualTo("first"));
|
||||
Assert.That(await second.WaitAsync(_testTimeout), Is.EqualTo("second"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task ExecuteAsync_WhenOneListenerCancels_ShouldKeepSharedRequestRunning()
|
||||
{
|
||||
var coalescer = CreateCoalescer();
|
||||
var requestCompletion = CreateCompletionSource<string>();
|
||||
var requestStarted = CreateCompletionSource<CancellationToken>();
|
||||
var requestCount = 0;
|
||||
using var firstCancellationSource = new CancellationTokenSource();
|
||||
|
||||
async Task<string> ExecuteRequest(CancellationToken cancellationToken)
|
||||
{
|
||||
Interlocked.Increment(ref requestCount);
|
||||
requestStarted.TrySetResult(cancellationToken);
|
||||
return await requestCompletion.Task;
|
||||
}
|
||||
|
||||
var first = coalescer.ExecuteAsync(CreateKey(), ExecuteRequest, () => "canceled", firstCancellationSource.Token);
|
||||
var requestCancellationToken = await requestStarted.Task.WaitAsync(_testTimeout);
|
||||
var second = coalescer.ExecuteAsync(CreateKey(), ExecuteRequest, () => "canceled", CancellationToken.None);
|
||||
|
||||
firstCancellationSource.Cancel();
|
||||
|
||||
Assert.That(await first.WaitAsync(_testTimeout), Is.EqualTo("canceled"));
|
||||
Assert.That(requestCancellationToken.IsCancellationRequested, Is.False);
|
||||
Assert.That(requestCount, Is.EqualTo(1));
|
||||
|
||||
requestCompletion.SetResult("result");
|
||||
|
||||
Assert.That(await second.WaitAsync(_testTimeout), Is.EqualTo("result"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task ExecuteAsync_WhenAllListenersCancel_ShouldCancelSharedRequest()
|
||||
{
|
||||
var coalescer = CreateCoalescer();
|
||||
var requestStarted = CreateCompletionSource<bool>();
|
||||
var requestCanceled = CreateCompletionSource<bool>();
|
||||
using var firstCancellationSource = new CancellationTokenSource();
|
||||
using var secondCancellationSource = new CancellationTokenSource();
|
||||
|
||||
async Task<string> ExecuteRequest(CancellationToken cancellationToken)
|
||||
{
|
||||
using (cancellationToken.Register(() => requestCanceled.TrySetResult(true)))
|
||||
{
|
||||
requestStarted.TrySetResult(true);
|
||||
await requestCanceled.Task;
|
||||
return "request canceled";
|
||||
}
|
||||
}
|
||||
|
||||
var first = coalescer.ExecuteAsync(CreateKey(), ExecuteRequest, () => "listener canceled", firstCancellationSource.Token);
|
||||
await requestStarted.Task.WaitAsync(_testTimeout);
|
||||
var second = coalescer.ExecuteAsync(CreateKey(), ExecuteRequest, () => "listener canceled", secondCancellationSource.Token);
|
||||
|
||||
firstCancellationSource.Cancel();
|
||||
Assert.That(await first.WaitAsync(_testTimeout), Is.EqualTo("listener canceled"));
|
||||
Assert.That(requestCanceled.Task.IsCompleted, Is.False);
|
||||
|
||||
secondCancellationSource.Cancel();
|
||||
|
||||
Assert.That(await second.WaitAsync(_testTimeout), Is.EqualTo("listener canceled"));
|
||||
Assert.That(await requestCanceled.Task.WaitAsync(_testTimeout), Is.True);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task ExecuteAsync_WithAlreadyCanceledListener_ShouldNotStartRequest()
|
||||
{
|
||||
var coalescer = CreateCoalescer();
|
||||
var requestCount = 0;
|
||||
using var cancellationSource = new CancellationTokenSource();
|
||||
cancellationSource.Cancel();
|
||||
|
||||
var result = await coalescer.ExecuteAsync(
|
||||
CreateKey(),
|
||||
cancellationToken =>
|
||||
{
|
||||
Interlocked.Increment(ref requestCount);
|
||||
return Task.FromResult("result");
|
||||
},
|
||||
() => "canceled",
|
||||
cancellationSource.Token);
|
||||
|
||||
Assert.That(result, Is.EqualTo("canceled"));
|
||||
Assert.That(requestCount, Is.Zero);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task ExecuteAsync_AfterRequestCompletes_ShouldStartNewRequest()
|
||||
{
|
||||
var coalescer = CreateCoalescer();
|
||||
var requestCount = 0;
|
||||
|
||||
Task<int> ExecuteRequest(CancellationToken cancellationToken)
|
||||
=> Task.FromResult(Interlocked.Increment(ref requestCount));
|
||||
|
||||
var first = await coalescer.ExecuteAsync(CreateKey(typeof(int)), ExecuteRequest, () => -1, CancellationToken.None);
|
||||
var second = await coalescer.ExecuteAsync(CreateKey(typeof(int)), ExecuteRequest, () => -1, CancellationToken.None);
|
||||
|
||||
Assert.That(first, Is.EqualTo(1));
|
||||
Assert.That(second, Is.EqualTo(2));
|
||||
Assert.That(requestCount, Is.EqualTo(2));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ExecuteAsync_AfterRequestFails_ShouldStartNewRequest()
|
||||
{
|
||||
var coalescer = CreateCoalescer();
|
||||
var requestCount = 0;
|
||||
|
||||
Task<string> ExecuteRequest(CancellationToken cancellationToken)
|
||||
{
|
||||
if (Interlocked.Increment(ref requestCount) == 1)
|
||||
return Task.FromException<string>(new InvalidOperationException("Request failed"));
|
||||
|
||||
return Task.FromResult("result");
|
||||
}
|
||||
|
||||
Assert.ThrowsAsync<InvalidOperationException>(async () =>
|
||||
await coalescer.ExecuteAsync(CreateKey(), ExecuteRequest, () => "canceled", CancellationToken.None));
|
||||
|
||||
Assert.That(
|
||||
coalescer.ExecuteAsync(CreateKey(), ExecuteRequest, () => "canceled", CancellationToken.None).GetAwaiter().GetResult(),
|
||||
Is.EqualTo("result"));
|
||||
Assert.That(requestCount, Is.EqualTo(2));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task ExecuteAsync_WhenAbandonedRequestCompletes_ShouldNotRemoveReplacementRequest()
|
||||
{
|
||||
var coalescer = CreateCoalescer();
|
||||
var key = CreateKey();
|
||||
var oldRequestCompletion = CreateCompletionSource<string>();
|
||||
var oldRequestStarted = CreateCompletionSource<bool>();
|
||||
var replacementCompletion = CreateCompletionSource<string>();
|
||||
var replacementStarted = CreateCompletionSource<bool>();
|
||||
var requestCount = 0;
|
||||
using var cancellationSource = new CancellationTokenSource();
|
||||
|
||||
async Task<string> ExecuteOldRequest(CancellationToken cancellationToken)
|
||||
{
|
||||
Interlocked.Increment(ref requestCount);
|
||||
oldRequestStarted.TrySetResult(true);
|
||||
return await oldRequestCompletion.Task;
|
||||
}
|
||||
|
||||
async Task<string> ExecuteReplacementRequest(CancellationToken cancellationToken)
|
||||
{
|
||||
Interlocked.Increment(ref requestCount);
|
||||
replacementStarted.TrySetResult(true);
|
||||
return await replacementCompletion.Task;
|
||||
}
|
||||
|
||||
var abandonedListener = coalescer.ExecuteAsync(key, ExecuteOldRequest, () => "canceled", cancellationSource.Token);
|
||||
await oldRequestStarted.Task.WaitAsync(_testTimeout);
|
||||
var oldPhysicalRequest = GetPhysicalRequest(coalescer, key);
|
||||
|
||||
cancellationSource.Cancel();
|
||||
Assert.That(await abandonedListener.WaitAsync(_testTimeout), Is.EqualTo("canceled"));
|
||||
|
||||
var replacementListener = coalescer.ExecuteAsync(key, ExecuteReplacementRequest, () => "canceled", CancellationToken.None);
|
||||
await replacementStarted.Task.WaitAsync(_testTimeout);
|
||||
|
||||
oldRequestCompletion.SetResult("old result");
|
||||
await oldPhysicalRequest.WaitAsync(_testTimeout);
|
||||
|
||||
var joinedReplacementListener = coalescer.ExecuteAsync(key, ExecuteReplacementRequest, () => "canceled", CancellationToken.None);
|
||||
Assert.That(requestCount, Is.EqualTo(2));
|
||||
|
||||
replacementCompletion.SetResult("replacement result");
|
||||
|
||||
Assert.That(await replacementListener.WaitAsync(_testTimeout), Is.EqualTo("replacement result"));
|
||||
Assert.That(await joinedReplacementListener.WaitAsync(_testTimeout), Is.EqualTo("replacement result"));
|
||||
Assert.That(requestCount, Is.EqualTo(2));
|
||||
}
|
||||
|
||||
private static RequestCoalescer CreateCoalescer()
|
||||
=> new RequestCoalescer(NullLogger.Instance);
|
||||
|
||||
private static RequestCoalescingKey CreateKey(Type? responseType = null, string? parameters = null)
|
||||
=> new RequestCoalescingKey("GET", "https://localhost/test", parameters, responseType ?? typeof(string));
|
||||
|
||||
private static TaskCompletionSource<T> CreateCompletionSource<T>()
|
||||
=> new TaskCompletionSource<T>(TaskCreationOptions.RunContinuationsAsynchronously);
|
||||
|
||||
private static Task GetPhysicalRequest(RequestCoalescer coalescer, RequestCoalescingKey key)
|
||||
{
|
||||
var requestsField = typeof(RequestCoalescer).GetField("_requests", BindingFlags.Instance | BindingFlags.NonPublic)!;
|
||||
var requests = (IDictionary)requestsField.GetValue(coalescer)!;
|
||||
var entry = requests[key]!;
|
||||
var requestProperty = entry.GetType().GetProperty("Request")!;
|
||||
return ((Lazy<Task<object>>)requestProperty.GetValue(entry)!).Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
using NUnit.Framework;
|
||||
using CryptoExchange.Net.SharedApis;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
namespace CryptoExchange.Net.UnitTests
|
||||
{
|
||||
[TestFixture]
|
||||
internal class SharedParametersTests
|
||||
{
|
||||
[Test]
|
||||
public void AllSharedAPIOptions_ShouldListAllDefaultParametersInRequestParameterRules()
|
||||
{
|
||||
var failures = new List<string>();
|
||||
|
||||
var optionsTypes = typeof(CapabilityOptions).Assembly
|
||||
.GetTypes()
|
||||
.Where(x => x.IsClass
|
||||
&& !x.IsAbstract
|
||||
&& typeof(CapabilityOptions).IsAssignableFrom(x))
|
||||
.OrderBy(x => x.FullName)
|
||||
.ToArray();
|
||||
|
||||
foreach (var optionsType in optionsTypes)
|
||||
{
|
||||
var genericOptionsType = GetGenericOptionsType(optionsType);
|
||||
if (genericOptionsType == null)
|
||||
{
|
||||
if (optionsType == typeof(ClosePositionOptions))
|
||||
continue;
|
||||
|
||||
failures.Add($"{optionsType.Name}: unable to determine request type");
|
||||
continue;
|
||||
}
|
||||
|
||||
var requestType = genericOptionsType.GetGenericArguments()[0];
|
||||
var defaultRulesField = GetDefaultParameterRulesField(optionsType);
|
||||
if (defaultRulesField == null)
|
||||
{
|
||||
failures.Add($"{optionsType.Name}: no _defaultParameterRules field found");
|
||||
continue;
|
||||
}
|
||||
|
||||
var rules = (RequestParameterDescription[]?)defaultRulesField.GetValue(null);
|
||||
if (rules == null)
|
||||
{
|
||||
failures.Add($"{optionsType.Name}: _defaultParameterRules is null");
|
||||
continue;
|
||||
}
|
||||
|
||||
var constructorParameterNames = requestType
|
||||
.GetConstructors(BindingFlags.Instance | BindingFlags.Public)
|
||||
.SelectMany(x => x.GetParameters())
|
||||
.Where(x => !string.Equals(
|
||||
x.Name,
|
||||
"exchangeParameters",
|
||||
StringComparison.OrdinalIgnoreCase))
|
||||
.Select(x => x.Name!)
|
||||
.ToHashSet(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
var parameterProperties = requestType
|
||||
.GetProperties(BindingFlags.Instance | BindingFlags.Public)
|
||||
.Where(x => x.DeclaringType == requestType
|
||||
|| constructorParameterNames.Contains(x.Name))
|
||||
.Where(x => x.Name != nameof(SharedRequest.ExchangeParameters))
|
||||
.Select(x => x.Name)
|
||||
.OrderBy(x => x)
|
||||
.ToArray();
|
||||
|
||||
var ruleNames = rules
|
||||
.Select(x => x.Name)
|
||||
.ToHashSet(StringComparer.Ordinal);
|
||||
|
||||
foreach (var parameterProperty in parameterProperties)
|
||||
{
|
||||
if (!ruleNames.Contains(parameterProperty))
|
||||
{
|
||||
failures.Add(
|
||||
$"{optionsType.Name}: request property " +
|
||||
$"{requestType.Name}.{parameterProperty} has no default request parameter rule");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Assert.That(
|
||||
failures,
|
||||
Is.Empty,
|
||||
$"Missing default request parameter rules:{Environment.NewLine}" +
|
||||
string.Join(Environment.NewLine, failures));
|
||||
}
|
||||
|
||||
private static Type? GetGenericOptionsType(Type optionsType)
|
||||
{
|
||||
for (var type = optionsType; type != null; type = type.BaseType)
|
||||
{
|
||||
if (type.IsGenericType
|
||||
&& type.GetGenericTypeDefinition() == typeof(CapabilityOptions<,>))
|
||||
return type;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static FieldInfo? GetDefaultParameterRulesField(Type optionsType)
|
||||
{
|
||||
for (var type = optionsType; type != null; type = type.BaseType)
|
||||
{
|
||||
var field = type.GetField(
|
||||
"_defaultParameterRules",
|
||||
BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.DeclaredOnly);
|
||||
if (field != null)
|
||||
return field;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -98,6 +98,10 @@ namespace CryptoExchange.Net.Clients
|
||||
/// Configured environment name
|
||||
/// </summary>
|
||||
public abstract string EnvironmentName { get; }
|
||||
/// <summary>
|
||||
/// Request coalescer
|
||||
/// </summary>
|
||||
protected RequestCoalescer RequestCoalescer { get; }
|
||||
|
||||
/// <summary>
|
||||
/// ctor
|
||||
@@ -123,6 +127,7 @@ namespace CryptoExchange.Net.Clients
|
||||
{
|
||||
TimeOffsetManager.RegisterRestApi(ClientName);
|
||||
|
||||
RequestCoalescer = new RequestCoalescer(_logger);
|
||||
RequestFactory.Configure(options, httpClient);
|
||||
}
|
||||
|
||||
@@ -177,8 +182,7 @@ namespace CryptoExchange.Net.Clients
|
||||
/// <param name="weight">Override the request weight for this request definition, for example when the weight depends on the parameters</param>
|
||||
/// <param name="weightSingleLimiter">Specify the weight to apply to the individual rate limit guard for this request</param>
|
||||
/// <param name="rateLimitKeySuffix">An additional optional suffix for the key selector. Can be used to make rate limiting work based on parameters.</param>
|
||||
/// <returns></returns>
|
||||
protected virtual async Task<HttpResult<T>> SendAsync<T>(
|
||||
protected virtual Task<HttpResult<T>> SendAsync<T>(
|
||||
RequestDefinition definition,
|
||||
Parameters? uriParameters,
|
||||
Parameters? bodyParameters,
|
||||
@@ -187,6 +191,61 @@ namespace CryptoExchange.Net.Clients
|
||||
int? weight = null,
|
||||
int? weightSingleLimiter = null,
|
||||
string? rateLimitKeySuffix = null)
|
||||
{
|
||||
if (!ShouldCoalesce(definition, additionalHeaders))
|
||||
{
|
||||
return SendCoreAsync<T>(
|
||||
definition,
|
||||
uriParameters,
|
||||
bodyParameters,
|
||||
cancellationToken,
|
||||
additionalHeaders,
|
||||
weight,
|
||||
weightSingleLimiter,
|
||||
rateLimitKeySuffix);
|
||||
}
|
||||
|
||||
var key = GetRequestCoalescingKey<T>(
|
||||
definition,
|
||||
uriParameters);
|
||||
|
||||
return RequestCoalescer.ExecuteAsync(
|
||||
key,
|
||||
requestCancellationToken => SendCoreAsync<T>(
|
||||
definition,
|
||||
uriParameters,
|
||||
bodyParameters,
|
||||
requestCancellationToken,
|
||||
additionalHeaders,
|
||||
weight,
|
||||
weightSingleLimiter,
|
||||
rateLimitKeySuffix),
|
||||
() => HttpResult.Fail<T>(
|
||||
Exchange,
|
||||
new CancellationRequestedError()),
|
||||
cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Send a request to the base address based on the request definition
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Response type</typeparam>
|
||||
/// <param name="definition">Request definition</param>
|
||||
/// <param name="uriParameters">Request query parameters</param>
|
||||
/// <param name="bodyParameters">Request body parameters</param>
|
||||
/// <param name="cancellationToken">Cancellation token</param>
|
||||
/// <param name="additionalHeaders">Additional headers for this request</param>
|
||||
/// <param name="weight">Override the request weight for this request definition, for example when the weight depends on the parameters</param>
|
||||
/// <param name="weightSingleLimiter">Specify the weight to apply to the individual rate limit guard for this request</param>
|
||||
/// <param name="rateLimitKeySuffix">An additional optional suffix for the key selector. Can be used to make rate limiting work based on parameters.</param>
|
||||
protected virtual async Task<HttpResult<T>> SendCoreAsync<T>(RequestDefinition definition,
|
||||
Parameters? uriParameters,
|
||||
Parameters? bodyParameters,
|
||||
CancellationToken cancellationToken,
|
||||
Dictionary<string, string>? additionalHeaders = null,
|
||||
int? weight = null,
|
||||
int? weightSingleLimiter = null,
|
||||
string? rateLimitKeySuffix = null)
|
||||
{
|
||||
var requestId = ExchangeHelpers.NextId();
|
||||
if (definition.Authenticated && GetAuthenticationProvider() == null)
|
||||
@@ -688,7 +747,10 @@ namespace CryptoExchange.Net.Clients
|
||||
stringData = stringSerializer.Serialize(parameters.BodyValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
stringData = stringSerializer.Serialize(parameters);
|
||||
}
|
||||
|
||||
request.SetContent(stringData, RequestBodyContentEncoding, contentType);
|
||||
}
|
||||
else if (contentType == Constants.FormContentHeader)
|
||||
@@ -808,6 +870,34 @@ namespace CryptoExchange.Net.Clients
|
||||
return definition.FullUrl + definition + parameters?.ToFormData();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Whether a request can be coalesced or not
|
||||
/// </summary>
|
||||
protected virtual bool ShouldCoalesce(
|
||||
RequestDefinition definition,
|
||||
Dictionary<string, string>? additionalHeaders)
|
||||
{
|
||||
return ClientOptions.RequestCoalescingEnabled // Enabled in client options
|
||||
&& !definition.PreventRequestCoalescing // Enabled in request definition
|
||||
&& definition.Method == HttpMethod.Get // Is a GET request
|
||||
&& !definition.Authenticated // Not an authenticated request
|
||||
&& (additionalHeaders == null || additionalHeaders.Count == 0); // No additional headers that might change the response
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a unique key for coalescing requests based on the request definition, parameters, and the type of the expected response.
|
||||
/// </summary>
|
||||
protected virtual RequestCoalescingKey GetRequestCoalescingKey<T>(
|
||||
RequestDefinition definition,
|
||||
Parameters? uriParameters)
|
||||
{
|
||||
return new RequestCoalescingKey(
|
||||
definition.Method.Method,
|
||||
definition.FullUrl,
|
||||
uriParameters?.ToFormData(),
|
||||
typeof(T));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual void SetOptions(UpdateOptions options)
|
||||
{
|
||||
|
||||
@@ -4,6 +4,7 @@ using CryptoExchange.Net.SharedApis;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
@@ -395,7 +396,6 @@ namespace CryptoExchange.Net
|
||||
services.AddTransient(x => (IBookTickerRestClient)client(x)!);
|
||||
if (typeof(ITransferRestClient).IsAssignableFrom(typeof(T)))
|
||||
services.AddTransient(x => (ITransferRestClient)client(x)!);
|
||||
|
||||
if (typeof(ISpotOrderRestClient).IsAssignableFrom(typeof(T)))
|
||||
services.AddTransient(x => (ISpotOrderRestClient)client(x)!);
|
||||
if (typeof(ISpotSymbolRestClient).IsAssignableFrom(typeof(T)))
|
||||
@@ -474,6 +474,47 @@ namespace CryptoExchange.Net
|
||||
return services;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Registers a strict Shared API aggregate and all capability interfaces implemented by it.
|
||||
/// </summary>
|
||||
public static IServiceCollection RegisterSharedApi<
|
||||
#if NET5_0_OR_GREATER
|
||||
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)]
|
||||
#endif
|
||||
TSharedApi>(
|
||||
this IServiceCollection services,
|
||||
Func<IServiceProvider, TSharedApi> factory)
|
||||
where TSharedApi : class, ISharedApi
|
||||
{
|
||||
services.AddTransient<TSharedApi>(factory);
|
||||
|
||||
var markerInterfaces = new[]
|
||||
{
|
||||
typeof(ISharedApiCapability),
|
||||
typeof(ISharedRest),
|
||||
typeof(ISharedSocket),
|
||||
typeof(ISharedSubscription)
|
||||
};
|
||||
|
||||
var capabilityInterfaces = typeof(TSharedApi)
|
||||
.GetInterfaces()
|
||||
.Where(x =>
|
||||
typeof(ISharedApiCapability).IsAssignableFrom(x)
|
||||
&& !markerInterfaces.Contains(x))
|
||||
.Distinct()
|
||||
.ToArray();
|
||||
|
||||
foreach (var capabilityInterface in capabilityInterfaces)
|
||||
{
|
||||
services.AddTransient(
|
||||
capabilityInterface,
|
||||
serviceProvider =>
|
||||
serviceProvider.GetRequiredService<TSharedApi>());
|
||||
}
|
||||
|
||||
return services;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert a hex encoded string to byte array
|
||||
/// </summary>
|
||||
|
||||
@@ -22,6 +22,7 @@ namespace CryptoExchange.Net.Logging.Extensions
|
||||
private static readonly Action<ILogger, string, Exception?> _restApiCacheHit;
|
||||
private static readonly Action<ILogger, string, Exception?> _restApiCacheNotHit;
|
||||
private static readonly Action<ILogger, int?, Exception?> _restApiCancellationRequested;
|
||||
private static readonly Action<ILogger, string, string, Exception?> _restApiRequestsJoined;
|
||||
|
||||
static RestApiClientLoggingExtensions()
|
||||
{
|
||||
@@ -89,7 +90,11 @@ namespace CryptoExchange.Net.Logging.Extensions
|
||||
LogLevel.Debug,
|
||||
new EventId(4012, "RestApiCancellationRequested"),
|
||||
"[Req {RequestId}] request cancelled by user");
|
||||
|
||||
|
||||
_restApiRequestsJoined = LoggerMessage.Define<string, string>(
|
||||
LogLevel.Debug,
|
||||
new EventId(4013, "RestApiRequestsJoined"),
|
||||
"Request for {Method} {Path} joined with in flight request");
|
||||
}
|
||||
|
||||
public static void RestApiErrorReceived(this ILogger logger, int? requestId, HttpStatusCode? responseStatusCode, long responseTime, string? error, string? originalData, Exception? exception)
|
||||
@@ -151,9 +156,15 @@ namespace CryptoExchange.Net.Logging.Extensions
|
||||
{
|
||||
_restApiCacheNotHit(logger, key, null);
|
||||
}
|
||||
|
||||
public static void RestApiCancellationRequested(this ILogger logger, int? requestId)
|
||||
{
|
||||
_restApiCancellationRequested(logger, requestId, null);
|
||||
}
|
||||
|
||||
public static void RestApiRequestsJoined(this ILogger logger, string method, string path)
|
||||
{
|
||||
_restApiRequestsJoined(logger, method, path, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,6 +34,11 @@ namespace CryptoExchange.Net.Objects.Options
|
||||
= new Version(1, 1);
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Whether concurrent identical REST requests may share the same in-flight request when allowed by the request definition.
|
||||
/// </summary>
|
||||
public bool RequestCoalescingEnabled { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Http client keep alive interval for keeping connections open. Only applied when using dotnet8.0 or higher and dependency injection
|
||||
/// </summary>
|
||||
@@ -73,6 +78,7 @@ namespace CryptoExchange.Net.Objects.Options
|
||||
item.CachingEnabled = CachingEnabled;
|
||||
item.CachingMaxAge = CachingMaxAge;
|
||||
item.HttpVersion = HttpVersion;
|
||||
item.RequestCoalescingEnabled = RequestCoalescingEnabled;
|
||||
item.HttpKeepAliveInterval = HttpKeepAliveInterval;
|
||||
#if NET5_0_OR_GREATER
|
||||
item.HttpMaxConnectionsPerServer = HttpMaxConnectionsPerServer;
|
||||
|
||||
@@ -0,0 +1,277 @@
|
||||
using CryptoExchange.Net.Logging.Extensions;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace CryptoExchange.Net.Objects
|
||||
{
|
||||
/// <summary>
|
||||
/// Request coalescer, used to detect multiple identical requests and wait for and return only a single actual request result
|
||||
/// </summary>
|
||||
public class RequestCoalescer
|
||||
{
|
||||
private sealed class RequestEntry
|
||||
{
|
||||
public RequestCoalescingKey Key { get; }
|
||||
|
||||
public CancellationTokenSource CancellationSource { get; } = new();
|
||||
|
||||
public Lazy<Task<object>> Request { get; set; } = null!;
|
||||
|
||||
public int ListenerCount { get; set; }
|
||||
|
||||
public bool Completed { get; set; }
|
||||
|
||||
public bool CancellationInProgress { get; set; }
|
||||
|
||||
public bool Disposed { get; set; }
|
||||
|
||||
public RequestEntry(RequestCoalescingKey key)
|
||||
{
|
||||
Key = key;
|
||||
}
|
||||
}
|
||||
|
||||
private readonly object _sync = new();
|
||||
private readonly ILogger _logger;
|
||||
|
||||
private readonly Dictionary<RequestCoalescingKey, RequestEntry> _requests = new();
|
||||
|
||||
/// <summary>
|
||||
/// ctor
|
||||
/// </summary>
|
||||
public RequestCoalescer(ILogger logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Execute a request, coalescing identical requests into a single request
|
||||
/// </summary>
|
||||
public Task<TResult> ExecuteAsync<TResult>(
|
||||
RequestCoalescingKey key,
|
||||
Func<CancellationToken, Task<TResult>> requestFactory,
|
||||
Func<TResult> cancellationResultFactory,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
return Task.FromResult(cancellationResultFactory());
|
||||
|
||||
RequestEntry entry;
|
||||
bool joined;
|
||||
|
||||
lock (_sync)
|
||||
{
|
||||
joined = _requests.TryGetValue(key, out entry!);
|
||||
|
||||
if (!joined)
|
||||
{
|
||||
entry = CreateEntry(key, requestFactory);
|
||||
_requests.Add(key, entry);
|
||||
}
|
||||
|
||||
entry.ListenerCount++;
|
||||
}
|
||||
|
||||
if (joined)
|
||||
_logger.RestApiRequestsJoined(key.Method, key.Url);
|
||||
|
||||
return WaitAsync(
|
||||
entry,
|
||||
cancellationResultFactory,
|
||||
cancellationToken);
|
||||
}
|
||||
|
||||
private RequestEntry CreateEntry<TResult>(
|
||||
RequestCoalescingKey key,
|
||||
Func<CancellationToken, Task<TResult>> requestFactory)
|
||||
{
|
||||
var entry = new RequestEntry(key);
|
||||
|
||||
entry.Request = new Lazy<Task<object>>(
|
||||
() => ExecuteCoreAsync(
|
||||
entry,
|
||||
async requestCancellationToken =>
|
||||
(await requestFactory(requestCancellationToken).ConfigureAwait(false))!),
|
||||
LazyThreadSafetyMode.ExecutionAndPublication);
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
private async Task<object> ExecuteCoreAsync(
|
||||
RequestEntry entry,
|
||||
Func<CancellationToken, Task<object>> requestFactory)
|
||||
{
|
||||
try
|
||||
{
|
||||
return await requestFactory(entry.CancellationSource.Token).ConfigureAwait(false);
|
||||
}
|
||||
finally
|
||||
{
|
||||
CompleteRequest(entry);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<TResult> WaitAsync<TResult>(
|
||||
RequestEntry entry,
|
||||
Func<TResult> cancellationResultFactory,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
try
|
||||
{
|
||||
var requestTask = entry.Request.Value;
|
||||
|
||||
if (!cancellationToken.CanBeCanceled)
|
||||
return (TResult)await requestTask.ConfigureAwait(false);
|
||||
|
||||
var cancellationCompletion = new TaskCompletionSource<bool>(TaskCreationOptions.RunContinuationsAsynchronously);
|
||||
|
||||
using (cancellationToken.Register(
|
||||
state => ((TaskCompletionSource<bool>)state!).TrySetResult(true),
|
||||
cancellationCompletion))
|
||||
{
|
||||
var completedTask = await Task.WhenAny(requestTask, cancellationCompletion.Task).ConfigureAwait(false);
|
||||
if (completedTask != requestTask)
|
||||
return cancellationResultFactory();
|
||||
}
|
||||
|
||||
return (TResult)await requestTask.ConfigureAwait(false);
|
||||
}
|
||||
finally
|
||||
{
|
||||
ReleaseListener(entry);
|
||||
}
|
||||
}
|
||||
|
||||
private void ReleaseListener(RequestEntry entry)
|
||||
{
|
||||
var cancelRequest = false;
|
||||
var disposeCancellationSource = false;
|
||||
|
||||
lock (_sync)
|
||||
{
|
||||
entry.ListenerCount--;
|
||||
|
||||
if (entry.ListenerCount == 0)
|
||||
{
|
||||
if (!entry.Completed)
|
||||
{
|
||||
// Remove the entry before canceling it. A caller arriving
|
||||
// after this point must create a new physical request
|
||||
// instead of joining one that is being canceled.
|
||||
RemoveEntry(entry);
|
||||
|
||||
entry.CancellationInProgress = true;
|
||||
cancelRequest = true;
|
||||
}
|
||||
else if (!entry.Disposed)
|
||||
{
|
||||
entry.Disposed = true;
|
||||
disposeCancellationSource = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (cancelRequest)
|
||||
{
|
||||
try
|
||||
{
|
||||
entry.CancellationSource.Cancel();
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
// Cancellation callbacks are external to the coalescer and
|
||||
// must not cause an exception to escape the library.
|
||||
_logger.LogWarning(
|
||||
exception,
|
||||
"Error canceling in-flight request {Method} {Url}",
|
||||
entry.Key.Method,
|
||||
entry.Key.Url);
|
||||
}
|
||||
finally
|
||||
{
|
||||
CompleteCancellation(entry);
|
||||
}
|
||||
}
|
||||
else if (disposeCancellationSource)
|
||||
{
|
||||
entry.CancellationSource.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
private void CompleteCancellation(RequestEntry entry)
|
||||
{
|
||||
var disposeCancellationSource = false;
|
||||
|
||||
lock (_sync)
|
||||
{
|
||||
entry.CancellationInProgress = false;
|
||||
|
||||
if (entry.Completed
|
||||
&& entry.ListenerCount == 0
|
||||
&& !entry.Disposed)
|
||||
{
|
||||
entry.Disposed = true;
|
||||
disposeCancellationSource = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (disposeCancellationSource)
|
||||
entry.CancellationSource.Dispose();
|
||||
}
|
||||
|
||||
private void CompleteRequest(RequestEntry entry)
|
||||
{
|
||||
var disposeCancellationSource = false;
|
||||
|
||||
lock (_sync)
|
||||
{
|
||||
entry.Completed = true;
|
||||
|
||||
// Only remove this specific entry. If all listeners canceled,
|
||||
// a replacement request may already have been created for the
|
||||
// same key.
|
||||
RemoveEntry(entry);
|
||||
|
||||
if (entry.ListenerCount == 0
|
||||
&& !entry.CancellationInProgress
|
||||
&& !entry.Disposed)
|
||||
{
|
||||
entry.Disposed = true;
|
||||
disposeCancellationSource = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (disposeCancellationSource)
|
||||
entry.CancellationSource.Dispose();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove an entry when it is still the current entry for its key.
|
||||
/// Must only be called while holding <see cref="_sync"/>.
|
||||
/// </summary>
|
||||
private void RemoveEntry(RequestEntry entry)
|
||||
{
|
||||
if (_requests.TryGetValue(entry.Key, out var current)
|
||||
&& ReferenceEquals(current, entry))
|
||||
{
|
||||
_requests.Remove(entry.Key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Key used to identify identical requests for coalescing
|
||||
/// </summary>
|
||||
/// <param name="Method">Request method</param>
|
||||
/// <param name="Url">Request URL</param>
|
||||
/// <param name="Parameters">Request parameter string</param>
|
||||
/// <param name="ResponseType">Response type</param>
|
||||
public sealed record RequestCoalescingKey(
|
||||
string Method,
|
||||
string Url,
|
||||
string? Parameters,
|
||||
Type ResponseType);
|
||||
}
|
||||
@@ -101,6 +101,11 @@ namespace CryptoExchange.Net.Objects
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Whether concurrent identical requests should be prevented from sharing the same request/response
|
||||
/// </summary>
|
||||
public bool PreventRequestCoalescing { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// ctor
|
||||
/// </summary>
|
||||
|
||||
@@ -53,6 +53,7 @@ namespace CryptoExchange.Net.Objects
|
||||
/// <param name="tryParseOnNonSuccess">Try parse the response even when status is not success</param>
|
||||
/// <param name="forcePathEndWithSlash">Force trailing `/`</param>
|
||||
/// <param name="identifier">Optional request identifier override</param>
|
||||
/// <param name="preventRequestCoalescing">Whether concurrent identical requests should be prevented from sharing the same request/response</param>
|
||||
/// <returns></returns>
|
||||
public RequestDefinition GetOrCreate(
|
||||
HttpMethod method,
|
||||
@@ -68,7 +69,8 @@ namespace CryptoExchange.Net.Objects
|
||||
bool? preventCaching = null,
|
||||
bool? tryParseOnNonSuccess = null,
|
||||
bool? forcePathEndWithSlash = null,
|
||||
string? identifier = null)
|
||||
string? identifier = null,
|
||||
bool? preventRequestCoalescing = null)
|
||||
{
|
||||
var identifierToUse = identifier ?? $"{path}{method.Method}{baseAddress}";
|
||||
if (!_definitions.TryGetValue(identifierToUse, out var def))
|
||||
@@ -85,6 +87,7 @@ namespace CryptoExchange.Net.Objects
|
||||
PreventCaching = preventCaching ?? false,
|
||||
TryParseOnNonSuccess = tryParseOnNonSuccess ?? false,
|
||||
ForcePathEndWithSlash = forcePathEndWithSlash ?? false,
|
||||
PreventRequestCoalescing = preventRequestCoalescing ?? false,
|
||||
};
|
||||
_definitions.TryAdd(identifierToUse, def);
|
||||
}
|
||||
|
||||
@@ -165,7 +165,10 @@ namespace CryptoExchange.Net.Objects.Sockets
|
||||
{
|
||||
StreamId = StreamId,
|
||||
UpdateType = UpdateType,
|
||||
Symbol = Symbol
|
||||
Symbol = Symbol,
|
||||
DataTime = DataTime,
|
||||
DataTimeLocal = DataTimeLocal,
|
||||
SequenceNumber = SequenceNumber
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
namespace CryptoExchange.Net.SharedApis
|
||||
{
|
||||
/// <summary>
|
||||
/// Ledger entry type
|
||||
/// </summary>
|
||||
public enum SharedLedgerEntryType
|
||||
{
|
||||
/// <summary>
|
||||
/// Trade execution
|
||||
/// </summary>
|
||||
Trade,
|
||||
/// <summary>
|
||||
/// Withdrawal
|
||||
/// </summary>
|
||||
Withdrawal,
|
||||
/// <summary>
|
||||
/// Deposit
|
||||
/// </summary>
|
||||
Deposit,
|
||||
/// <summary>
|
||||
/// Transfer
|
||||
/// </summary>
|
||||
Transfer,
|
||||
/// <summary>
|
||||
/// Fee payment
|
||||
/// </summary>
|
||||
Fee,
|
||||
/// <summary>
|
||||
/// Funding fee payment
|
||||
/// </summary>
|
||||
FundingFee,
|
||||
/// <summary>
|
||||
/// Rebate
|
||||
/// </summary>
|
||||
Rebate,
|
||||
|
||||
/// <summary>
|
||||
/// Other or unknown
|
||||
/// </summary>
|
||||
Unknown
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace CryptoExchange.Net.SharedApis
|
||||
{
|
||||
/// <summary>
|
||||
/// The type of updates the incremental order book subscription produces
|
||||
/// </summary>
|
||||
public enum SharedOrderBookSubscriptionType
|
||||
{
|
||||
/// <summary>
|
||||
/// Subscription produces an initial snapshot update, followed by incremental change updates
|
||||
/// </summary>
|
||||
SnapshotThenIncremental,
|
||||
/// <summary>
|
||||
/// Subscription produces only incremental change updates
|
||||
/// </summary>
|
||||
OnlyIncremental
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace CryptoExchange.Net.SharedApis
|
||||
{
|
||||
/// <summary>
|
||||
/// The type of transport used for the shared API
|
||||
/// </summary>
|
||||
public record SharedTransport(string Name)
|
||||
{
|
||||
/// <summary>
|
||||
/// REST transport
|
||||
/// </summary>
|
||||
public static SharedTransport Rest { get; } = new("REST");
|
||||
/// <summary>
|
||||
/// WebSocket transport
|
||||
/// </summary>
|
||||
public static SharedTransport Socket { get; } = new("WebSocket");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace CryptoExchange.Net.SharedApis
|
||||
{
|
||||
/// <summary>
|
||||
/// A shared/common client interface
|
||||
/// </summary>
|
||||
public interface ISharedClient : ISharedApi
|
||||
{
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -7,7 +7,7 @@ namespace CryptoExchange.Net.SharedApis
|
||||
/// <summary>
|
||||
/// Options for canceling a futures order
|
||||
/// </summary>
|
||||
public class CancelFuturesOrderSocketOptions : EndpointOptions<CancelOrderRequest, IFuturesOrderManagementSocketClient>
|
||||
public class CancelFuturesOrderSocketOptions : CancelFuturesOrderOptions
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override string Description => "Cancel a futures order over a socket connection";
|
||||
@@ -15,7 +15,7 @@ namespace CryptoExchange.Net.SharedApis
|
||||
/// <summary>
|
||||
/// ctor
|
||||
/// </summary>
|
||||
public CancelFuturesOrderSocketOptions(string exchange, bool authenticated) : base(exchange, authenticated, nameof(IFuturesOrderManagementSocketClient.CancelFuturesOrderAsync))
|
||||
public CancelFuturesOrderSocketOptions(string exchange, bool authenticated) : base(exchange, authenticated)
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using CryptoExchange.Net.Objects;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace CryptoExchange.Net.SharedApis
|
||||
{
|
||||
/// <summary>
|
||||
/// Options for canceling a spot order
|
||||
/// </summary>
|
||||
public class CancelSpotOrderSocketOptions : CancelSpotOrderOptions
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override string Description => "Cancel a spot order over a socket connection";
|
||||
|
||||
/// <summary>
|
||||
/// ctor
|
||||
/// </summary>
|
||||
public CancelSpotOrderSocketOptions(string exchange, bool authenticated) : base(exchange, authenticated)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
using CryptoExchange.Net.Objects;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
|
||||
namespace CryptoExchange.Net.SharedApis
|
||||
{
|
||||
/// <summary>
|
||||
/// Options for closing position
|
||||
/// </summary>
|
||||
#pragma warning disable CS0618 // Type or member is obsolete
|
||||
public class ClosePositionOptions : EndpointOptions
|
||||
#pragma warning restore CS0618 // Type or member is obsolete
|
||||
{
|
||||
private static PropertyInfo[] _requestProperties = typeof(ClosePositionRequest).GetProperties();
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string Description => "Close an open futures position";
|
||||
|
||||
/// <inheritdoc />
|
||||
public override Type CapabilityType => typeof(IFuturesOrderRestClient);
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual RequestParameterRuleOverride[] ParameterRuleOverwrites
|
||||
{
|
||||
set => SetRequestParameters(value);
|
||||
}
|
||||
|
||||
private static readonly RequestParameterDescription[] _defaultParameterRules = new[]
|
||||
{
|
||||
RequestParameterRule<ClosePositionRequest>.Required(x => x.Symbol, "The symbol of the position to close", new SharedSymbol(TradingMode.PerpetualLinear, "ETH", "USDT")),
|
||||
RequestParameterRule<ClosePositionRequest>.Required(x => x.PositionMode, "The current position mode of the account", SharedPositionMode.OneWay),
|
||||
RequestParameterRule<ClosePositionRequest>.Optional(x => x.PositionSide, "The side of the position to close", SharedPositionSide.Long),
|
||||
RequestParameterRule<ClosePositionRequest>.Optional(x => x.MarginMode, "The margin mode of the position", SharedMarginMode.Cross),
|
||||
RequestParameterRule<ClosePositionRequest>.Optional(x => x.Quantity, "The quantity of the position to close", 1m),
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// ctor
|
||||
/// </summary>
|
||||
public ClosePositionOptions(string exchange, bool authenticated) : base(exchange, nameof(IFuturesOrderRestClient.ClosePositionAsync), true, _defaultParameterRules)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validate request
|
||||
/// </summary>
|
||||
public Error? ValidateRequest(ClosePositionRequest request, IFuturesOrderRestClient client)
|
||||
{
|
||||
if (NeedsAuthentication && !client.Authenticated)
|
||||
return new NoApiCredentialsError();
|
||||
|
||||
foreach (var param in RequestParameterRules)
|
||||
{
|
||||
var property = _requestProperties.Single(x => x.Name == param.Name);
|
||||
var value = property.GetValue(request);
|
||||
|
||||
if (param.Support == RequestParameterSupport.Required)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
return ArgumentError.Invalid(
|
||||
param.Name,
|
||||
$"Request parameter `{param.Name}` for exchange `{Exchange}` is required and should be provided. Example: {param.ExampleValue}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (request is SharedSymbolRequest symbolsRequest)
|
||||
{
|
||||
if (symbolsRequest.Symbols != null)
|
||||
{
|
||||
if (!SupportsMultipleSymbols)
|
||||
return ArgumentError.Invalid(nameof(SharedSymbolRequest.Symbols), $"Only a single symbol parameter is allowed, multiple symbols are not supported");
|
||||
|
||||
if (symbolsRequest.Symbols.Length > MaxSymbolCount)
|
||||
return ArgumentError.Invalid(nameof(SharedSymbolRequest.Symbols), $"Max number of symbols is {MaxSymbolCount} but {symbolsRequest.Symbols.Length} were passed");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return ValidateRequest(request.ExchangeParameters, request.TradingMode, client.SupportedTradingModes);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using CryptoExchange.Net.Objects;
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace CryptoExchange.Net.SharedApis
|
||||
{
|
||||
/// <summary>
|
||||
/// Options for placing a new futures order
|
||||
/// </summary>
|
||||
public class PlaceFuturesOrderSocketOptions : PlaceFuturesOrderOptions
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override string Description => "Place a new futures order over a socket connection";
|
||||
|
||||
/// <summary>
|
||||
/// ctor
|
||||
/// </summary>
|
||||
public PlaceFuturesOrderSocketOptions(string exchange, bool supportsTpSl) : base(exchange, supportsTpSl)
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using CryptoExchange.Net.Objects;
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace CryptoExchange.Net.SharedApis
|
||||
{
|
||||
/// <summary>
|
||||
/// Options for placing a new spot order
|
||||
/// </summary>
|
||||
public class PlaceSpotOrderSocketOptions : PlaceSpotOrderOptions
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override string Description => "Place a new spot order over a socket connection";
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// ctor
|
||||
/// </summary>
|
||||
public PlaceSpotOrderSocketOptions(string exchange) : base(exchange)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -11,7 +11,7 @@ namespace CryptoExchange.Net.SharedApis
|
||||
{
|
||||
/// <summary>
|
||||
/// Funding rate request options.<br />
|
||||
/// Use <see cref="EndpointOptions.RequiredExchangeParameters"/> and <see cref="EndpointOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Use <see cref="CapabilityOptions.RequiredExchangeParameters"/> and <see cref="CapabilityOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Exchange specific parameters can be added to the request via the `ExchangeParameters` property of the request object.
|
||||
/// </summary>
|
||||
GetFundingRateHistoryOptions GetFundingRateHistoryOptions { get; }
|
||||
+2
-2
@@ -11,7 +11,7 @@ namespace CryptoExchange.Net.SharedApis
|
||||
{
|
||||
/// <summary>
|
||||
/// Futures get order by client order id request options.<br />
|
||||
/// Use <see cref="EndpointOptions.RequiredExchangeParameters"/> and <see cref="EndpointOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Use <see cref="CapabilityOptions.RequiredExchangeParameters"/> and <see cref="CapabilityOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Exchange specific parameters can be added to the request via the `ExchangeParameters` property of the request object.
|
||||
/// </summary>
|
||||
GetFuturesOrderByClientOrderIdOptions GetFuturesOrderByClientOrderIdOptions { get; }
|
||||
@@ -25,7 +25,7 @@ namespace CryptoExchange.Net.SharedApis
|
||||
|
||||
/// <summary>
|
||||
/// Futures cancel order by client order id request options.<br />
|
||||
/// Use <see cref="EndpointOptions.RequiredExchangeParameters"/> and <see cref="EndpointOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Use <see cref="CapabilityOptions.RequiredExchangeParameters"/> and <see cref="CapabilityOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Exchange specific parameters can be added to the request via the `ExchangeParameters` property of the request object.
|
||||
/// </summary>
|
||||
CancelFuturesOrderByClientOrderIdOptions CancelFuturesOrderByClientOrderIdOptions { get; }
|
||||
+10
-10
@@ -38,7 +38,7 @@ namespace CryptoExchange.Net.SharedApis
|
||||
|
||||
/// <summary>
|
||||
/// Futures place order request options.<br />
|
||||
/// Use <see cref="EndpointOptions.RequiredExchangeParameters"/> and <see cref="EndpointOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Use <see cref="CapabilityOptions.RequiredExchangeParameters"/> and <see cref="CapabilityOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Exchange specific parameters can be added to the request via the `ExchangeParameters` property of the request object.
|
||||
/// </summary>
|
||||
PlaceFuturesOrderOptions PlaceFuturesOrderOptions { get; }
|
||||
@@ -52,7 +52,7 @@ namespace CryptoExchange.Net.SharedApis
|
||||
|
||||
/// <summary>
|
||||
/// Futures get order request options.<br />
|
||||
/// Use <see cref="EndpointOptions.RequiredExchangeParameters"/> and <see cref="EndpointOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Use <see cref="CapabilityOptions.RequiredExchangeParameters"/> and <see cref="CapabilityOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Exchange specific parameters can be added to the request via the `ExchangeParameters` property of the request object.
|
||||
/// </summary>
|
||||
GetFuturesOrderOptions GetFuturesOrderOptions { get; }
|
||||
@@ -65,7 +65,7 @@ namespace CryptoExchange.Net.SharedApis
|
||||
|
||||
/// <summary>
|
||||
/// Futures get open orders request options.<br />
|
||||
/// Use <see cref="EndpointOptions.RequiredExchangeParameters"/> and <see cref="EndpointOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Use <see cref="CapabilityOptions.RequiredExchangeParameters"/> and <see cref="CapabilityOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Exchange specific parameters can be added to the request via the `ExchangeParameters` property of the request object.
|
||||
/// </summary>
|
||||
GetOpenFuturesOrdersOptions GetOpenFuturesOrdersOptions { get; }
|
||||
@@ -78,7 +78,7 @@ namespace CryptoExchange.Net.SharedApis
|
||||
|
||||
/// <summary>
|
||||
/// Spot get closed orders request options.<br />
|
||||
/// Use <see cref="EndpointOptions.RequiredExchangeParameters"/> and <see cref="EndpointOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Use <see cref="CapabilityOptions.RequiredExchangeParameters"/> and <see cref="CapabilityOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Exchange specific parameters can be added to the request via the `ExchangeParameters` property of the request object.
|
||||
/// </summary>
|
||||
GetFuturesClosedOrdersOptions GetClosedFuturesOrdersOptions { get; }
|
||||
@@ -93,7 +93,7 @@ namespace CryptoExchange.Net.SharedApis
|
||||
|
||||
/// <summary>
|
||||
/// Futures get order trades request options.<br />
|
||||
/// Use <see cref="EndpointOptions.RequiredExchangeParameters"/> and <see cref="EndpointOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Use <see cref="CapabilityOptions.RequiredExchangeParameters"/> and <see cref="CapabilityOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Exchange specific parameters can be added to the request via the `ExchangeParameters` property of the request object.
|
||||
/// </summary>
|
||||
GetFuturesOrderTradesOptions GetFuturesOrderTradesOptions { get; }
|
||||
@@ -106,10 +106,10 @@ namespace CryptoExchange.Net.SharedApis
|
||||
|
||||
/// <summary>
|
||||
/// Futures user trades request options.<br />
|
||||
/// Use <see cref="EndpointOptions.RequiredExchangeParameters"/> and <see cref="EndpointOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Use <see cref="CapabilityOptions.RequiredExchangeParameters"/> and <see cref="CapabilityOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Exchange specific parameters can be added to the request via the `ExchangeParameters` property of the request object.
|
||||
/// </summary>
|
||||
GetFuturesUserTradesOptions GetFuturesUserTradesOptions { get; }
|
||||
GetFuturesUserTradeHistoryOptions GetFuturesUserTradesOptions { get; }
|
||||
/// <summary>
|
||||
/// Get futures user trade records, see <see cref="GetFuturesUserTradesOptions"/> for request options and exchange specific required/optional parameters. <br />
|
||||
/// The result is paginated, if there are more results to be retrieved, the `NextPageRequest` property of the result will contain the pagination request to be used for the next request to continue pagination.
|
||||
@@ -121,7 +121,7 @@ namespace CryptoExchange.Net.SharedApis
|
||||
|
||||
/// <summary>
|
||||
/// Futures cancel order request options.<br />
|
||||
/// Use <see cref="EndpointOptions.RequiredExchangeParameters"/> and <see cref="EndpointOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Use <see cref="CapabilityOptions.RequiredExchangeParameters"/> and <see cref="CapabilityOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Exchange specific parameters can be added to the request via the `ExchangeParameters` property of the request object.
|
||||
/// </summary>
|
||||
CancelFuturesOrderOptions CancelFuturesOrderOptions { get; }
|
||||
@@ -134,7 +134,7 @@ namespace CryptoExchange.Net.SharedApis
|
||||
|
||||
/// <summary>
|
||||
/// Positions request options.<br />
|
||||
/// Use <see cref="EndpointOptions.RequiredExchangeParameters"/> and <see cref="EndpointOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Use <see cref="CapabilityOptions.RequiredExchangeParameters"/> and <see cref="CapabilityOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Exchange specific parameters can be added to the request via the `ExchangeParameters` property of the request object.
|
||||
/// </summary>
|
||||
GetPositionsOptions GetPositionsOptions { get; }
|
||||
@@ -147,7 +147,7 @@ namespace CryptoExchange.Net.SharedApis
|
||||
|
||||
/// <summary>
|
||||
/// Close position order request options.<br />
|
||||
/// Use <see cref="EndpointOptions.RequiredExchangeParameters"/> and <see cref="EndpointOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Use <see cref="CapabilityOptions.RequiredExchangeParameters"/> and <see cref="CapabilityOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Exchange specific parameters can be added to the request via the `ExchangeParameters` property of the request object.
|
||||
/// </summary>
|
||||
ClosePositionOptions ClosePositionOptions { get; }
|
||||
+1
-1
@@ -16,7 +16,7 @@ namespace CryptoExchange.Net.SharedApis
|
||||
|
||||
/// <summary>
|
||||
/// Futures symbol request options.<br />
|
||||
/// Use <see cref="EndpointOptions.RequiredExchangeParameters"/> and <see cref="EndpointOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Use <see cref="CapabilityOptions.RequiredExchangeParameters"/> and <see cref="CapabilityOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Exchange specific parameters can be added to the request via the `ExchangeParameters` property of the request object.
|
||||
/// </summary>
|
||||
GetFuturesSymbolsOptions GetFuturesSymbolsOptions { get; }
|
||||
+4
-4
@@ -11,10 +11,10 @@ namespace CryptoExchange.Net.SharedApis
|
||||
{
|
||||
/// <summary>
|
||||
/// Futures get ticker request options.<br />
|
||||
/// Use <see cref="EndpointOptions.RequiredExchangeParameters"/> and <see cref="EndpointOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Use <see cref="CapabilityOptions.RequiredExchangeParameters"/> and <see cref="CapabilityOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Exchange specific parameters can be added to the request via the `ExchangeParameters` property of the request object.
|
||||
/// </summary>
|
||||
GetFuturesTickerOptions GetFuturesTickerOptions { get; }
|
||||
GetTickerOptions GetFuturesTickerOptions { get; }
|
||||
/// <summary>
|
||||
/// Get ticker info for a specific futures symbol, see <see cref="GetFuturesTickerOptions"/> for request options and exchange specific required/optional parameters. <br />
|
||||
/// </summary>
|
||||
@@ -24,10 +24,10 @@ namespace CryptoExchange.Net.SharedApis
|
||||
|
||||
/// <summary>
|
||||
/// Futures get tickers request options.<br />
|
||||
/// Use <see cref="EndpointOptions.RequiredExchangeParameters"/> and <see cref="EndpointOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Use <see cref="CapabilityOptions.RequiredExchangeParameters"/> and <see cref="CapabilityOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Exchange specific parameters can be added to the request via the `ExchangeParameters` property of the request object.
|
||||
/// </summary>
|
||||
GetFuturesTickersOptions GetFuturesTickersOptions { get; }
|
||||
GetAllTickersOptions GetFuturesTickersOptions { get; }
|
||||
/// <summary>
|
||||
/// Get ticker info for all futures symbols, see <see cref="GetFuturesTickersOptions"/> for request options and exchange specific required/optional parameters. <br />
|
||||
/// </summary>
|
||||
+2
-2
@@ -11,7 +11,7 @@ namespace CryptoExchange.Net.SharedApis
|
||||
{
|
||||
/// <summary>
|
||||
/// Set take profit and/or stop loss options.<br />
|
||||
/// Use <see cref="EndpointOptions.RequiredExchangeParameters"/> and <see cref="EndpointOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Use <see cref="CapabilityOptions.RequiredExchangeParameters"/> and <see cref="CapabilityOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Exchange specific parameters can be added to the request via the `ExchangeParameters` property of the request object.
|
||||
/// </summary>
|
||||
SetFuturesTpSlOptions SetFuturesTpSlOptions { get; }
|
||||
@@ -25,7 +25,7 @@ namespace CryptoExchange.Net.SharedApis
|
||||
|
||||
/// <summary>
|
||||
/// Cancel a take profit and/or stop loss options.<br />
|
||||
/// Use <see cref="EndpointOptions.RequiredExchangeParameters"/> and <see cref="EndpointOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Use <see cref="CapabilityOptions.RequiredExchangeParameters"/> and <see cref="CapabilityOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Exchange specific parameters can be added to the request via the `ExchangeParameters` property of the request object.
|
||||
/// </summary>
|
||||
CancelFuturesTpSlOptions CancelFuturesTpSlOptions { get; }
|
||||
+3
-3
@@ -11,7 +11,7 @@ namespace CryptoExchange.Net.SharedApis
|
||||
{
|
||||
/// <summary>
|
||||
/// Place spot trigger order options.<br />
|
||||
/// Use <see cref="EndpointOptions.RequiredExchangeParameters"/> and <see cref="EndpointOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Use <see cref="CapabilityOptions.RequiredExchangeParameters"/> and <see cref="CapabilityOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Exchange specific parameters can be added to the request via the `ExchangeParameters` property of the request object.
|
||||
/// </summary>
|
||||
PlaceFuturesTriggerOrderOptions PlaceFuturesTriggerOrderOptions { get; }
|
||||
@@ -26,7 +26,7 @@ namespace CryptoExchange.Net.SharedApis
|
||||
|
||||
/// <summary>
|
||||
/// Get trigger order request options.<br />
|
||||
/// Use <see cref="EndpointOptions.RequiredExchangeParameters"/> and <see cref="EndpointOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Use <see cref="CapabilityOptions.RequiredExchangeParameters"/> and <see cref="CapabilityOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Exchange specific parameters can be added to the request via the `ExchangeParameters` property of the request object.
|
||||
/// </summary>
|
||||
GetFuturesTriggerOrderOptions GetFuturesTriggerOrderOptions { get; }
|
||||
@@ -39,7 +39,7 @@ namespace CryptoExchange.Net.SharedApis
|
||||
|
||||
/// <summary>
|
||||
/// Cancel trigger order request options.<br />
|
||||
/// Use <see cref="EndpointOptions.RequiredExchangeParameters"/> and <see cref="EndpointOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Use <see cref="CapabilityOptions.RequiredExchangeParameters"/> and <see cref="CapabilityOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Exchange specific parameters can be added to the request via the `ExchangeParameters` property of the request object.
|
||||
/// </summary>
|
||||
CancelFuturesTriggerOrderOptions CancelFuturesTriggerOrderOptions { get; }
|
||||
+1
-1
@@ -11,7 +11,7 @@ namespace CryptoExchange.Net.SharedApis
|
||||
{
|
||||
/// <summary>
|
||||
/// Index price klines request options.<br />
|
||||
/// Use <see cref="EndpointOptions.RequiredExchangeParameters"/> and <see cref="EndpointOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Use <see cref="CapabilityOptions.RequiredExchangeParameters"/> and <see cref="CapabilityOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Exchange specific parameters can be added to the request via the `ExchangeParameters` property of the request object.
|
||||
/// </summary>
|
||||
GetIndexPriceKlinesOptions GetIndexPriceKlinesOptions { get; }
|
||||
+2
-2
@@ -16,7 +16,7 @@ namespace CryptoExchange.Net.SharedApis
|
||||
|
||||
/// <summary>
|
||||
/// Leverage request options.<br />
|
||||
/// Use <see cref="EndpointOptions.RequiredExchangeParameters"/> and <see cref="EndpointOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Use <see cref="CapabilityOptions.RequiredExchangeParameters"/> and <see cref="CapabilityOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Exchange specific parameters can be added to the request via the `ExchangeParameters` property of the request object.
|
||||
/// </summary>
|
||||
GetLeverageOptions GetLeverageOptions { get; }
|
||||
@@ -29,7 +29,7 @@ namespace CryptoExchange.Net.SharedApis
|
||||
|
||||
/// <summary>
|
||||
/// Leverage set request options.<br />
|
||||
/// Use <see cref="EndpointOptions.RequiredExchangeParameters"/> and <see cref="EndpointOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Use <see cref="CapabilityOptions.RequiredExchangeParameters"/> and <see cref="CapabilityOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Exchange specific parameters can be added to the request via the `ExchangeParameters` property of the request object.
|
||||
/// </summary>
|
||||
SetLeverageOptions SetLeverageOptions { get; }
|
||||
+1
-1
@@ -11,7 +11,7 @@ namespace CryptoExchange.Net.SharedApis
|
||||
{
|
||||
/// <summary>
|
||||
/// Mark price klines request options.<br />
|
||||
/// Use <see cref="EndpointOptions.RequiredExchangeParameters"/> and <see cref="EndpointOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Use <see cref="CapabilityOptions.RequiredExchangeParameters"/> and <see cref="CapabilityOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Exchange specific parameters can be added to the request via the `ExchangeParameters` property of the request object.
|
||||
/// </summary>
|
||||
GetMarkPriceKlinesOptions GetMarkPriceKlinesOptions { get; }
|
||||
+1
-1
@@ -11,7 +11,7 @@ namespace CryptoExchange.Net.SharedApis
|
||||
{
|
||||
/// <summary>
|
||||
/// Open interest request options.<br />
|
||||
/// Use <see cref="EndpointOptions.RequiredExchangeParameters"/> and <see cref="EndpointOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Use <see cref="CapabilityOptions.RequiredExchangeParameters"/> and <see cref="CapabilityOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Exchange specific parameters can be added to the request via the `ExchangeParameters` property of the request object.
|
||||
/// </summary>
|
||||
GetOpenInterestOptions GetOpenInterestOptions { get; }
|
||||
+1
-1
@@ -11,7 +11,7 @@ namespace CryptoExchange.Net.SharedApis
|
||||
{
|
||||
/// <summary>
|
||||
/// Position history request options.<br />
|
||||
/// Use <see cref="EndpointOptions.RequiredExchangeParameters"/> and <see cref="EndpointOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Use <see cref="CapabilityOptions.RequiredExchangeParameters"/> and <see cref="CapabilityOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Exchange specific parameters can be added to the request via the `ExchangeParameters` property of the request object.
|
||||
/// </summary>
|
||||
GetPositionHistoryOptions GetPositionHistoryOptions { get; }
|
||||
+2
-2
@@ -16,7 +16,7 @@ namespace CryptoExchange.Net.SharedApis
|
||||
|
||||
/// <summary>
|
||||
/// Position mode request options.<br />
|
||||
/// Use <see cref="EndpointOptions.RequiredExchangeParameters"/> and <see cref="EndpointOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Use <see cref="CapabilityOptions.RequiredExchangeParameters"/> and <see cref="CapabilityOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Exchange specific parameters can be added to the request via the `ExchangeParameters` property of the request object.
|
||||
/// </summary>
|
||||
GetPositionModeOptions GetPositionModeOptions { get; }
|
||||
@@ -29,7 +29,7 @@ namespace CryptoExchange.Net.SharedApis
|
||||
|
||||
/// <summary>
|
||||
/// Position mode set request options.<br />
|
||||
/// Use <see cref="EndpointOptions.RequiredExchangeParameters"/> and <see cref="EndpointOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Use <see cref="CapabilityOptions.RequiredExchangeParameters"/> and <see cref="CapabilityOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Exchange specific parameters can be added to the request via the `ExchangeParameters` property of the request object.
|
||||
/// </summary>
|
||||
SetPositionModeOptions SetPositionModeOptions { get; }
|
||||
+3
-3
@@ -11,7 +11,7 @@ namespace CryptoExchange.Net.SharedApis
|
||||
{
|
||||
/// <summary>
|
||||
/// Asset request options.<br />
|
||||
/// Use <see cref="EndpointOptions.RequiredExchangeParameters"/> and <see cref="EndpointOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Use <see cref="CapabilityOptions.RequiredExchangeParameters"/> and <see cref="CapabilityOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Exchange specific parameters can be added to the request via the `ExchangeParameters` property of the request object.
|
||||
/// </summary>
|
||||
GetAssetOptions GetAssetOptions { get; }
|
||||
@@ -25,10 +25,10 @@ namespace CryptoExchange.Net.SharedApis
|
||||
|
||||
/// <summary>
|
||||
/// Assets request options.<br />
|
||||
/// Use <see cref="EndpointOptions.RequiredExchangeParameters"/> and <see cref="EndpointOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Use <see cref="CapabilityOptions.RequiredExchangeParameters"/> and <see cref="CapabilityOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Exchange specific parameters can be added to the request via the `ExchangeParameters` property of the request object.
|
||||
/// </summary>
|
||||
GetAssetsOptions GetAssetsOptions { get; }
|
||||
GetAllAssetsOptions GetAssetsOptions { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Get info on all assets the exchange supports, see <see cref="GetAssetsOptions"/> for request options and exchange specific required/optional parameters. <br />
|
||||
+1
-1
@@ -11,7 +11,7 @@ namespace CryptoExchange.Net.SharedApis
|
||||
{
|
||||
/// <summary>
|
||||
/// Balances request options.<br />
|
||||
/// Use <see cref="EndpointOptions.RequiredExchangeParameters"/> and <see cref="EndpointOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Use <see cref="CapabilityOptions.RequiredExchangeParameters"/> and <see cref="CapabilityOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Exchange specific parameters can be added to the request via the `ExchangeParameters` property of the request object.
|
||||
/// </summary>
|
||||
GetBalancesOptions GetBalancesOptions { get; }
|
||||
+1
-1
@@ -11,7 +11,7 @@ namespace CryptoExchange.Net.SharedApis
|
||||
{
|
||||
/// <summary>
|
||||
/// Book ticker request options.<br />
|
||||
/// Use <see cref="EndpointOptions.RequiredExchangeParameters"/> and <see cref="EndpointOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Use <see cref="CapabilityOptions.RequiredExchangeParameters"/> and <see cref="CapabilityOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Exchange specific parameters can be added to the request via the `ExchangeParameters` property of the request object.
|
||||
/// </summary>
|
||||
GetBookTickerOptions GetBookTickerOptions { get; }
|
||||
+3
-3
@@ -11,7 +11,7 @@ namespace CryptoExchange.Net.SharedApis
|
||||
{
|
||||
/// <summary>
|
||||
/// Deposit addresses request options.<br />
|
||||
/// Use <see cref="EndpointOptions.RequiredExchangeParameters"/> and <see cref="EndpointOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Use <see cref="CapabilityOptions.RequiredExchangeParameters"/> and <see cref="CapabilityOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Exchange specific parameters can be added to the request via the `ExchangeParameters` property of the request object.
|
||||
/// </summary>
|
||||
GetDepositAddressesOptions GetDepositAddressesOptions { get; }
|
||||
@@ -26,10 +26,10 @@ namespace CryptoExchange.Net.SharedApis
|
||||
|
||||
/// <summary>
|
||||
/// Deposits request options.<br />
|
||||
/// Use <see cref="EndpointOptions.RequiredExchangeParameters"/> and <see cref="EndpointOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Use <see cref="CapabilityOptions.RequiredExchangeParameters"/> and <see cref="CapabilityOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Exchange specific parameters can be added to the request via the `ExchangeParameters` property of the request object.
|
||||
/// </summary>
|
||||
GetDepositsOptions GetDepositsOptions { get; }
|
||||
GetDepositHistoryOptions GetDepositsOptions { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Get deposit records, see <see cref="GetDepositsOptions"/> for request options and exchange specific required/optional parameters. <br />
|
||||
+1
-1
@@ -11,7 +11,7 @@ namespace CryptoExchange.Net.SharedApis
|
||||
{
|
||||
/// <summary>
|
||||
/// Fee request options.<br />
|
||||
/// Use <see cref="EndpointOptions.RequiredExchangeParameters"/> and <see cref="EndpointOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Use <see cref="CapabilityOptions.RequiredExchangeParameters"/> and <see cref="CapabilityOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Exchange specific parameters can be added to the request via the `ExchangeParameters` property of the request object.
|
||||
/// </summary>
|
||||
GetFeeOptions GetFeeOptions { get; }
|
||||
+1
-1
@@ -11,7 +11,7 @@ namespace CryptoExchange.Net.SharedApis
|
||||
{
|
||||
/// <summary>
|
||||
/// Kline request options.<br />
|
||||
/// Use <see cref="EndpointOptions.RequiredExchangeParameters"/> and <see cref="EndpointOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Use <see cref="CapabilityOptions.RequiredExchangeParameters"/> and <see cref="CapabilityOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Exchange specific parameters can be added to the request via the `ExchangeParameters` property of the request object.
|
||||
/// </summary>
|
||||
GetKlinesOptions GetKlinesOptions { get; }
|
||||
+1
-1
@@ -11,7 +11,7 @@ namespace CryptoExchange.Net.SharedApis
|
||||
{
|
||||
/// <summary>
|
||||
/// Order book request options.<br />
|
||||
/// Use <see cref="EndpointOptions.RequiredExchangeParameters"/> and <see cref="EndpointOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Use <see cref="CapabilityOptions.RequiredExchangeParameters"/> and <see cref="CapabilityOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Exchange specific parameters can be added to the request via the `ExchangeParameters` property of the request object.
|
||||
/// </summary>
|
||||
GetOrderBookOptions GetOrderBookOptions { get; }
|
||||
+1
-1
@@ -11,7 +11,7 @@ namespace CryptoExchange.Net.SharedApis
|
||||
{
|
||||
/// <summary>
|
||||
/// Recent trades request options.<br />
|
||||
/// Use <see cref="EndpointOptions.RequiredExchangeParameters"/> and <see cref="EndpointOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Use <see cref="CapabilityOptions.RequiredExchangeParameters"/> and <see cref="CapabilityOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Exchange specific parameters can be added to the request via the `ExchangeParameters` property of the request object.
|
||||
/// </summary>
|
||||
GetRecentTradesOptions GetRecentTradesOptions { get; }
|
||||
+1
-1
@@ -11,7 +11,7 @@ namespace CryptoExchange.Net.SharedApis
|
||||
{
|
||||
/// <summary>
|
||||
/// Trade history request options.<br />
|
||||
/// Use <see cref="EndpointOptions.RequiredExchangeParameters"/> and <see cref="EndpointOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Use <see cref="CapabilityOptions.RequiredExchangeParameters"/> and <see cref="CapabilityOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Exchange specific parameters can be added to the request via the `ExchangeParameters` property of the request object.
|
||||
/// </summary>
|
||||
GetTradeHistoryOptions GetTradeHistoryOptions { get; }
|
||||
+2
-2
@@ -11,7 +11,7 @@ namespace CryptoExchange.Net.SharedApis
|
||||
{
|
||||
/// <summary>
|
||||
/// Transfer request options.<br />
|
||||
/// Use <see cref="EndpointOptions.RequiredExchangeParameters"/> and <see cref="EndpointOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Use <see cref="CapabilityOptions.RequiredExchangeParameters"/> and <see cref="CapabilityOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Exchange specific parameters can be added to the request via the `ExchangeParameters` property of the request object.
|
||||
/// </summary>
|
||||
TransferOptions TransferOptions { get; }
|
||||
@@ -23,4 +23,4 @@ namespace CryptoExchange.Net.SharedApis
|
||||
/// <param name="ct">Cancellation token</param>
|
||||
Task<HttpResult<SharedId>> TransferAsync(TransferRequest request, CancellationToken ct = default);
|
||||
}
|
||||
}
|
||||
}
|
||||
+6
-3
@@ -1,17 +1,20 @@
|
||||
using CryptoExchange.Net.Objects;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace CryptoExchange.Net.SharedApis
|
||||
{
|
||||
/// <summary>
|
||||
/// Client for requesting to withdraw funds from the exchange
|
||||
/// Client for withdrawing funds
|
||||
/// </summary>
|
||||
public interface IWithdrawRestClient : ISharedClient
|
||||
{
|
||||
/// <summary>
|
||||
/// Withdraw request options.<br />
|
||||
/// Use <see cref="EndpointOptions.RequiredExchangeParameters"/> and <see cref="EndpointOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Use <see cref="CapabilityOptions.RequiredExchangeParameters"/> and <see cref="CapabilityOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Exchange specific parameters can be added to the request via the `ExchangeParameters` property of the request object.
|
||||
/// </summary>
|
||||
WithdrawOptions WithdrawOptions { get; }
|
||||
@@ -24,4 +27,4 @@ namespace CryptoExchange.Net.SharedApis
|
||||
/// <returns></returns>
|
||||
Task<HttpResult<SharedId>> WithdrawAsync(WithdrawRequest request, CancellationToken ct = default);
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -11,10 +11,10 @@ namespace CryptoExchange.Net.SharedApis
|
||||
{
|
||||
/// <summary>
|
||||
/// Withdrawal records request options.<br />
|
||||
/// Use <see cref="EndpointOptions.RequiredExchangeParameters"/> and <see cref="EndpointOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Use <see cref="CapabilityOptions.RequiredExchangeParameters"/> and <see cref="CapabilityOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Exchange specific parameters can be added to the request via the `ExchangeParameters` property of the request object.
|
||||
/// </summary>
|
||||
GetWithdrawalsOptions GetWithdrawalsOptions { get; }
|
||||
GetWithdrawalHistoryOptions GetWithdrawalsOptions { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Get withdrawal records, see <see cref="GetWithdrawalsOptions"/> for request options and exchange specific required/optional parameters. <br />
|
||||
+2
-2
@@ -11,7 +11,7 @@ namespace CryptoExchange.Net.SharedApis
|
||||
{
|
||||
/// <summary>
|
||||
/// Spot get order by client order id request options.<br />
|
||||
/// Use <see cref="EndpointOptions.RequiredExchangeParameters"/> and <see cref="EndpointOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Use <see cref="CapabilityOptions.RequiredExchangeParameters"/> and <see cref="CapabilityOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Exchange specific parameters can be added to the request via the `ExchangeParameters` property of the request object.
|
||||
/// </summary>
|
||||
GetSpotOrderByClientOrderIdOptions GetSpotOrderByClientOrderIdOptions { get; }
|
||||
@@ -25,7 +25,7 @@ namespace CryptoExchange.Net.SharedApis
|
||||
|
||||
/// <summary>
|
||||
/// Spot cancel order by client order id request options.<br />
|
||||
/// Use <see cref="EndpointOptions.RequiredExchangeParameters"/> and <see cref="EndpointOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Use <see cref="CapabilityOptions.RequiredExchangeParameters"/> and <see cref="CapabilityOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Exchange specific parameters can be added to the request via the `ExchangeParameters` property of the request object.
|
||||
/// </summary>
|
||||
CancelSpotOrderByClientOrderIdOptions CancelSpotOrderByClientOrderIdOptions { get; }
|
||||
+8
-8
@@ -38,7 +38,7 @@ namespace CryptoExchange.Net.SharedApis
|
||||
|
||||
/// <summary>
|
||||
/// Spot place order request options.<br />
|
||||
/// Use <see cref="EndpointOptions.RequiredExchangeParameters"/> and <see cref="EndpointOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Use <see cref="CapabilityOptions.RequiredExchangeParameters"/> and <see cref="CapabilityOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Exchange specific parameters can be added to the request via the `ExchangeParameters` property of the request object.
|
||||
/// </summary>
|
||||
PlaceSpotOrderOptions PlaceSpotOrderOptions { get; }
|
||||
@@ -51,7 +51,7 @@ namespace CryptoExchange.Net.SharedApis
|
||||
|
||||
/// <summary>
|
||||
/// Spot get order request options.<br />
|
||||
/// Use <see cref="EndpointOptions.RequiredExchangeParameters"/> and <see cref="EndpointOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Use <see cref="CapabilityOptions.RequiredExchangeParameters"/> and <see cref="CapabilityOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Exchange specific parameters can be added to the request via the `ExchangeParameters` property of the request object.
|
||||
/// </summary>
|
||||
GetSpotOrderOptions GetSpotOrderOptions { get; }
|
||||
@@ -64,7 +64,7 @@ namespace CryptoExchange.Net.SharedApis
|
||||
|
||||
/// <summary>
|
||||
/// Spot get open orders request options.<br />
|
||||
/// Use <see cref="EndpointOptions.RequiredExchangeParameters"/> and <see cref="EndpointOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Use <see cref="CapabilityOptions.RequiredExchangeParameters"/> and <see cref="CapabilityOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Exchange specific parameters can be added to the request via the `ExchangeParameters` property of the request object.
|
||||
/// </summary>
|
||||
GetOpenSpotOrdersOptions GetOpenSpotOrdersOptions { get; }
|
||||
@@ -77,7 +77,7 @@ namespace CryptoExchange.Net.SharedApis
|
||||
|
||||
/// <summary>
|
||||
/// Spot get closed orders request options.<br />
|
||||
/// Use <see cref="EndpointOptions.RequiredExchangeParameters"/> and <see cref="EndpointOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Use <see cref="CapabilityOptions.RequiredExchangeParameters"/> and <see cref="CapabilityOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Exchange specific parameters can be added to the request via the `ExchangeParameters` property of the request object.
|
||||
/// </summary>
|
||||
GetSpotClosedOrdersOptions GetClosedSpotOrdersOptions { get; }
|
||||
@@ -92,7 +92,7 @@ namespace CryptoExchange.Net.SharedApis
|
||||
|
||||
/// <summary>
|
||||
/// Spot get order trades request options.<br />
|
||||
/// Use <see cref="EndpointOptions.RequiredExchangeParameters"/> and <see cref="EndpointOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Use <see cref="CapabilityOptions.RequiredExchangeParameters"/> and <see cref="CapabilityOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Exchange specific parameters can be added to the request via the `ExchangeParameters` property of the request object.
|
||||
/// </summary>
|
||||
GetSpotOrderTradesOptions GetSpotOrderTradesOptions { get; }
|
||||
@@ -106,10 +106,10 @@ namespace CryptoExchange.Net.SharedApis
|
||||
|
||||
/// <summary>
|
||||
/// Spot user trades request options.<br />
|
||||
/// Use <see cref="EndpointOptions.RequiredExchangeParameters"/> and <see cref="EndpointOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Use <see cref="CapabilityOptions.RequiredExchangeParameters"/> and <see cref="CapabilityOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Exchange specific parameters can be added to the request via the `ExchangeParameters` property of the request object.
|
||||
/// </summary>
|
||||
GetSpotUserTradesOptions GetSpotUserTradesOptions { get; }
|
||||
GetSpotUserTradeHistoryOptions GetSpotUserTradesOptions { get; }
|
||||
/// <summary>
|
||||
/// Get spot user trade records, see <see cref="GetSpotUserTradesOptions"/> for request options and exchange specific required/optional parameters. <br />
|
||||
/// The result is paginated, if there are more results to be retrieved, the `NextPageRequest` property of the result will contain the pagination request to be used for the next request to continue pagination.
|
||||
@@ -121,7 +121,7 @@ namespace CryptoExchange.Net.SharedApis
|
||||
|
||||
/// <summary>
|
||||
/// Spot cancel order request options.<br />
|
||||
/// Use <see cref="EndpointOptions.RequiredExchangeParameters"/> and <see cref="EndpointOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Use <see cref="CapabilityOptions.RequiredExchangeParameters"/> and <see cref="CapabilityOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Exchange specific parameters can be added to the request via the `ExchangeParameters` property of the request object.
|
||||
/// </summary>
|
||||
CancelSpotOrderOptions CancelSpotOrderOptions { get; }
|
||||
+1
-1
@@ -16,7 +16,7 @@ namespace CryptoExchange.Net.SharedApis
|
||||
|
||||
/// <summary>
|
||||
/// Spot symbols request options.<br />
|
||||
/// Use <see cref="EndpointOptions.RequiredExchangeParameters"/> and <see cref="EndpointOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Use <see cref="CapabilityOptions.RequiredExchangeParameters"/> and <see cref="CapabilityOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Exchange specific parameters can be added to the request via the `ExchangeParameters` property of the request object.
|
||||
/// </summary>
|
||||
GetSpotSymbolsOptions GetSpotSymbolsOptions { get; }
|
||||
+4
-4
@@ -11,10 +11,10 @@ namespace CryptoExchange.Net.SharedApis
|
||||
{
|
||||
/// <summary>
|
||||
/// Spot ticker request options.<br />
|
||||
/// Use <see cref="EndpointOptions.RequiredExchangeParameters"/> and <see cref="EndpointOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Use <see cref="CapabilityOptions.RequiredExchangeParameters"/> and <see cref="CapabilityOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Exchange specific parameters can be added to the request via the `ExchangeParameters` property of the request object.
|
||||
/// </summary>
|
||||
GetSpotTickerOptions GetSpotTickerOptions { get; }
|
||||
GetTickerOptions GetSpotTickerOptions { get; }
|
||||
/// <summary>
|
||||
/// Get ticker for a specific spot symbol, see <see cref="GetSpotTickerOptions"/> for request options and exchange specific required/optional parameters. <br />
|
||||
/// </summary>
|
||||
@@ -23,10 +23,10 @@ namespace CryptoExchange.Net.SharedApis
|
||||
Task<HttpResult<SharedSpotTicker>> GetSpotTickerAsync(GetTickerRequest request, CancellationToken ct = default);
|
||||
/// <summary>
|
||||
/// Spot tickers request options.<br />
|
||||
/// Use <see cref="EndpointOptions.RequiredExchangeParameters"/> and <see cref="EndpointOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Use <see cref="CapabilityOptions.RequiredExchangeParameters"/> and <see cref="CapabilityOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Exchange specific parameters can be added to the request via the `ExchangeParameters` property of the request object.
|
||||
/// </summary>
|
||||
GetSpotTickersOptions GetSpotTickersOptions { get; }
|
||||
GetAllTickersOptions GetSpotTickersOptions { get; }
|
||||
/// <summary>
|
||||
/// Get tickers for all spot symbols, see <see cref="GetSpotTickersOptions"/> for request options and exchange specific required/optional parameters. <br />
|
||||
/// </summary>
|
||||
+3
-3
@@ -11,7 +11,7 @@ namespace CryptoExchange.Net.SharedApis
|
||||
{
|
||||
/// <summary>
|
||||
/// Place spot trigger order options.<br />
|
||||
/// Use <see cref="EndpointOptions.RequiredExchangeParameters"/> and <see cref="EndpointOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Use <see cref="CapabilityOptions.RequiredExchangeParameters"/> and <see cref="CapabilityOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Exchange specific parameters can be added to the request via the `ExchangeParameters` property of the request object.
|
||||
/// </summary>
|
||||
PlaceSpotTriggerOrderOptions PlaceSpotTriggerOrderOptions { get; }
|
||||
@@ -26,7 +26,7 @@ namespace CryptoExchange.Net.SharedApis
|
||||
|
||||
/// <summary>
|
||||
/// Get trigger order request options.<br />
|
||||
/// Use <see cref="EndpointOptions.RequiredExchangeParameters"/> and <see cref="EndpointOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Use <see cref="CapabilityOptions.RequiredExchangeParameters"/> and <see cref="CapabilityOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Exchange specific parameters can be added to the request via the `ExchangeParameters` property of the request object.
|
||||
/// </summary>
|
||||
GetSpotTriggerOrderOptions GetSpotTriggerOrderOptions { get; }
|
||||
@@ -39,7 +39,7 @@ namespace CryptoExchange.Net.SharedApis
|
||||
|
||||
/// <summary>
|
||||
/// Cancel trigger order request options.<br />
|
||||
/// Use <see cref="EndpointOptions.RequiredExchangeParameters"/> and <see cref="EndpointOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Use <see cref="CapabilityOptions.RequiredExchangeParameters"/> and <see cref="CapabilityOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Exchange specific parameters can be added to the request via the `ExchangeParameters` property of the request object.
|
||||
/// </summary>
|
||||
CancelSpotTriggerOrderOptions CancelSpotTriggerOrderOptions { get; }
|
||||
+2
-2
@@ -38,7 +38,7 @@ namespace CryptoExchange.Net.SharedApis
|
||||
|
||||
/// <summary>
|
||||
/// Futures place order request options.<br />
|
||||
/// Use <see cref="EndpointOptions.RequiredExchangeParameters"/> and <see cref="EndpointOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Use <see cref="CapabilityOptions.RequiredExchangeParameters"/> and <see cref="CapabilityOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Exchange specific parameters can be added to the request via the `ExchangeParameters` property of the request object.
|
||||
/// </summary>
|
||||
PlaceFuturesOrderSocketOptions PlaceFuturesOrderOptions { get; }
|
||||
@@ -52,7 +52,7 @@ namespace CryptoExchange.Net.SharedApis
|
||||
|
||||
/// <summary>
|
||||
/// Futures cancel order request options.<br />
|
||||
/// Use <see cref="EndpointOptions.RequiredExchangeParameters"/> and <see cref="EndpointOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Use <see cref="CapabilityOptions.RequiredExchangeParameters"/> and <see cref="CapabilityOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Exchange specific parameters can be added to the request via the `ExchangeParameters` property of the request object.
|
||||
/// </summary>
|
||||
CancelFuturesOrderSocketOptions CancelFuturesOrderOptions { get; }
|
||||
+2
-2
@@ -38,7 +38,7 @@ namespace CryptoExchange.Net.SharedApis
|
||||
|
||||
/// <summary>
|
||||
/// Spot place order request options.<br />
|
||||
/// Use <see cref="EndpointOptions.RequiredExchangeParameters"/> and <see cref="EndpointOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Use <see cref="CapabilityOptions.RequiredExchangeParameters"/> and <see cref="CapabilityOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Exchange specific parameters can be added to the request via the `ExchangeParameters` property of the request object.
|
||||
/// </summary>
|
||||
PlaceSpotOrderSocketOptions PlaceSpotOrderOptions { get; }
|
||||
@@ -51,7 +51,7 @@ namespace CryptoExchange.Net.SharedApis
|
||||
|
||||
/// <summary>
|
||||
/// Spot cancel order request options.<br />
|
||||
/// Use <see cref="EndpointOptions.RequiredExchangeParameters"/> and <see cref="EndpointOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Use <see cref="CapabilityOptions.RequiredExchangeParameters"/> and <see cref="CapabilityOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||
/// Exchange specific parameters can be added to the request via the `ExchangeParameters` property of the request object.
|
||||
/// </summary>
|
||||
CancelSpotOrderSocketOptions CancelSpotOrderOptions { get; }
|
||||
-18
@@ -1,18 +0,0 @@
|
||||
namespace CryptoExchange.Net.SharedApis
|
||||
{
|
||||
/// <summary>
|
||||
/// Options for canceling a futures order by client order id
|
||||
/// </summary>
|
||||
public class CancelFuturesOrderByClientOrderIdOptions : EndpointOptions<CancelOrderRequest, IFuturesOrderClientIdRestClient>
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override string Description => "Cancel a futures order by its client order id";
|
||||
|
||||
/// <summary>
|
||||
/// ctor
|
||||
/// </summary>
|
||||
public CancelFuturesOrderByClientOrderIdOptions(string exchange, bool authenticated) : base(exchange, authenticated, nameof(IFuturesOrderClientIdRestClient.CancelFuturesOrderByClientOrderIdAsync))
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace CryptoExchange.Net.SharedApis
|
||||
{
|
||||
/// <summary>
|
||||
/// Options for canceling a futures order
|
||||
/// </summary>
|
||||
public class CancelFuturesOrderOptions : EndpointOptions<CancelOrderRequest, IFuturesOrderRestClient>
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override string Description => "Cancel a futures order";
|
||||
|
||||
/// <summary>
|
||||
/// ctor
|
||||
/// </summary>
|
||||
public CancelFuturesOrderOptions(string exchange, bool authenticated) : base(exchange, authenticated, nameof(IFuturesOrderRestClient.CancelFuturesOrderAsync))
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace CryptoExchange.Net.SharedApis
|
||||
{
|
||||
/// <summary>
|
||||
/// Options for canceling a TP/SL
|
||||
/// </summary>
|
||||
public class CancelFuturesTpSlOptions : EndpointOptions<CancelTpSlRequest, IFuturesTpSlRestClient>
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override string Description => "Cancel a take profit or stop loss order for a futures position";
|
||||
|
||||
/// <summary>
|
||||
/// ctor
|
||||
/// </summary>
|
||||
public CancelFuturesTpSlOptions(string exchange, bool authenticated) : base(exchange, authenticated, nameof(IFuturesTpSlRestClient.CancelFuturesTpSlAsync))
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
-22
@@ -1,22 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace CryptoExchange.Net.SharedApis
|
||||
{
|
||||
/// <summary>
|
||||
/// Options for canceling spot trigger order
|
||||
/// </summary>
|
||||
public class CancelFuturesTriggerOrderOptions : EndpointOptions<CancelOrderRequest, IFuturesTriggerOrderRestClient>
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override string Description => "Cancel a futures trigger order";
|
||||
|
||||
/// <summary>
|
||||
/// ctor
|
||||
/// </summary>
|
||||
public CancelFuturesTriggerOrderOptions(string exchange, bool authenticated) : base(exchange, authenticated, nameof(IFuturesTriggerOrderRestClient.CancelFuturesTriggerOrderAsync))
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
-32
@@ -1,32 +0,0 @@
|
||||
using CryptoExchange.Net.Objects;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace CryptoExchange.Net.SharedApis
|
||||
{
|
||||
/// <summary>
|
||||
/// Options for canceling a spot order
|
||||
/// </summary>
|
||||
public class CancelSpotOrderByClientOrderIdOptions : EndpointOptions<CancelOrderRequest, ISpotOrderClientIdRestClient>
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override string Description => "Cancel a spot order by its client order id";
|
||||
|
||||
/// <summary>
|
||||
/// ctor
|
||||
/// </summary>
|
||||
public CancelSpotOrderByClientOrderIdOptions(string exchange, bool authenticated) : base(exchange, authenticated, nameof(ISpotOrderClientIdRestClient.CancelSpotOrderByClientOrderIdAsync))
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override Error? ValidateRequest(CancelOrderRequest request, ISpotOrderClientIdRestClient client)
|
||||
{
|
||||
if (request.Symbol!.TradingMode != TradingMode.Spot)
|
||||
return ArgumentError.Invalid("TradingMode", $"TradingMode.{request.Symbol!.TradingMode} is not supported, should be Spot");
|
||||
|
||||
return base.ValidateRequest(request, client);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
using CryptoExchange.Net.Objects;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace CryptoExchange.Net.SharedApis
|
||||
{
|
||||
/// <summary>
|
||||
/// Options for canceling a spot order
|
||||
/// </summary>
|
||||
public class CancelSpotOrderOptions : EndpointOptions<CancelOrderRequest, ISpotOrderRestClient>
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override string Description => "Cancel a spot order";
|
||||
|
||||
/// <summary>
|
||||
/// ctor
|
||||
/// </summary>
|
||||
public CancelSpotOrderOptions(string exchange, bool authenticated) : base(exchange, authenticated, nameof(ISpotOrderRestClient.CancelSpotOrderAsync))
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override Error? ValidateRequest(CancelOrderRequest request, ISpotOrderRestClient client)
|
||||
{
|
||||
if (request.Symbol!.TradingMode != TradingMode.Spot)
|
||||
return ArgumentError.Invalid("TradingMode", $"TradingMode.{request.Symbol!.TradingMode} is not supported, should be Spot");
|
||||
|
||||
return base.ValidateRequest(request, client);
|
||||
}
|
||||
}
|
||||
}
|
||||
-32
@@ -1,32 +0,0 @@
|
||||
using CryptoExchange.Net.Objects;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace CryptoExchange.Net.SharedApis
|
||||
{
|
||||
/// <summary>
|
||||
/// Options for canceling a spot order
|
||||
/// </summary>
|
||||
public class CancelSpotOrderSocketOptions : EndpointOptions<CancelOrderRequest, ISpotOrderManagementSocketClient>
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override string Description => "Cancel a spot order over a socket connection";
|
||||
|
||||
/// <summary>
|
||||
/// ctor
|
||||
/// </summary>
|
||||
public CancelSpotOrderSocketOptions(string exchange, bool authenticated) : base(exchange, authenticated, nameof(ISpotOrderManagementSocketClient.CancelSpotOrderAsync))
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override Error? ValidateRequest(CancelOrderRequest request, ISpotOrderManagementSocketClient client)
|
||||
{
|
||||
if (request.Symbol!.TradingMode != TradingMode.Spot)
|
||||
return ArgumentError.Invalid("TradingMode", $"TradingMode.{request.Symbol!.TradingMode} is not supported, should be Spot");
|
||||
|
||||
return base.ValidateRequest(request, client);
|
||||
}
|
||||
}
|
||||
}
|
||||
-32
@@ -1,32 +0,0 @@
|
||||
using CryptoExchange.Net.Objects;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace CryptoExchange.Net.SharedApis
|
||||
{
|
||||
/// <summary>
|
||||
/// Options for requesting spot trigger order
|
||||
/// </summary>
|
||||
public class CancelSpotTriggerOrderOptions : EndpointOptions<CancelOrderRequest, ISpotTriggerOrderRestClient>
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override string Description => "Cancel a spot trigger order";
|
||||
|
||||
/// <summary>
|
||||
/// ctor
|
||||
/// </summary>
|
||||
public CancelSpotTriggerOrderOptions(string exchange, bool authenticated) : base(exchange, authenticated, nameof(ISpotTriggerOrderRestClient.CancelSpotTriggerOrderAsync))
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override Error? ValidateRequest(CancelOrderRequest request, ISpotTriggerOrderRestClient client)
|
||||
{
|
||||
if (request.Symbol!.TradingMode != TradingMode.Spot)
|
||||
return ArgumentError.Invalid("TradingMode", $"TradingMode.{request.Symbol!.TradingMode} is not supported, should be Spot");
|
||||
|
||||
return base.ValidateRequest(request, client);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace CryptoExchange.Net.SharedApis
|
||||
{
|
||||
/// <summary>
|
||||
/// Options for closing position
|
||||
/// </summary>
|
||||
public class ClosePositionOptions : EndpointOptions<ClosePositionRequest, IFuturesOrderRestClient>
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override string Description => "Close an open futures position";
|
||||
|
||||
/// <summary>
|
||||
/// ctor
|
||||
/// </summary>
|
||||
public ClosePositionOptions(string exchange, bool authenticated) : base(exchange, authenticated, nameof(IFuturesOrderRestClient.ClosePositionAsync))
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,226 +0,0 @@
|
||||
using CryptoExchange.Net.Objects;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
|
||||
namespace CryptoExchange.Net.SharedApis
|
||||
{
|
||||
/// <summary>
|
||||
/// Options for an exchange endpoint
|
||||
/// </summary>
|
||||
public abstract class EndpointOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// Required exchange-specific parameters. These can be provided via the `exchangeParameters` property of the request object.
|
||||
/// </summary>
|
||||
public List<ParameterDescription> RequiredExchangeParameters { get; set; } = new List<ParameterDescription>();
|
||||
/// <summary>
|
||||
/// Optional exchange-specific parameters. These can be provided via the `exchangeParameters` property of the request object.
|
||||
/// </summary>
|
||||
public List<ParameterDescription> OptionalExchangeParameters { get; set; } = new List<ParameterDescription>();
|
||||
/// <summary>
|
||||
/// Exchange
|
||||
/// </summary>
|
||||
public string Exchange { get; set; }
|
||||
/// <summary>
|
||||
/// Endpoint name
|
||||
/// </summary>
|
||||
public string EndpointName { get; set; }
|
||||
/// <summary>
|
||||
/// Exchange specific additional info
|
||||
/// </summary>
|
||||
public string? RequestNotes { get; set; }
|
||||
/// <summary>
|
||||
/// Whether the call requires authentication
|
||||
/// </summary>
|
||||
public bool NeedsAuthentication { get; set; }
|
||||
/// <summary>
|
||||
/// Whether the call is supported. If false the exchange API does not support this operation.
|
||||
/// </summary>
|
||||
public bool Supported { get; set; } = true;
|
||||
/// <summary>
|
||||
/// Description of the endpoint
|
||||
/// </summary>
|
||||
public abstract string Description { get; }
|
||||
|
||||
/// <summary>
|
||||
/// ctor
|
||||
/// </summary>
|
||||
public EndpointOptions(string exchange, string endpointName, bool needAuthentication)
|
||||
{
|
||||
Exchange = exchange;
|
||||
EndpointName = endpointName;
|
||||
NeedsAuthentication = needAuthentication;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validate a request
|
||||
/// </summary>
|
||||
/// <param name="exchangeParameters">Provided exchange parameters</param>
|
||||
/// <param name="tradingMode">Request trading mode</param>
|
||||
/// <param name="supportedTradingModes">Supported trading modes</param>
|
||||
/// <returns></returns>
|
||||
public virtual Error? ValidateRequest(ExchangeParameters? exchangeParameters, TradingMode? tradingMode, TradingMode[] supportedTradingModes)
|
||||
{
|
||||
if (!Supported)
|
||||
return ArgumentError.Invalid("Endpoint", $"Endpoint {Exchange} {EndpointName} is not supported by the API");
|
||||
|
||||
if (tradingMode != null && !supportedTradingModes.Contains(tradingMode.Value))
|
||||
return ArgumentError.Invalid("TradingMode", $"TradingMode.{tradingMode} is not supported, supported types: {string.Join(", ", supportedTradingModes)}");
|
||||
|
||||
foreach (var param in RequiredExchangeParameters)
|
||||
{
|
||||
if (param.Names!.All(x => ExchangeParameters.HasValue(exchangeParameters, Exchange, x, param.ValueType) != true))
|
||||
{
|
||||
if (param.Names.Length == 1)
|
||||
return ArgumentError.Invalid(string.Join("/", param.Names!), $"Exchange parameter `{param.Names[0]}` for exchange `{Exchange}` should be provided. Example: {param.ExampleValue}");
|
||||
else
|
||||
return ArgumentError.Invalid(string.Join("/", param.Names!), $"One of exchange parameters `{string.Join(", ", param.Names!)}` for exchange `{Exchange}` should be provided. Example: {param.ExampleValue}");
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Options for an exchange endpoint
|
||||
/// </summary>
|
||||
/// <typeparam name="TRequest">Type of data</typeparam>
|
||||
#if NET5_0_OR_GREATER
|
||||
public abstract class EndpointOptions<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)] TRequest> : EndpointOptions
|
||||
where TRequest : SharedRequest
|
||||
#else
|
||||
public abstract class EndpointOptions<TRequest> : EndpointOptions
|
||||
where TRequest : SharedRequest
|
||||
#endif
|
||||
{
|
||||
/// <summary>
|
||||
/// ctor
|
||||
/// </summary>
|
||||
public EndpointOptions(string exchange, bool needsAuthentication, string requestName) : base(exchange, requestName, needsAuthentication)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Options for an exchange endpoint
|
||||
/// </summary>
|
||||
/// <typeparam name="TRequest">Type of data</typeparam>
|
||||
/// <typeparam name="TClient">Type of the client</typeparam>
|
||||
#if NET5_0_OR_GREATER
|
||||
public abstract class EndpointOptions<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)] TRequest, TClient> : EndpointOptions <TRequest>
|
||||
where TRequest : SharedRequest
|
||||
where TClient : ISharedClient
|
||||
#else
|
||||
public abstract class EndpointOptions<TRequest, TClient> : EndpointOptions<TRequest>
|
||||
where TRequest : SharedRequest
|
||||
where TClient : ISharedClient
|
||||
#endif
|
||||
{
|
||||
private static PropertyInfo[] _requestProperties = typeof(TRequest).GetProperties();
|
||||
|
||||
/// <summary>
|
||||
/// Required optional parameters in the request. These can be provided via the `exchangeParameters` property of the request object.
|
||||
/// </summary>
|
||||
public List<ParameterDescription> RequiredOptionalParameters { get; set; } = new List<ParameterDescription>();
|
||||
|
||||
/// <summary>
|
||||
/// Whether this accepts multiple symbols (Only applicable to request requiring symbol parameters)
|
||||
/// </summary>
|
||||
public bool SupportsMultipleSymbols { get; set; } = false;
|
||||
/// <summary>
|
||||
/// The max number of symbols which can be passed in a call (Only applicable to request requiring symbol parameters)
|
||||
/// </summary>
|
||||
public int? MaxSymbolCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// ctor
|
||||
/// </summary>
|
||||
public EndpointOptions(string exchange, bool needsAuthentication, string requestName) : base(exchange, needsAuthentication, requestName)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validate a request
|
||||
/// </summary>
|
||||
/// <param name="request">The request</param>
|
||||
/// <param name="client">Containing client</param>
|
||||
/// <returns></returns>
|
||||
public virtual Error? ValidateRequest(TRequest request, TClient client)
|
||||
{
|
||||
if (NeedsAuthentication && !client.Authenticated)
|
||||
return new NoApiCredentialsError();
|
||||
|
||||
foreach (var param in RequiredOptionalParameters)
|
||||
{
|
||||
if (param.Names!.All(x => _requestProperties.Single(p => p.Name == x).GetValue(request, null) == null))
|
||||
{
|
||||
if (param.Names.Length == 1)
|
||||
return ArgumentError.Invalid(string.Join("/", param.Names!), $"Optional parameter `{param.Names[0]}` for exchange `{Exchange}` should be provided. Example: {param.ExampleValue}");
|
||||
else
|
||||
return ArgumentError.Invalid(string.Join("/", param.Names!), $"One of optional parameters `{string.Join(", ", param.Names!)}` for exchange `{Exchange}` should be provided. Example: {param.ExampleValue}");
|
||||
}
|
||||
}
|
||||
|
||||
if (request is SharedSymbolRequest symbolsRequest)
|
||||
{
|
||||
if (symbolsRequest.Symbols != null)
|
||||
{
|
||||
if (!SupportsMultipleSymbols)
|
||||
return ArgumentError.Invalid(nameof(SharedSymbolRequest.Symbols), $"Only a single symbol parameter is allowed, multiple symbols are not supported");
|
||||
|
||||
if (symbolsRequest.Symbols.Length > MaxSymbolCount)
|
||||
return ArgumentError.Invalid(nameof(SharedSymbolRequest.Symbols), $"Max number of symbols is {MaxSymbolCount} but {symbolsRequest.Symbols.Length} were passed");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return ValidateRequest(request.ExchangeParameters, request.TradingMode, client.SupportedTradingModes);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
sb.AppendLine($"{EndpointName}");
|
||||
if (!Supported)
|
||||
{
|
||||
sb.AppendLine(" NOT SUPPORTED");
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
sb.AppendLine($"{Description}");
|
||||
if (!string.IsNullOrEmpty(RequestNotes))
|
||||
{
|
||||
sb.Append(" Notes: ");
|
||||
sb.AppendLine(RequestNotes);
|
||||
}
|
||||
if (RequiredOptionalParameters.Any())
|
||||
{
|
||||
sb.AppendLine($" Required optional parameters:");
|
||||
foreach(var param in RequiredOptionalParameters)
|
||||
sb.AppendLine($" {param}");
|
||||
}
|
||||
if (RequiredExchangeParameters.Any())
|
||||
{
|
||||
sb.AppendLine($" Required exchange specific parameters:");
|
||||
foreach (var param in RequiredExchangeParameters)
|
||||
sb.AppendLine($" {param}");
|
||||
}
|
||||
if (OptionalExchangeParameters.Any())
|
||||
{
|
||||
sb.AppendLine($" Optional exchange specific parameters:");
|
||||
foreach (var param in OptionalExchangeParameters)
|
||||
sb.AppendLine($" {param}");
|
||||
}
|
||||
sb.Append(" Needs authentication: ");
|
||||
sb.AppendLine($"{NeedsAuthentication}");
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace CryptoExchange.Net.SharedApis
|
||||
{
|
||||
/// <summary>
|
||||
/// Options for requesting book ticker
|
||||
/// </summary>
|
||||
public class GetBookTickerOptions : EndpointOptions<GetBookTickerRequest, IBookTickerRestClient>
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override string Description => "Retrieve the best bid and ask price for a symbol";
|
||||
|
||||
/// <summary>
|
||||
/// ctor
|
||||
/// </summary>
|
||||
public GetBookTickerOptions(string exchange, bool authenticated) : base(exchange, authenticated, nameof(IBookTickerRestClient.GetBookTickerAsync))
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace CryptoExchange.Net.SharedApis
|
||||
{
|
||||
/// <summary>
|
||||
/// Options for requesting deposit address
|
||||
/// </summary>
|
||||
public class GetDepositAddressesOptions : EndpointOptions<GetDepositAddressesRequest, IDepositRestClient>
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override string Description => "Retrieve deposit addresses for an asset";
|
||||
|
||||
/// <summary>
|
||||
/// ctor
|
||||
/// </summary>
|
||||
public GetDepositAddressesOptions(string exchange, bool authenticated) : base(exchange, authenticated, nameof(IDepositRestClient.GetDepositAddressesAsync))
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
-22
@@ -1,22 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace CryptoExchange.Net.SharedApis
|
||||
{
|
||||
/// <summary>
|
||||
/// Options for getting a spot order by client order id
|
||||
/// </summary>
|
||||
public class GetFuturesOrderByClientOrderIdOptions : EndpointOptions<GetOrderRequest, IFuturesOrderClientIdRestClient>
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override string Description => "Retrieve a futures order by its client order id";
|
||||
|
||||
/// <summary>
|
||||
/// ctor
|
||||
/// </summary>
|
||||
public GetFuturesOrderByClientOrderIdOptions(string exchange, bool authenticated) : base(exchange, authenticated, nameof(IFuturesOrderClientIdRestClient.GetFuturesOrderByClientOrderIdAsync))
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace CryptoExchange.Net.SharedApis
|
||||
{
|
||||
/// <summary>
|
||||
/// Options for getting a futures order by id endpoint
|
||||
/// </summary>
|
||||
public class GetFuturesOrderOptions : EndpointOptions<GetOrderRequest, IFuturesOrderRestClient>
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override string Description => "Retrieve a futures order";
|
||||
|
||||
/// <summary>
|
||||
/// ctor
|
||||
/// </summary>
|
||||
public GetFuturesOrderOptions(string exchange, bool authenticated) : base(exchange, authenticated, nameof(IFuturesOrderRestClient.GetFuturesOrderAsync))
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
-22
@@ -1,22 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace CryptoExchange.Net.SharedApis
|
||||
{
|
||||
/// <summary>
|
||||
/// Options for getting a trades for an order
|
||||
/// </summary>
|
||||
public class GetFuturesOrderTradesOptions : EndpointOptions<GetOrderTradesRequest, IFuturesOrderRestClient>
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override string Description => "Retrieve trades for a futures order";
|
||||
|
||||
/// <summary>
|
||||
/// ctor
|
||||
/// </summary>
|
||||
public GetFuturesOrderTradesOptions(string exchange, bool authenticated) : base(exchange, authenticated, nameof(IFuturesOrderRestClient.GetFuturesOrderTradesAsync))
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
-22
@@ -1,22 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace CryptoExchange.Net.SharedApis
|
||||
{
|
||||
/// <summary>
|
||||
/// Options for requesting futures trigger order
|
||||
/// </summary>
|
||||
public class GetFuturesTriggerOrderOptions : EndpointOptions<GetOrderRequest, IFuturesTriggerOrderRestClient>
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override string Description => "Retrieve a futures trigger order";
|
||||
|
||||
/// <summary>
|
||||
/// ctor
|
||||
/// </summary>
|
||||
public GetFuturesTriggerOrderOptions(string exchange, bool authenticated) : base(exchange, authenticated, nameof(IFuturesTriggerOrderRestClient.GetFuturesTriggerOrderAsync))
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace CryptoExchange.Net.SharedApis
|
||||
{
|
||||
/// <summary>
|
||||
/// Options for requesting asset info
|
||||
/// </summary>
|
||||
public class GetLeverageOptions : EndpointOptions<GetLeverageRequest, ILeverageRestClient>
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override string Description => "Retrieve the current leverage for a futures symbol";
|
||||
|
||||
/// <summary>
|
||||
/// ctor
|
||||
/// </summary>
|
||||
public GetLeverageOptions(string exchange, bool authenticated) : base(exchange, authenticated, nameof(ILeverageRestClient.GetLeverageAsync))
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace CryptoExchange.Net.SharedApis
|
||||
{
|
||||
/// <summary>
|
||||
/// Options for getting a futures order by id endpoint
|
||||
/// </summary>
|
||||
public class GetOpenFuturesOrdersOptions : EndpointOptions<GetOpenOrdersRequest, IFuturesOrderRestClient>
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override string Description => "Retrieve open futures orders";
|
||||
|
||||
/// <summary>
|
||||
/// ctor
|
||||
/// </summary>
|
||||
public GetOpenFuturesOrdersOptions(string exchange, bool authenticated) : base(exchange, authenticated, nameof(IFuturesOrderRestClient.GetOpenFuturesOrdersAsync))
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace CryptoExchange.Net.SharedApis
|
||||
{
|
||||
/// <summary>
|
||||
/// Options for requesting open interest
|
||||
/// </summary>
|
||||
public class GetOpenInterestOptions : EndpointOptions<GetOpenInterestRequest, IOpenInterestRestClient>
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override string Description => "Retrieve open interest for a futures symbol";
|
||||
|
||||
/// <summary>
|
||||
/// ctor
|
||||
/// </summary>
|
||||
public GetOpenInterestOptions(string exchange, bool authenticated) : base(exchange, authenticated, nameof(IOpenInterestRestClient.GetOpenInterestAsync))
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace CryptoExchange.Net.SharedApis
|
||||
{
|
||||
/// <summary>
|
||||
/// Options for getting a spot order by id endpoint
|
||||
/// </summary>
|
||||
public class GetOpenSpotOrdersOptions : EndpointOptions<GetOpenOrdersRequest, ISpotOrderRestClient>
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override string Description => "Retrieve open spot orders";
|
||||
|
||||
/// <summary>
|
||||
/// ctor
|
||||
/// </summary>
|
||||
public GetOpenSpotOrdersOptions(string exchange, bool authenticated) : base(exchange, authenticated, nameof(ISpotOrderRestClient.GetOpenSpotOrdersAsync))
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
namespace CryptoExchange.Net.SharedApis
|
||||
{
|
||||
/// <summary>
|
||||
/// Options for requesting current position mode
|
||||
/// </summary>
|
||||
public class GetPositionModeOptions : EndpointOptions<GetPositionModeRequest, IPositionModeRestClient>
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override string Description => "Retrieve the current futures position mode";
|
||||
|
||||
/// <summary>
|
||||
/// ctor
|
||||
/// </summary>
|
||||
public GetPositionModeOptions(string exchange) : base(exchange, true, nameof(IPositionModeRestClient.GetPositionModeAsync))
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace CryptoExchange.Net.SharedApis
|
||||
{
|
||||
/// <summary>
|
||||
/// Options for requesting open positions
|
||||
/// </summary>
|
||||
public class GetPositionsOptions : EndpointOptions<GetPositionsRequest, IFuturesOrderRestClient>
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override string Description => "Retrieve open futures positions";
|
||||
|
||||
/// <summary>
|
||||
/// ctor
|
||||
/// </summary>
|
||||
public GetPositionsOptions(string exchange, bool authenticated) : base(exchange, authenticated, nameof(IFuturesOrderRestClient.GetPositionsAsync))
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
-32
@@ -1,32 +0,0 @@
|
||||
using CryptoExchange.Net.Objects;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace CryptoExchange.Net.SharedApis
|
||||
{
|
||||
/// <summary>
|
||||
/// Options for getting a spot order by client order id endpoint
|
||||
/// </summary>
|
||||
public class GetSpotOrderByClientOrderIdOptions : EndpointOptions<GetOrderRequest, ISpotOrderClientIdRestClient>
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override string Description => "Retrieve a spot order by its client order id";
|
||||
|
||||
/// <summary>
|
||||
/// ctor
|
||||
/// </summary>
|
||||
public GetSpotOrderByClientOrderIdOptions(string exchange, bool authenticated) : base(exchange, authenticated, nameof(ISpotOrderClientIdRestClient.GetSpotOrderByClientOrderIdAsync))
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override Error? ValidateRequest(GetOrderRequest request, ISpotOrderClientIdRestClient client)
|
||||
{
|
||||
if (request.Symbol!.TradingMode != TradingMode.Spot)
|
||||
return ArgumentError.Invalid("TradingMode", $"TradingMode.{request.Symbol!.TradingMode} is not supported, should be Spot");
|
||||
|
||||
return base.ValidateRequest(request, client);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
using CryptoExchange.Net.Objects;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace CryptoExchange.Net.SharedApis
|
||||
{
|
||||
/// <summary>
|
||||
/// Options for getting trades for a spot order
|
||||
/// </summary>
|
||||
public class GetSpotOrderTradesOptions : EndpointOptions<GetOrderTradesRequest, ISpotOrderRestClient>
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override string Description => "Retrieve trades for a spot order";
|
||||
|
||||
/// <summary>
|
||||
/// ctor
|
||||
/// </summary>
|
||||
public GetSpotOrderTradesOptions(string exchange, bool authenticated) : base(exchange, authenticated, nameof(ISpotOrderRestClient.GetSpotOrderTradesAsync))
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override Error? ValidateRequest(GetOrderTradesRequest request, ISpotOrderRestClient client)
|
||||
{
|
||||
if (request.Symbol!.TradingMode != TradingMode.Spot)
|
||||
return ArgumentError.Invalid("TradingMode", $"TradingMode.{request.Symbol!.TradingMode} is not supported, should be Spot");
|
||||
|
||||
return base.ValidateRequest(request, client);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
using System.Text;
|
||||
|
||||
namespace CryptoExchange.Net.SharedApis
|
||||
{
|
||||
/// <summary>
|
||||
/// Options for requesting ticker
|
||||
/// </summary>
|
||||
public class GetSpotTickerOptions : EndpointOptions<GetTickerRequest, ISpotTickerRestClient>
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override string Description => "Retrieve price ticker information for a spot symbol";
|
||||
|
||||
/// <summary>
|
||||
/// Type of ticker calculation
|
||||
/// </summary>
|
||||
public SharedTickerType TickerType { get; set; } = SharedTickerType.Day24H;
|
||||
|
||||
/// <summary>
|
||||
/// ctor
|
||||
/// </summary>
|
||||
public GetSpotTickerOptions(string exchange, SharedTickerType? tickerCalcType = null) : base(exchange, false, nameof(ISpotTickerRestClient.GetSpotTickerAsync))
|
||||
{
|
||||
TickerType = tickerCalcType ?? SharedTickerType.Day24H;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
var sb = new StringBuilder(base.ToString());
|
||||
sb.AppendLine($" Ticker data calculation type: {TickerType}");
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
using System.Text;
|
||||
|
||||
namespace CryptoExchange.Net.SharedApis
|
||||
{
|
||||
/// <summary>
|
||||
/// Options for requesting tickers
|
||||
/// </summary>
|
||||
public class GetSpotTickersOptions : EndpointOptions<GetTickersRequest, ISpotTickerRestClient>
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override string Description => "Retrieve price ticker information for all spot symbols";
|
||||
|
||||
/// <summary>
|
||||
/// Type of ticker calculation
|
||||
/// </summary>
|
||||
public SharedTickerType TickerType { get; set; } = SharedTickerType.Day24H;
|
||||
|
||||
/// <summary>
|
||||
/// ctor
|
||||
/// </summary>
|
||||
public GetSpotTickersOptions(string exchange, SharedTickerType? tickerCalcType = null) : base(exchange, false, nameof(ISpotTickerRestClient.GetSpotTickersAsync))
|
||||
{
|
||||
TickerType = tickerCalcType ?? SharedTickerType.Day24H;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
var sb = new StringBuilder(base.ToString());
|
||||
sb.AppendLine($" Ticker data calculation type: {TickerType}");
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
using CryptoExchange.Net.Objects;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace CryptoExchange.Net.SharedApis
|
||||
{
|
||||
/// <summary>
|
||||
/// Options for requesting spot trigger order
|
||||
/// </summary>
|
||||
public class GetSpotTriggerOrderOptions : EndpointOptions<GetOrderRequest, ISpotTriggerOrderRestClient>
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override string Description => "Retrieve a spot trigger order";
|
||||
|
||||
/// <summary>
|
||||
/// ctor
|
||||
/// </summary>
|
||||
public GetSpotTriggerOrderOptions(string exchange, bool authenticated) : base(exchange, authenticated, nameof(ISpotTriggerOrderRestClient.GetSpotTriggerOrderAsync))
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override Error? ValidateRequest(GetOrderRequest request, ISpotTriggerOrderRestClient client)
|
||||
{
|
||||
if (request.Symbol!.TradingMode != TradingMode.Spot)
|
||||
return ArgumentError.Invalid("TradingMode", $"TradingMode.{request.Symbol!.TradingMode} is not supported, should be Spot");
|
||||
|
||||
return base.ValidateRequest(request, client);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
using CryptoExchange.Net.Objects;
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace CryptoExchange.Net.SharedApis
|
||||
{
|
||||
/// <summary>
|
||||
/// Options for placing a new futures order
|
||||
/// </summary>
|
||||
public class PlaceFuturesOrderOptions : EndpointOptions<PlaceFuturesOrderRequest, IFuturesOrderRestClient>
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override string Description => "Place a new futures order";
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not the API supports setting take profit / stop loss with the order
|
||||
/// </summary>
|
||||
public bool SupportsTpSl { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// ctor
|
||||
/// </summary>
|
||||
public PlaceFuturesOrderOptions(string exchange, bool supportsTpSl) : base(exchange, true, nameof(IFuturesOrderRestClient.PlaceFuturesOrderAsync))
|
||||
{
|
||||
SupportsTpSl = supportsTpSl;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validate a request
|
||||
/// </summary>
|
||||
public override Error? ValidateRequest(
|
||||
PlaceFuturesOrderRequest request,
|
||||
IFuturesOrderRestClient client
|
||||
)
|
||||
{
|
||||
if (!SupportsTpSl && (request.StopLossPrice != null || request.TakeProfitPrice != null))
|
||||
return ArgumentError.Invalid(nameof(PlaceFuturesOrderRequest.StopLossPrice) + " / " + nameof(PlaceFuturesOrderRequest.TakeProfitPrice), "Tp/Sl parameters not supported");
|
||||
|
||||
if (request.OrderType == SharedOrderType.Other)
|
||||
throw new ArgumentException("OrderType can't be `Other`", nameof(request.OrderType));
|
||||
|
||||
if (!client.FuturesSupportedOrderTypes.Contains(request.OrderType))
|
||||
return ArgumentError.Invalid(nameof(PlaceFuturesOrderRequest.OrderType), "Order type not supported");
|
||||
|
||||
if (request.TimeInForce != null && !client.FuturesSupportedTimeInForce.Contains(request.TimeInForce.Value))
|
||||
return ArgumentError.Invalid(nameof(PlaceFuturesOrderRequest.TimeInForce), "Order time in force not supported");
|
||||
|
||||
var quantityError = client.FuturesSupportedOrderQuantity.Validate(request.Side, request.OrderType, request.Quantity);
|
||||
if (quantityError != null)
|
||||
return quantityError;
|
||||
|
||||
return base.ValidateRequest(request, client);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
-56
@@ -1,56 +0,0 @@
|
||||
using CryptoExchange.Net.Objects;
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace CryptoExchange.Net.SharedApis
|
||||
{
|
||||
/// <summary>
|
||||
/// Options for placing a new futures order
|
||||
/// </summary>
|
||||
public class PlaceFuturesOrderSocketOptions : EndpointOptions<PlaceFuturesOrderRequest, IFuturesOrderManagementSocketClient>
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override string Description => "Place a new futures order over a socket connection";
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not the API supports setting take profit / stop loss with the order
|
||||
/// </summary>
|
||||
public bool SupportsTpSl { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// ctor
|
||||
/// </summary>
|
||||
public PlaceFuturesOrderSocketOptions(string exchange, bool supportsTpSl) : base(exchange, true, nameof(IFuturesOrderManagementSocketClient.PlaceFuturesOrderAsync))
|
||||
{
|
||||
SupportsTpSl = supportsTpSl;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validate a request
|
||||
/// </summary>
|
||||
public override Error? ValidateRequest(
|
||||
PlaceFuturesOrderRequest request,
|
||||
IFuturesOrderManagementSocketClient client
|
||||
)
|
||||
{
|
||||
if (!SupportsTpSl && (request.StopLossPrice != null || request.TakeProfitPrice != null))
|
||||
return ArgumentError.Invalid(nameof(PlaceFuturesOrderRequest.StopLossPrice) + " / " + nameof(PlaceFuturesOrderRequest.TakeProfitPrice), "Tp/Sl parameters not supported");
|
||||
|
||||
if (request.OrderType == SharedOrderType.Other)
|
||||
throw new ArgumentException("OrderType can't be `Other`", nameof(request.OrderType));
|
||||
|
||||
if (!client.FuturesSupportedOrderTypes.Contains(request.OrderType))
|
||||
return ArgumentError.Invalid(nameof(PlaceFuturesOrderRequest.OrderType), "Order type not supported");
|
||||
|
||||
if (request.TimeInForce != null && !client.FuturesSupportedTimeInForce.Contains(request.TimeInForce.Value))
|
||||
return ArgumentError.Invalid(nameof(PlaceFuturesOrderRequest.TimeInForce), "Order time in force not supported");
|
||||
|
||||
var quantityError = client.FuturesSupportedOrderQuantity.Validate(request.Side, request.OrderType, request.Quantity);
|
||||
if (quantityError != null)
|
||||
return quantityError;
|
||||
|
||||
return base.ValidateRequest(request, client);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
-26
@@ -1,26 +0,0 @@
|
||||
using CryptoExchange.Net.Objects;
|
||||
|
||||
namespace CryptoExchange.Net.SharedApis
|
||||
{
|
||||
/// <summary>
|
||||
/// Options for placing a new spot trigger order
|
||||
/// </summary>
|
||||
public class PlaceFuturesTriggerOrderOptions : EndpointOptions<PlaceFuturesTriggerOrderRequest, IFuturesTriggerOrderRestClient>
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override string Description => "Place a new futures trigger order";
|
||||
|
||||
/// <summary>
|
||||
/// When true the API holds the funds until the order is triggered or canceled. When false the funds will only be required when the order is triggered and will fail if the funds are not available at that time.
|
||||
/// </summary>
|
||||
public bool HoldsFunds { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// ctor
|
||||
/// </summary>
|
||||
public PlaceFuturesTriggerOrderOptions(string exchange, bool holdsFunds) : base(exchange, true, nameof(IFuturesTriggerOrderRestClient.PlaceFuturesTriggerOrderAsync))
|
||||
{
|
||||
HoldsFunds = holdsFunds;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
using CryptoExchange.Net.Objects;
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace CryptoExchange.Net.SharedApis
|
||||
{
|
||||
/// <summary>
|
||||
/// Options for placing a new spot order
|
||||
/// </summary>
|
||||
public class PlaceSpotOrderSocketOptions : EndpointOptions<PlaceSpotOrderRequest, ISpotOrderManagementSocketClient>
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override string Description => "Place a new spot order over a socket connection";
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// ctor
|
||||
/// </summary>
|
||||
public PlaceSpotOrderSocketOptions(string exchange) : base(exchange, true, nameof(ISpotOrderManagementSocketClient.PlaceSpotOrderAsync))
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validate a request
|
||||
/// </summary>
|
||||
public override Error? ValidateRequest(
|
||||
PlaceSpotOrderRequest request,
|
||||
ISpotOrderManagementSocketClient client)
|
||||
{
|
||||
if (request.Symbol!.TradingMode != TradingMode.Spot)
|
||||
return ArgumentError.Invalid("TradingMode", $"TradingMode.{request.Symbol!.TradingMode} is not supported, should be Spot");
|
||||
|
||||
if (request.OrderType == SharedOrderType.Other)
|
||||
throw new ArgumentException("OrderType can't be `Other`", nameof(request.OrderType));
|
||||
|
||||
if (!client.SpotSupportedOrderTypes.Contains(request.OrderType))
|
||||
return ArgumentError.Invalid(nameof(PlaceSpotOrderRequest.OrderType), "Order type not supported");
|
||||
|
||||
if (request.TimeInForce != null && !client.SpotSupportedTimeInForce.Contains(request.TimeInForce.Value))
|
||||
return ArgumentError.Invalid(nameof(PlaceSpotOrderRequest.TimeInForce), "Order time in force not supported");
|
||||
|
||||
var quantityError = client.SpotSupportedOrderQuantity.Validate(request.Side, request.OrderType, request.Quantity);
|
||||
if (quantityError != null)
|
||||
return quantityError;
|
||||
|
||||
return base.ValidateRequest(request, client);
|
||||
}
|
||||
}
|
||||
}
|
||||
-43
@@ -1,43 +0,0 @@
|
||||
using CryptoExchange.Net.Objects;
|
||||
|
||||
namespace CryptoExchange.Net.SharedApis
|
||||
{
|
||||
/// <summary>
|
||||
/// Options for placing a new spot trigger order
|
||||
/// </summary>
|
||||
public class PlaceSpotTriggerOrderOptions : EndpointOptions<PlaceSpotTriggerOrderRequest, ISpotOrderRestClient>
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override string Description => "Place a new spot trigger order";
|
||||
|
||||
/// <summary>
|
||||
/// When true the API holds the funds until the order is triggered or canceled. When false the funds will only be required when the order is triggered and will fail if the funds are not available at that time.
|
||||
/// </summary>
|
||||
public bool HoldsFunds { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// ctor
|
||||
/// </summary>
|
||||
public PlaceSpotTriggerOrderOptions(string exchange, bool holdsFunds) : base(exchange, true, nameof(ISpotTriggerOrderRestClient.PlaceSpotTriggerOrderAsync))
|
||||
{
|
||||
HoldsFunds = holdsFunds;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validate a request
|
||||
/// </summary>
|
||||
public override Error? ValidateRequest(
|
||||
PlaceSpotTriggerOrderRequest request,
|
||||
ISpotOrderRestClient client)
|
||||
{
|
||||
if (request.Symbol!.TradingMode != TradingMode.Spot)
|
||||
return ArgumentError.Invalid("TradingMode", $"TradingMode.{request.Symbol!.TradingMode} is not supported, should be Spot");
|
||||
|
||||
var quantityError = client.SpotSupportedOrderQuantity.Validate(request.OrderSide, request.OrderPrice == null ? SharedOrderType.Market : SharedOrderType.Limit, request.Quantity);
|
||||
if (quantityError != null)
|
||||
return quantityError;
|
||||
|
||||
return base.ValidateRequest(request, client);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace CryptoExchange.Net.SharedApis
|
||||
{
|
||||
/// <summary>
|
||||
/// Options for setting a TP/SL
|
||||
/// </summary>
|
||||
public class SetFuturesTpSlOptions : EndpointOptions<SetTpSlRequest, IFuturesTpSlRestClient>
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override string Description => "Set take profit or stop loss values for a futures position";
|
||||
|
||||
/// <summary>
|
||||
/// ctor
|
||||
/// </summary>
|
||||
public SetFuturesTpSlOptions(string exchange, bool authenticated) : base(exchange, authenticated, nameof(IFuturesTpSlRestClient.SetFuturesTpSlAsync))
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
namespace CryptoExchange.Net.SharedApis
|
||||
{
|
||||
/// <summary>
|
||||
/// Options for setting leverage
|
||||
/// </summary>
|
||||
public class SetLeverageOptions : EndpointOptions<SetLeverageRequest, ILeverageRestClient>
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override string Description => "Set the leverage for a futures symbol";
|
||||
|
||||
/// <summary>
|
||||
/// ctor
|
||||
/// </summary>
|
||||
public SetLeverageOptions(string exchange) : base(exchange, true, nameof(ILeverageRestClient.SetLeverageAsync))
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
namespace CryptoExchange.Net.SharedApis
|
||||
{
|
||||
/// <summary>
|
||||
/// Options for setting position mode
|
||||
/// </summary>
|
||||
public class SetPositionModeOptions : EndpointOptions<SetPositionModeRequest, IPositionModeRestClient>
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override string Description => "Set the futures position mode";
|
||||
|
||||
/// <summary>
|
||||
/// ctor
|
||||
/// </summary>
|
||||
public SetPositionModeOptions(string exchange) : base(exchange, true, nameof(IPositionModeRestClient.SetPositionModeOptions))
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
namespace CryptoExchange.Net.SharedApis
|
||||
{
|
||||
/// <summary>
|
||||
/// Options for requesting a withdrawal
|
||||
/// </summary>
|
||||
public class WithdrawOptions : EndpointOptions<WithdrawRequest, IWithdrawRestClient>
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override string Description => "Withdraw an asset";
|
||||
|
||||
/// <summary>
|
||||
/// ctor
|
||||
/// </summary>
|
||||
public WithdrawOptions(string exchange) : base(exchange, true, nameof(IWithdrawRestClient.WithdrawAsync))
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace CryptoExchange.Net.SharedApis
|
||||
{
|
||||
/// <summary>
|
||||
/// Parameter description
|
||||
/// </summary>
|
||||
public class ParameterDescription
|
||||
{
|
||||
/// <summary>
|
||||
/// Possible names for the parameter. One of these names can be used to provide the parameter in the ExchangeParameters of the request.
|
||||
/// </summary>
|
||||
public string[] Names { get; set; }
|
||||
/// <summary>
|
||||
/// Type of the value
|
||||
/// </summary>
|
||||
public Type ValueType { get; set; }
|
||||
/// <summary>
|
||||
/// Parameter description
|
||||
/// </summary>
|
||||
public string Description { get; set; }
|
||||
/// <summary>
|
||||
/// Example value
|
||||
/// </summary>
|
||||
public object ExampleValue { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// ctor
|
||||
/// </summary>
|
||||
public ParameterDescription(string parameterName, Type valueType, string description, object exampleValue)
|
||||
{
|
||||
Names = [parameterName];
|
||||
ValueType = valueType;
|
||||
Description = description;
|
||||
ExampleValue = exampleValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ctor
|
||||
/// </summary>
|
||||
public ParameterDescription(string[] parameterNames, Type valueType, string description, object exampleValue)
|
||||
{
|
||||
Names = parameterNames;
|
||||
ValueType = valueType;
|
||||
Description = description;
|
||||
ExampleValue = exampleValue;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
return $"[{ValueType.Name}] {string.Join(" / ", Names.Select(x => $"\"{x}\""))}: {Description}";
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user