diff --git a/CryptoExchange.Net/ExtensionMethods.cs b/CryptoExchange.Net/ExtensionMethods.cs
index f1166de4..a3aa296d 100644
--- a/CryptoExchange.Net/ExtensionMethods.cs
+++ b/CryptoExchange.Net/ExtensionMethods.cs
@@ -461,11 +461,15 @@ namespace CryptoExchange.Net
if (typeof(ISpotOrderSocketClient).IsAssignableFrom(typeof(T)))
services.AddTransient(x => (ISpotOrderSocketClient)client(x)!);
+ if (typeof(ISpotOrderManagementSocketClient).IsAssignableFrom(typeof(T)))
+ services.AddTransient(x => (ISpotOrderManagementSocketClient)client(x)!);
if (typeof(IFuturesOrderSocketClient).IsAssignableFrom(typeof(T)))
services.AddTransient(x => (IFuturesOrderSocketClient)client(x)!);
if (typeof(IPositionSocketClient).IsAssignableFrom(typeof(T)))
services.AddTransient(x => (IPositionSocketClient)client(x)!);
+ if (typeof(IFuturesOrderManagementSocketClient).IsAssignableFrom(typeof(T)))
+ services.AddTransient(x => (IFuturesOrderManagementSocketClient)client(x)!);
return services;
}
diff --git a/CryptoExchange.Net/SharedApis/Interfaces/Rest/Spot/ISpotOrderRestClient.cs b/CryptoExchange.Net/SharedApis/Interfaces/Rest/Spot/ISpotOrderRestClient.cs
index 7f7c0d36..47af549b 100644
--- a/CryptoExchange.Net/SharedApis/Interfaces/Rest/Spot/ISpotOrderRestClient.cs
+++ b/CryptoExchange.Net/SharedApis/Interfaces/Rest/Spot/ISpotOrderRestClient.cs
@@ -44,7 +44,6 @@ namespace CryptoExchange.Net.SharedApis
PlaceSpotOrderOptions PlaceSpotOrderOptions { get; }
///
/// Place a new spot order, see for request options and exchange specific required/optional parameters.
- /// 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.
///
/// Request info
/// Cancellation token
diff --git a/CryptoExchange.Net/SharedApis/Interfaces/Socket/Futures/IFuturesOrderManagementSocketClient.cs b/CryptoExchange.Net/SharedApis/Interfaces/Socket/Futures/IFuturesOrderManagementSocketClient.cs
new file mode 100644
index 00000000..50212b79
--- /dev/null
+++ b/CryptoExchange.Net/SharedApis/Interfaces/Socket/Futures/IFuturesOrderManagementSocketClient.cs
@@ -0,0 +1,66 @@
+using CryptoExchange.Net.Objects;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace CryptoExchange.Net.SharedApis
+{
+ ///
+ /// Client for placing and managing futures orders
+ ///
+ public interface IFuturesOrderManagementSocketClient : ISharedClient
+ {
+ ///
+ /// How the trading fee is deducted
+ ///
+ SharedFeeDeductionType FuturesFeeDeductionType { get; }
+ ///
+ /// How the asset is determined in which the trading fee is paid
+ ///
+ SharedFeeAssetType FuturesFeeAssetType { get; }
+ ///
+ /// Supported order types for futures orders
+ ///
+ SharedOrderType[] FuturesSupportedOrderTypes { get; }
+ ///
+ /// Supported time in force types for futures orders
+ ///
+ SharedTimeInForce[] FuturesSupportedTimeInForce { get; }
+ ///
+ /// Supported quantity types for futures orders
+ ///
+ SharedQuantitySupport FuturesSupportedOrderQuantity { get; }
+
+ ///
+ /// Generate a new random client order id
+ ///
+ ///
+ string GenerateClientOrderId();
+
+ ///
+ /// Futures place order request options.
+ /// Use and to check for required and optional parameters for the request.
+ /// Exchange specific parameters can be added to the request via the `ExchangeParameters` property of the request object.
+ ///
+ PlaceFuturesOrderSocketOptions PlaceFuturesOrderOptions { get; }
+
+ ///
+ /// Place a new futures order, see for request options and exchange specific required/optional parameters.
+ ///
+ /// Request info
+ /// Cancellation token
+ Task> PlaceFuturesOrderAsync(PlaceFuturesOrderRequest request, CancellationToken ct = default);
+
+ ///
+ /// Futures cancel order request options.
+ /// Use and to check for required and optional parameters for the request.
+ /// Exchange specific parameters can be added to the request via the `ExchangeParameters` property of the request object.
+ ///
+ CancelFuturesOrderSocketOptions CancelFuturesOrderOptions { get; }
+ ///
+ /// Cancel a futures order, see for request options and exchange specific required/optional parameters.
+ ///
+ /// Request info
+ /// Cancellation token
+ Task> CancelFuturesOrderAsync(CancelOrderRequest request, CancellationToken ct = default);
+ }
+}
diff --git a/CryptoExchange.Net/SharedApis/Interfaces/Socket/Spot/ISpotOrderManagementSocketClient.cs b/CryptoExchange.Net/SharedApis/Interfaces/Socket/Spot/ISpotOrderManagementSocketClient.cs
new file mode 100644
index 00000000..cfa34e94
--- /dev/null
+++ b/CryptoExchange.Net/SharedApis/Interfaces/Socket/Spot/ISpotOrderManagementSocketClient.cs
@@ -0,0 +1,66 @@
+using CryptoExchange.Net.Objects;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace CryptoExchange.Net.SharedApis
+{
+ ///
+ /// Client for placing and managing spot orders
+ ///
+ public interface ISpotOrderManagementSocketClient : ISharedClient
+ {
+ ///
+ /// How the trading fee is deducted
+ ///
+ SharedFeeDeductionType SpotFeeDeductionType { get; }
+ ///
+ /// How the asset is determined in which the trading fee is paid
+ ///
+ SharedFeeAssetType SpotFeeAssetType { get; }
+ ///
+ /// Supported order types for spot orders
+ ///
+ SharedOrderType[] SpotSupportedOrderTypes { get; }
+ ///
+ /// Supported time in force types for placing spot orders
+ ///
+ SharedTimeInForce[] SpotSupportedTimeInForce { get; }
+ ///
+ /// Supported quantity types for placing spot orders
+ ///
+ SharedQuantitySupport SpotSupportedOrderQuantity { get; }
+
+ ///
+ /// Generate a new random client order id
+ ///
+ ///
+ string GenerateClientOrderId();
+
+ ///
+ /// Spot place order request options.
+ /// Use and to check for required and optional parameters for the request.
+ /// Exchange specific parameters can be added to the request via the `ExchangeParameters` property of the request object.
+ ///
+ PlaceSpotOrderSocketOptions PlaceSpotOrderOptions { get; }
+ ///
+ /// Place a new spot order, see for request options and exchange specific required/optional parameters.
+ ///
+ /// Request info
+ /// Cancellation token
+ Task> PlaceSpotOrderAsync(PlaceSpotOrderRequest request, CancellationToken ct = default);
+
+ ///
+ /// Spot cancel order request options.
+ /// Use and to check for required and optional parameters for the request.
+ /// Exchange specific parameters can be added to the request via the `ExchangeParameters` property of the request object.
+ ///
+ CancelSpotOrderSocketOptions CancelSpotOrderOptions { get; }
+ ///
+ /// Cancel a spot order, see for request options and exchange specific required/optional parameters.
+ ///
+ /// Request info
+ /// Cancellation token
+ Task> CancelSpotOrderAsync(CancelOrderRequest request, CancellationToken ct = default);
+
+ }
+}
diff --git a/CryptoExchange.Net/SharedApis/Models/Options/Endpoints/CancelFuturesOrderSocketOptions.cs b/CryptoExchange.Net/SharedApis/Models/Options/Endpoints/CancelFuturesOrderSocketOptions.cs
new file mode 100644
index 00000000..8289f432
--- /dev/null
+++ b/CryptoExchange.Net/SharedApis/Models/Options/Endpoints/CancelFuturesOrderSocketOptions.cs
@@ -0,0 +1,22 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace CryptoExchange.Net.SharedApis
+{
+ ///
+ /// Options for canceling a futures order
+ ///
+ public class CancelFuturesOrderSocketOptions : EndpointOptions
+ {
+ ///
+ public override string Description => "Cancel a futures order over a socket connection";
+
+ ///
+ /// ctor
+ ///
+ public CancelFuturesOrderSocketOptions(string exchange, bool authenticated) : base(exchange, authenticated, nameof(IFuturesOrderManagementSocketClient.CancelFuturesOrderAsync))
+ {
+ }
+ }
+}
diff --git a/CryptoExchange.Net/SharedApis/Models/Options/Endpoints/CancelSpotOrderSocketOptions.cs b/CryptoExchange.Net/SharedApis/Models/Options/Endpoints/CancelSpotOrderSocketOptions.cs
new file mode 100644
index 00000000..4e0a4274
--- /dev/null
+++ b/CryptoExchange.Net/SharedApis/Models/Options/Endpoints/CancelSpotOrderSocketOptions.cs
@@ -0,0 +1,32 @@
+using CryptoExchange.Net.Objects;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace CryptoExchange.Net.SharedApis
+{
+ ///
+ /// Options for canceling a spot order
+ ///
+ public class CancelSpotOrderSocketOptions : EndpointOptions
+ {
+ ///
+ public override string Description => "Cancel a spot order over a socket connection";
+
+ ///
+ /// ctor
+ ///
+ public CancelSpotOrderSocketOptions(string exchange, bool authenticated) : base(exchange, authenticated, nameof(ISpotOrderManagementSocketClient.CancelSpotOrderAsync))
+ {
+ }
+
+ ///
+ 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);
+ }
+ }
+}
diff --git a/CryptoExchange.Net/SharedApis/Models/Options/Endpoints/PlaceFuturesOrderSocketOptions.cs b/CryptoExchange.Net/SharedApis/Models/Options/Endpoints/PlaceFuturesOrderSocketOptions.cs
new file mode 100644
index 00000000..0f249138
--- /dev/null
+++ b/CryptoExchange.Net/SharedApis/Models/Options/Endpoints/PlaceFuturesOrderSocketOptions.cs
@@ -0,0 +1,56 @@
+using CryptoExchange.Net.Objects;
+using System;
+using System.Linq;
+
+namespace CryptoExchange.Net.SharedApis
+{
+ ///
+ /// Options for placing a new futures order
+ ///
+ public class PlaceFuturesOrderSocketOptions : EndpointOptions
+ {
+ ///
+ public override string Description => "Place a new futures order over a socket connection";
+
+ ///
+ /// Whether or not the API supports setting take profit / stop loss with the order
+ ///
+ public bool SupportsTpSl { get; set; }
+
+ ///
+ /// ctor
+ ///
+ public PlaceFuturesOrderSocketOptions(string exchange, bool supportsTpSl) : base(exchange, true, nameof(IFuturesOrderManagementSocketClient.PlaceFuturesOrderAsync))
+ {
+ SupportsTpSl = supportsTpSl;
+ }
+
+ ///
+ /// Validate a request
+ ///
+ 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);
+ }
+
+ }
+}
diff --git a/CryptoExchange.Net/SharedApis/Models/Options/Endpoints/PlaceSpotOrderSocketOptions.cs b/CryptoExchange.Net/SharedApis/Models/Options/Endpoints/PlaceSpotOrderSocketOptions.cs
new file mode 100644
index 00000000..341482b5
--- /dev/null
+++ b/CryptoExchange.Net/SharedApis/Models/Options/Endpoints/PlaceSpotOrderSocketOptions.cs
@@ -0,0 +1,49 @@
+using CryptoExchange.Net.Objects;
+using System;
+using System.Linq;
+
+namespace CryptoExchange.Net.SharedApis
+{
+ ///
+ /// Options for placing a new spot order
+ ///
+ public class PlaceSpotOrderSocketOptions : EndpointOptions
+ {
+ ///
+ public override string Description => "Place a new spot order over a socket connection";
+
+
+ ///
+ /// ctor
+ ///
+ public PlaceSpotOrderSocketOptions(string exchange) : base(exchange, true, nameof(ISpotOrderManagementSocketClient.PlaceSpotOrderAsync))
+ {
+ }
+
+ ///
+ /// Validate a request
+ ///
+ 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);
+ }
+ }
+}
diff --git a/CryptoExchange.Net/SharedApis/SharedUtils.cs b/CryptoExchange.Net/SharedApis/SharedUtils.cs
index a8719471..f716767c 100644
--- a/CryptoExchange.Net/SharedApis/SharedUtils.cs
+++ b/CryptoExchange.Net/SharedApis/SharedUtils.cs
@@ -169,13 +169,23 @@ namespace CryptoExchange.Net.SharedApis
if (client is ISpotOrderSocketClient spotOrderSocketClient)
result.Add(spotOrderSocketClient.SubscribeSpotOrderOptions);
+ if (client is ISpotOrderManagementSocketClient spotOrderManagementSocketClient)
+ {
+ result.Add(spotOrderManagementSocketClient.PlaceSpotOrderOptions);
+ result.Add(spotOrderManagementSocketClient.CancelSpotOrderOptions);
+ }
if (client is IFuturesOrderSocketClient futuresOrderSocketClient)
result.Add(futuresOrderSocketClient.SubscribeFuturesOrderOptions);
if (client is IPositionSocketClient positionSocketClient)
result.Add(positionSocketClient.SubscribePositionOptions);
+ if (client is IFuturesOrderManagementSocketClient futuresOrderManagementSocketClient)
+ {
+ result.Add(futuresOrderManagementSocketClient.PlaceFuturesOrderOptions);
+ result.Add(futuresOrderManagementSocketClient.CancelFuturesOrderOptions);
+ }
- return result.ToArray();
+ return result.Where(x => x.Supported).ToArray();
}
///