From d4965ad68d3451212b0f06abb5118eadec1b9b25 Mon Sep 17 00:00:00 2001 From: Jkorf Date: Fri, 13 Feb 2026 16:28:26 +0100 Subject: [PATCH] wip --- CryptoExchange.Net/ExchangeHelpers.cs | 254 ++++++++++++++++-- CryptoExchange.Net/Objects/CallResult.cs | 20 +- .../SharedApis/Interfaces/INextPageToken.cs | 226 ++++++++-------- .../Rest/Futures/IFundingRateRestClient.cs | 2 +- .../Rest/Futures/IFuturesOrderRestClient.cs | 4 +- .../Futures/IIndexPriceKlineRestClient.cs | 2 +- .../Rest/Futures/IMarkPriceKlineRestClient.cs | 2 +- .../Futures/IPositionHistoryRestClient.cs | 2 +- .../Interfaces/Rest/IDepositRestClient.cs | 2 +- .../Interfaces/Rest/IKlineRestClient.cs | 2 +- .../Interfaces/Rest/IWithdrawalRestClient .cs | 2 +- .../Rest/Spot/ISpotOrderRestClient.cs | 2 +- .../SharedApis/Models/ExchangeWebResult.cs | 71 +---- .../Endpoints/GetClosedOrdersOptions.cs | 13 +- .../Options/Endpoints/GetDepositsOptions.cs | 13 +- .../Endpoints/GetFundingRateHistoryOptions.cs | 25 +- .../Options/Endpoints/GetKlinesOptions.cs | 10 +- .../Endpoints/GetPositionHistoryOptions.cs | 25 +- .../Endpoints/GetTradeHistoryOptions.cs | 3 +- .../Endpoints/GetWithdrawalsOptions.cs | 13 +- .../Options/Endpoints/PageEndpointOptions.cs | 33 --- .../Endpoints/PaginatedEndpointOptions.cs | 28 +- .../SharedApis/Models/Pagination.cs | 37 +-- .../Models/Rest/GetClosedOrdersRequest.cs | 10 +- .../Models/Rest/GetDepositsRequest.cs | 8 +- .../Rest/GetFundingRateHistoryRequest.cs | 8 +- .../Models/Rest/GetKlinesRequest.cs | 8 +- .../Models/Rest/GetPositionHistoryRequest.cs | 12 +- .../Models/Rest/GetTradeHistoryRequest.cs | 10 +- .../Models/Rest/GetUserTradesRequest.cs | 8 +- .../Models/Rest/GetWithdrawalsRequest.cs | 8 +- 31 files changed, 534 insertions(+), 329 deletions(-) delete mode 100644 CryptoExchange.Net/SharedApis/Models/Options/Endpoints/PageEndpointOptions.cs diff --git a/CryptoExchange.Net/ExchangeHelpers.cs b/CryptoExchange.Net/ExchangeHelpers.cs index fa4dfe0..e8bc445 100644 --- a/CryptoExchange.Net/ExchangeHelpers.cs +++ b/CryptoExchange.Net/ExchangeHelpers.cs @@ -311,11 +311,11 @@ namespace CryptoExchange.Net /// The request parameters /// Cancellation token /// - public static async IAsyncEnumerable> ExecutePages(Func>> paginatedFunc, U request, [EnumeratorCancellation]CancellationToken ct = default) + public static async IAsyncEnumerable> ExecutePages(Func>> paginatedFunc, U request, [EnumeratorCancellation]CancellationToken ct = default) { var result = new List(); ExchangeWebResult batch; - INextPageToken? nextPageToken = null; + PageRequest? nextPageToken = null; while (true) { batch = await paginatedFunc(request, nextPageToken, ct).ConfigureAwait(false); @@ -324,7 +324,7 @@ namespace CryptoExchange.Net break; result.AddRange(batch.Data); - nextPageToken = batch.NextPageToken; + nextPageToken = batch.NextPageRequest; if (nextPageToken == null) break; } @@ -335,9 +335,9 @@ namespace CryptoExchange.Net Func timeSelector, DateTime? startTime, DateTime? endTime, - PageDirection direction) + DataDirection direction) { - if (direction == PageDirection.Ascending) + if (direction == DataDirection.Ascending) data = data.OrderBy(timeSelector); else data = data.OrderByDescending(timeSelector); @@ -357,12 +357,15 @@ namespace CryptoExchange.Net DateTime? startTime, DateTime? endTime, int limit, - PageDirection paginationDirection) + DataDirection paginationDirection) { if (resultCount < limit) return false; - if (paginationDirection == PageDirection.Ascending) + if (!timestamps.Any()) + return false; + + if (paginationDirection == DataDirection.Ascending) { if (timestamps.Max() >= endTime) return false; @@ -382,13 +385,230 @@ namespace CryptoExchange.Net { FromId, Time, + Offset + } + + public enum TimeParameterSetType + { + None, + OnlyMatchingDirection, + Both + } + + // 1.1 Apply moving time filter, set the startTime to new startTime in future (asc) or endTime to new endTime in the past (desc), while setting other time parameter to null + // 1.2 Apply moving time filter, set the startTime to new startTime in future (asc) or endTime to new endTime in the past (desc), set the other time parameter to a max period offset value + // 2. Apply fromId filter, set the fromId to the new fromId (direction depends on id filter direction) + // 3. Apply offset filter, set the offset to the new offset (direction depends on id filter direction) + + + + public static PaginationParameters ApplyFromIdFilter(PageRequest pageRequest) + { + if (pageRequest.FromId == null) + throw new Exception(); + + return new PaginationParameters { FromId = pageRequest.FromId }; + } + + public static PaginationParameters ApplyOffsetFilter(PageRequest pageRequest) + { + if (pageRequest.Offset == null) + throw new Exception(); + + return new PaginationParameters { Offset = pageRequest.Offset }; + } + + public static PaginationParameters ApplyAscendingMovingStartTimeFilter(PageRequest pageRequest) + { + if (pageRequest.StartTime == null) + throw new Exception(); + + return new PaginationParameters + { + StartTime = pageRequest.StartTime, + }; + } + + public static PaginationParameters ApplyDescendingMovingEndTimeFilter(PageRequest pageRequest) + { + if (pageRequest.EndTime == null) + throw new Exception(); + + return new PaginationParameters + { + EndTime = pageRequest.EndTime, + }; + } + + public static PageRequest? GetNextPageRequest( + Func normalNextPageCallback, + int responseLength, + IEnumerable timeSelector, + int limit, + PageRequest? previousPageRequest, + TimeParameterSetType parameterSetType, + DateTime? currentRequestStartTime, + DataDirection direction, + DateTime? requestStartTime, + DateTime? requestEndTime, + TimeSpan? maxTimePeriodPerRequest = null + ) + { + if (CheckForNextPage(responseLength, timeSelector, previousPageRequest?.StartTime ?? requestStartTime, previousPageRequest?.EndTime ?? requestEndTime, limit, direction)) + { + var result = normalNextPageCallback(); + if (parameterSetType == TimeParameterSetType.OnlyMatchingDirection) + { + if (direction == DataDirection.Ascending) + result.StartTime ??= previousPageRequest?.StartTime ?? requestStartTime; + else + result.EndTime ??= previousPageRequest?.EndTime ?? requestEndTime; + } + else if (parameterSetType == TimeParameterSetType.Both) + { + result.StartTime ??= previousPageRequest?.StartTime ?? requestStartTime; + result.EndTime ??= previousPageRequest?.EndTime ?? requestEndTime; + } + + //if (previousPageRequest != null && result.StartTime == null && result.EndTime == null) + //{ + // result.StartTime = previousPageRequest.StartTime; + // result.EndTime = previousPageRequest.EndTime; + //} + + return result; + } + + if (maxTimePeriodPerRequest == null) + return null; + + if (requestEndTime == null) + requestEndTime = DateTime.UtcNow; + +#warning this is only for DESC? + // No next page, for this set, but we might have split for multiple time periods + PageRequest? nextPageRequest = null; + if (requestStartTime.HasValue + && previousPageRequest?.StartTime != requestStartTime + && (requestEndTime - requestStartTime) > maxTimePeriodPerRequest) + { + var currentStartTime = (currentRequestStartTime ?? (requestEndTime.Value.Add(-maxTimePeriodPerRequest.Value))); + var nextPeriod = currentStartTime.Add(-maxTimePeriodPerRequest.Value); + var nextStartTime = nextPeriod < requestStartTime ? requestStartTime : nextPeriod; + if (currentStartTime - nextStartTime > TimeSpan.FromSeconds(1)) + { + nextPageRequest = new PageRequest + { + Offset = 0, + EndTime = currentStartTime, + StartTime = nextStartTime + }; + } + } + + return nextPageRequest; + } + + public static PaginationParameters ApplyPaginationParameters( + DataDirection direction, + PageRequest? pageRequest, + PaginationFilterType? filterTypeAsc, + PaginationFilterType? filterTypeDec, + TimeParameterSetType parameterSetType, + DateTime? requestStartTime, + DateTime? requestEndTime, + TimeSpan? maxTimePeriodPerRequest = null) + { + var filterType = direction == DataDirection.Ascending ? filterTypeAsc : filterTypeDec; + if (filterType == null) + throw new Exception(); + + if (requestEndTime == null) + requestEndTime = DateTime.UtcNow; + + if (pageRequest == null) + { + // No pagination data yet, initial request + var result = new PaginationParameters + { + StartTime = ShouldSet(parameterSetType, direction, true) ? requestStartTime : null, + EndTime = ShouldSet(parameterSetType, direction, false) ? requestEndTime : null + }; + + ApplyMaxTimePeriodPerRequest(maxTimePeriodPerRequest, direction, result); + return result; + } + + if (filterType == PaginationFilterType.FromId) + // From id doesn't need any other parameters + return ApplyFromIdFilter(pageRequest); + + if (filterType == PaginationFilterType.Offset) + { + var result = ApplyOffsetFilter(pageRequest); + result.StartTime = pageRequest.StartTime ?? requestStartTime; + result.EndTime = pageRequest.EndTime ?? requestEndTime; + ApplyMaxTimePeriodPerRequest(maxTimePeriodPerRequest, direction, result); + return result; + } + + if (filterType == PaginationFilterType.Time) + { + var result = direction == DataDirection.Ascending + ? ApplyAscendingMovingStartTimeFilter(pageRequest) + : ApplyDescendingMovingEndTimeFilter(pageRequest); + + if (parameterSetType == TimeParameterSetType.Both) + { + if (direction == DataDirection.Ascending) + result.EndTime = requestEndTime; + else + result.StartTime = requestStartTime; + + ApplyMaxTimePeriodPerRequest(maxTimePeriodPerRequest, direction, result); + } + + return result; + } + + throw new Exception(); + } + + private static void ApplyMaxTimePeriodPerRequest(TimeSpan? maxTimePeriodPerRequest, DataDirection direction, PaginationParameters parameters) + { + if (maxTimePeriodPerRequest != null + && parameters.StartTime.HasValue + && parameters.EndTime.HasValue + && (parameters.EndTime - parameters.StartTime) > maxTimePeriodPerRequest) + { + if (direction == DataDirection.Ascending) + parameters.EndTime = parameters.StartTime.Value.Add(maxTimePeriodPerRequest.Value); + else + parameters.StartTime = parameters.EndTime.Value.Add(-maxTimePeriodPerRequest.Value); + } + } + + private static bool ShouldSet(TimeParameterSetType type, DataDirection direction, bool startTime) + { + if (type == TimeParameterSetType.None) + return false; + + if (type == TimeParameterSetType.Both) + return true; + + if (direction == DataDirection.Ascending) + // If ascending startTime is the moving + return startTime; + + // If descending startTime is the opposite + return !startTime; } public static (DateTime? startTime, DateTime? endTime, long? fromId) ApplyPaginationRequestFilters( PaginationFilterType? ascendingFilterType, PaginationFilterType? descendingFilterType, - PageDirection defaultDirection, - PageDirection requestDirection, + DataDirection defaultDirection, + DataDirection requestDirection, DateTime? userFilterStartTime, DateTime? userFilterEndTime, DateTime? paginationStartTime, @@ -396,10 +616,10 @@ namespace CryptoExchange.Net TimeSpan? maxTimePeriod, string? paginationFromId) { - if (requestDirection == PageDirection.Ascending && userFilterStartTime == null) + if (requestDirection == DataDirection.Ascending && userFilterStartTime == null) throw new InvalidOperationException("Ascending without start time"); - var filterType = requestDirection == PageDirection.Ascending ? ascendingFilterType : descendingFilterType; + var filterType = requestDirection == DataDirection.Ascending ? ascendingFilterType : descendingFilterType; if (filterType == PaginationFilterType.FromId) { long? fromId = ApplyFromId(paginationFromId); @@ -410,7 +630,7 @@ namespace CryptoExchange.Net && fromId == null && startTime == null) { - if (requestDirection == PageDirection.Ascending) + if (requestDirection == DataDirection.Ascending) { // If user requests in ASC order but the default is DESC order and user provides no parameters // set startTime to a specific date to search data from that time forward @@ -437,19 +657,19 @@ namespace CryptoExchange.Net if (fromId == null && startTime != null && endTime != null) { // If we're not filtering by fromId we don't want to specify bot start and end time to prevent limitations in time period - if (requestDirection == PageDirection.Ascending) endTime = null; - if (requestDirection == PageDirection.Descending) startTime = null; + if (requestDirection == DataDirection.Ascending) endTime = null; + if (requestDirection == DataDirection.Descending) startTime = null; } return (startTime, endTime, fromId); } else // Time { - DateTime? startTime = requestDirection == PageDirection.Descending ? null : ApplyTime(userFilterStartTime, paginationStartTime); - DateTime? endTime = (requestDirection == PageDirection.Ascending && paginationStartTime != null) ? null : ApplyTime(userFilterEndTime, paginationEndTime); + DateTime? startTime = requestDirection == DataDirection.Descending ? null : ApplyTime(userFilterStartTime, paginationStartTime); + DateTime? endTime = (requestDirection == DataDirection.Ascending && paginationStartTime != null) ? null : ApplyTime(userFilterEndTime, paginationEndTime); if (maxTimePeriod.HasValue && endTime - startTime > maxTimePeriod.Value) { - if (requestDirection == PageDirection.Ascending) + if (requestDirection == DataDirection.Ascending) endTime = startTime.Value.Add(maxTimePeriod.Value); else startTime = endTime.Value.Add(-maxTimePeriod.Value); diff --git a/CryptoExchange.Net/Objects/CallResult.cs b/CryptoExchange.Net/Objects/CallResult.cs index 59f97d7..8f64505 100644 --- a/CryptoExchange.Net/Objects/CallResult.cs +++ b/CryptoExchange.Net/Objects/CallResult.cs @@ -519,7 +519,7 @@ namespace CryptoExchange.Net.Objects /// The exchange /// Trade modes the result applies to /// - public ExchangeWebResult AsExchangeResult(string exchange, TradingMode[] tradeModes) + public ExchangeWebResult AsExchangeResult(string exchange, TradingMode[]? tradeModes) { return new ExchangeWebResult(exchange, tradeModes, this); } @@ -533,25 +533,11 @@ namespace CryptoExchange.Net.Objects /// Data /// Next page token /// - public ExchangeWebResult AsExchangeResult(string exchange, TradingMode tradeMode, [AllowNull] K data, INextPageToken? nextPageToken = null) + public ExchangeWebResult AsExchangeResult(string exchange, TradingMode tradeMode, [AllowNull] K data, PageRequest? nextPageToken = null) { return new ExchangeWebResult(exchange, tradeMode, As(data), nextPageToken); } - /// - /// Copy the WebCallResult to an ExchangeWebResult of a new data type - /// - /// The new type - /// The exchange - /// Trade mode the result applies to - /// Data - /// Next page token - /// - public ExchangeWebResult AsExchangeResult(string exchange, TradingMode tradeMode, [AllowNull] K data, PageRequest? nextPageRequest) - { - return new ExchangeWebResult(exchange, tradeMode, As(data), nextPageRequest); - } - /// /// Copy the WebCallResult to an ExchangeWebResult of a new data type /// @@ -561,7 +547,7 @@ namespace CryptoExchange.Net.Objects /// Data /// Next page token /// - public ExchangeWebResult AsExchangeResult(string exchange, TradingMode[]? tradeModes, [AllowNull] K data, INextPageToken? nextPageToken = null) + public ExchangeWebResult AsExchangeResult(string exchange, TradingMode[]? tradeModes, [AllowNull] K data, PageRequest? nextPageToken = null) { return new ExchangeWebResult(exchange, tradeModes, As(data), nextPageToken); } diff --git a/CryptoExchange.Net/SharedApis/Interfaces/INextPageToken.cs b/CryptoExchange.Net/SharedApis/Interfaces/INextPageToken.cs index 6f5df99..ded984e 100644 --- a/CryptoExchange.Net/SharedApis/Interfaces/INextPageToken.cs +++ b/CryptoExchange.Net/SharedApis/Interfaces/INextPageToken.cs @@ -1,131 +1,131 @@ -using System; +//using System; -namespace CryptoExchange.Net.SharedApis -{ - /// - /// A token which a request can use to retrieve the next page if there are more pages in the result set - /// - public interface INextPageToken - { +//namespace CryptoExchange.Net.SharedApis +//{ +// /// +// /// A token which a request can use to retrieve the next page if there are more pages in the result set +// /// +// public interface INextPageToken +// { - } +// } - /// - /// A datetime offset token - /// - public record DateTimeToken: INextPageToken - { - /// - /// Last result time - /// - public DateTime LastTime { get; set; } +// /// +// /// A datetime offset token +// /// +// public record DateTimeToken: INextPageToken +// { +// /// +// /// Last result time +// /// +// public DateTime LastTime { get; set; } - /// - /// ctor - /// - public DateTimeToken(DateTime timestamp) - { - LastTime = timestamp; - } +// /// +// /// ctor +// /// +// public DateTimeToken(DateTime timestamp) +// { +// LastTime = timestamp; +// } - public DateTimeToken GetNextToken(DateTime nextTime) => this with { LastTime = nextTime }; - } +// public DateTimeToken GetNextToken(DateTime nextTime) => this with { LastTime = nextTime }; +// } - /// - /// A current page index token - /// - public record PageToken: INextPageToken - { - /// - /// The next page index - /// - public int Page { get; set; } - /// - /// Page size - /// - public int PageSize { get; set; } +// /// +// /// A current page index token +// /// +// public record PageToken: INextPageToken +// { +// /// +// /// The next page index +// /// +// public int Page { get; set; } +// /// +// /// Page size +// /// +// public int PageSize { get; set; } - /// - /// ctor - /// - public PageToken(int page, int pageSize) - { - Page = page; - PageSize = pageSize; - } +// /// +// /// ctor +// /// +// public PageToken(int page, int pageSize) +// { +// Page = page; +// PageSize = pageSize; +// } - public PageToken GetNextToken() => this with { Page = Page + 1 }; - } +// public PageToken GetNextToken() => this with { Page = Page + 1 }; +// } - /// - /// A id offset token - /// - public record FromIdToken : INextPageToken - { - /// - /// The last id from previous result - /// - public string FromToken { get; set; } +// /// +// /// A id offset token +// /// +// public record FromIdToken : INextPageToken +// { +// /// +// /// The last id from previous result +// /// +// public string FromToken { get; set; } - /// - /// ctor - /// - public FromIdToken(string fromToken) - { - FromToken = fromToken; - } +// /// +// /// ctor +// /// +// public FromIdToken(string fromToken) +// { +// FromToken = fromToken; +// } - /// - /// ctor - /// - public FromIdToken(long fromToken) - { - FromToken = fromToken.ToString(); - } +// /// +// /// ctor +// /// +// public FromIdToken(long fromToken) +// { +// FromToken = fromToken.ToString(); +// } - public FromIdToken GetNextToken(string nextToken) => this with { FromToken = nextToken }; - public FromIdToken GetNextToken(long nextToken) => this with { FromToken = nextToken.ToString() }; - } +// public FromIdToken GetNextToken(string nextToken) => this with { FromToken = nextToken }; +// public FromIdToken GetNextToken(long nextToken) => this with { FromToken = nextToken.ToString() }; +// } - /// - /// A cursor token - /// - public record CursorToken : INextPageToken - { - /// - /// The next page cursor - /// - public string Cursor { get; set; } +// /// +// /// A cursor token +// /// +// public record CursorToken : INextPageToken +// { +// /// +// /// The next page cursor +// /// +// public string Cursor { get; set; } - /// - /// ctor - /// - public CursorToken(string cursor) - { - Cursor = cursor; - } +// /// +// /// ctor +// /// +// public CursorToken(string cursor) +// { +// Cursor = cursor; +// } - public CursorToken GetNextToken(string nextCursor) => this with { Cursor = nextCursor }; - } +// public CursorToken GetNextToken(string nextCursor) => this with { Cursor = nextCursor }; +// } - /// - /// A result offset token - /// - public record OffsetToken : INextPageToken - { - /// - /// Offset in the result set - /// - public int Offset { get; set; } +// /// +// /// A result offset token +// /// +// public record OffsetToken : INextPageToken +// { +// /// +// /// Offset in the result set +// /// +// public int Offset { get; set; } - /// - /// ctor - /// - public OffsetToken(int offset) - { - Offset = offset; - } +// /// +// /// ctor +// /// +// public OffsetToken(int offset) +// { +// Offset = offset; +// } - public OffsetToken GetNextToken() => this with { Offset = Offset + Offset }; - } -} +// public OffsetToken GetNextToken() => this with { Offset = Offset + Offset }; +// } +//} diff --git a/CryptoExchange.Net/SharedApis/Interfaces/Rest/Futures/IFundingRateRestClient.cs b/CryptoExchange.Net/SharedApis/Interfaces/Rest/Futures/IFundingRateRestClient.cs index 057cb36..a45ab29 100644 --- a/CryptoExchange.Net/SharedApis/Interfaces/Rest/Futures/IFundingRateRestClient.cs +++ b/CryptoExchange.Net/SharedApis/Interfaces/Rest/Futures/IFundingRateRestClient.cs @@ -18,6 +18,6 @@ namespace CryptoExchange.Net.SharedApis /// Request info /// The pagination token from the previous request to continue pagination /// Cancellation token - Task> GetFundingRateHistoryAsync(GetFundingRateHistoryRequest request, INextPageToken? nextPageToken = null, CancellationToken ct = default); + Task> GetFundingRateHistoryAsync(GetFundingRateHistoryRequest request, PageRequest? nextPageToken = null, CancellationToken ct = default); } } diff --git a/CryptoExchange.Net/SharedApis/Interfaces/Rest/Futures/IFuturesOrderRestClient.cs b/CryptoExchange.Net/SharedApis/Interfaces/Rest/Futures/IFuturesOrderRestClient.cs index 5c3af62..30f9030 100644 --- a/CryptoExchange.Net/SharedApis/Interfaces/Rest/Futures/IFuturesOrderRestClient.cs +++ b/CryptoExchange.Net/SharedApis/Interfaces/Rest/Futures/IFuturesOrderRestClient.cs @@ -80,7 +80,7 @@ namespace CryptoExchange.Net.SharedApis /// Request info /// The pagination token from the previous request to continue pagination /// Cancellation token - Task> GetClosedFuturesOrdersAsync(GetClosedOrdersRequest request, INextPageToken? nextPageToken = null, CancellationToken ct = default); + Task> GetClosedFuturesOrdersAsync(GetClosedOrdersRequest request, PageRequest? nextPageToken = null, CancellationToken ct = default); /// /// Futures get order trades request options @@ -103,7 +103,7 @@ namespace CryptoExchange.Net.SharedApis /// Request info /// The pagination token from the previous request to continue pagination /// Cancellation token - Task> GetFuturesUserTradesAsync(GetUserTradesRequest request, INextPageToken? nextPageToken = null, CancellationToken ct = default); + Task> GetFuturesUserTradesAsync(GetUserTradesRequest request, PageRequest? nextPageToken = null, CancellationToken ct = default); /// /// Futures cancel order request options diff --git a/CryptoExchange.Net/SharedApis/Interfaces/Rest/Futures/IIndexPriceKlineRestClient.cs b/CryptoExchange.Net/SharedApis/Interfaces/Rest/Futures/IIndexPriceKlineRestClient.cs index 4c2299f..1f0b5e3 100644 --- a/CryptoExchange.Net/SharedApis/Interfaces/Rest/Futures/IIndexPriceKlineRestClient.cs +++ b/CryptoExchange.Net/SharedApis/Interfaces/Rest/Futures/IIndexPriceKlineRestClient.cs @@ -18,6 +18,6 @@ namespace CryptoExchange.Net.SharedApis /// Request info /// The pagination token from the previous request to continue pagination /// Cancellation token - Task> GetIndexPriceKlinesAsync(GetKlinesRequest request, INextPageToken? nextPageToken = null, CancellationToken ct = default); + Task> GetIndexPriceKlinesAsync(GetKlinesRequest request, PageRequest? nextPageToken = null, CancellationToken ct = default); } } diff --git a/CryptoExchange.Net/SharedApis/Interfaces/Rest/Futures/IMarkPriceKlineRestClient.cs b/CryptoExchange.Net/SharedApis/Interfaces/Rest/Futures/IMarkPriceKlineRestClient.cs index 0b02528..2581eae 100644 --- a/CryptoExchange.Net/SharedApis/Interfaces/Rest/Futures/IMarkPriceKlineRestClient.cs +++ b/CryptoExchange.Net/SharedApis/Interfaces/Rest/Futures/IMarkPriceKlineRestClient.cs @@ -18,6 +18,6 @@ namespace CryptoExchange.Net.SharedApis /// Request info /// The pagination token from the previous request to continue pagination /// Cancellation token - Task> GetMarkPriceKlinesAsync(GetKlinesRequest request, INextPageToken? nextPageToken = null, CancellationToken ct = default); + Task> GetMarkPriceKlinesAsync(GetKlinesRequest request, PageRequest? nextPageToken = null, CancellationToken ct = default); } } diff --git a/CryptoExchange.Net/SharedApis/Interfaces/Rest/Futures/IPositionHistoryRestClient.cs b/CryptoExchange.Net/SharedApis/Interfaces/Rest/Futures/IPositionHistoryRestClient.cs index 5905927..2db7a42 100644 --- a/CryptoExchange.Net/SharedApis/Interfaces/Rest/Futures/IPositionHistoryRestClient.cs +++ b/CryptoExchange.Net/SharedApis/Interfaces/Rest/Futures/IPositionHistoryRestClient.cs @@ -18,6 +18,6 @@ namespace CryptoExchange.Net.SharedApis /// Request info /// The pagination token from the previous request to continue pagination /// Cancellation token - Task> GetPositionHistoryAsync(GetPositionHistoryRequest request, INextPageToken? nextPageToken = null, CancellationToken ct = default); + Task> GetPositionHistoryAsync(GetPositionHistoryRequest request, PageRequest? nextPageToken = null, CancellationToken ct = default); } } diff --git a/CryptoExchange.Net/SharedApis/Interfaces/Rest/IDepositRestClient.cs b/CryptoExchange.Net/SharedApis/Interfaces/Rest/IDepositRestClient.cs index c50758e..9b2df8a 100644 --- a/CryptoExchange.Net/SharedApis/Interfaces/Rest/IDepositRestClient.cs +++ b/CryptoExchange.Net/SharedApis/Interfaces/Rest/IDepositRestClient.cs @@ -33,6 +33,6 @@ namespace CryptoExchange.Net.SharedApis /// The pagination token from the previous request to continue pagination /// Cancellation token /// - Task> GetDepositsAsync(GetDepositsRequest request, INextPageToken? nextPageToken = null, CancellationToken ct = default); + Task> GetDepositsAsync(GetDepositsRequest request, PageRequest? nextPageToken = null, CancellationToken ct = default); } } diff --git a/CryptoExchange.Net/SharedApis/Interfaces/Rest/IKlineRestClient.cs b/CryptoExchange.Net/SharedApis/Interfaces/Rest/IKlineRestClient.cs index a71ac1e..388ecb2 100644 --- a/CryptoExchange.Net/SharedApis/Interfaces/Rest/IKlineRestClient.cs +++ b/CryptoExchange.Net/SharedApis/Interfaces/Rest/IKlineRestClient.cs @@ -20,6 +20,6 @@ namespace CryptoExchange.Net.SharedApis /// The pagination token from the previous request to continue pagination /// Cancellation token /// - Task> GetKlinesAsync(GetKlinesRequest request, INextPageToken? nextPageToken = null, CancellationToken ct = default); + Task> GetKlinesAsync(GetKlinesRequest request, PageRequest? nextPageToken = null, CancellationToken ct = default); } } diff --git a/CryptoExchange.Net/SharedApis/Interfaces/Rest/IWithdrawalRestClient .cs b/CryptoExchange.Net/SharedApis/Interfaces/Rest/IWithdrawalRestClient .cs index c2f3600..2f511e3 100644 --- a/CryptoExchange.Net/SharedApis/Interfaces/Rest/IWithdrawalRestClient .cs +++ b/CryptoExchange.Net/SharedApis/Interfaces/Rest/IWithdrawalRestClient .cs @@ -20,6 +20,6 @@ namespace CryptoExchange.Net.SharedApis /// The pagination token from the previous request to continue pagination /// Cancellation token /// - Task> GetWithdrawalsAsync(GetWithdrawalsRequest request, INextPageToken? nextPageToken = null, CancellationToken ct = default); + Task> GetWithdrawalsAsync(GetWithdrawalsRequest request, PageRequest? nextPageToken = null, CancellationToken ct = default); } } diff --git a/CryptoExchange.Net/SharedApis/Interfaces/Rest/Spot/ISpotOrderRestClient.cs b/CryptoExchange.Net/SharedApis/Interfaces/Rest/Spot/ISpotOrderRestClient.cs index 0d3a8d5..4ad5c22 100644 --- a/CryptoExchange.Net/SharedApis/Interfaces/Rest/Spot/ISpotOrderRestClient.cs +++ b/CryptoExchange.Net/SharedApis/Interfaces/Rest/Spot/ISpotOrderRestClient.cs @@ -102,7 +102,7 @@ namespace CryptoExchange.Net.SharedApis /// Request info /// The pagination token from the previous request to continue pagination /// Cancellation token - Task> GetSpotUserTradesAsync(GetUserTradesRequest request, INextPageToken? nextPageToken = null, CancellationToken ct = default); + Task> GetSpotUserTradesAsync(GetUserTradesRequest request, PageRequest? nextPageToken = null, CancellationToken ct = default); /// /// Spot cancel order request options diff --git a/CryptoExchange.Net/SharedApis/Models/ExchangeWebResult.cs b/CryptoExchange.Net/SharedApis/Models/ExchangeWebResult.cs index cb942a1..abeeee4 100644 --- a/CryptoExchange.Net/SharedApis/Models/ExchangeWebResult.cs +++ b/CryptoExchange.Net/SharedApis/Models/ExchangeWebResult.cs @@ -23,11 +23,6 @@ namespace CryptoExchange.Net.SharedApis /// public TradingMode[]? DataTradeMode { get; } - /// - /// Token to retrieve the next page with - /// - public INextPageToken? NextPageToken { get; } - /// /// /// @@ -51,63 +46,7 @@ namespace CryptoExchange.Net.SharedApis string exchange, TradingMode dataTradeMode, WebCallResult result, - INextPageToken? nextPageToken = null) : - base(result.ResponseStatusCode, - result.HttpVersion, - result.ResponseHeaders, - result.ResponseTime, - result.ResponseLength, - result.OriginalData, - result.RequestId, - result.RequestUrl, - result.RequestBody, - result.RequestMethod, - result.RequestHeaders, - result.DataSource, - result.Data, - result.Error) - { - DataTradeMode = new[] { dataTradeMode }; - Exchange = exchange; - NextPageToken = nextPageToken; - } - - /// - /// ctor - /// - public ExchangeWebResult( - string exchange, - TradingMode[]? dataTradeModes, - WebCallResult result, - INextPageToken? nextPageToken = null) : - base(result.ResponseStatusCode, - result.HttpVersion, - result.ResponseHeaders, - result.ResponseTime, - result.ResponseLength, - result.OriginalData, - result.RequestId, - result.RequestUrl, - result.RequestBody, - result.RequestMethod, - result.RequestHeaders, - result.DataSource, - result.Data, - result.Error) - { - DataTradeMode = dataTradeModes; - Exchange = exchange; - NextPageToken = nextPageToken; - } - - /// - /// ctor - /// - public ExchangeWebResult( - string exchange, - TradingMode dataTradeMode, - WebCallResult result, - PageRequest? nextPageToken) : + PageRequest? nextPageToken = null) : base(result.ResponseStatusCode, result.HttpVersion, result.ResponseHeaders, @@ -135,7 +74,7 @@ namespace CryptoExchange.Net.SharedApis string exchange, TradingMode[]? dataTradeModes, WebCallResult result, - PageRequest? nextPageRequest) : + PageRequest? nextPageRequest = null) : base(result.ResponseStatusCode, result.HttpVersion, result.ResponseHeaders, @@ -176,7 +115,7 @@ namespace CryptoExchange.Net.SharedApis ResultDataSource dataSource, [AllowNull] T data, Error? error, - INextPageToken? nextPageToken = null) : base( + PageRequest? nextPageToken = null) : base( code, httpVersion, responseHeaders, @@ -194,7 +133,7 @@ namespace CryptoExchange.Net.SharedApis { DataTradeMode = dataTradeModes; Exchange = exchange; - NextPageToken = nextPageToken; + NextPageRequest = nextPageToken; } /// @@ -205,7 +144,7 @@ namespace CryptoExchange.Net.SharedApis /// public new ExchangeWebResult As([AllowNull] K data) { - return new ExchangeWebResult(Exchange, DataTradeMode, ResponseStatusCode, HttpVersion, ResponseHeaders, ResponseTime, ResponseLength, OriginalData, RequestId, RequestUrl, RequestBody, RequestMethod, RequestHeaders, DataSource, data, Error, NextPageToken); + return new ExchangeWebResult(Exchange, DataTradeMode, ResponseStatusCode, HttpVersion, ResponseHeaders, ResponseTime, ResponseLength, OriginalData, RequestId, RequestUrl, RequestBody, RequestMethod, RequestHeaders, DataSource, data, Error, NextPageRequest); } /// diff --git a/CryptoExchange.Net/SharedApis/Models/Options/Endpoints/GetClosedOrdersOptions.cs b/CryptoExchange.Net/SharedApis/Models/Options/Endpoints/GetClosedOrdersOptions.cs index 114a15e..6332398 100644 --- a/CryptoExchange.Net/SharedApis/Models/Options/Endpoints/GetClosedOrdersOptions.cs +++ b/CryptoExchange.Net/SharedApis/Models/Options/Endpoints/GetClosedOrdersOptions.cs @@ -8,23 +8,18 @@ namespace CryptoExchange.Net.SharedApis /// public class GetClosedOrdersOptions : PaginatedEndpointOptions { - /// - /// Whether the start/end time filter is supported - /// - public bool TimeFilterSupported { get; set; } - /// /// ctor /// - public GetClosedOrdersOptions(SharedPaginationSupport paginationType, bool timeFilterSupported, int maxLimit) : base(timeFilterSupported, maxLimit, true) + public GetClosedOrdersOptions(bool supportsAscending, bool supportsDescending, bool timeFilterSupported, int maxLimit) + : base(supportsAscending, supportsDescending, timeFilterSupported, maxLimit, true) { - TimeFilterSupported = timeFilterSupported; } /// public override Error? ValidateRequest(string exchange, GetClosedOrdersRequest request, TradingMode? tradingMode, TradingMode[] supportedApiTypes) { - if (!TimeFilterSupported && request.StartTime != null) + if (!TimePeriodFilterSupport && request.StartTime != null) return ArgumentError.Invalid(nameof(GetClosedOrdersRequest.StartTime), $"Time filter is not supported"); return base.ValidateRequest(exchange, request, tradingMode, supportedApiTypes); @@ -34,7 +29,7 @@ namespace CryptoExchange.Net.SharedApis public override string ToString(string exchange) { var sb = new StringBuilder(base.ToString(exchange)); - sb.AppendLine($"Time filter supported: {TimeFilterSupported}"); + sb.AppendLine($"Time filter supported: {TimePeriodFilterSupport}"); return sb.ToString(); } } diff --git a/CryptoExchange.Net/SharedApis/Models/Options/Endpoints/GetDepositsOptions.cs b/CryptoExchange.Net/SharedApis/Models/Options/Endpoints/GetDepositsOptions.cs index 22283a9..17e0ce5 100644 --- a/CryptoExchange.Net/SharedApis/Models/Options/Endpoints/GetDepositsOptions.cs +++ b/CryptoExchange.Net/SharedApis/Models/Options/Endpoints/GetDepositsOptions.cs @@ -8,23 +8,18 @@ namespace CryptoExchange.Net.SharedApis /// public class GetDepositsOptions : PaginatedEndpointOptions { - /// - /// Whether the start/end time filter is supported - /// - public bool TimeFilterSupported { get; set; } - /// /// ctor /// - public GetDepositsOptions(SharedPaginationSupport paginationType, bool timeFilterSupported, int maxLimit) : base(timeFilterSupported, maxLimit, true) + public GetDepositsOptions(bool supportsAscending, bool supportsDescending, bool timeFilterSupported, int maxLimit) + : base(supportsAscending, supportsDescending, timeFilterSupported, maxLimit, true) { - TimeFilterSupported = timeFilterSupported; } /// public override Error? ValidateRequest(string exchange, GetDepositsRequest request, TradingMode? tradingMode, TradingMode[] supportedApiTypes) { - if (!TimeFilterSupported && request.StartTime != null) + if (!TimePeriodFilterSupport && request.StartTime != null) return ArgumentError.Invalid(nameof(GetDepositsRequest.StartTime), $"Time filter is not supported"); return base.ValidateRequest(exchange, request, tradingMode, supportedApiTypes); @@ -34,7 +29,7 @@ namespace CryptoExchange.Net.SharedApis public override string ToString(string exchange) { var sb = new StringBuilder(base.ToString(exchange)); - sb.AppendLine($"Time filter supported: {TimeFilterSupported}"); + sb.AppendLine($"Time filter supported: {TimePeriodFilterSupport}"); return sb.ToString(); } } diff --git a/CryptoExchange.Net/SharedApis/Models/Options/Endpoints/GetFundingRateHistoryOptions.cs b/CryptoExchange.Net/SharedApis/Models/Options/Endpoints/GetFundingRateHistoryOptions.cs index 61686b9..bc7fded 100644 --- a/CryptoExchange.Net/SharedApis/Models/Options/Endpoints/GetFundingRateHistoryOptions.cs +++ b/CryptoExchange.Net/SharedApis/Models/Options/Endpoints/GetFundingRateHistoryOptions.cs @@ -1,4 +1,7 @@ -namespace CryptoExchange.Net.SharedApis +using CryptoExchange.Net.Objects; +using System.Text; + +namespace CryptoExchange.Net.SharedApis { /// /// Options for requesting funding rate history @@ -8,8 +11,26 @@ /// /// ctor /// - public GetFundingRateHistoryOptions(SharedPaginationSupport paginationType, bool timeFilterSupported, int maxLimit, bool needsAuthentication) : base(timeFilterSupported, maxLimit, needsAuthentication) + public GetFundingRateHistoryOptions(bool supportsAscending, bool supportsDescending, bool timeFilterSupported, int maxLimit, bool needsAuthentication) + : base(supportsAscending, supportsDescending, timeFilterSupported, maxLimit, needsAuthentication) { } + + /// + public override Error? ValidateRequest(string exchange, GetFundingRateHistoryRequest request, TradingMode? tradingMode, TradingMode[] supportedApiTypes) + { + if (!TimePeriodFilterSupport && request.StartTime != null) + return ArgumentError.Invalid(nameof(GetDepositsRequest.StartTime), $"Time filter is not supported"); + + return base.ValidateRequest(exchange, request, tradingMode, supportedApiTypes); + } + + /// + public override string ToString(string exchange) + { + var sb = new StringBuilder(base.ToString(exchange)); + sb.AppendLine($"Time filter supported: {TimePeriodFilterSupport}"); + return sb.ToString(); + } } } diff --git a/CryptoExchange.Net/SharedApis/Models/Options/Endpoints/GetKlinesOptions.cs b/CryptoExchange.Net/SharedApis/Models/Options/Endpoints/GetKlinesOptions.cs index 3d54a8e..c42d11c 100644 --- a/CryptoExchange.Net/SharedApis/Models/Options/Endpoints/GetKlinesOptions.cs +++ b/CryptoExchange.Net/SharedApis/Models/Options/Endpoints/GetKlinesOptions.cs @@ -26,7 +26,8 @@ namespace CryptoExchange.Net.SharedApis /// /// ctor /// - public GetKlinesOptions(SharedPaginationSupport paginationType, bool timeFilterSupported, int maxLimit, bool needsAuthentication) : base(timeFilterSupported, maxLimit, needsAuthentication) + public GetKlinesOptions(bool supportsAscending, bool supportsDescending, bool timeFilterSupported, int maxLimit, bool needsAuthentication) + : base(supportsAscending, supportsDescending, timeFilterSupported, maxLimit, needsAuthentication) { SupportIntervals = new[] { @@ -50,7 +51,8 @@ namespace CryptoExchange.Net.SharedApis /// /// ctor /// - public GetKlinesOptions(SharedPaginationSupport paginationType, bool timeFilterSupported, int maxLimit, bool needsAuthentication, params SharedKlineInterval[] intervals) : base(timeFilterSupported, maxLimit, needsAuthentication) + public GetKlinesOptions(bool supportsAscending, bool supportsDescending, bool timeFilterSupported, int maxLimit, bool needsAuthentication, params SharedKlineInterval[] intervals) + : base(supportsAscending, supportsDescending, timeFilterSupported, maxLimit, needsAuthentication) { SupportIntervals = intervals; } @@ -68,6 +70,9 @@ namespace CryptoExchange.Net.SharedApis if (!IsSupported(request.Interval)) return ArgumentError.Invalid(nameof(GetKlinesRequest.Interval), "Interval not supported"); + if (!TimePeriodFilterSupport && request.StartTime != null) + return ArgumentError.Invalid(nameof(GetDepositsRequest.StartTime), $"Time filter is not supported"); + if (MaxAge.HasValue && request.StartTime < DateTime.UtcNow.Add(-MaxAge.Value)) return ArgumentError.Invalid(nameof(GetKlinesRequest.StartTime), $"Only the most recent {MaxAge} klines are available"); @@ -93,6 +98,7 @@ namespace CryptoExchange.Net.SharedApis public override string ToString(string exchange) { var sb = new StringBuilder(base.ToString(exchange)); + sb.AppendLine($"Time filter supported: {TimePeriodFilterSupport}"); sb.AppendLine($"Supported SharedKlineInterval values: {string.Join(", ", SupportIntervals)}"); if (MaxAge != null) sb.AppendLine($"Max age of data: {MaxAge}"); diff --git a/CryptoExchange.Net/SharedApis/Models/Options/Endpoints/GetPositionHistoryOptions.cs b/CryptoExchange.Net/SharedApis/Models/Options/Endpoints/GetPositionHistoryOptions.cs index a1976d2..4d5ccbe 100644 --- a/CryptoExchange.Net/SharedApis/Models/Options/Endpoints/GetPositionHistoryOptions.cs +++ b/CryptoExchange.Net/SharedApis/Models/Options/Endpoints/GetPositionHistoryOptions.cs @@ -1,4 +1,7 @@ -namespace CryptoExchange.Net.SharedApis +using CryptoExchange.Net.Objects; +using System.Text; + +namespace CryptoExchange.Net.SharedApis { /// /// Options for requesting position history @@ -8,8 +11,26 @@ /// /// ctor /// - public GetPositionHistoryOptions(SharedPaginationSupport paginationType, bool timeFilterSupported, int maxLimit) : base(timeFilterSupported, maxLimit, true) + public GetPositionHistoryOptions(bool supportsAscending, bool supportsDescending, bool timeFilterSupported, int maxLimit) + : base(supportsAscending, supportsDescending, timeFilterSupported, maxLimit, true) { } + + /// + public override Error? ValidateRequest(string exchange, GetPositionHistoryRequest request, TradingMode? tradingMode, TradingMode[] supportedApiTypes) + { + if (!TimePeriodFilterSupport && request.StartTime != null) + return ArgumentError.Invalid(nameof(GetDepositsRequest.StartTime), $"Time filter is not supported"); + + return base.ValidateRequest(exchange, request, tradingMode, supportedApiTypes); + } + + /// + public override string ToString(string exchange) + { + var sb = new StringBuilder(base.ToString(exchange)); + sb.AppendLine($"Time filter supported: {TimePeriodFilterSupport}"); + return sb.ToString(); + } } } diff --git a/CryptoExchange.Net/SharedApis/Models/Options/Endpoints/GetTradeHistoryOptions.cs b/CryptoExchange.Net/SharedApis/Models/Options/Endpoints/GetTradeHistoryOptions.cs index 00e26d0..805e44f 100644 --- a/CryptoExchange.Net/SharedApis/Models/Options/Endpoints/GetTradeHistoryOptions.cs +++ b/CryptoExchange.Net/SharedApis/Models/Options/Endpoints/GetTradeHistoryOptions.cs @@ -17,7 +17,8 @@ namespace CryptoExchange.Net.SharedApis /// /// ctor /// - public GetTradeHistoryOptions(bool timeFilterSupported, int maxLimit, bool needsAuthentication) : base(timeFilterSupported, maxLimit, needsAuthentication) + public GetTradeHistoryOptions(bool supportsAscending, bool supportsDescending, bool timeFilterSupported, int maxLimit, bool needsAuthentication) + : base(supportsAscending, supportsDescending, timeFilterSupported, maxLimit, needsAuthentication) { } diff --git a/CryptoExchange.Net/SharedApis/Models/Options/Endpoints/GetWithdrawalsOptions.cs b/CryptoExchange.Net/SharedApis/Models/Options/Endpoints/GetWithdrawalsOptions.cs index 2dbc838..e95de79 100644 --- a/CryptoExchange.Net/SharedApis/Models/Options/Endpoints/GetWithdrawalsOptions.cs +++ b/CryptoExchange.Net/SharedApis/Models/Options/Endpoints/GetWithdrawalsOptions.cs @@ -8,23 +8,18 @@ namespace CryptoExchange.Net.SharedApis /// public class GetWithdrawalsOptions : PaginatedEndpointOptions { - /// - /// Whether the start/end time filter is supported - /// - public bool TimeFilterSupported { get; set; } - /// /// ctor /// - public GetWithdrawalsOptions(SharedPaginationSupport paginationType, bool timeFilterSupported, int maxLimit) : base(timeFilterSupported, maxLimit, true) + public GetWithdrawalsOptions(bool supportsAscending, bool supportsDescending, bool timeFilterSupported, int maxLimit) + : base(supportsAscending, supportsDescending, timeFilterSupported, maxLimit, true) { - TimeFilterSupported = timeFilterSupported; } /// public override Error? ValidateRequest(string exchange, GetWithdrawalsRequest request, TradingMode? tradingMode, TradingMode[] supportedApiTypes) { - if (!TimeFilterSupported && request.StartTime != null) + if (!TimePeriodFilterSupport && request.StartTime != null) return ArgumentError.Invalid(nameof(GetWithdrawalsRequest.StartTime), $"Time filter is not supported"); return base.ValidateRequest(exchange, request, tradingMode, supportedApiTypes); @@ -34,7 +29,7 @@ namespace CryptoExchange.Net.SharedApis public override string ToString(string exchange) { var sb = new StringBuilder(base.ToString(exchange)); - sb.AppendLine($"Time filter supported: {TimeFilterSupported}"); + sb.AppendLine($"Time filter supported: {TimePeriodFilterSupport}"); return sb.ToString(); } } diff --git a/CryptoExchange.Net/SharedApis/Models/Options/Endpoints/PageEndpointOptions.cs b/CryptoExchange.Net/SharedApis/Models/Options/Endpoints/PageEndpointOptions.cs deleted file mode 100644 index 370818c..0000000 --- a/CryptoExchange.Net/SharedApis/Models/Options/Endpoints/PageEndpointOptions.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System.Diagnostics.CodeAnalysis; -using System.Text; - -namespace CryptoExchange.Net.SharedApis -{ - /// - /// Options for paginated endpoints - /// - /// -#if NET5_0_OR_GREATER - public class PageEndpointOptions<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)] T> : EndpointOptions where T : SharedRequest -#else - public class PageEndpointOptions : EndpointOptions where T : SharedRequest -#endif - { - - - /// - /// ctor - /// - public PageEndpointOptions(bool needsAuthentication) : base(needsAuthentication) - { - } - - /// - public override string ToString(string exchange) - { - var sb = new StringBuilder(base.ToString(exchange)); - - return sb.ToString(); - } - } -} diff --git a/CryptoExchange.Net/SharedApis/Models/Options/Endpoints/PaginatedEndpointOptions.cs b/CryptoExchange.Net/SharedApis/Models/Options/Endpoints/PaginatedEndpointOptions.cs index 01e5655..442f7ea 100644 --- a/CryptoExchange.Net/SharedApis/Models/Options/Endpoints/PaginatedEndpointOptions.cs +++ b/CryptoExchange.Net/SharedApis/Models/Options/Endpoints/PaginatedEndpointOptions.cs @@ -13,13 +13,14 @@ namespace CryptoExchange.Net.SharedApis public class PaginatedEndpointOptions : EndpointOptions where T : SharedRequest #endif { - ///// - ///// Type of pagination supported - ///// - //public SharedPaginationSupport PaginationSupport { get; } - - public bool SupportsAscendingPagination { get; set; } - public bool SupportsDescendingPagination { get; set; } + /// + /// Whether ascending data retrieval and pagination is available + /// + public bool SupportsAscending { get; set; } + /// + /// Whether ascending data retrieval and pagination is available + /// + public bool SupportsDescending { get; set; } /// /// Whether filtering based on start/end time is supported @@ -34,8 +35,15 @@ namespace CryptoExchange.Net.SharedApis /// /// ctor /// - public PaginatedEndpointOptions(bool timePeriodSupport, int maxLimit, bool needsAuthentication) : base(needsAuthentication) + public PaginatedEndpointOptions( + bool supportsAscending, + bool supportsDescending, + bool timePeriodSupport, + int maxLimit, + bool needsAuthentication) : base(needsAuthentication) { + SupportsAscending = supportsAscending; + SupportsDescending = supportsDescending; TimePeriodFilterSupport = timePeriodSupport; MaxLimit = maxLimit; } @@ -44,8 +52,8 @@ namespace CryptoExchange.Net.SharedApis public override string ToString(string exchange) { var sb = new StringBuilder(base.ToString(exchange)); - sb.AppendLine($"Pagination ASC supported: {SupportsAscendingPagination}"); - sb.AppendLine($"Pagination DESC supported: {SupportsDescendingPagination}"); + sb.AppendLine($"Ascending retrieval supported: {SupportsAscending}"); + sb.AppendLine($"Descending retrieval supported: {SupportsDescending}"); sb.AppendLine($"Time period filter support: {TimePeriodFilterSupport}"); sb.AppendLine($"Max limit: {MaxLimit}"); return sb.ToString(); diff --git a/CryptoExchange.Net/SharedApis/Models/Pagination.cs b/CryptoExchange.Net/SharedApis/Models/Pagination.cs index 3f8f037..5c31fe0 100644 --- a/CryptoExchange.Net/SharedApis/Models/Pagination.cs +++ b/CryptoExchange.Net/SharedApis/Models/Pagination.cs @@ -6,32 +6,37 @@ using System.Text; namespace CryptoExchange.Net.SharedApis { - public enum PageDirection + public enum DataDirection { Ascending, // Old to new Descending // New to old } + public record PaginationParameters + { + public DateTime? StartTime { get; set; } + public DateTime? EndTime { get; set; } + public string? FromId { get; set; } + public int? Offset { get; set; } + } public class PageRequest { - public string? NextCursor { get; set; } - public int? NextPage { get; set; } - public int? NextOffset { get; set; } - public string? NextFromId { get; set; } - public DateTime? NextStartTime { get; set; } - public DateTime? NextEndTime { get; set; } + public string? Cursor { get; set; } + public int? Page { get; set; } + public int? Offset { get; set; } + public string? FromId { get; set; } + public DateTime? StartTime { get; set; } + public DateTime? EndTime { get; set; } - public static PageRequest FromNextCursor(string nextCursor) => new PageRequest { NextCursor = nextCursor }; - public static PageRequest FromNextPage(int nextPage) => new PageRequest { NextPage = nextPage }; - public static PageRequest FromNextOffset(int nextOffset) => new PageRequest { NextOffset = nextOffset }; + public static PageRequest NextCursor(string nextCursor) => new PageRequest { Cursor = nextCursor }; + public static PageRequest NextPage(int nextPage) => new PageRequest { Page = nextPage }; + public static PageRequest NextOffset(int nextOffset) => new PageRequest { Offset = nextOffset }; - public static PageRequest FromNextFromIdAsc(IEnumerable idSelector) => new PageRequest { NextFromId = (idSelector.Max() + 1).ToString() }; - public static PageRequest FromNextFromIdDesc(IEnumerable idSelector) => new PageRequest { NextFromId = (idSelector.Min() - 1).ToString() }; - public static PageRequest FromNextStartTimeAsc(IEnumerable timestampSelector) => new PageRequest { NextStartTime = timestampSelector.Max().AddMilliseconds(1) }; - public static PageRequest FromNextStartTimeDesc(IEnumerable timestampSelector) => new PageRequest { NextStartTime = timestampSelector.Min().AddMilliseconds(-1) }; - public static PageRequest FromNextEndTimeAsc(IEnumerable timestampSelector) => new PageRequest { NextEndTime = timestampSelector.Max().AddMilliseconds(1) }; - public static PageRequest FromNextEndTimeDesc(IEnumerable timestampSelector) => new PageRequest { NextEndTime = timestampSelector.Min().AddMilliseconds(-1) }; + public static PageRequest NextFromIdAsc(IEnumerable idSelector) => new PageRequest { FromId = (idSelector.Max() + 1).ToString() }; + public static PageRequest NextFromIdDesc(IEnumerable idSelector) => new PageRequest { FromId = (idSelector.Min() - 1).ToString() }; + public static PageRequest NextStartTimeAsc(IEnumerable timestampSelector) => new PageRequest { StartTime = timestampSelector.Max().AddMilliseconds(1) }; + public static PageRequest NextEndTimeDesc(IEnumerable timestampSelector) => new PageRequest { EndTime = timestampSelector.Min().AddMilliseconds(-1) }; } } diff --git a/CryptoExchange.Net/SharedApis/Models/Rest/GetClosedOrdersRequest.cs b/CryptoExchange.Net/SharedApis/Models/Rest/GetClosedOrdersRequest.cs index a621240..5e1808e 100644 --- a/CryptoExchange.Net/SharedApis/Models/Rest/GetClosedOrdersRequest.cs +++ b/CryptoExchange.Net/SharedApis/Models/Rest/GetClosedOrdersRequest.cs @@ -19,8 +19,10 @@ namespace CryptoExchange.Net.SharedApis /// Max number of results /// public int? Limit { get; } - - public PageDirection? Direction { get; set; } + /// + /// Data direction + /// + public DataDirection? Direction { get; set; } /// /// ctor @@ -29,12 +31,14 @@ namespace CryptoExchange.Net.SharedApis /// Filter by start time /// Filter by end time /// Max number of results + /// Data direction /// Exchange specific parameters - public GetClosedOrdersRequest(SharedSymbol symbol, DateTime? startTime = null, DateTime? endTime = null, int? limit = null, ExchangeParameters? exchangeParameters = null) : base(symbol, exchangeParameters) + public GetClosedOrdersRequest(SharedSymbol symbol, DateTime? startTime = null, DateTime? endTime = null, int? limit = null, DataDirection? direction = null, ExchangeParameters? exchangeParameters = null) : base(symbol, exchangeParameters) { StartTime = startTime; EndTime = endTime; Limit = limit; + Direction = direction; } } } diff --git a/CryptoExchange.Net/SharedApis/Models/Rest/GetDepositsRequest.cs b/CryptoExchange.Net/SharedApis/Models/Rest/GetDepositsRequest.cs index 5f53be2..78fc887 100644 --- a/CryptoExchange.Net/SharedApis/Models/Rest/GetDepositsRequest.cs +++ b/CryptoExchange.Net/SharedApis/Models/Rest/GetDepositsRequest.cs @@ -23,6 +23,10 @@ namespace CryptoExchange.Net.SharedApis /// Max number of results /// public int? Limit { get; } + /// + /// Data direction + /// + public DataDirection? Direction { get; set; } /// /// ctor @@ -31,13 +35,15 @@ namespace CryptoExchange.Net.SharedApis /// Filter by start time /// Filter by end time /// Max number of results + /// Data direction /// Exchange specific parameters - public GetDepositsRequest(string? asset = null, DateTime? startTime = null, DateTime? endTime = null, int? limit = null, ExchangeParameters? exchangeParameters = null) : base(exchangeParameters) + public GetDepositsRequest(string? asset = null, DateTime? startTime = null, DateTime? endTime = null, int? limit = null, DataDirection? direction = null, ExchangeParameters? exchangeParameters = null) : base(exchangeParameters) { Asset = asset; StartTime = startTime; EndTime = endTime; Limit = limit; + Direction = direction; } } } diff --git a/CryptoExchange.Net/SharedApis/Models/Rest/GetFundingRateHistoryRequest.cs b/CryptoExchange.Net/SharedApis/Models/Rest/GetFundingRateHistoryRequest.cs index 213657f..6f9ad50 100644 --- a/CryptoExchange.Net/SharedApis/Models/Rest/GetFundingRateHistoryRequest.cs +++ b/CryptoExchange.Net/SharedApis/Models/Rest/GetFundingRateHistoryRequest.cs @@ -19,6 +19,10 @@ namespace CryptoExchange.Net.SharedApis /// Max number of results /// public int? Limit { get; set; } + /// + /// Data direction + /// + public DataDirection? Direction { get; set; } /// /// ctor @@ -27,12 +31,14 @@ namespace CryptoExchange.Net.SharedApis /// Filter by start time /// Filter by end time /// Max number of results + /// Data direction /// Exchange specific parameters - public GetFundingRateHistoryRequest(SharedSymbol symbol, DateTime? startTime = null, DateTime? endTime = null, int? limit = null, ExchangeParameters? exchangeParameters = null) : base(symbol, exchangeParameters) + public GetFundingRateHistoryRequest(SharedSymbol symbol, DateTime? startTime = null, DateTime? endTime = null, int? limit = null, DataDirection? direction = null, ExchangeParameters? exchangeParameters = null) : base(symbol, exchangeParameters) { StartTime = startTime; EndTime = endTime; Limit = limit; + Direction = direction; } } } diff --git a/CryptoExchange.Net/SharedApis/Models/Rest/GetKlinesRequest.cs b/CryptoExchange.Net/SharedApis/Models/Rest/GetKlinesRequest.cs index 6eef5a2..54b1013 100644 --- a/CryptoExchange.Net/SharedApis/Models/Rest/GetKlinesRequest.cs +++ b/CryptoExchange.Net/SharedApis/Models/Rest/GetKlinesRequest.cs @@ -23,6 +23,10 @@ namespace CryptoExchange.Net.SharedApis /// Max number of results /// public int? Limit { get; set; } + /// + /// Data direction + /// + public DataDirection? Direction { get; set; } /// /// ctor @@ -32,13 +36,15 @@ namespace CryptoExchange.Net.SharedApis /// Filter by start time /// Filter by end time /// Max number of results + /// Data direction /// Exchange specific parameters - public GetKlinesRequest(SharedSymbol symbol, SharedKlineInterval interval, DateTime? startTime = null, DateTime? endTime = null, int? limit = null, ExchangeParameters? exchangeParameters = null) : base(symbol, exchangeParameters) + public GetKlinesRequest(SharedSymbol symbol, SharedKlineInterval interval, DateTime? startTime = null, DateTime? endTime = null, int? limit = null, DataDirection? direction = null, ExchangeParameters? exchangeParameters = null) : base(symbol, exchangeParameters) { Interval = interval; StartTime = startTime; EndTime = endTime; Limit = limit; + Direction = direction; } } } diff --git a/CryptoExchange.Net/SharedApis/Models/Rest/GetPositionHistoryRequest.cs b/CryptoExchange.Net/SharedApis/Models/Rest/GetPositionHistoryRequest.cs index 7bbb209..db62b2f 100644 --- a/CryptoExchange.Net/SharedApis/Models/Rest/GetPositionHistoryRequest.cs +++ b/CryptoExchange.Net/SharedApis/Models/Rest/GetPositionHistoryRequest.cs @@ -27,6 +27,10 @@ namespace CryptoExchange.Net.SharedApis /// Max number of results /// public int? Limit { get; set; } + /// + /// Data direction + /// + public DataDirection? Direction { get; set; } /// /// ctor @@ -35,13 +39,15 @@ namespace CryptoExchange.Net.SharedApis /// Filter by start time /// Filter by end time /// Max number of results + /// Data direction /// Exchange specific parameters - public GetPositionHistoryRequest(SharedSymbol symbol, DateTime? startTime = null, DateTime? endTime = null, int? limit = null, ExchangeParameters? exchangeParameters = null) : base(exchangeParameters) + public GetPositionHistoryRequest(SharedSymbol symbol, DateTime? startTime = null, DateTime? endTime = null, int? limit = null, DataDirection? direction = null, ExchangeParameters? exchangeParameters = null) : base(exchangeParameters) { Symbol = symbol; StartTime = startTime; EndTime = endTime; Limit = limit; + Direction = direction; } /// @@ -51,13 +57,15 @@ namespace CryptoExchange.Net.SharedApis /// Filter by start time /// Filter by end time /// Max number of results + /// Data direction /// Exchange specific parameters - public GetPositionHistoryRequest(TradingMode? tradeMode = null, DateTime? startTime = null, DateTime? endTime = null, int? limit = null, ExchangeParameters? exchangeParameters = null) : base(exchangeParameters) + public GetPositionHistoryRequest(TradingMode? tradeMode = null, DateTime? startTime = null, DateTime? endTime = null, int? limit = null, DataDirection? direction = null, ExchangeParameters? exchangeParameters = null) : base(exchangeParameters) { TradingMode = tradeMode; StartTime = startTime; EndTime = endTime; Limit = limit; + Direction = direction; } } } diff --git a/CryptoExchange.Net/SharedApis/Models/Rest/GetTradeHistoryRequest.cs b/CryptoExchange.Net/SharedApis/Models/Rest/GetTradeHistoryRequest.cs index 6c1c816..1a19955 100644 --- a/CryptoExchange.Net/SharedApis/Models/Rest/GetTradeHistoryRequest.cs +++ b/CryptoExchange.Net/SharedApis/Models/Rest/GetTradeHistoryRequest.cs @@ -19,8 +19,10 @@ namespace CryptoExchange.Net.SharedApis /// Max number of results /// public int? Limit { get; set; } - - public PageDirection? Direction { get; set; } + /// + /// Data direction + /// + public DataDirection? Direction { get; set; } /// /// ctor @@ -29,12 +31,14 @@ namespace CryptoExchange.Net.SharedApis /// Filter by start time /// Filter by end time /// Max number of results + /// Data direction /// Exchange specific parameters - public GetTradeHistoryRequest(SharedSymbol symbol, DateTime startTime, DateTime endTime, int? limit = null, ExchangeParameters? exchangeParameters = null) : base(symbol, exchangeParameters) + public GetTradeHistoryRequest(SharedSymbol symbol, DateTime startTime, DateTime endTime, int? limit = null, DataDirection? direction = null, ExchangeParameters? exchangeParameters = null) : base(symbol, exchangeParameters) { StartTime = startTime; EndTime = endTime; Limit = limit; + Direction = direction; } } } diff --git a/CryptoExchange.Net/SharedApis/Models/Rest/GetUserTradesRequest.cs b/CryptoExchange.Net/SharedApis/Models/Rest/GetUserTradesRequest.cs index 8fd8407..0cf88b0 100644 --- a/CryptoExchange.Net/SharedApis/Models/Rest/GetUserTradesRequest.cs +++ b/CryptoExchange.Net/SharedApis/Models/Rest/GetUserTradesRequest.cs @@ -19,6 +19,10 @@ namespace CryptoExchange.Net.SharedApis /// Max number of results /// public int? Limit { get; } + /// + /// Data direction + /// + public DataDirection? Direction { get; set; } /// /// ctor @@ -27,12 +31,14 @@ namespace CryptoExchange.Net.SharedApis /// Filter by start time /// Filter by end time /// Max number of results + /// Data direction /// Exchange specific parameters - public GetUserTradesRequest(SharedSymbol symbol, DateTime? startTime = null, DateTime? endTime = null, int? limit = null, ExchangeParameters? exchangeParameters = null) : base(symbol, exchangeParameters) + public GetUserTradesRequest(SharedSymbol symbol, DateTime? startTime = null, DateTime? endTime = null, int? limit = null, DataDirection? direction = null, ExchangeParameters? exchangeParameters = null) : base(symbol, exchangeParameters) { StartTime = startTime; EndTime = endTime; Limit = limit; + Direction = direction; } } } diff --git a/CryptoExchange.Net/SharedApis/Models/Rest/GetWithdrawalsRequest.cs b/CryptoExchange.Net/SharedApis/Models/Rest/GetWithdrawalsRequest.cs index 5130079..0438b70 100644 --- a/CryptoExchange.Net/SharedApis/Models/Rest/GetWithdrawalsRequest.cs +++ b/CryptoExchange.Net/SharedApis/Models/Rest/GetWithdrawalsRequest.cs @@ -23,6 +23,10 @@ namespace CryptoExchange.Net.SharedApis /// Max number of results /// public int? Limit { get; } + /// + /// Data direction + /// + public DataDirection? Direction { get; set; } /// /// ctor @@ -31,13 +35,15 @@ namespace CryptoExchange.Net.SharedApis /// Filter by start time /// Filter by end time /// Max number of results + /// Data direction /// Exchange specific parameters - public GetWithdrawalsRequest(string? asset = null, DateTime? startTime = null, DateTime? endTime = null, int? limit = null, ExchangeParameters? exchangeParameters = null) : base(exchangeParameters) + public GetWithdrawalsRequest(string? asset = null, DateTime? startTime = null, DateTime? endTime = null, int? limit = null, DataDirection? direction = null, ExchangeParameters? exchangeParameters = null) : base(exchangeParameters) { Asset = asset; StartTime = startTime; EndTime = endTime; Limit = limit; + Direction = direction; } } }