mirror of
https://github.com/JKorf/CryptoExchange.Net.git
synced 2026-10-15 07:31:50 +00:00
wip
This commit is contained in:
@@ -0,0 +1,117 @@
|
|||||||
|
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)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
using CryptoExchange.Net.Objects;
|
using CryptoExchange.Net.Objects;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@@ -227,6 +229,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
where TCapability : ISharedApiCapability
|
where TCapability : ISharedApiCapability
|
||||||
{
|
{
|
||||||
private static PropertyInfo[] _requestProperties = typeof(TRequest).GetProperties();
|
private static PropertyInfo[] _requestProperties = typeof(TRequest).GetProperties();
|
||||||
|
private static readonly ConcurrentDictionary<(string Exchange, string Operation, string Parameter), byte> _loggedUnsupportedParameters = new();
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override Type CapabilityType => typeof(TCapability);
|
public override Type CapabilityType => typeof(TCapability);
|
||||||
@@ -274,9 +277,19 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
{
|
{
|
||||||
if (value != null)
|
if (value != null)
|
||||||
{
|
{
|
||||||
return ArgumentError.Invalid(
|
// For backwards compatibility don't return an error for provided unsupported parameters, only log a warning.
|
||||||
param.Name,
|
// In a future release this will be changed to return an error.
|
||||||
$"Request parameter `{param.Name}` is not supported by exchange `{Exchange}`");
|
//return ArgumentError.Invalid(
|
||||||
|
// param.Name,
|
||||||
|
// $"Request parameter `{param.Name}` is not supported by exchange `{Exchange}`");
|
||||||
|
|
||||||
|
var warningKey = (Exchange, OperationName, param.Name);
|
||||||
|
if (_loggedUnsupportedParameters.TryAdd(warningKey, 0))
|
||||||
|
{
|
||||||
|
LibraryHelpers.StaticLogger?.LogWarning("The parameter {ParamName} has a supplied value for {Exchange}.{CapabilityName}, but is not supported. " +
|
||||||
|
"In a future major release this will return an error. To check supported/required parameters use the option RequestParameterRules.",
|
||||||
|
param.Name, Exchange, OperationName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,10 +37,14 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
GetBalancesRequest request,
|
GetBalancesRequest request,
|
||||||
IGetBalancesRest client)
|
IGetBalancesRest client)
|
||||||
{
|
{
|
||||||
|
var error = base.ValidateRequest(request, client);
|
||||||
|
if (error != null)
|
||||||
|
return error;
|
||||||
|
|
||||||
if (request.AccountType != null && !IsValid(request.AccountType.Value))
|
if (request.AccountType != null && !IsValid(request.AccountType.Value))
|
||||||
return ArgumentError.Invalid(nameof(request.AccountType), "Invalid AccountType");
|
return ArgumentError.Invalid(nameof(request.AccountType), "Invalid AccountType");
|
||||||
|
|
||||||
return base.ValidateRequest(request, client);
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
+5
-1
@@ -32,6 +32,10 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override Error? ValidateRequest(GetDepositsRequest request, IGetDepositHistoryRest client)
|
public override Error? ValidateRequest(GetDepositsRequest request, IGetDepositHistoryRest client)
|
||||||
{
|
{
|
||||||
|
var error = base.ValidateRequest(request, client);
|
||||||
|
if (error != null)
|
||||||
|
return error;
|
||||||
|
|
||||||
if (!SupportsAscending && request.Direction == DataDirection.Ascending)
|
if (!SupportsAscending && request.Direction == DataDirection.Ascending)
|
||||||
return ArgumentError.Invalid(nameof(GetWithdrawalsRequest.Direction), $"Ascending direction is not supported");
|
return ArgumentError.Invalid(nameof(GetWithdrawalsRequest.Direction), $"Ascending direction is not supported");
|
||||||
|
|
||||||
@@ -52,7 +56,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return base.ValidateRequest(request, client);
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-1
@@ -32,6 +32,10 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override Error? ValidateRequest(GetFundingRateHistoryRequest request, IGetFundingRateHistoryRest client)
|
public override Error? ValidateRequest(GetFundingRateHistoryRequest request, IGetFundingRateHistoryRest client)
|
||||||
{
|
{
|
||||||
|
var error = base.ValidateRequest(request, client);
|
||||||
|
if (error != null)
|
||||||
|
return error;
|
||||||
|
|
||||||
if (!SupportsAscending && request.Direction == DataDirection.Ascending)
|
if (!SupportsAscending && request.Direction == DataDirection.Ascending)
|
||||||
return ArgumentError.Invalid(nameof(GetWithdrawalsRequest.Direction), $"Ascending direction is not supported");
|
return ArgumentError.Invalid(nameof(GetWithdrawalsRequest.Direction), $"Ascending direction is not supported");
|
||||||
|
|
||||||
@@ -52,7 +56,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return base.ValidateRequest(request, client);
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-1
@@ -32,6 +32,10 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override Error? ValidateRequest(GetUserFundingHistoryRequest request, IGetUserFundingHistoryRest client)
|
public override Error? ValidateRequest(GetUserFundingHistoryRequest request, IGetUserFundingHistoryRest client)
|
||||||
{
|
{
|
||||||
|
var error = base.ValidateRequest(request, client);
|
||||||
|
if (error != null)
|
||||||
|
return error;
|
||||||
|
|
||||||
if (!SupportsAscending && request.Direction == DataDirection.Ascending)
|
if (!SupportsAscending && request.Direction == DataDirection.Ascending)
|
||||||
return ArgumentError.Invalid(nameof(GetUserFundingHistoryRequest.Direction), $"Ascending direction is not supported");
|
return ArgumentError.Invalid(nameof(GetUserFundingHistoryRequest.Direction), $"Ascending direction is not supported");
|
||||||
|
|
||||||
@@ -52,7 +56,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return base.ValidateRequest(request, client);
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-1
@@ -76,6 +76,10 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override Error? ValidateRequest(GetKlinesRequest request, IGetIndexPriceKlinesRest client)
|
public override Error? ValidateRequest(GetKlinesRequest request, IGetIndexPriceKlinesRest client)
|
||||||
{
|
{
|
||||||
|
var error = base.ValidateRequest(request, client);
|
||||||
|
if (error != null)
|
||||||
|
return error;
|
||||||
|
|
||||||
if (!IsSupported(request.Interval))
|
if (!IsSupported(request.Interval))
|
||||||
return ArgumentError.Invalid(nameof(GetKlinesRequest.Interval), $"Interval {request.Interval} not supported");
|
return ArgumentError.Invalid(nameof(GetKlinesRequest.Interval), $"Interval {request.Interval} not supported");
|
||||||
|
|
||||||
@@ -114,7 +118,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return base.ValidateRequest(request, client);
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
|||||||
+5
-1
@@ -76,6 +76,10 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override Error? ValidateRequest(GetKlinesRequest request, IGetMarkPriceKlinesRest client)
|
public override Error? ValidateRequest(GetKlinesRequest request, IGetMarkPriceKlinesRest client)
|
||||||
{
|
{
|
||||||
|
var error = base.ValidateRequest(request, client);
|
||||||
|
if (error != null)
|
||||||
|
return error;
|
||||||
|
|
||||||
if (!IsSupported(request.Interval))
|
if (!IsSupported(request.Interval))
|
||||||
return ArgumentError.Invalid(nameof(GetKlinesRequest.Interval), $"Interval {request.Interval} not supported");
|
return ArgumentError.Invalid(nameof(GetKlinesRequest.Interval), $"Interval {request.Interval} not supported");
|
||||||
|
|
||||||
@@ -114,7 +118,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return base.ValidateRequest(request, client);
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
|||||||
@@ -76,6 +76,10 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override Error? ValidateRequest(GetKlinesRequest request, IGetKlinesRest client)
|
public override Error? ValidateRequest(GetKlinesRequest request, IGetKlinesRest client)
|
||||||
{
|
{
|
||||||
|
var error = base.ValidateRequest(request, client);
|
||||||
|
if (error != null)
|
||||||
|
return error;
|
||||||
|
|
||||||
if (!IsSupported(request.Interval))
|
if (!IsSupported(request.Interval))
|
||||||
return ArgumentError.Invalid(nameof(GetKlinesRequest.Interval), $"Interval {request.Interval} not supported");
|
return ArgumentError.Invalid(nameof(GetKlinesRequest.Interval), $"Interval {request.Interval} not supported");
|
||||||
|
|
||||||
@@ -114,7 +118,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return base.ValidateRequest(request, client);
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
|||||||
@@ -69,10 +69,14 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public override Error? ValidateRequest(SubscribeKlineRequest request, ISubscribeKlinesSocket client)
|
public override Error? ValidateRequest(SubscribeKlineRequest request, ISubscribeKlinesSocket client)
|
||||||
{
|
{
|
||||||
|
var error = base.ValidateRequest(request, client);
|
||||||
|
if (error != null)
|
||||||
|
return error;
|
||||||
|
|
||||||
if (!IsSupported(request.Interval))
|
if (!IsSupported(request.Interval))
|
||||||
return ArgumentError.Invalid(nameof(SubscribeKlineRequest.Interval), "Interval not supported");
|
return ArgumentError.Invalid(nameof(SubscribeKlineRequest.Interval), "Interval not supported");
|
||||||
|
|
||||||
return base.ValidateRequest(request, client);
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,6 +32,10 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override Error? ValidateRequest(GetLedgerRequest request, IGetLedgerRest client)
|
public override Error? ValidateRequest(GetLedgerRequest request, IGetLedgerRest client)
|
||||||
{
|
{
|
||||||
|
var error = base.ValidateRequest(request, client);
|
||||||
|
if (error != null)
|
||||||
|
return error;
|
||||||
|
|
||||||
if (!SupportsAscending && request.Direction == DataDirection.Ascending)
|
if (!SupportsAscending && request.Direction == DataDirection.Ascending)
|
||||||
return ArgumentError.Invalid(nameof(GetLedgerRequest.Direction), $"Ascending direction is not supported");
|
return ArgumentError.Invalid(nameof(GetLedgerRequest.Direction), $"Ascending direction is not supported");
|
||||||
|
|
||||||
@@ -52,7 +56,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return base.ValidateRequest(request, client);
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,6 +55,10 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override Error? ValidateRequest(GetOrderBookRequest request, IGetOrderBookRest client)
|
public override Error? ValidateRequest(GetOrderBookRequest request, IGetOrderBookRest client)
|
||||||
{
|
{
|
||||||
|
var error = base.ValidateRequest(request, client);
|
||||||
|
if (error != null)
|
||||||
|
return error;
|
||||||
|
|
||||||
if (request.Limit == null)
|
if (request.Limit == null)
|
||||||
return base.ValidateRequest(request, client);
|
return base.ValidateRequest(request, client);
|
||||||
|
|
||||||
@@ -67,7 +71,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
if (SupportedLimits != null && !SupportedLimits.Contains(request.Limit.Value))
|
if (SupportedLimits != null && !SupportedLimits.Contains(request.Limit.Value))
|
||||||
return ArgumentError.Invalid(nameof(GetOrderBookRequest.Limit), $"Limit should be one of " + string.Join(", ", SupportedLimits));
|
return ArgumentError.Invalid(nameof(GetOrderBookRequest.Limit), $"Limit should be one of " + string.Join(", ", SupportedLimits));
|
||||||
|
|
||||||
return base.ValidateRequest(request, client);
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
|||||||
+5
-1
@@ -44,10 +44,14 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public override Error? ValidateRequest(SubscribeOrderBookRequest request, ISubscribeIncrementalOrderBookSocket client)
|
public override Error? ValidateRequest(SubscribeOrderBookRequest request, ISubscribeIncrementalOrderBookSocket client)
|
||||||
{
|
{
|
||||||
|
var error = base.ValidateRequest(request, client);
|
||||||
|
if (error != null)
|
||||||
|
return error;
|
||||||
|
|
||||||
if (request.Limit != null && !SupportedLimits.Contains(request.Limit.Value))
|
if (request.Limit != null && !SupportedLimits.Contains(request.Limit.Value))
|
||||||
return ArgumentError.Invalid(nameof(SubscribeOrderBookRequest.Limit), "Limit not supported");
|
return ArgumentError.Invalid(nameof(SubscribeOrderBookRequest.Limit), "Limit not supported");
|
||||||
|
|
||||||
return base.ValidateRequest(request, client);
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-1
@@ -37,10 +37,14 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public override Error? ValidateRequest(SubscribeOrderBookRequest request, ISubscribeOrderBookSocket client)
|
public override Error? ValidateRequest(SubscribeOrderBookRequest request, ISubscribeOrderBookSocket client)
|
||||||
{
|
{
|
||||||
|
var error = base.ValidateRequest(request, client);
|
||||||
|
if (error != null)
|
||||||
|
return error;
|
||||||
|
|
||||||
if (request.Limit != null && !SupportedLimits.Contains(request.Limit.Value))
|
if (request.Limit != null && !SupportedLimits.Contains(request.Limit.Value))
|
||||||
return ArgumentError.Invalid(nameof(SubscribeOrderBookRequest.Limit), "Limit not supported");
|
return ArgumentError.Invalid(nameof(SubscribeOrderBookRequest.Limit), "Limit not supported");
|
||||||
|
|
||||||
return base.ValidateRequest(request, client);
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-1
@@ -32,6 +32,10 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override Error? ValidateRequest(GetClosedOrdersRequest request, IGetClosedFuturesOrdersRest client)
|
public override Error? ValidateRequest(GetClosedOrdersRequest request, IGetClosedFuturesOrdersRest client)
|
||||||
{
|
{
|
||||||
|
var error = base.ValidateRequest(request, client);
|
||||||
|
if (error != null)
|
||||||
|
return error;
|
||||||
|
|
||||||
if (!SupportsAscending && request.Direction == DataDirection.Ascending)
|
if (!SupportsAscending && request.Direction == DataDirection.Ascending)
|
||||||
return ArgumentError.Invalid(nameof(GetClosedOrdersRequest.Direction), $"Ascending direction is not supported");
|
return ArgumentError.Invalid(nameof(GetClosedOrdersRequest.Direction), $"Ascending direction is not supported");
|
||||||
|
|
||||||
@@ -52,7 +56,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return base.ValidateRequest(request, client);
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+5
-1
@@ -50,6 +50,10 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
IPlaceFuturesOrder client
|
IPlaceFuturesOrder client
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
var error = base.ValidateRequest(request, client);
|
||||||
|
if (error != null)
|
||||||
|
return error;
|
||||||
|
|
||||||
if (!SupportsTpSl && (request.StopLossPrice != null || request.TakeProfitPrice != null))
|
if (!SupportsTpSl && (request.StopLossPrice != null || request.TakeProfitPrice != null))
|
||||||
return ArgumentError.Invalid(nameof(PlaceFuturesOrderRequest.StopLossPrice) + " / " + nameof(PlaceFuturesOrderRequest.TakeProfitPrice), "Tp/Sl parameters not supported");
|
return ArgumentError.Invalid(nameof(PlaceFuturesOrderRequest.StopLossPrice) + " / " + nameof(PlaceFuturesOrderRequest.TakeProfitPrice), "Tp/Sl parameters not supported");
|
||||||
|
|
||||||
@@ -66,7 +70,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
if (quantityError != null)
|
if (quantityError != null)
|
||||||
return quantityError;
|
return quantityError;
|
||||||
|
|
||||||
return base.ValidateRequest(request, client);
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-1
@@ -30,10 +30,14 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override Error? ValidateRequest(CancelOrderRequest request, ICancelSpotOrder client)
|
public override Error? ValidateRequest(CancelOrderRequest request, ICancelSpotOrder client)
|
||||||
{
|
{
|
||||||
|
var error = base.ValidateRequest(request, client);
|
||||||
|
if (error != null)
|
||||||
|
return error;
|
||||||
|
|
||||||
if (request.Symbol!.TradingMode != TradingMode.Spot)
|
if (request.Symbol!.TradingMode != TradingMode.Spot)
|
||||||
return ArgumentError.Invalid("TradingMode", $"TradingMode.{request.Symbol!.TradingMode} is not supported, should be Spot");
|
return ArgumentError.Invalid("TradingMode", $"TradingMode.{request.Symbol!.TradingMode} is not supported, should be Spot");
|
||||||
|
|
||||||
return base.ValidateRequest(request, client);
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-1
@@ -30,10 +30,14 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override Error? ValidateRequest(CancelOrderRequest request, ICancelSpotOrderByClientOrderIdRest client)
|
public override Error? ValidateRequest(CancelOrderRequest request, ICancelSpotOrderByClientOrderIdRest client)
|
||||||
{
|
{
|
||||||
|
var error = base.ValidateRequest(request, client);
|
||||||
|
if (error != null)
|
||||||
|
return error;
|
||||||
|
|
||||||
if (request.Symbol!.TradingMode != TradingMode.Spot)
|
if (request.Symbol!.TradingMode != TradingMode.Spot)
|
||||||
return ArgumentError.Invalid("TradingMode", $"TradingMode.{request.Symbol!.TradingMode} is not supported, should be Spot");
|
return ArgumentError.Invalid("TradingMode", $"TradingMode.{request.Symbol!.TradingMode} is not supported, should be Spot");
|
||||||
|
|
||||||
return base.ValidateRequest(request, client);
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,10 +35,14 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
EditSpotOrderRequest request,
|
EditSpotOrderRequest request,
|
||||||
IEditSpotOrder client)
|
IEditSpotOrder client)
|
||||||
{
|
{
|
||||||
|
var error = base.ValidateRequest(request, client);
|
||||||
|
if (error != null)
|
||||||
|
return error;
|
||||||
|
|
||||||
if (request.Symbol!.TradingMode != TradingMode.Spot)
|
if (request.Symbol!.TradingMode != TradingMode.Spot)
|
||||||
return ArgumentError.Invalid("TradingMode", $"TradingMode.{request.Symbol!.TradingMode} is not supported, should be Spot");
|
return ArgumentError.Invalid("TradingMode", $"TradingMode.{request.Symbol!.TradingMode} is not supported, should be Spot");
|
||||||
|
|
||||||
return base.ValidateRequest(request, client);
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-1
@@ -32,6 +32,10 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override Error? ValidateRequest(GetClosedOrdersRequest request, IGetClosedSpotOrdersRest client)
|
public override Error? ValidateRequest(GetClosedOrdersRequest request, IGetClosedSpotOrdersRest client)
|
||||||
{
|
{
|
||||||
|
var error = base.ValidateRequest(request, client);
|
||||||
|
if (error != null)
|
||||||
|
return error;
|
||||||
|
|
||||||
if (request.Symbol!.TradingMode != TradingMode.Spot)
|
if (request.Symbol!.TradingMode != TradingMode.Spot)
|
||||||
return ArgumentError.Invalid("TradingMode", $"TradingMode.{request.Symbol!.TradingMode} is not supported, should be Spot");
|
return ArgumentError.Invalid("TradingMode", $"TradingMode.{request.Symbol!.TradingMode} is not supported, should be Spot");
|
||||||
|
|
||||||
@@ -55,7 +59,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return base.ValidateRequest(request, client);
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,10 +30,14 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override Error? ValidateRequest(GetOrderRequest request, IGetSpotOrderRest client)
|
public override Error? ValidateRequest(GetOrderRequest request, IGetSpotOrderRest client)
|
||||||
{
|
{
|
||||||
|
var error = base.ValidateRequest(request, client);
|
||||||
|
if (error != null)
|
||||||
|
return error;
|
||||||
|
|
||||||
if (request.Symbol!.TradingMode != TradingMode.Spot)
|
if (request.Symbol!.TradingMode != TradingMode.Spot)
|
||||||
return ArgumentError.Invalid("TradingMode", $"TradingMode.{request.Symbol!.TradingMode} is not supported, should be Spot");
|
return ArgumentError.Invalid("TradingMode", $"TradingMode.{request.Symbol!.TradingMode} is not supported, should be Spot");
|
||||||
|
|
||||||
return base.ValidateRequest(request, client);
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-1
@@ -30,10 +30,14 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override Error? ValidateRequest(GetOrderRequest request, IGetSpotOrderByClientOrderIdRest client)
|
public override Error? ValidateRequest(GetOrderRequest request, IGetSpotOrderByClientOrderIdRest client)
|
||||||
{
|
{
|
||||||
|
var error = base.ValidateRequest(request, client);
|
||||||
|
if (error != null)
|
||||||
|
return error;
|
||||||
|
|
||||||
if (request.Symbol!.TradingMode != TradingMode.Spot)
|
if (request.Symbol!.TradingMode != TradingMode.Spot)
|
||||||
return ArgumentError.Invalid("TradingMode", $"TradingMode.{request.Symbol!.TradingMode} is not supported, should be Spot");
|
return ArgumentError.Invalid("TradingMode", $"TradingMode.{request.Symbol!.TradingMode} is not supported, should be Spot");
|
||||||
|
|
||||||
return base.ValidateRequest(request, client);
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace CryptoExchange.Net.SharedApis
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Options for fully closing a position
|
||||||
|
/// </summary>
|
||||||
|
public class CloseFullPositionOptions : CapabilityOptions<CloseFullPositionRequest, ICloseFullPositionRest>
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string Description => "Fully close an open futures position";
|
||||||
|
|
||||||
|
private static readonly RequestParameterDescription[] _defaultParameterRules = new[]
|
||||||
|
{
|
||||||
|
RequestParameterRule<CloseFullPositionRequest>.Required(x => x.Symbol, "The symbol of the position to close", new SharedSymbol(TradingMode.PerpetualLinear, "ETH", "USDT")),
|
||||||
|
RequestParameterRule<CloseFullPositionRequest>.Optional(x => x.PositionMode, "The current position mode of the account", SharedPositionMode.OneWay),
|
||||||
|
RequestParameterRule<CloseFullPositionRequest>.Optional(x => x.PositionSide, "The side of the position to close", SharedPositionSide.Long),
|
||||||
|
RequestParameterRule<CloseFullPositionRequest>.Optional(x => x.MarginMode, "The margin mode of the position", SharedMarginMode.Cross),
|
||||||
|
RequestParameterRule<CloseFullPositionRequest>.Optional(x => x.PositionId, "The id of the position to close", "12345"),
|
||||||
|
};
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ctor
|
||||||
|
/// </summary>
|
||||||
|
public CloseFullPositionOptions(string exchange, bool authenticated) : base(exchange, authenticated, nameof(ICloseFullPositionRest.CloseFullPositionAsync), _defaultParameterRules)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
namespace CryptoExchange.Net.SharedApis
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Request to fully close a currently open position
|
||||||
|
/// </summary>
|
||||||
|
public record CloseFullPositionRequest : SharedSymbolRequest
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The id of the position to close
|
||||||
|
/// </summary>
|
||||||
|
public string? PositionId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The current position mode of the account for the symbol
|
||||||
|
/// </summary>
|
||||||
|
public SharedPositionMode? PositionMode { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// The position side to close. Required when in hedge mode
|
||||||
|
/// </summary>
|
||||||
|
public SharedPositionSide? PositionSide { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// Margin mode
|
||||||
|
/// </summary>
|
||||||
|
public SharedMarginMode? MarginMode { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ctor
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="symbol">Symbol to close the position on</param>
|
||||||
|
/// <param name="mode">The current position mode of the account for the symbol</param>
|
||||||
|
/// <param name="positionSide">The position side to close. Required when in hedge mode</param>
|
||||||
|
/// <param name="marginMode">Margin mode</param>
|
||||||
|
/// <param name="positionId">Id of the position to close</param>
|
||||||
|
/// <param name="exchangeParameters">Exchange specific parameters</param>
|
||||||
|
public CloseFullPositionRequest(
|
||||||
|
SharedSymbol symbol,
|
||||||
|
SharedPositionMode? mode = null,
|
||||||
|
SharedPositionSide? positionSide = null,
|
||||||
|
SharedMarginMode? marginMode = null,
|
||||||
|
string? positionId = null,
|
||||||
|
ExchangeParameters? exchangeParameters = null) : base(symbol, exchangeParameters)
|
||||||
|
{
|
||||||
|
PositionId = positionId;
|
||||||
|
PositionMode = mode;
|
||||||
|
PositionSide = positionSide;
|
||||||
|
MarginMode = marginMode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace CryptoExchange.Net.SharedApis
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Options for closing position
|
|
||||||
/// </summary>
|
|
||||||
public class ClosePositionOptions : CapabilityOptions<ClosePositionRequest, IClosePositionRest>
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
public override string Description => "Close an open futures position";
|
|
||||||
|
|
||||||
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, authenticated, nameof(IClosePositionRest.ClosePositionAsync), _defaultParameterRules)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+8
-8
@@ -8,31 +8,31 @@ using System.Threading.Tasks;
|
|||||||
namespace CryptoExchange.Net.SharedApis
|
namespace CryptoExchange.Net.SharedApis
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Operation for closing an open position on an exchange.
|
/// Operation for fully closing an open position on an exchange.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IClosePosition : ISharedApiCapability
|
public interface ICloseFullPosition : ISharedApiCapability
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Close position order request options.<br />
|
/// Close position order request options.<br />
|
||||||
/// Use <see cref="CapabilityOptions.RequestParameterRules"/> and <see cref="CapabilityOptions.ExchangeParameterRules"/> to check for required and optional parameters for the request. <br />
|
/// Use <see cref="CapabilityOptions.RequestParameterRules"/> and <see cref="CapabilityOptions.ExchangeParameterRules"/> 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.
|
/// Exchange specific parameters can be added to the request via the `ExchangeParameters` property of the request object.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
ClosePositionOptions ClosePositionOptions { get; }
|
CloseFullPositionOptions CloseFullPositionOptions { get; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Close a currently open position, see <see cref="ClosePositionOptions"/> for request options and exchange specific required/optional parameters. <br />
|
/// Fully close a currently open position, see <see cref="CloseFullPositionOptions"/> for request options and exchange specific required/optional parameters. <br />
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="request">Request info</param>
|
/// <param name="request">Request info</param>
|
||||||
/// <param name="ct">Cancellation token</param>
|
/// <param name="ct">Cancellation token</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<ICallResult<SharedId>> ClosePositionAsync(ClosePositionRequest request, CancellationToken ct = default);
|
Task<ICallResult<SharedId>> CloseFullPositionAsync(CloseFullPositionRequest request, CancellationToken ct = default);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Operation for closing an open position on an exchange via the REST API.
|
/// Operation for fully closing an open position on an exchange via the REST API.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IClosePositionRest : IClosePosition, ISharedRest
|
public interface ICloseFullPositionRest : ICloseFullPosition, ISharedRest
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
new Task<HttpResult<SharedId>> ClosePositionAsync(ClosePositionRequest request, CancellationToken ct = default);
|
new Task<HttpResult<SharedId>> CloseFullPositionAsync(CloseFullPositionRequest request, CancellationToken ct = default);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+5
-1
@@ -33,6 +33,10 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override Error? ValidateRequest(GetPositionHistoryRequest request, IGetPositionHistoryRest client)
|
public override Error? ValidateRequest(GetPositionHistoryRequest request, IGetPositionHistoryRest client)
|
||||||
{
|
{
|
||||||
|
var error = base.ValidateRequest(request, client);
|
||||||
|
if (error != null)
|
||||||
|
return error;
|
||||||
|
|
||||||
if (!SupportsAscending && request.Direction == DataDirection.Ascending)
|
if (!SupportsAscending && request.Direction == DataDirection.Ascending)
|
||||||
return ArgumentError.Invalid(nameof(GetWithdrawalsRequest.Direction), $"Ascending direction is not supported");
|
return ArgumentError.Invalid(nameof(GetWithdrawalsRequest.Direction), $"Ascending direction is not supported");
|
||||||
|
|
||||||
@@ -53,7 +57,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return base.ValidateRequest(request, client);
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-3
@@ -32,21 +32,25 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override Error? ValidateRequest(GetSymbolsRequest request, IGetFuturesSymbolsRest client)
|
public override Error? ValidateRequest(GetSymbolsRequest request, IGetFuturesSymbolsRest client)
|
||||||
{
|
{
|
||||||
|
var error = base.ValidateRequest(request, client);
|
||||||
|
if (error != null)
|
||||||
|
return error;
|
||||||
|
|
||||||
if (request.BaseAssetType != null && request.BaseAssetSubType != null)
|
if (request.BaseAssetType != null && request.BaseAssetSubType != null)
|
||||||
{
|
{
|
||||||
var error = ValidateAssetTypeCombination(request.BaseAssetType.Value, request.BaseAssetSubType.Value);
|
error = ValidateAssetTypeCombination(request.BaseAssetType.Value, request.BaseAssetSubType.Value);
|
||||||
if (error != null)
|
if (error != null)
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request.QuoteAssetType != null && request.QuoteAssetSubType != null)
|
if (request.QuoteAssetType != null && request.QuoteAssetSubType != null)
|
||||||
{
|
{
|
||||||
var error = ValidateAssetTypeCombination(request.QuoteAssetType.Value, request.QuoteAssetSubType.Value);
|
error = ValidateAssetTypeCombination(request.QuoteAssetType.Value, request.QuoteAssetSubType.Value);
|
||||||
if (error != null)
|
if (error != null)
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
return base.ValidateRequest(request, client);
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Error? ValidateAssetTypeCombination(SharedAssetType type, SharedAssetSubType subType)
|
private Error? ValidateAssetTypeCombination(SharedAssetType type, SharedAssetSubType subType)
|
||||||
|
|||||||
@@ -33,21 +33,25 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override Error? ValidateRequest(GetSymbolsRequest request, IGetSpotSymbolsRest client)
|
public override Error? ValidateRequest(GetSymbolsRequest request, IGetSpotSymbolsRest client)
|
||||||
{
|
{
|
||||||
|
var error = base.ValidateRequest(request, client);
|
||||||
|
if (error != null)
|
||||||
|
return error;
|
||||||
|
|
||||||
if (request.BaseAssetType != null && request.BaseAssetSubType != null)
|
if (request.BaseAssetType != null && request.BaseAssetSubType != null)
|
||||||
{
|
{
|
||||||
var error = ValidateAssetTypeCombination(request.BaseAssetType.Value, request.BaseAssetSubType.Value);
|
error = ValidateAssetTypeCombination(request.BaseAssetType.Value, request.BaseAssetSubType.Value);
|
||||||
if (error != null)
|
if (error != null)
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request.QuoteAssetType != null && request.QuoteAssetSubType != null)
|
if (request.QuoteAssetType != null && request.QuoteAssetSubType != null)
|
||||||
{
|
{
|
||||||
var error = ValidateAssetTypeCombination(request.QuoteAssetType.Value, request.QuoteAssetSubType.Value);
|
error = ValidateAssetTypeCombination(request.QuoteAssetType.Value, request.QuoteAssetSubType.Value);
|
||||||
if (error != null)
|
if (error != null)
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
return base.ValidateRequest(request, client);
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Error? ValidateAssetTypeCombination(SharedAssetType type, SharedAssetSubType subType)
|
private Error? ValidateAssetTypeCombination(SharedAssetType type, SharedAssetSubType subType)
|
||||||
|
|||||||
@@ -8,11 +8,11 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
public class GetAllTickersOptions : CapabilityOptions<GetTickersRequest, IGetAllTickersRest>
|
public class GetAllTickersOptions : CapabilityOptions<GetTickersRequest, IGetAllTickersRest>
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override string Description => "Retrieve price ticker information for all symbols";
|
public override string Description => "Retrieve price ticker information for all symbols in a trading mode";
|
||||||
|
|
||||||
private static readonly RequestParameterDescription[] _defaultParameterRules = new[]
|
private static readonly RequestParameterDescription[] _defaultParameterRules = new[]
|
||||||
{
|
{
|
||||||
RequestParameterRule<GetTickersRequest>.Optional(x => x.TradingMode, "Filter the tickers by trading mode", TradingMode.Spot),
|
RequestParameterRule<GetTickersRequest>.Optional(x => x.TradingMode, "The trading mode to retrieve tickers for", TradingMode.Spot),
|
||||||
};
|
};
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace CryptoExchange.Net.SharedApis
|
namespace CryptoExchange.Net.SharedApis
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Request to retrieve all symbol tickers
|
/// Request to retrieve all symbol tickers
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// ctor
|
/// ctor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="tradingMode">Trading mode</param>
|
/// <param name="tradingMode">The trading mode to retrieve tickers for. Required when using <see cref="IGetAllTickers"/>.</param>
|
||||||
/// <param name="exchangeParameters">Exchange specific parameters</param>
|
/// <param name="exchangeParameters">Exchange specific parameters</param>
|
||||||
public GetTickersRequest(TradingMode? tradingMode = null, ExchangeParameters? exchangeParameters = null) : base(tradingMode, exchangeParameters)
|
public GetTickersRequest(TradingMode? tradingMode = null, ExchangeParameters? exchangeParameters = null) : base(tradingMode, exchangeParameters)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -32,6 +32,10 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override Error? ValidateRequest(GetTradeHistoryRequest request, IGetTradeHistoryRest client)
|
public override Error? ValidateRequest(GetTradeHistoryRequest request, IGetTradeHistoryRest client)
|
||||||
{
|
{
|
||||||
|
var error = base.ValidateRequest(request, client);
|
||||||
|
if (error != null)
|
||||||
|
return error;
|
||||||
|
|
||||||
if (!SupportsAscending && request.Direction == DataDirection.Ascending)
|
if (!SupportsAscending && request.Direction == DataDirection.Ascending)
|
||||||
return ArgumentError.Invalid(nameof(GetTradeHistoryRequest.Direction), $"Ascending direction is not supported");
|
return ArgumentError.Invalid(nameof(GetTradeHistoryRequest.Direction), $"Ascending direction is not supported");
|
||||||
|
|
||||||
@@ -41,7 +45,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
if (MaxAge.HasValue && request.StartTime < DateTime.UtcNow.Add(-MaxAge.Value))
|
if (MaxAge.HasValue && request.StartTime < DateTime.UtcNow.Add(-MaxAge.Value))
|
||||||
return ArgumentError.Invalid(nameof(GetTradeHistoryRequest.StartTime), $"Only the most recent {MaxAge} period data is available");
|
return ArgumentError.Invalid(nameof(GetTradeHistoryRequest.StartTime), $"Only the most recent {MaxAge} period data is available");
|
||||||
|
|
||||||
return base.ValidateRequest(request, client);
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-1
@@ -32,6 +32,10 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override Error? ValidateRequest(GetTransferHistoryRequest request, IGetTransferHistoryRest client)
|
public override Error? ValidateRequest(GetTransferHistoryRequest request, IGetTransferHistoryRest client)
|
||||||
{
|
{
|
||||||
|
var error = base.ValidateRequest(request, client);
|
||||||
|
if (error != null)
|
||||||
|
return error;
|
||||||
|
|
||||||
if (!SupportsAscending && request.Direction == DataDirection.Ascending)
|
if (!SupportsAscending && request.Direction == DataDirection.Ascending)
|
||||||
return ArgumentError.Invalid(nameof(GetTransferHistoryRequest.Direction), $"Ascending direction is not supported");
|
return ArgumentError.Invalid(nameof(GetTransferHistoryRequest.Direction), $"Ascending direction is not supported");
|
||||||
|
|
||||||
@@ -52,7 +56,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return base.ValidateRequest(request, client);
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,13 +42,17 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
TransferRequest request,
|
TransferRequest request,
|
||||||
ITransferRest client)
|
ITransferRest client)
|
||||||
{
|
{
|
||||||
|
var error = base.ValidateRequest(request, client);
|
||||||
|
if (error != null)
|
||||||
|
return error;
|
||||||
|
|
||||||
if (!SupportedAccountTypes.Contains(request.FromAccountType))
|
if (!SupportedAccountTypes.Contains(request.FromAccountType))
|
||||||
return ArgumentError.Invalid(nameof(request.FromAccountType), "Invalid FromAccountType");
|
return ArgumentError.Invalid(nameof(request.FromAccountType), "Invalid FromAccountType");
|
||||||
|
|
||||||
if (!SupportedAccountTypes.Contains(request.ToAccountType))
|
if (!SupportedAccountTypes.Contains(request.ToAccountType))
|
||||||
return ArgumentError.Invalid(nameof(request.FromAccountType), "Invalid ToAccountType");
|
return ArgumentError.Invalid(nameof(request.FromAccountType), "Invalid ToAccountType");
|
||||||
|
|
||||||
return base.ValidateRequest(request, client);
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
|||||||
+14
@@ -25,6 +25,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
RequestParameterRule<PlaceFuturesTriggerOrderRequest>.Optional(x => x.MarginMode, "The margin mode of the order", SharedMarginMode.Cross),
|
RequestParameterRule<PlaceFuturesTriggerOrderRequest>.Optional(x => x.MarginMode, "The margin mode of the order", SharedMarginMode.Cross),
|
||||||
RequestParameterRule<PlaceFuturesTriggerOrderRequest>.Optional(x => x.Leverage, "The leverage for the position", 10m),
|
RequestParameterRule<PlaceFuturesTriggerOrderRequest>.Optional(x => x.Leverage, "The leverage for the position", 10m),
|
||||||
RequestParameterRule<PlaceFuturesTriggerOrderRequest>.Optional(x => x.TriggerPriceType, "The price type used to trigger the order", SharedTriggerPriceType.LastPrice),
|
RequestParameterRule<PlaceFuturesTriggerOrderRequest>.Optional(x => x.TriggerPriceType, "The price type used to trigger the order", SharedTriggerPriceType.LastPrice),
|
||||||
|
RequestParameterRule<PlaceFuturesTriggerOrderRequest>.Optional(x => x.ReduceOnly, "Whether the order is reduce only", true),
|
||||||
};
|
};
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -39,5 +40,18 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
{
|
{
|
||||||
HoldsFunds = holdsFunds;
|
HoldsFunds = holdsFunds;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override Error? ValidateRequest(PlaceFuturesTriggerOrderRequest request, IPlaceFuturesTriggerOrderRest client)
|
||||||
|
{
|
||||||
|
var error = base.ValidateRequest(request, client);
|
||||||
|
if (error != null)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
if (request.ReduceOnly == true && request.OrderDirection != SharedTriggerOrderDirection.Exit)
|
||||||
|
return ArgumentError.Invalid(nameof(request.ReduceOnly), "ReduceOnly can only be enabled for an exit trigger order");
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-1
@@ -29,10 +29,14 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override Error? ValidateRequest(CancelOrderRequest request, ICancelSpotTriggerOrderRest client)
|
public override Error? ValidateRequest(CancelOrderRequest request, ICancelSpotTriggerOrderRest client)
|
||||||
{
|
{
|
||||||
|
var error = base.ValidateRequest(request, client);
|
||||||
|
if (error != null)
|
||||||
|
return error;
|
||||||
|
|
||||||
if (request.Symbol!.TradingMode != TradingMode.Spot)
|
if (request.Symbol!.TradingMode != TradingMode.Spot)
|
||||||
return ArgumentError.Invalid("TradingMode", $"TradingMode.{request.Symbol!.TradingMode} is not supported, should be Spot");
|
return ArgumentError.Invalid("TradingMode", $"TradingMode.{request.Symbol!.TradingMode} is not supported, should be Spot");
|
||||||
|
|
||||||
return base.ValidateRequest(request, client);
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-1
@@ -29,10 +29,14 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override Error? ValidateRequest(GetOrderRequest request, IGetSpotTriggerOrderRest client)
|
public override Error? ValidateRequest(GetOrderRequest request, IGetSpotTriggerOrderRest client)
|
||||||
{
|
{
|
||||||
|
var error = base.ValidateRequest(request, client);
|
||||||
|
if (error != null)
|
||||||
|
return error;
|
||||||
|
|
||||||
if (request.Symbol!.TradingMode != TradingMode.Spot)
|
if (request.Symbol!.TradingMode != TradingMode.Spot)
|
||||||
return ArgumentError.Invalid("TradingMode", $"TradingMode.{request.Symbol!.TradingMode} is not supported, should be Spot");
|
return ArgumentError.Invalid("TradingMode", $"TradingMode.{request.Symbol!.TradingMode} is not supported, should be Spot");
|
||||||
|
|
||||||
return base.ValidateRequest(request, client);
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-1
@@ -42,10 +42,14 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
PlaceSpotTriggerOrderRequest request,
|
PlaceSpotTriggerOrderRequest request,
|
||||||
IPlaceSpotTriggerOrderRest client)
|
IPlaceSpotTriggerOrderRest client)
|
||||||
{
|
{
|
||||||
|
var error = base.ValidateRequest(request, client);
|
||||||
|
if (error != null)
|
||||||
|
return error;
|
||||||
|
|
||||||
if (request.Symbol!.TradingMode != TradingMode.Spot)
|
if (request.Symbol!.TradingMode != TradingMode.Spot)
|
||||||
return ArgumentError.Invalid("TradingMode", $"TradingMode.{request.Symbol!.TradingMode} is not supported, should be Spot");
|
return ArgumentError.Invalid("TradingMode", $"TradingMode.{request.Symbol!.TradingMode} is not supported, should be Spot");
|
||||||
|
|
||||||
return base.ValidateRequest(request, client);
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-1
@@ -32,6 +32,10 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override Error? ValidateRequest(GetUserTradesRequest request, IGetFuturesUserTradeHistoryRest client)
|
public override Error? ValidateRequest(GetUserTradesRequest request, IGetFuturesUserTradeHistoryRest client)
|
||||||
{
|
{
|
||||||
|
var error = base.ValidateRequest(request, client);
|
||||||
|
if (error != null)
|
||||||
|
return error;
|
||||||
|
|
||||||
if (!SupportsAscending && request.Direction == DataDirection.Ascending)
|
if (!SupportsAscending && request.Direction == DataDirection.Ascending)
|
||||||
return ArgumentError.Invalid(nameof(GetUserTradesRequest.Direction), $"Ascending direction is not supported");
|
return ArgumentError.Invalid(nameof(GetUserTradesRequest.Direction), $"Ascending direction is not supported");
|
||||||
|
|
||||||
@@ -52,7 +56,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return base.ValidateRequest(request, client);
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-1
@@ -29,10 +29,14 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override Error? ValidateRequest(GetOrderTradesRequest request, IGetSpotOrderTradesRest client)
|
public override Error? ValidateRequest(GetOrderTradesRequest request, IGetSpotOrderTradesRest client)
|
||||||
{
|
{
|
||||||
|
var error = base.ValidateRequest(request, client);
|
||||||
|
if (error != null)
|
||||||
|
return error;
|
||||||
|
|
||||||
if (request.Symbol!.TradingMode != TradingMode.Spot)
|
if (request.Symbol!.TradingMode != TradingMode.Spot)
|
||||||
return ArgumentError.Invalid("TradingMode", $"TradingMode.{request.Symbol!.TradingMode} is not supported, should be Spot");
|
return ArgumentError.Invalid("TradingMode", $"TradingMode.{request.Symbol!.TradingMode} is not supported, should be Spot");
|
||||||
|
|
||||||
return base.ValidateRequest(request, client);
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-1
@@ -32,6 +32,10 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override Error? ValidateRequest(GetUserTradesRequest request, IGetSpotUserTradeHistoryRest client)
|
public override Error? ValidateRequest(GetUserTradesRequest request, IGetSpotUserTradeHistoryRest client)
|
||||||
{
|
{
|
||||||
|
var error = base.ValidateRequest(request, client);
|
||||||
|
if (error != null)
|
||||||
|
return error;
|
||||||
|
|
||||||
if (request.Symbol!.TradingMode != TradingMode.Spot)
|
if (request.Symbol!.TradingMode != TradingMode.Spot)
|
||||||
return ArgumentError.Invalid("TradingMode", $"TradingMode.{request.Symbol!.TradingMode} is not supported, should be Spot");
|
return ArgumentError.Invalid("TradingMode", $"TradingMode.{request.Symbol!.TradingMode} is not supported, should be Spot");
|
||||||
|
|
||||||
@@ -55,7 +59,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return base.ValidateRequest(request, client);
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-1
@@ -32,6 +32,10 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override Error? ValidateRequest(GetWithdrawalsRequest request, IGetWithdrawalHistoryRest client)
|
public override Error? ValidateRequest(GetWithdrawalsRequest request, IGetWithdrawalHistoryRest client)
|
||||||
{
|
{
|
||||||
|
var error = base.ValidateRequest(request, client);
|
||||||
|
if (error != null)
|
||||||
|
return error;
|
||||||
|
|
||||||
if (!SupportsAscending && request.Direction == DataDirection.Ascending)
|
if (!SupportsAscending && request.Direction == DataDirection.Ascending)
|
||||||
return ArgumentError.Invalid(nameof(GetWithdrawalsRequest.Direction), $"Ascending direction is not supported");
|
return ArgumentError.Invalid(nameof(GetWithdrawalsRequest.Direction), $"Ascending direction is not supported");
|
||||||
|
|
||||||
@@ -52,7 +56,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return base.ValidateRequest(request, client);
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user