diff --git a/CryptoExchange.Net/SharedApis/Enums/SharedLedgerEntryType.cs b/CryptoExchange.Net/SharedApis/Enums/SharedLedgerEntryType.cs new file mode 100644 index 00000000..e97106fe --- /dev/null +++ b/CryptoExchange.Net/SharedApis/Enums/SharedLedgerEntryType.cs @@ -0,0 +1,42 @@ +namespace CryptoExchange.Net.SharedApis +{ + /// + /// Ledger entry type + /// + public enum SharedLedgerEntryType + { + /// + /// Trade execution + /// + Trade, + /// + /// Withdrawal + /// + Withdrawal, + /// + /// Deposit + /// + Deposit, + /// + /// Transfer + /// + Transfer, + /// + /// Fee payment + /// + Fee, + /// + /// Funding fee payment + /// + FundingFee, + /// + /// Rebate + /// + Rebate, + + /// + /// Other or unknown + /// + Unknown + } +} diff --git a/CryptoExchange.Net/SharedApis/Legacy/Rest/Futures/IFuturesTickerRestClient.cs b/CryptoExchange.Net/SharedApis/Legacy/Rest/Futures/IFuturesTickerRestClient.cs index 86fe87ab..8e8d2ce8 100644 --- a/CryptoExchange.Net/SharedApis/Legacy/Rest/Futures/IFuturesTickerRestClient.cs +++ b/CryptoExchange.Net/SharedApis/Legacy/Rest/Futures/IFuturesTickerRestClient.cs @@ -14,7 +14,7 @@ namespace CryptoExchange.Net.SharedApis /// 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. /// - GetFuturesTickerOptions GetFuturesTickerOptions { get; } + GetTickerOptions GetFuturesTickerOptions { get; } /// /// Get ticker info for a specific futures symbol, see for request options and exchange specific required/optional parameters.
///
@@ -27,7 +27,7 @@ namespace CryptoExchange.Net.SharedApis /// 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. /// - GetAllFuturesTickersOptions GetFuturesTickersOptions { get; } + GetAllTickersOptions GetFuturesTickersOptions { get; } /// /// Get ticker info for all futures symbols, see for request options and exchange specific required/optional parameters.
///
diff --git a/CryptoExchange.Net/SharedApis/Legacy/Rest/Spot/ISpotTickerRestClient.cs b/CryptoExchange.Net/SharedApis/Legacy/Rest/Spot/ISpotTickerRestClient.cs index 9f2778ff..f5c9a436 100644 --- a/CryptoExchange.Net/SharedApis/Legacy/Rest/Spot/ISpotTickerRestClient.cs +++ b/CryptoExchange.Net/SharedApis/Legacy/Rest/Spot/ISpotTickerRestClient.cs @@ -14,7 +14,7 @@ namespace CryptoExchange.Net.SharedApis /// 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. /// - GetSpotTickerOptions GetSpotTickerOptions { get; } + GetTickerOptions GetSpotTickerOptions { get; } /// /// Get ticker for a specific spot symbol, see for request options and exchange specific required/optional parameters.
///
@@ -26,7 +26,7 @@ namespace CryptoExchange.Net.SharedApis /// 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. /// - GetAllSpotTickersOptions GetSpotTickersOptions { get; } + GetAllTickersOptions GetSpotTickersOptions { get; } /// /// Get tickers for all spot symbols, see for request options and exchange specific required/optional parameters.
///
diff --git a/CryptoExchange.Net/SharedApis/Models/SharedFundingFee.cs b/CryptoExchange.Net/SharedApis/Models/SharedFundingFee.cs new file mode 100644 index 00000000..d963b7e2 --- /dev/null +++ b/CryptoExchange.Net/SharedApis/Models/SharedFundingFee.cs @@ -0,0 +1,51 @@ +using System; +using System.Diagnostics; + +namespace CryptoExchange.Net.SharedApis +{ + /// + /// Funding fee payment + /// + [DebuggerDisplay("[{Timestamp}] {Symbol,nq} {Fee} {Asset,nq}")] + public record SharedFundingFee + { + /// + /// Id + /// + public string? Id { get; set; } + + /// + /// The symbol + /// + public string Symbol { get; set; } + + /// + /// The asset the funding fee was paid in + /// + public string? Asset { get; set; } + + /// + /// The funding fee paid + /// + public decimal Fee { get; set; } + /// + /// Timestamp + /// + public DateTime Timestamp { get; set; } + + /// + /// The side of the position + /// + public SharedPositionSide? Side { get; set; } + + /// + /// ctor + /// + public SharedFundingFee(string symbol, decimal fee, DateTime timestamp) + { + Symbol = symbol; + Fee = fee; + Timestamp = timestamp; + } + } +} diff --git a/CryptoExchange.Net/SharedApis/Models/SharedFundingInfo.cs b/CryptoExchange.Net/SharedApis/Models/SharedFundingInfo.cs new file mode 100644 index 00000000..9798fe1d --- /dev/null +++ b/CryptoExchange.Net/SharedApis/Models/SharedFundingInfo.cs @@ -0,0 +1,34 @@ +using System; +using System.Diagnostics; + +namespace CryptoExchange.Net.SharedApis +{ + /// + /// Funding info + /// + public record SharedFundingInfo + { + /// + /// The current funding rate + /// + public decimal FundingRate { get; set; } + /// + /// Next funding timestamp + /// + public DateTime? NextFundingTime { get; set; } + /// + /// Funding interval in hours + /// + public int? FundingInterval { get; set; } + + /// + /// ctor + /// + public SharedFundingInfo(decimal fundingRate, DateTime? nextFundingTime, int? fundingInterval) + { + FundingRate = fundingRate; + NextFundingTime = nextFundingTime; + FundingInterval = fundingInterval; + } + } +} diff --git a/CryptoExchange.Net/SharedApis/Models/SharedLedgerEntry.cs b/CryptoExchange.Net/SharedApis/Models/SharedLedgerEntry.cs new file mode 100644 index 00000000..5fabd44e --- /dev/null +++ b/CryptoExchange.Net/SharedApis/Models/SharedLedgerEntry.cs @@ -0,0 +1,55 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Text; + +namespace CryptoExchange.Net.SharedApis +{ + /// + /// Ledger entry + /// + [DebuggerDisplay("[{Timestamp}] {DeltaQuantity} {Asset,nq}")] + public record SharedLedgerEntry + { + /// + /// The id of the entry + /// + public string? Id { get; set; } + /// + /// The id of the relation that changed the balance, for example a trade id or transfer id + /// + public string? RelationId { get; set; } + /// + /// The asset + /// + public string Asset { get; set; } + /// + /// The adjustment quantity, positive means the balance increased, negative means the balance decreased + /// + public decimal DeltaQuantity { get; set; } + /// + /// Timestamp of the action + /// + public DateTime Timestamp { get; set; } + /// + /// The type of the entry + /// + public SharedLedgerEntryType Type { get; set; } + /// + /// The type of the entry as string, can be used for entry types not recognized by the Shared API + /// + public string TypeString { get; set; } + + /// + /// ctor + /// + public SharedLedgerEntry(string asset, decimal deltaQuantity, SharedLedgerEntryType type, string typeString, DateTime timestamp) + { + Asset = asset; + DeltaQuantity = deltaQuantity; + Type = type; + TypeString = typeString; + Timestamp = timestamp; + } + } +} \ No newline at end of file diff --git a/CryptoExchange.Net/SharedApis/Models/SharedLeverageTier.cs b/CryptoExchange.Net/SharedApis/Models/SharedLeverageTier.cs new file mode 100644 index 00000000..50ef325a --- /dev/null +++ b/CryptoExchange.Net/SharedApis/Models/SharedLeverageTier.cs @@ -0,0 +1,54 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Text; + +namespace CryptoExchange.Net.SharedApis +{ + /// + /// Leverage tier + /// + [DebuggerDisplay("[{Index}] {MinNotional} - {MaxNotional}")] + public record SharedLeverageTier : SharedSymbolModel + { + /// + /// Tier index + /// + public int Index { get; set; } + /// + /// The asset the notional value is in + /// + public string? Asset { get; set; } + /// + /// Min notional value for activation of this tier + /// + public decimal MinNotional { get; set; } + /// + /// Max notional value for this tier, null if no limit + /// + public decimal? MaxNotional { get; set; } + /// + /// Maintenance margin rate for this tier + /// + public decimal? MaintenanceMarginRate { get; set; } + /// + /// Max leverage for this tier + /// + public decimal? MaxLeverage { get; set; } + + /// + /// ctor + /// + public SharedLeverageTier(SharedSymbol? sharedSymbol, string symbol, int index, string? asset, decimal minNotional, decimal? maxNotional, decimal? maintenanceMarginRate, decimal? maxLeverage) + : base(sharedSymbol, symbol) + { + Index = index; + Asset = asset; + MinNotional = minNotional; + MaxNotional = maxNotional; + MaintenanceMarginRate = maintenanceMarginRate; + MaxLeverage = maxLeverage; + } + + } +} diff --git a/CryptoExchange.Net/SharedApis/Models/SharedTransfer.cs b/CryptoExchange.Net/SharedApis/Models/SharedTransfer.cs new file mode 100644 index 00000000..1b881fdd --- /dev/null +++ b/CryptoExchange.Net/SharedApis/Models/SharedTransfer.cs @@ -0,0 +1,50 @@ +using System; +using System.Diagnostics; + +namespace CryptoExchange.Net.SharedApis +{ + /// + /// Transfer info + /// + [DebuggerDisplay("[{Timestamp}] {Quantity} {Asset,nq} {FromAccountType} -> {ToAccountType}")] + public record SharedTransfer + { + /// + /// The id of the Transfer + /// + public string? Id { get; set; } + /// + /// The asset of the Transfer + /// + public string Asset { get; set; } + /// + /// The quantity that was Transfered + /// + public decimal Quantity { get; set; } + /// + /// Timestamp of the Transfer + /// + public DateTime Timestamp { get; set; } + /// + /// Source account type + /// + public SharedAccountType FromAccountType { get; set; } + /// + /// Target account type + /// + public SharedAccountType ToAccountType { get; set; } + + /// + /// ctor + /// + public SharedTransfer(string asset, decimal quantity, SharedAccountType fromAccountType, SharedAccountType toAccountType, DateTime timestamp) + { + Asset = asset; + Quantity = quantity; + Timestamp = timestamp; + FromAccountType = fromAccountType; + ToAccountType = toAccountType; + } + } + +} diff --git a/CryptoExchange.Net/SharedApis/V2/Funding/GetFundingInfo/GetFundingInfoOptions.cs b/CryptoExchange.Net/SharedApis/V2/Funding/GetFundingInfo/GetFundingInfoOptions.cs new file mode 100644 index 00000000..6791fa20 --- /dev/null +++ b/CryptoExchange.Net/SharedApis/V2/Funding/GetFundingInfo/GetFundingInfoOptions.cs @@ -0,0 +1,28 @@ +using CryptoExchange.Net.Objects; +using System; +using System.Text; + +namespace CryptoExchange.Net.SharedApis +{ + /// + /// Options for requesting funding info + /// + public class GetFundingInfoOptions : PaginatedCapabilityOptions + { + /// + public override string Description => "Retrieve the current funding info for a symbol"; + + private static readonly RequestParameterDescription[] _defaultParameterRules = new[] + { + RequestParameterRule.Required(x => x.Symbol, "The symbol", new SharedSymbol(TradingMode.PerpetualLinear, "ETH", "USDT")), + }; + + /// + /// ctor + /// + public GetFundingInfoOptions(string exchange, bool supportsAscending, bool supportsDescending, bool timeFilterSupported, int maxLimit, bool needsAuthentication) + : base(exchange, supportsAscending, supportsDescending, timeFilterSupported, maxLimit, needsAuthentication, nameof(IGetFundingInfoRest.GetFundingInfoAsync), _defaultParameterRules) + { + } + } +} diff --git a/CryptoExchange.Net/SharedApis/V2/Funding/GetFundingInfo/GetFundingInfoRequest.cs b/CryptoExchange.Net/SharedApis/V2/Funding/GetFundingInfo/GetFundingInfoRequest.cs new file mode 100644 index 00000000..fb8f7811 --- /dev/null +++ b/CryptoExchange.Net/SharedApis/V2/Funding/GetFundingInfo/GetFundingInfoRequest.cs @@ -0,0 +1,22 @@ +using System; + +namespace CryptoExchange.Net.SharedApis +{ + /// + /// Request to retrieve the current funding info for a symbol + /// + public record GetFundingInfoRequest : SharedSymbolRequest + { + /// + /// ctor + /// + /// Symbol to request funding info for + /// Exchange specific parameters + public GetFundingInfoRequest( + SharedSymbol symbol, + ExchangeParameters? exchangeParameters = null) + : base(symbol, exchangeParameters) + { + } + } +} diff --git a/CryptoExchange.Net/SharedApis/V2/Funding/GetFundingInfo/IGetFundingInfo.cs b/CryptoExchange.Net/SharedApis/V2/Funding/GetFundingInfo/IGetFundingInfo.cs new file mode 100644 index 00000000..c447799e --- /dev/null +++ b/CryptoExchange.Net/SharedApis/V2/Funding/GetFundingInfo/IGetFundingInfo.cs @@ -0,0 +1,37 @@ +using CryptoExchange.Net.Objects; +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace CryptoExchange.Net.SharedApis +{ + /// + /// Operation for retrieving the current funding info for a symbol on an exchange. + /// + public interface IGetFundingInfo : ISharedApiCapability + { + /// + /// Funding info 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. + ///
+ GetFundingInfoOptions GetFundingInfoOptions { get; } + /// + /// Get current funding info for a symbol, see for request options and exchange specific required/optional parameters.
+ ///
+ /// Request info + /// Cancellation token + Task> GetFundingInfoAsync(GetFundingInfoRequest request, CancellationToken ct = default); + } + + /// + /// Operation for retrieving the current funding info for a symbol on an exchange via the REST API. + /// + public interface IGetFundingInfoRest : IGetFundingInfo, ISharedRest + { + /// + new Task> GetFundingInfoAsync(GetFundingInfoRequest request, CancellationToken ct = default); + } +} diff --git a/CryptoExchange.Net/SharedApis/V2/Funding/GetFundingRateHistory/GetFundingRateHistoryRequest.cs b/CryptoExchange.Net/SharedApis/V2/Funding/GetFundingRateHistory/GetFundingRateHistoryRequest.cs index 6f9ad50f..c8b6c69f 100644 --- a/CryptoExchange.Net/SharedApis/V2/Funding/GetFundingRateHistory/GetFundingRateHistoryRequest.cs +++ b/CryptoExchange.Net/SharedApis/V2/Funding/GetFundingRateHistory/GetFundingRateHistoryRequest.cs @@ -27,7 +27,7 @@ namespace CryptoExchange.Net.SharedApis /// /// ctor /// - /// Symbol to request klines for + /// Symbol to request funding rate history for /// Filter by start time /// Filter by end time /// Max number of results diff --git a/CryptoExchange.Net/SharedApis/V2/Funding/GetUserFundingHistory/GetUserFundingHistoryOptions.cs b/CryptoExchange.Net/SharedApis/V2/Funding/GetUserFundingHistory/GetUserFundingHistoryOptions.cs new file mode 100644 index 00000000..b52264e4 --- /dev/null +++ b/CryptoExchange.Net/SharedApis/V2/Funding/GetUserFundingHistory/GetUserFundingHistoryOptions.cs @@ -0,0 +1,58 @@ +using CryptoExchange.Net.Objects; +using System; +using System.Text; + +namespace CryptoExchange.Net.SharedApis +{ + /// + /// Options for requesting funding rate history + /// + public class GetUserFundingHistoryOptions : PaginatedCapabilityOptions + { + /// + public override string Description => "Retrieve funding fee payments for the user"; + + private static readonly RequestParameterDescription[] _defaultParameterRules = new[] + { + RequestParameterRule.Optional(x => x.Symbol, "Filter by symbol", new SharedSymbol(TradingMode.PerpetualLinear, "ETH", "USDT")), + RequestParameterRule.Optional(x => x.StartTime, "Filter the result set by start time", DateTime.UtcNow.AddDays(-1)), + RequestParameterRule.Optional(x => x.EndTime, "Filter the result set by end time", DateTime.UtcNow.AddHours(-1)), + RequestParameterRule.Optional(x => x.Limit, "Limit the result set to a maximum number of items", 100), + RequestParameterRule.Optional(x => x.Direction, "The direction in which to retrieve the results", DataDirection.Descending), + }; + + /// + /// ctor + /// + public GetUserFundingHistoryOptions(string exchange, bool supportsAscending, bool supportsDescending, bool timeFilterSupported, int maxLimit, bool needsAuthentication) + : base(exchange, supportsAscending, supportsDescending, timeFilterSupported, maxLimit, needsAuthentication, nameof(IGetUserFundingHistoryRest.GetUserFundingHistoryAsync), _defaultParameterRules) + { + } + + /// + public override Error? ValidateRequest(GetUserFundingHistoryRequest request, IGetUserFundingHistoryRest client) + { + if (!SupportsAscending && request.Direction == DataDirection.Ascending) + return ArgumentError.Invalid(nameof(GetUserFundingHistoryRequest.Direction), $"Ascending direction is not supported"); + + if (!SupportsDescending && request.Direction == DataDirection.Descending) + return ArgumentError.Invalid(nameof(GetUserFundingHistoryRequest.Direction), $"Descending direction is not supported"); + + if (MaxAge.HasValue && request.StartTime < DateTime.UtcNow.Add(-MaxAge.Value)) + return ArgumentError.Invalid(nameof(GetUserFundingHistoryRequest.StartTime), $"Only the most recent {MaxAge} period data is available"); + + if (!TimePeriodFilterSupport) + { + // When going descending we can still allow startTime filter to limit the results + var now = DateTime.UtcNow; + if ((request.Direction != DataDirection.Descending && request.StartTime != null) + || (request.EndTime != null && now - request.EndTime > TimeSpan.FromSeconds(5))) + { + return ArgumentError.Invalid(nameof(GetUserFundingHistoryRequest.StartTime), $"Time filter is not supported"); + } + } + + return base.ValidateRequest(request, client); + } + } +} diff --git a/CryptoExchange.Net/SharedApis/V2/Funding/GetUserFundingHistory/GetUserFundingHistoryRequest.cs b/CryptoExchange.Net/SharedApis/V2/Funding/GetUserFundingHistory/GetUserFundingHistoryRequest.cs new file mode 100644 index 00000000..2deb55f1 --- /dev/null +++ b/CryptoExchange.Net/SharedApis/V2/Funding/GetUserFundingHistory/GetUserFundingHistoryRequest.cs @@ -0,0 +1,56 @@ +using System; + +namespace CryptoExchange.Net.SharedApis +{ + /// + /// Request to retrieve user funding fee payment history + /// + public record GetUserFundingHistoryRequest : SharedRequest + { + /// + /// Filter be symbol + /// + public SharedSymbol? Symbol { get; set; } + /// + /// Filter by start time + /// + public DateTime? StartTime { get; set; } + /// + /// Filter by end time + /// + public DateTime? EndTime { get; set; } + /// + /// Max number of results + /// + public int? Limit { get; set; } + /// + /// Data direction + /// + public DataDirection? Direction { get; set; } + + /// + /// ctor + /// + /// Symbol to request funding history + /// Filter by start time + /// Filter by end time + /// Max number of results + /// Data direction + /// Exchange specific parameters + public GetUserFundingHistoryRequest( + SharedSymbol? symbol = null, + DateTime? startTime = null, + DateTime? endTime = null, + int? limit = null, + DataDirection? direction = null, + ExchangeParameters? exchangeParameters = null) + : base(null, exchangeParameters) + { + Symbol = symbol; + StartTime = startTime; + EndTime = endTime; + Limit = limit; + Direction = direction; + } + } +} diff --git a/CryptoExchange.Net/SharedApis/V2/Funding/GetUserFundingHistory/IGetUserFundingHistory.cs b/CryptoExchange.Net/SharedApis/V2/Funding/GetUserFundingHistory/IGetUserFundingHistory.cs new file mode 100644 index 00000000..80a00fd7 --- /dev/null +++ b/CryptoExchange.Net/SharedApis/V2/Funding/GetUserFundingHistory/IGetUserFundingHistory.cs @@ -0,0 +1,39 @@ +using CryptoExchange.Net.Objects; +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace CryptoExchange.Net.SharedApis +{ + /// + /// Operation for retrieving funding history for a user on an exchange. + /// + public interface IGetUserFundingHistory : ISharedApiCapability + { + /// + /// Funding history 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. + ///
+ GetUserFundingHistoryOptions GetUserFundingHistoryOptions { get; } + /// + /// Get funding history records, see for request options and exchange specific required/optional parameters.
+ /// The result is paginated, if there are more results to be retrieved, the property of the result will contain the pagination request to be used for the next request to continue pagination. + ///
+ /// Request info + /// The pagination request from the previous request result property to continue pagination + /// Cancellation token + Task> GetUserFundingHistoryAsync(GetUserFundingHistoryRequest request, PageRequest? nextPageToken = null, CancellationToken ct = default); + } + + /// + /// Operation for retrieving funding history for a user on an exchange via the REST API. + /// + public interface IGetUserFundingHistoryRest : IGetUserFundingHistory, ISharedRest + { + /// + new Task> GetUserFundingHistoryAsync(GetUserFundingHistoryRequest request, PageRequest? nextPageToken = null, CancellationToken ct = default); + } +} diff --git a/CryptoExchange.Net/SharedApis/V2/IndexPrice/SubscribeIndexPrice/ISubscribeMarkPriceSocket.cs b/CryptoExchange.Net/SharedApis/V2/IndexPrice/SubscribeIndexPrice/ISubscribeMarkPriceSocket.cs new file mode 100644 index 00000000..a0c8bd8c --- /dev/null +++ b/CryptoExchange.Net/SharedApis/V2/IndexPrice/SubscribeIndexPrice/ISubscribeMarkPriceSocket.cs @@ -0,0 +1,28 @@ +using CryptoExchange.Net.Objects; +using CryptoExchange.Net.Objects.Sockets; +using System; +using System.Threading; +using System.Threading.Tasks; + +namespace CryptoExchange.Net.SharedApis +{ + /// + /// Operation for subscribing to user Index price updates + /// + public interface ISubscribeIndexPriceSocket : ISharedSubscription + { + /// + /// Index price subscription options + /// + SubscribeIndexPriceOptions SubscribeIndexPriceOptions { get; } + + /// + /// Subscribe to user Index price updates + /// + /// Request info + /// Update handler + /// Cancellation token, can be used to stop the updates + /// + Task> SubscribeToIndexPriceUpdatesAsync(SubscribeIndexPriceRequest request, Action> handler, CancellationToken ct = default); + } +} diff --git a/CryptoExchange.Net/SharedApis/V2/IndexPrice/SubscribeIndexPrice/SubscribeMarkPriceOptions.cs b/CryptoExchange.Net/SharedApis/V2/IndexPrice/SubscribeIndexPrice/SubscribeMarkPriceOptions.cs new file mode 100644 index 00000000..899b583f --- /dev/null +++ b/CryptoExchange.Net/SharedApis/V2/IndexPrice/SubscribeIndexPrice/SubscribeMarkPriceOptions.cs @@ -0,0 +1,29 @@ +using CryptoExchange.Net.Objects; +using System; +using System.Linq; + +namespace CryptoExchange.Net.SharedApis +{ + /// + /// Options for subscribing to Index price updates + /// + public class SubscribeIndexPriceOptions : CapabilityOptions + { + /// + public override string Description => "Subscribe to Index price updates for a symbol"; + + private static readonly RequestParameterDescription[] _defaultParameterRules = new[] + { + RequestParameterRule.Optional(x => x.Symbol, "The symbol to subscribe to", new SharedSymbol(TradingMode.Spot, "ETH", "USDT")), + RequestParameterRule.Optional(x => x.Symbols, "The symbols to subscribe to", new[] { new SharedSymbol(TradingMode.Spot, "ETH", "USDT") }), + }; + + /// + /// ctor + /// + public SubscribeIndexPriceOptions(string exchange, bool needsAuthentication) + : base(exchange, needsAuthentication, nameof(ISubscribeIndexPriceSocket.SubscribeToIndexPriceUpdatesAsync), _defaultParameterRules) + { + } + } +} diff --git a/CryptoExchange.Net/SharedApis/V2/IndexPrice/SubscribeIndexPrice/SubscribeMarkPriceRequest.cs b/CryptoExchange.Net/SharedApis/V2/IndexPrice/SubscribeIndexPrice/SubscribeMarkPriceRequest.cs new file mode 100644 index 00000000..97feca8e --- /dev/null +++ b/CryptoExchange.Net/SharedApis/V2/IndexPrice/SubscribeIndexPrice/SubscribeMarkPriceRequest.cs @@ -0,0 +1,38 @@ +using System.Collections.Generic; + +namespace CryptoExchange.Net.SharedApis +{ + /// + /// Request to subscribe to Index price updates for a symbol + /// + public record SubscribeIndexPriceRequest : SharedSymbolRequest + { + /// + /// ctor + /// + /// The symbol to subscribe to + /// Exchange specific parameters + public SubscribeIndexPriceRequest(SharedSymbol symbol, ExchangeParameters? exchangeParameters = null) + : base(symbol, exchangeParameters) + { + } + + /// + /// ctor + /// + /// The symbols to subscribe to + /// Exchange specific parameters + public SubscribeIndexPriceRequest(IEnumerable symbols, ExchangeParameters? exchangeParameters = null) + : base(symbols, exchangeParameters) + { + } + + /// + /// ctor + /// + /// The symbols to subscribe to + public SubscribeIndexPriceRequest(params SharedSymbol[] symbols) : base(symbols, null) + { + } + } +} diff --git a/CryptoExchange.Net/SharedApis/V2/Ledger/GetLedger/GetLedgerOptions.cs b/CryptoExchange.Net/SharedApis/V2/Ledger/GetLedger/GetLedgerOptions.cs new file mode 100644 index 00000000..0360ff85 --- /dev/null +++ b/CryptoExchange.Net/SharedApis/V2/Ledger/GetLedger/GetLedgerOptions.cs @@ -0,0 +1,58 @@ +using CryptoExchange.Net.Objects; +using System; +using System.Text; + +namespace CryptoExchange.Net.SharedApis +{ + /// + /// Options for requesting account ledger + /// + public class GetLedgerOptions : PaginatedCapabilityOptions + { + /// + public override string Description => "Retrieve the account ledger"; + + private static readonly RequestParameterDescription[] _defaultParameterRules = new[] + { + RequestParameterRule.Optional(x => x.Asset, "Filter the result set by asset", "ETH"), + RequestParameterRule.Optional(x => x.StartTime, "Filter the result set by start time", DateTime.UtcNow.AddDays(-1)), + RequestParameterRule.Optional(x => x.EndTime, "Filter the result set by end time", DateTime.UtcNow.AddHours(-1)), + RequestParameterRule.Optional(x => x.Limit, "Limit the result set to a maximum number of items", 100), + RequestParameterRule.Optional(x => x.Direction, "The direction in which to retrieve the results", DataDirection.Descending), + }; + + /// + /// ctor + /// + public GetLedgerOptions(string exchange, bool supportsAscending, bool supportsDescending, bool timeFilterSupported, int maxLimit) + : base(exchange, supportsAscending, supportsDescending, timeFilterSupported, maxLimit, true, nameof(IGetLedgerRest.GetLedgerAsync), _defaultParameterRules) + { + } + + /// + public override Error? ValidateRequest(GetLedgerRequest request, IGetLedgerRest client) + { + if (!SupportsAscending && request.Direction == DataDirection.Ascending) + return ArgumentError.Invalid(nameof(GetLedgerRequest.Direction), $"Ascending direction is not supported"); + + if (!SupportsDescending && request.Direction == DataDirection.Descending) + return ArgumentError.Invalid(nameof(GetLedgerRequest.Direction), $"Descending direction is not supported"); + + if (MaxAge.HasValue && request.StartTime < DateTime.UtcNow.Add(-MaxAge.Value)) + return ArgumentError.Invalid(nameof(GetLedgerRequest.StartTime), $"Only the most recent {MaxAge} period data is available"); + + if (!TimePeriodFilterSupport) + { + // When going descending we can still allow startTime filter to limit the results + var now = DateTime.UtcNow; + if ((request.Direction != DataDirection.Descending && request.StartTime != null) + || (request.EndTime != null && now - request.EndTime > TimeSpan.FromSeconds(5))) + { + return ArgumentError.Invalid(nameof(GetLedgerRequest.StartTime), $"Time filter is not supported"); + } + } + + return base.ValidateRequest(request, client); + } + } +} diff --git a/CryptoExchange.Net/SharedApis/V2/Ledger/GetLedger/GetLedgerRequest.cs b/CryptoExchange.Net/SharedApis/V2/Ledger/GetLedger/GetLedgerRequest.cs new file mode 100644 index 00000000..3734092f --- /dev/null +++ b/CryptoExchange.Net/SharedApis/V2/Ledger/GetLedger/GetLedgerRequest.cs @@ -0,0 +1,55 @@ +using System; + +namespace CryptoExchange.Net.SharedApis +{ + /// + /// Request to retrieve the account ledger of the user + /// + public record GetLedgerRequest : SharedRequest + { + /// + /// Filter by asset + /// + public string? Asset { get; set; } + /// + /// Filter by start time + /// + public DateTime? StartTime { get; } + /// + /// Filter by end time + /// + public DateTime? EndTime { get; } + /// + /// Max number of results + /// + public int? Limit { get; } + /// + /// Data direction + /// + public DataDirection? Direction { get; set; } + + /// + /// ctor + /// + /// Filter by asset + /// Filter by start time + /// Filter by end time + /// Max number of results + /// Data direction + /// Exchange specific parameters + public GetLedgerRequest( + string? asset = null, + DateTime? startTime = null, + DateTime? endTime = null, + int? limit = null, + DataDirection? direction = null, + ExchangeParameters? exchangeParameters = null) : base(null, exchangeParameters) + { + Asset = asset; + StartTime = startTime; + EndTime = endTime; + Limit = limit; + Direction = direction; + } + } +} diff --git a/CryptoExchange.Net/SharedApis/V2/Ledger/GetLedger/IGetLedger.cs b/CryptoExchange.Net/SharedApis/V2/Ledger/GetLedger/IGetLedger.cs new file mode 100644 index 00000000..274811ad --- /dev/null +++ b/CryptoExchange.Net/SharedApis/V2/Ledger/GetLedger/IGetLedger.cs @@ -0,0 +1,39 @@ +using CryptoExchange.Net.Objects; +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace CryptoExchange.Net.SharedApis +{ + /// + /// Operation for retrieving the account ledger from an exchange. + /// + public interface IGetLedger : ISharedApiCapability + { + /// + /// Ledger 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. + ///
+ GetLedgerOptions GetLedgerOptions { get; } + /// + /// Get ledger entries, see for request options and exchange specific required/optional parameters.
+ /// The result is paginated, if there are more results to be retrieved, the property of the result will contain the pagination request to be used for the next request to continue pagination. + ///
+ /// Request info + /// The pagination request from the previous request result property to continue pagination + /// Cancellation token + Task> GetLedgerAsync(GetLedgerRequest request, PageRequest? nextPageToken = null, CancellationToken ct = default); + } + + /// + /// Operation for retrieving the account ledger from an exchange via the REST API. + /// + public interface IGetLedgerRest : IGetLedger, ISharedRest + { + /// + new Task> GetLedgerAsync(GetLedgerRequest request, PageRequest? nextPageToken = null, CancellationToken ct = default); + } +} diff --git a/CryptoExchange.Net/SharedApis/V2/Leverage/GetLeverage/GetLeverageOptions.cs b/CryptoExchange.Net/SharedApis/V2/Leverage/GetLeverage/GetLeverageOptions.cs index a1ba3b21..49c1c053 100644 --- a/CryptoExchange.Net/SharedApis/V2/Leverage/GetLeverage/GetLeverageOptions.cs +++ b/CryptoExchange.Net/SharedApis/V2/Leverage/GetLeverage/GetLeverageOptions.cs @@ -5,7 +5,7 @@ using System.Text; namespace CryptoExchange.Net.SharedApis { /// - /// Options for requesting asset info + /// Options for requesting leverage info /// public class GetLeverageOptions : CapabilityOptions { diff --git a/CryptoExchange.Net/SharedApis/V2/Leverage/GetLeverageTiers/GetLeverageTiersOptions.cs b/CryptoExchange.Net/SharedApis/V2/Leverage/GetLeverageTiers/GetLeverageTiersOptions.cs new file mode 100644 index 00000000..f838452a --- /dev/null +++ b/CryptoExchange.Net/SharedApis/V2/Leverage/GetLeverageTiers/GetLeverageTiersOptions.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace CryptoExchange.Net.SharedApis +{ + /// + /// Options for requesting leverage tier info + /// + public class GetLeverageTiersOptions : CapabilityOptions + { + /// + public override string Description => "Retrieve the current leverage tier information for a futures symbol"; + + private static readonly RequestParameterDescription[] _defaultParameterRules = new[] + { + RequestParameterRule.Required(x => x.Symbol, "The symbol to retrieve leverage tiers for", new SharedSymbol(TradingMode.PerpetualLinear, "ETH", "USDT")), + }; + + /// + /// ctor + /// + public GetLeverageTiersOptions(string exchange, bool authenticated) : base(exchange, authenticated, nameof(IGetLeverageTiersRest.GetLeverageTiersAsync), _defaultParameterRules) + { + } + } +} diff --git a/CryptoExchange.Net/SharedApis/V2/Leverage/GetLeverageTiers/GetLeverageTiersRequest.cs b/CryptoExchange.Net/SharedApis/V2/Leverage/GetLeverageTiers/GetLeverageTiersRequest.cs new file mode 100644 index 00000000..854688c2 --- /dev/null +++ b/CryptoExchange.Net/SharedApis/V2/Leverage/GetLeverageTiers/GetLeverageTiersRequest.cs @@ -0,0 +1,17 @@ +namespace CryptoExchange.Net.SharedApis +{ + /// + /// Request to retrieve the leverage tier information for a symbol + /// + public record GetLeverageTiersRequest : SharedSymbolRequest + { + /// + /// ctor + /// + /// Symbol to request leverage for + /// Exchange specific parameters + public GetLeverageTiersRequest(SharedSymbol symbol, ExchangeParameters? exchangeParameters = null) : base(symbol, exchangeParameters) + { + } + } +} diff --git a/CryptoExchange.Net/SharedApis/V2/Leverage/GetLeverageTiers/IGetLeverageTiers.cs b/CryptoExchange.Net/SharedApis/V2/Leverage/GetLeverageTiers/IGetLeverageTiers.cs new file mode 100644 index 00000000..4de4ea35 --- /dev/null +++ b/CryptoExchange.Net/SharedApis/V2/Leverage/GetLeverageTiers/IGetLeverageTiers.cs @@ -0,0 +1,37 @@ +using CryptoExchange.Net.Objects; +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace CryptoExchange.Net.SharedApis +{ + /// + /// Operation for retrieving leverage tier information for a symbol on an exchange. + /// + public interface IGetLeverageTiers : ISharedApiCapability + { + /// + /// Leverage tier 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. + ///
+ GetLeverageTiersOptions GetLeverageTiersOptions { get; } + /// + /// Get the leverage tiers for a symbol, see for request options and exchange specific required/optional parameters.
+ ///
+ /// Request info + /// Cancellation token + Task> GetLeverageTiersAsync(GetLeverageTiersRequest request, CancellationToken ct = default); + } + + /// + /// Operation for retrieving leverage tier information for a symbol on an exchange via the REST API. + /// + public interface IGetLeverageTiersRest : IGetLeverageTiers, ISharedRest + { + /// + new Task> GetLeverageTiersAsync(GetLeverageTiersRequest request, CancellationToken ct = default); + } +} diff --git a/CryptoExchange.Net/SharedApis/V2/MarkPrice/SubscribeMarkPrice/ISubscribeMarkPriceSocket.cs b/CryptoExchange.Net/SharedApis/V2/MarkPrice/SubscribeMarkPrice/ISubscribeMarkPriceSocket.cs new file mode 100644 index 00000000..6d69bd66 --- /dev/null +++ b/CryptoExchange.Net/SharedApis/V2/MarkPrice/SubscribeMarkPrice/ISubscribeMarkPriceSocket.cs @@ -0,0 +1,28 @@ +using CryptoExchange.Net.Objects; +using CryptoExchange.Net.Objects.Sockets; +using System; +using System.Threading; +using System.Threading.Tasks; + +namespace CryptoExchange.Net.SharedApis +{ + /// + /// Operation for subscribing to user mark price updates + /// + public interface ISubscribeMarkPriceSocket : ISharedSubscription + { + /// + /// Mark price subscription options + /// + SubscribeMarkPriceOptions SubscribeMarkPriceOptions { get; } + + /// + /// Subscribe to user mark price updates + /// + /// Request info + /// Update handler + /// Cancellation token, can be used to stop the updates + /// + Task> SubscribeToMarkPriceUpdatesAsync(SubscribeMarkPriceRequest request, Action> handler, CancellationToken ct = default); + } +} diff --git a/CryptoExchange.Net/SharedApis/V2/MarkPrice/SubscribeMarkPrice/SubscribeMarkPriceOptions.cs b/CryptoExchange.Net/SharedApis/V2/MarkPrice/SubscribeMarkPrice/SubscribeMarkPriceOptions.cs new file mode 100644 index 00000000..05510a3e --- /dev/null +++ b/CryptoExchange.Net/SharedApis/V2/MarkPrice/SubscribeMarkPrice/SubscribeMarkPriceOptions.cs @@ -0,0 +1,29 @@ +using CryptoExchange.Net.Objects; +using System; +using System.Linq; + +namespace CryptoExchange.Net.SharedApis +{ + /// + /// Options for subscribing to mark price updates + /// + public class SubscribeMarkPriceOptions : CapabilityOptions + { + /// + public override string Description => "Subscribe to mark price updates for a symbol"; + + private static readonly RequestParameterDescription[] _defaultParameterRules = new[] + { + RequestParameterRule.Optional(x => x.Symbol, "The symbol to subscribe to", new SharedSymbol(TradingMode.Spot, "ETH", "USDT")), + RequestParameterRule.Optional(x => x.Symbols, "The symbols to subscribe to", new[] { new SharedSymbol(TradingMode.Spot, "ETH", "USDT") }), + }; + + /// + /// ctor + /// + public SubscribeMarkPriceOptions(string exchange, bool needsAuthentication) + : base(exchange, needsAuthentication, nameof(ISubscribeMarkPriceSocket.SubscribeToMarkPriceUpdatesAsync), _defaultParameterRules) + { + } + } +} diff --git a/CryptoExchange.Net/SharedApis/V2/MarkPrice/SubscribeMarkPrice/SubscribeMarkPriceRequest.cs b/CryptoExchange.Net/SharedApis/V2/MarkPrice/SubscribeMarkPrice/SubscribeMarkPriceRequest.cs new file mode 100644 index 00000000..0d03fef2 --- /dev/null +++ b/CryptoExchange.Net/SharedApis/V2/MarkPrice/SubscribeMarkPrice/SubscribeMarkPriceRequest.cs @@ -0,0 +1,38 @@ +using System.Collections.Generic; + +namespace CryptoExchange.Net.SharedApis +{ + /// + /// Request to subscribe to mark price updates for a symbol + /// + public record SubscribeMarkPriceRequest : SharedSymbolRequest + { + /// + /// ctor + /// + /// The symbol to subscribe to + /// Exchange specific parameters + public SubscribeMarkPriceRequest(SharedSymbol symbol, ExchangeParameters? exchangeParameters = null) + : base(symbol, exchangeParameters) + { + } + + /// + /// ctor + /// + /// The symbols to subscribe to + /// Exchange specific parameters + public SubscribeMarkPriceRequest(IEnumerable symbols, ExchangeParameters? exchangeParameters = null) + : base(symbols, exchangeParameters) + { + } + + /// + /// ctor + /// + /// The symbols to subscribe to + public SubscribeMarkPriceRequest(params SharedSymbol[] symbols) : base(symbols, null) + { + } + } +} diff --git a/CryptoExchange.Net/SharedApis/V2/Orders/Futures/PlaceMultipleFuturesOrders/IPlaceMultipleFuturesOrders.cs b/CryptoExchange.Net/SharedApis/V2/Orders/Futures/PlaceMultipleFuturesOrders/IPlaceMultipleFuturesOrders.cs new file mode 100644 index 00000000..bfac320b --- /dev/null +++ b/CryptoExchange.Net/SharedApis/V2/Orders/Futures/PlaceMultipleFuturesOrders/IPlaceMultipleFuturesOrders.cs @@ -0,0 +1,84 @@ +using CryptoExchange.Net.Objects; +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace CryptoExchange.Net.SharedApis +{ + /// + /// Operation for placing multiple futures order on an exchange in single call. + /// + public interface IPlaceMultipleFuturesOrders : ISharedApiCapability + { + /// + /// 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 placing futures orders + /// + SharedTimeInForce[] FuturesSupportedTimeInForce { get; } + /// + /// Supported quantity types for placing futures orders + /// + SharedQuantitySupport FuturesSupportedOrderQuantity { get; } + /// + /// Max number of orders per request + /// + public int? MaxFuturesOrdersPerRequest { get; } + /// + /// Whether orders for different symbols are allowed in a single place order request + /// + public bool PlaceMultipleFuturesOrdersAllowsMultipleSymbols { get; } + + /// + /// Generate a new random client order id in a format that is accepted by the exchange. + /// + /// + 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. + ///
+ PlaceMultipleFuturesOrdersOptions PlaceMultipleFuturesOrdersOptions { get; } + + /// + /// Place multiple new futures orders, see for request options and exchange specific required/optional parameters.
+ ///
+ /// Request info + /// Cancellation token + Task[]>> PlaceMultipleFuturesOrdersAsync( + PlaceMultipleFuturesOrdersRequest request, + CancellationToken ct = default); + } + + /// + /// Operation for placing multiple futures orders on an exchange via the REST API. + /// + public interface IPlaceMultipleFuturesOrdersRest : IPlaceMultipleFuturesOrders, ISharedRest + { + /// + new Task[]>> PlaceMultipleFuturesOrdersAsync(PlaceMultipleFuturesOrdersRequest request, CancellationToken ct = default); + } + + /// + /// Operation for placing multiple futures orders on an exchange via the WebSocket API. + /// + public interface IPlaceMultipleFuturesOrdersSocket : IPlaceMultipleFuturesOrders, ISharedSocket + { + /// + new Task[]>> PlaceMultipleFuturesOrdersAsync(PlaceMultipleFuturesOrdersRequest request, CancellationToken ct = default); + } +} diff --git a/CryptoExchange.Net/SharedApis/V2/Orders/Futures/PlaceMultipleFuturesOrders/PlaceMultipleFuturesOrdersOptions.cs b/CryptoExchange.Net/SharedApis/V2/Orders/Futures/PlaceMultipleFuturesOrders/PlaceMultipleFuturesOrdersOptions.cs new file mode 100644 index 00000000..2b977eec --- /dev/null +++ b/CryptoExchange.Net/SharedApis/V2/Orders/Futures/PlaceMultipleFuturesOrders/PlaceMultipleFuturesOrdersOptions.cs @@ -0,0 +1,80 @@ +using CryptoExchange.Net.Objects; +using System; +using System.Collections; +using System.Linq; + +namespace CryptoExchange.Net.SharedApis +{ + /// + /// Options for placing multiple new futures orders + /// + public class PlaceMultipleFuturesOrdersOptions : CapabilityOptions + { + /// + public override string Description => "Place multiple new futures orders"; + + private static readonly RequestParameterDescription[] _defaultParameterRules = new[] + { + RequestParameterRule.Required(x => x.Orders, "The orders to place", []), + }; + + + /// + /// ctor + /// + public PlaceMultipleFuturesOrdersOptions(string exchange) + : base(exchange, true, nameof(IPlaceMultipleFuturesOrders.PlaceMultipleFuturesOrdersAsync), _defaultParameterRules) + { + } + + /// + /// Validate a request + /// + public override Error? ValidateRequest( + PlaceMultipleFuturesOrdersRequest request, + IPlaceMultipleFuturesOrders client) + { + var error = base.ValidateRequest(request, client); + if (error != null) + return error; + + if (request.Orders.Length > client.MaxFuturesOrdersPerRequest) + return ArgumentError.Invalid(nameof(PlaceMultipleFuturesOrdersRequest.Orders), $"Too many orders, max {client.MaxFuturesOrdersPerRequest}"); + + if (request.Orders.Length == 0) + return ArgumentError.Invalid(nameof(PlaceMultipleFuturesOrdersRequest.Orders), "No orders provided"); + + if (!client.PlaceMultipleFuturesOrdersAllowsMultipleSymbols) + { + var firstSymbol = request.Orders[0].Symbol; + if (request.Orders.Any(order => order.Symbol!.BaseAsset != firstSymbol!.BaseAsset + || order.Symbol.QuoteAsset != firstSymbol.QuoteAsset + || order.Symbol.TradingMode != firstSymbol.TradingMode)) + { + return ArgumentError.Invalid(nameof(PlaceFuturesOrderRequest.Symbol), "All orders in the request should have matching symbols"); + } + } + + if (!request.Orders.All(x => x.TradingMode == request.TradingMode)) + return ArgumentError.Invalid(nameof(PlaceFuturesOrderRequest.TradingMode), "All orders in the request should have matching trading modes"); + + foreach (var order in request.Orders) + { + if (order.OrderType == SharedOrderType.Other) + throw new ArgumentException("OrderType can't be `Other`", nameof(order.OrderType)); + + if (!client.FuturesSupportedOrderTypes.Contains(order.OrderType)) + return ArgumentError.Invalid(nameof(PlaceFuturesOrderRequest.OrderType), "Order type not supported"); + + if (order.TimeInForce != null && !client.FuturesSupportedTimeInForce.Contains(order.TimeInForce.Value)) + return ArgumentError.Invalid(nameof(PlaceFuturesOrderRequest.TimeInForce), "Order time in force not supported"); + + var quantityError = client.FuturesSupportedOrderQuantity.Validate(order.Side, order.OrderType, order.Quantity); + if (quantityError != null) + return quantityError; + } + + return null; + } + } +} diff --git a/CryptoExchange.Net/SharedApis/V2/Orders/Futures/PlaceMultipleFuturesOrders/PlaceMultipleFuturesOrdersRequest.cs b/CryptoExchange.Net/SharedApis/V2/Orders/Futures/PlaceMultipleFuturesOrders/PlaceMultipleFuturesOrdersRequest.cs new file mode 100644 index 00000000..77e5e5ea --- /dev/null +++ b/CryptoExchange.Net/SharedApis/V2/Orders/Futures/PlaceMultipleFuturesOrders/PlaceMultipleFuturesOrdersRequest.cs @@ -0,0 +1,29 @@ +using System.Collections.Generic; +using System.Linq; + +namespace CryptoExchange.Net.SharedApis +{ + /// + /// Request to place multiple new futures orders + /// + public record PlaceMultipleFuturesOrdersRequest : SharedRequest + { + /// + /// Orders to place + /// + public PlaceFuturesOrderRequest[] Orders { get; set; } + + /// + /// ctor + /// + /// Orders to place + /// Exchange specific parameters + public PlaceMultipleFuturesOrdersRequest( + IEnumerable orders, + ExchangeParameters? exchangeParameters = null) : base(null, exchangeParameters) + { + Orders = orders.ToArray(); + TradingMode = Orders.FirstOrDefault()?.TradingMode; + } + } +} diff --git a/CryptoExchange.Net/SharedApis/V2/Orders/Spot/PlaceMultipleSpotOrders/IPlaceMultipleSpotOrders.cs b/CryptoExchange.Net/SharedApis/V2/Orders/Spot/PlaceMultipleSpotOrders/IPlaceMultipleSpotOrders.cs new file mode 100644 index 00000000..2cc67eec --- /dev/null +++ b/CryptoExchange.Net/SharedApis/V2/Orders/Spot/PlaceMultipleSpotOrders/IPlaceMultipleSpotOrders.cs @@ -0,0 +1,84 @@ +using CryptoExchange.Net.Objects; +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace CryptoExchange.Net.SharedApis +{ + /// + /// Operation for placing multiple spot order on an exchange in single call. + /// + public interface IPlaceMultipleSpotOrders : ISharedApiCapability + { + /// + /// 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; } + /// + /// Max number of orders per request + /// + public int? MaxSpotOrdersPerRequest { get; } + /// + /// Whether orders for different symbols are allowed in a single place order request + /// + public bool PlaceMultipleSpotOrdersAllowsMultipleSymbols { get; } + + /// + /// Generate a new random client order id in a format that is accepted by the exchange. + /// + /// + 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. + ///
+ PlaceMultipleSpotOrdersOptions PlaceMultipleSpotOrdersOptions { get; } + + /// + /// Place multiple new spot orders, see for request options and exchange specific required/optional parameters.
+ ///
+ /// Request info + /// Cancellation token + Task[]>> PlaceMultipleSpotOrdersAsync( + PlaceMultipleSpotOrdersRequest request, + CancellationToken ct = default); + } + + /// + /// Operation for placing multiple spot orders on an exchange via the REST API. + /// s + public interface IPlaceMultipleSpotOrdersRest : IPlaceMultipleSpotOrders, ISharedRest + { + /// + new Task[]>> PlaceMultipleSpotOrdersAsync(PlaceMultipleSpotOrdersRequest request, CancellationToken ct = default); + } + + /// + /// Operation for placing multiple spot orders on an exchange via the WebSocket API. + /// + public interface IPlaceMultipleSpotOrdersSocket : IPlaceMultipleSpotOrders, ISharedSocket + { + /// + new Task[]>> PlaceMultipleSpotOrdersAsync(PlaceMultipleSpotOrdersRequest request, CancellationToken ct = default); + } +} diff --git a/CryptoExchange.Net/SharedApis/V2/Orders/Spot/PlaceMultipleSpotOrders/PlaceMultipleSpotOrdersOptions.cs b/CryptoExchange.Net/SharedApis/V2/Orders/Spot/PlaceMultipleSpotOrders/PlaceMultipleSpotOrdersOptions.cs new file mode 100644 index 00000000..a9a6d7cc --- /dev/null +++ b/CryptoExchange.Net/SharedApis/V2/Orders/Spot/PlaceMultipleSpotOrders/PlaceMultipleSpotOrdersOptions.cs @@ -0,0 +1,82 @@ +using CryptoExchange.Net.Objects; +using System; +using System.Collections; +using System.Linq; + +namespace CryptoExchange.Net.SharedApis +{ + /// + /// Options for placing multiple new spot orders + /// + public class PlaceMultipleSpotOrdersOptions : CapabilityOptions + { + /// + public override string Description => "Place multiple new spot orders"; + + private static readonly RequestParameterDescription[] _defaultParameterRules = new[] + { + RequestParameterRule.Required(x => x.Orders, "The orders to place", []), + }; + + + /// + /// ctor + /// + public PlaceMultipleSpotOrdersOptions(string exchange) + : base(exchange, true, nameof(IPlaceMultipleSpotOrders.PlaceMultipleSpotOrdersAsync), _defaultParameterRules) + { + } + + /// + /// Validate a request + /// + public override Error? ValidateRequest( + PlaceMultipleSpotOrdersRequest request, + IPlaceMultipleSpotOrders client) + { + var error = base.ValidateRequest(request, client); + if (error != null) + return error; + + if (request.Orders.Length > client.MaxSpotOrdersPerRequest) + return ArgumentError.Invalid(nameof(PlaceMultipleSpotOrdersRequest.Orders), $"Too many orders, max {client.MaxSpotOrdersPerRequest}"); + + if (request.Orders.Length == 0) + return ArgumentError.Invalid(nameof(PlaceMultipleSpotOrdersRequest.Orders), "No orders provided"); + + if (request.TradingMode != TradingMode.Spot) + return ArgumentError.Invalid("TradingMode", $"TradingMode.{request.TradingMode} is not supported, should be Spot"); + + if (!client.PlaceMultipleSpotOrdersAllowsMultipleSymbols) + { + var firstSymbol = request.Orders[0].Symbol; + if (request.Orders.Any(order => order.Symbol!.BaseAsset != firstSymbol!.BaseAsset + || order.Symbol.QuoteAsset != firstSymbol.QuoteAsset + || order.Symbol.TradingMode != firstSymbol.TradingMode)) + { + return ArgumentError.Invalid(nameof(PlaceSpotOrderRequest.Symbol), "All orders in the request should have matching symbols"); + } + } + + foreach (var order in request.Orders) + { + if (order.OrderType == SharedOrderType.Other) + throw new ArgumentException("OrderType can't be `Other`", nameof(order.OrderType)); + + if (!client.SpotSupportedOrderTypes.Contains(order.OrderType)) + return ArgumentError.Invalid(nameof(PlaceSpotOrderRequest.OrderType), "Order type not supported"); + + if (order.TimeInForce != null && !client.SpotSupportedTimeInForce.Contains(order.TimeInForce.Value)) + return ArgumentError.Invalid(nameof(PlaceSpotOrderRequest.TimeInForce), "Order time in force not supported"); + + var quantityError = client.SpotSupportedOrderQuantity.Validate(order.Side, order.OrderType, order.Quantity); + if (quantityError != null) + return quantityError; + } + + + + return null; + } + } +} diff --git a/CryptoExchange.Net/SharedApis/V2/Orders/Spot/PlaceMultipleSpotOrders/PlaceMultipleSpotOrdersRequest.cs b/CryptoExchange.Net/SharedApis/V2/Orders/Spot/PlaceMultipleSpotOrders/PlaceMultipleSpotOrdersRequest.cs new file mode 100644 index 00000000..696b554e --- /dev/null +++ b/CryptoExchange.Net/SharedApis/V2/Orders/Spot/PlaceMultipleSpotOrders/PlaceMultipleSpotOrdersRequest.cs @@ -0,0 +1,29 @@ +using System.Collections.Generic; +using System.Linq; + +namespace CryptoExchange.Net.SharedApis +{ + /// + /// Request to place multiple new spot orders + /// + public record PlaceMultipleSpotOrdersRequest : SharedRequest + { + /// + /// Orders to place + /// + public PlaceSpotOrderRequest[] Orders { get; set; } + + /// + /// ctor + /// + /// Orders to place + /// Exchange specific parameters + public PlaceMultipleSpotOrdersRequest( + IEnumerable orders, + ExchangeParameters? exchangeParameters = null) : base(null, exchangeParameters) + { + Orders = orders.ToArray(); + TradingMode = Orders.FirstOrDefault()?.TradingMode; + } + } +} diff --git a/CryptoExchange.Net/SharedApis/V2/Tickers/Futures/GetAllFuturesTicker/GetAllFuturesTickersOptions.cs b/CryptoExchange.Net/SharedApis/V2/Tickers/Futures/GetAllFuturesTicker/GetAllFuturesTickersOptions.cs deleted file mode 100644 index af2fede2..00000000 --- a/CryptoExchange.Net/SharedApis/V2/Tickers/Futures/GetAllFuturesTicker/GetAllFuturesTickersOptions.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System.Text; - -namespace CryptoExchange.Net.SharedApis -{ - /// - /// Options for requesting tickers - /// - public class GetAllFuturesTickersOptions : CapabilityOptions - { - /// - public override string Description => "Retrieve price ticker information for all futures symbols"; - - private static readonly RequestParameterDescription[] _defaultParameterRules = new[] - { - RequestParameterRule.Optional(x => x.TradingMode, "Filter the tickers by trading mode", TradingMode.PerpetualLinear), - }; - - /// - /// Type of ticker calculation - /// - public SharedTickerType TickerType { get; set; } = SharedTickerType.Day24H; - - /// - /// ctor - /// - public GetAllFuturesTickersOptions(string exchange, SharedTickerType? tickerCalcType = null) : base(exchange, false, nameof(IGetAllFuturesTickersRest.GetAllFuturesTickersAsync), _defaultParameterRules) - { - TickerType = tickerCalcType ?? SharedTickerType.Day24H; - } - - /// - public override string ToString() - { - var sb = new StringBuilder(base.ToString()); - sb.AppendLine($" Ticker data calculation type: {TickerType}"); - return sb.ToString(); - } - } -} diff --git a/CryptoExchange.Net/SharedApis/V2/Tickers/Futures/GetAllFuturesTicker/IGetAllFuturesTickers.cs b/CryptoExchange.Net/SharedApis/V2/Tickers/Futures/GetAllFuturesTicker/IGetAllFuturesTickers.cs deleted file mode 100644 index 45f53dd4..00000000 --- a/CryptoExchange.Net/SharedApis/V2/Tickers/Futures/GetAllFuturesTicker/IGetAllFuturesTickers.cs +++ /dev/null @@ -1,37 +0,0 @@ -using CryptoExchange.Net.Objects; -using System; -using System.Collections.Generic; -using System.Text; -using System.Threading; -using System.Threading.Tasks; - -namespace CryptoExchange.Net.SharedApis -{ - /// - /// Operation for retrieving all futures tickers from an exchange. - /// - public interface IGetAllFuturesTickers : ISharedApiCapability - { - /// - /// Futures get tickers 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. - ///
- GetAllFuturesTickersOptions GetAllFuturesTickersOptions { get; } - /// - /// Get ticker info for all futures symbols, see for request options and exchange specific required/optional parameters.
- ///
- /// Request info - /// Cancellation token - Task> GetAllFuturesTickersAsync(GetTickersRequest request, CancellationToken ct = default); - } - - /// - /// Operation for retrieving all futures tickers from an exchange via the REST API. - /// - public interface IGetAllFuturesTickersRest : IGetAllFuturesTickers - { - /// - new Task> GetAllFuturesTickersAsync(GetTickersRequest request, CancellationToken ct = default); - } -} diff --git a/CryptoExchange.Net/SharedApis/V2/Tickers/Futures/GetFuturesTicker/GetFuturesTickerOptions.cs b/CryptoExchange.Net/SharedApis/V2/Tickers/Futures/GetFuturesTicker/GetFuturesTickerOptions.cs deleted file mode 100644 index ecfd749c..00000000 --- a/CryptoExchange.Net/SharedApis/V2/Tickers/Futures/GetFuturesTicker/GetFuturesTickerOptions.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System.Text; - -namespace CryptoExchange.Net.SharedApis -{ - /// - /// Options for requesting ticker - /// - public class GetFuturesTickerOptions : CapabilityOptions - { - /// - public override string Description => "Retrieve price ticker information for a futures symbol"; - - private static readonly RequestParameterDescription[] _defaultParameterRules = new[] - { - RequestParameterRule.Required(x => x.Symbol, "The symbol to retrieve ticker information for", new SharedSymbol(TradingMode.PerpetualLinear, "ETH", "USDT")), - }; - - /// - /// Type of ticker calculation - /// - public SharedTickerType TickerType { get; set; } = SharedTickerType.Day24H; - - /// - /// ctor - /// - public GetFuturesTickerOptions(string exchange, SharedTickerType? tickerCalcType = null) : base(exchange, false, nameof(IGetFuturesTickerRest.GetFuturesTickerAsync), _defaultParameterRules) - { - TickerType = tickerCalcType ?? SharedTickerType.Day24H; - } - - /// - public override string ToString() - { - var sb = new StringBuilder(base.ToString()); - sb.AppendLine($" Ticker data calculation type: {TickerType}"); - return sb.ToString(); - } - } -} diff --git a/CryptoExchange.Net/SharedApis/V2/Tickers/Futures/GetFuturesTicker/IGetFuturesTicker.cs b/CryptoExchange.Net/SharedApis/V2/Tickers/Futures/GetFuturesTicker/IGetFuturesTicker.cs deleted file mode 100644 index f25de2ef..00000000 --- a/CryptoExchange.Net/SharedApis/V2/Tickers/Futures/GetFuturesTicker/IGetFuturesTicker.cs +++ /dev/null @@ -1,37 +0,0 @@ -using CryptoExchange.Net.Objects; -using System; -using System.Collections.Generic; -using System.Text; -using System.Threading; -using System.Threading.Tasks; - -namespace CryptoExchange.Net.SharedApis -{ - /// - /// Operation for retrieving a single futures ticker from an exchange. - /// - public interface IGetFuturesTicker : ISharedApiCapability - { - /// - /// Futures get ticker 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. - ///
- GetFuturesTickerOptions GetFuturesTickerOptions { get; } - /// - /// Get ticker info for a specific futures symbol, see for request options and exchange specific required/optional parameters.
- ///
- /// Request info - /// Cancellation token - Task> GetFuturesTickerAsync(GetTickerRequest request, CancellationToken ct = default); - } - - /// - /// Operation for retrieving a single futures ticker from an exchange via the REST API. - /// - public interface IGetFuturesTickerRest : IGetFuturesTicker, ISharedRest - { - /// - new Task> GetFuturesTickerAsync(GetTickerRequest request, CancellationToken ct = default); - } -} diff --git a/CryptoExchange.Net/SharedApis/V2/Tickers/Spot/GetAllSpotTickers/GetAllSpotTickersOptions.cs b/CryptoExchange.Net/SharedApis/V2/Tickers/GetAllTickers/GetAllTickersOptions.cs similarity index 75% rename from CryptoExchange.Net/SharedApis/V2/Tickers/Spot/GetAllSpotTickers/GetAllSpotTickersOptions.cs rename to CryptoExchange.Net/SharedApis/V2/Tickers/GetAllTickers/GetAllTickersOptions.cs index 77446379..80ec1968 100644 --- a/CryptoExchange.Net/SharedApis/V2/Tickers/Spot/GetAllSpotTickers/GetAllSpotTickersOptions.cs +++ b/CryptoExchange.Net/SharedApis/V2/Tickers/GetAllTickers/GetAllTickersOptions.cs @@ -5,10 +5,10 @@ namespace CryptoExchange.Net.SharedApis /// /// Options for requesting tickers /// - public class GetAllSpotTickersOptions : CapabilityOptions + public class GetAllTickersOptions : CapabilityOptions { /// - public override string Description => "Retrieve price ticker information for all spot symbols"; + public override string Description => "Retrieve price ticker information for all symbols"; private static readonly RequestParameterDescription[] _defaultParameterRules = new[] { @@ -23,7 +23,7 @@ namespace CryptoExchange.Net.SharedApis /// /// ctor /// - public GetAllSpotTickersOptions(string exchange, SharedTickerType? tickerCalcType = null) : base(exchange, false, nameof(IGetAllSpotTickersRest.GetAllSpotTickersAsync), _defaultParameterRules) + public GetAllTickersOptions(string exchange, SharedTickerType? tickerCalcType = null) : base(exchange, false, nameof(IGetAllTickersRest.GetAllTickersAsync), _defaultParameterRules) { TickerType = tickerCalcType ?? SharedTickerType.Day24H; } diff --git a/CryptoExchange.Net/SharedApis/V2/Tickers/Spot/GetSpotTicker/IGetSpotTicker.cs b/CryptoExchange.Net/SharedApis/V2/Tickers/GetAllTickers/IGetAllTickers.cs similarity index 51% rename from CryptoExchange.Net/SharedApis/V2/Tickers/Spot/GetSpotTicker/IGetSpotTicker.cs rename to CryptoExchange.Net/SharedApis/V2/Tickers/GetAllTickers/IGetAllTickers.cs index 60027aa8..63089a8b 100644 --- a/CryptoExchange.Net/SharedApis/V2/Tickers/Spot/GetSpotTicker/IGetSpotTicker.cs +++ b/CryptoExchange.Net/SharedApis/V2/Tickers/GetAllTickers/IGetAllTickers.cs @@ -8,30 +8,30 @@ using System.Threading.Tasks; namespace CryptoExchange.Net.SharedApis { /// - /// Operation for retrieving a single spot ticker from an exchange. + /// Operation for retrieving all tickers from an exchange. /// - public interface IGetSpotTicker : ISharedApiCapability + public interface IGetAllTickers : ISharedApiCapability { /// - /// Spot ticker request options.
+ /// Tickers 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. ///
- GetSpotTickerOptions GetSpotTickerOptions { get; } + GetAllTickersOptions GetAllTickersOptions { get; } /// - /// Get ticker for a specific spot symbol, see for request options and exchange specific required/optional parameters.
+ /// Get tickers for all symbols, see for request options and exchange specific required/optional parameters.
///
/// Request info /// Cancellation token - Task> GetSpotTickerAsync(GetTickerRequest request, CancellationToken ct = default); + Task> GetAllTickersAsync(GetTickersRequest request, CancellationToken ct = default); } /// - /// Operation for retrieving a single spot ticker from an exchange via the REST API + /// Operation for retrieving all tickers from an exchange via the REST API. /// - public interface IGetSpotTickerRest : IGetSpotTicker, ISharedRest + public interface IGetAllTickersRest : IGetAllTickers, ISharedRest { /// - new Task> GetSpotTickerAsync(GetTickerRequest request, CancellationToken ct = default); + new Task> GetAllTickersAsync(GetTickersRequest request, CancellationToken ct = default); } } diff --git a/CryptoExchange.Net/SharedApis/V2/Tickers/Spot/GetSpotTicker/GetSpotTickerOptions.cs b/CryptoExchange.Net/SharedApis/V2/Tickers/GetTicker/GetTickerOptions.cs similarity index 77% rename from CryptoExchange.Net/SharedApis/V2/Tickers/Spot/GetSpotTicker/GetSpotTickerOptions.cs rename to CryptoExchange.Net/SharedApis/V2/Tickers/GetTicker/GetTickerOptions.cs index 86734676..1e853b6f 100644 --- a/CryptoExchange.Net/SharedApis/V2/Tickers/Spot/GetSpotTicker/GetSpotTickerOptions.cs +++ b/CryptoExchange.Net/SharedApis/V2/Tickers/GetTicker/GetTickerOptions.cs @@ -5,10 +5,10 @@ namespace CryptoExchange.Net.SharedApis /// /// Options for requesting ticker /// - public class GetSpotTickerOptions : CapabilityOptions + public class GetTickerOptions : CapabilityOptions { /// - public override string Description => "Retrieve price ticker information for a spot symbol"; + public override string Description => "Retrieve price ticker information for a symbol"; private static readonly RequestParameterDescription[] _defaultParameterRules = new[] { @@ -23,7 +23,7 @@ namespace CryptoExchange.Net.SharedApis /// /// ctor /// - public GetSpotTickerOptions(string exchange, SharedTickerType? tickerCalcType = null) : base(exchange, false, nameof(IGetSpotTickerRest.GetSpotTickerAsync), _defaultParameterRules) + public GetTickerOptions(string exchange, SharedTickerType? tickerCalcType = null) : base(exchange, false, nameof(IGetTickerRest.GetTickerAsync), _defaultParameterRules) { TickerType = tickerCalcType ?? SharedTickerType.Day24H; } diff --git a/CryptoExchange.Net/SharedApis/V2/Tickers/Spot/GetAllSpotTickers/IGetAllSpotTickers.cs b/CryptoExchange.Net/SharedApis/V2/Tickers/GetTicker/IGetTicker.cs similarity index 50% rename from CryptoExchange.Net/SharedApis/V2/Tickers/Spot/GetAllSpotTickers/IGetAllSpotTickers.cs rename to CryptoExchange.Net/SharedApis/V2/Tickers/GetTicker/IGetTicker.cs index 03bb6e56..c67fa4a0 100644 --- a/CryptoExchange.Net/SharedApis/V2/Tickers/Spot/GetAllSpotTickers/IGetAllSpotTickers.cs +++ b/CryptoExchange.Net/SharedApis/V2/Tickers/GetTicker/IGetTicker.cs @@ -8,30 +8,30 @@ using System.Threading.Tasks; namespace CryptoExchange.Net.SharedApis { /// - /// Operation for retrieving all spot tickers from an exchange. + /// Operation for retrieving a single ticker from an exchange. /// - public interface IGetAllSpotTickers : ISharedApiCapability + public interface IGetTicker : ISharedApiCapability { /// - /// Spot tickers request options.
+ /// Ticker 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. ///
- GetAllSpotTickersOptions GetAllSpotTickersOptions { get; } + GetTickerOptions GetTickerOptions { get; } /// - /// Get tickers for all spot symbols, see for request options and exchange specific required/optional parameters.
+ /// Get ticker for a specific symbol, see for request options and exchange specific required/optional parameters.
///
/// Request info /// Cancellation token - Task> GetAllSpotTickersAsync(GetTickersRequest request, CancellationToken ct = default); + Task> GetTickerAsync(GetTickerRequest request, CancellationToken ct = default); } /// - /// Operation for retrieving all spot tickers from an exchange via the REST API. + /// Operation for retrieving a single ticker from an exchange via the REST API /// - public interface IGetAllSpotTickersRest : IGetAllSpotTickers, ISharedRest + public interface IGetTickerRest : IGetTicker, ISharedRest { /// - new Task> GetAllSpotTickersAsync(GetTickersRequest request, CancellationToken ct = default); + new Task> GetTickerAsync(GetTickerRequest request, CancellationToken ct = default); } } diff --git a/CryptoExchange.Net/SharedApis/V2/Transfers/GetTransferHistory/GetTransferHistoryOptions.cs b/CryptoExchange.Net/SharedApis/V2/Transfers/GetTransferHistory/GetTransferHistoryOptions.cs new file mode 100644 index 00000000..7a56bc11 --- /dev/null +++ b/CryptoExchange.Net/SharedApis/V2/Transfers/GetTransferHistory/GetTransferHistoryOptions.cs @@ -0,0 +1,58 @@ +using CryptoExchange.Net.Objects; +using System; +using System.Text; + +namespace CryptoExchange.Net.SharedApis +{ + /// + /// Options for requesting transfer history + /// + public class GetTransferHistoryOptions : PaginatedCapabilityOptions + { + /// + public override string Description => "Retrieve spot user trade history"; + + private static readonly RequestParameterDescription[] _defaultParameterRules = new[] + { + RequestParameterRule.Optional(x => x.Asset, "Filter the result set by asset", "ETH"), + RequestParameterRule.Optional(x => x.StartTime, "Filter the result set by start time", DateTime.UtcNow.AddDays(-1)), + RequestParameterRule.Optional(x => x.EndTime, "Filter the result set by end time", DateTime.UtcNow.AddHours(-1)), + RequestParameterRule.Optional(x => x.Limit, "Limit the result set to a maximum number of items", 100), + RequestParameterRule.Optional(x => x.Direction, "The direction in which to retrieve the results", DataDirection.Descending), + }; + + /// + /// ctor + /// + public GetTransferHistoryOptions(string exchange, bool supportsAscending, bool supportsDescending, bool timeFilterSupported, int maxLimit) + : base(exchange, supportsAscending, supportsDescending, timeFilterSupported, maxLimit, true, nameof(IGetTransferHistoryRest.GetTransferHistoryAsync), _defaultParameterRules) + { + } + + /// + public override Error? ValidateRequest(GetTransferHistoryRequest request, IGetTransferHistoryRest client) + { + if (!SupportsAscending && request.Direction == DataDirection.Ascending) + return ArgumentError.Invalid(nameof(GetTransferHistoryRequest.Direction), $"Ascending direction is not supported"); + + if (!SupportsDescending && request.Direction == DataDirection.Descending) + return ArgumentError.Invalid(nameof(GetTransferHistoryRequest.Direction), $"Descending direction is not supported"); + + if (MaxAge.HasValue && request.StartTime < DateTime.UtcNow.Add(-MaxAge.Value)) + return ArgumentError.Invalid(nameof(GetTransferHistoryRequest.StartTime), $"Only the most recent {MaxAge} period data is available"); + + if (!TimePeriodFilterSupport) + { + // When going descending we can still allow startTime filter to limit the results + var now = DateTime.UtcNow; + if ((request.Direction != DataDirection.Descending && request.StartTime != null) + || (request.EndTime != null && now - request.EndTime > TimeSpan.FromSeconds(5))) + { + return ArgumentError.Invalid(nameof(GetTransferHistoryRequest.StartTime), $"Time filter is not supported"); + } + } + + return base.ValidateRequest(request, client); + } + } +} diff --git a/CryptoExchange.Net/SharedApis/V2/Transfers/GetTransferHistory/GetTransferHistoryRequest.cs b/CryptoExchange.Net/SharedApis/V2/Transfers/GetTransferHistory/GetTransferHistoryRequest.cs new file mode 100644 index 00000000..26eff425 --- /dev/null +++ b/CryptoExchange.Net/SharedApis/V2/Transfers/GetTransferHistory/GetTransferHistoryRequest.cs @@ -0,0 +1,55 @@ +using System; + +namespace CryptoExchange.Net.SharedApis +{ + /// + /// Request to retrieve the transfer history of the user + /// + public record GetTransferHistoryRequest : SharedRequest + { + /// + /// Filter by asset + /// + public string? Asset { get; set; } + /// + /// Filter by start time + /// + public DateTime? StartTime { get; } + /// + /// Filter by end time + /// + public DateTime? EndTime { get; } + /// + /// Max number of results + /// + public int? Limit { get; } + /// + /// Data direction + /// + public DataDirection? Direction { get; set; } + + /// + /// ctor + /// + /// Filter by asset + /// Filter by start time + /// Filter by end time + /// Max number of results + /// Data direction + /// Exchange specific parameters + public GetTransferHistoryRequest( + string? asset = null, + DateTime? startTime = null, + DateTime? endTime = null, + int? limit = null, + DataDirection? direction = null, + ExchangeParameters? exchangeParameters = null) : base(null, exchangeParameters) + { + Asset = asset; + StartTime = startTime; + EndTime = endTime; + Limit = limit; + Direction = direction; + } + } +} diff --git a/CryptoExchange.Net/SharedApis/V2/Transfers/GetTransferHistory/IGetTransferHistory.cs b/CryptoExchange.Net/SharedApis/V2/Transfers/GetTransferHistory/IGetTransferHistory.cs new file mode 100644 index 00000000..d03f50db --- /dev/null +++ b/CryptoExchange.Net/SharedApis/V2/Transfers/GetTransferHistory/IGetTransferHistory.cs @@ -0,0 +1,39 @@ +using CryptoExchange.Net.Objects; +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace CryptoExchange.Net.SharedApis +{ + /// + /// Operation for retrieving transfer history from an exchange. + /// + public interface IGetTransferHistory : ISharedApiCapability + { + /// + /// Transfer history 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. + ///
+ GetTransferHistoryOptions GetTransferHistoryOptions { get; } + /// + /// Get transfer history, see for request options and exchange specific required/optional parameters.
+ /// The result is paginated, if there are more results to be retrieved, the property of the result will contain the pagination request to be used for the next request to continue pagination. + ///
+ /// Request info + /// The pagination request from the previous request result property to continue pagination + /// Cancellation token + Task> GetTransferHistoryAsync(GetTransferHistoryRequest request, PageRequest? nextPageToken = null, CancellationToken ct = default); + } + + /// + /// Operation for retrieving transfer history from an exchange via the REST API. + /// + public interface IGetTransferHistoryRest : IGetTransferHistory, ISharedRest + { + /// + new Task> GetTransferHistoryAsync(GetTransferHistoryRequest request, PageRequest? nextPageToken = null, CancellationToken ct = default); + } +} diff --git a/CryptoExchange.Net/SharedApis/V2/TriggerOrders/Futures/PlaceFuturesTriggerOrder/PlaceFuturesTriggerOrderRequest.cs b/CryptoExchange.Net/SharedApis/V2/TriggerOrders/Futures/PlaceFuturesTriggerOrder/PlaceFuturesTriggerOrderRequest.cs index 83559b13..806a4e7a 100644 --- a/CryptoExchange.Net/SharedApis/V2/TriggerOrders/Futures/PlaceFuturesTriggerOrder/PlaceFuturesTriggerOrderRequest.cs +++ b/CryptoExchange.Net/SharedApis/V2/TriggerOrders/Futures/PlaceFuturesTriggerOrder/PlaceFuturesTriggerOrderRequest.cs @@ -53,6 +53,10 @@ /// Trigger price type /// public SharedTriggerPriceType? TriggerPriceType { get; set; } + /// + /// Reduce only flag + /// + public bool? ReduceOnly { get; set; } /// /// ctor