1
0
mirror of https://github.com/JKorf/CryptoExchange.Net synced 2026-02-16 14:13:46 +00:00
This commit is contained in:
Jkorf 2026-02-13 16:28:26 +01:00
parent c5fa985841
commit d4965ad68d
31 changed files with 534 additions and 329 deletions

View File

@ -311,11 +311,11 @@ namespace CryptoExchange.Net
/// <param name="request">The request parameters</param> /// <param name="request">The request parameters</param>
/// <param name="ct">Cancellation token</param> /// <param name="ct">Cancellation token</param>
/// <returns></returns> /// <returns></returns>
public static async IAsyncEnumerable<ExchangeWebResult<T[]>> ExecutePages<T, U>(Func<U, INextPageToken?, CancellationToken, Task<ExchangeWebResult<T[]>>> paginatedFunc, U request, [EnumeratorCancellation]CancellationToken ct = default) public static async IAsyncEnumerable<ExchangeWebResult<T[]>> ExecutePages<T, U>(Func<U, PageRequest?, CancellationToken, Task<ExchangeWebResult<T[]>>> paginatedFunc, U request, [EnumeratorCancellation]CancellationToken ct = default)
{ {
var result = new List<T>(); var result = new List<T>();
ExchangeWebResult<T[]> batch; ExchangeWebResult<T[]> batch;
INextPageToken? nextPageToken = null; PageRequest? nextPageToken = null;
while (true) while (true)
{ {
batch = await paginatedFunc(request, nextPageToken, ct).ConfigureAwait(false); batch = await paginatedFunc(request, nextPageToken, ct).ConfigureAwait(false);
@ -324,7 +324,7 @@ namespace CryptoExchange.Net
break; break;
result.AddRange(batch.Data); result.AddRange(batch.Data);
nextPageToken = batch.NextPageToken; nextPageToken = batch.NextPageRequest;
if (nextPageToken == null) if (nextPageToken == null)
break; break;
} }
@ -335,9 +335,9 @@ namespace CryptoExchange.Net
Func<T, DateTime> timeSelector, Func<T, DateTime> timeSelector,
DateTime? startTime, DateTime? startTime,
DateTime? endTime, DateTime? endTime,
PageDirection direction) DataDirection direction)
{ {
if (direction == PageDirection.Ascending) if (direction == DataDirection.Ascending)
data = data.OrderBy(timeSelector); data = data.OrderBy(timeSelector);
else else
data = data.OrderByDescending(timeSelector); data = data.OrderByDescending(timeSelector);
@ -357,12 +357,15 @@ namespace CryptoExchange.Net
DateTime? startTime, DateTime? startTime,
DateTime? endTime, DateTime? endTime,
int limit, int limit,
PageDirection paginationDirection) DataDirection paginationDirection)
{ {
if (resultCount < limit) if (resultCount < limit)
return false; return false;
if (paginationDirection == PageDirection.Ascending) if (!timestamps.Any())
return false;
if (paginationDirection == DataDirection.Ascending)
{ {
if (timestamps.Max() >= endTime) if (timestamps.Max() >= endTime)
return false; return false;
@ -382,13 +385,230 @@ namespace CryptoExchange.Net
{ {
FromId, FromId,
Time, 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<PageRequest> normalNextPageCallback,
int responseLength,
IEnumerable<DateTime> 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( public static (DateTime? startTime, DateTime? endTime, long? fromId) ApplyPaginationRequestFilters(
PaginationFilterType? ascendingFilterType, PaginationFilterType? ascendingFilterType,
PaginationFilterType? descendingFilterType, PaginationFilterType? descendingFilterType,
PageDirection defaultDirection, DataDirection defaultDirection,
PageDirection requestDirection, DataDirection requestDirection,
DateTime? userFilterStartTime, DateTime? userFilterStartTime,
DateTime? userFilterEndTime, DateTime? userFilterEndTime,
DateTime? paginationStartTime, DateTime? paginationStartTime,
@ -396,10 +616,10 @@ namespace CryptoExchange.Net
TimeSpan? maxTimePeriod, TimeSpan? maxTimePeriod,
string? paginationFromId) string? paginationFromId)
{ {
if (requestDirection == PageDirection.Ascending && userFilterStartTime == null) if (requestDirection == DataDirection.Ascending && userFilterStartTime == null)
throw new InvalidOperationException("Ascending without start time"); 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) if (filterType == PaginationFilterType.FromId)
{ {
long? fromId = ApplyFromId(paginationFromId); long? fromId = ApplyFromId(paginationFromId);
@ -410,7 +630,7 @@ namespace CryptoExchange.Net
&& fromId == null && fromId == null
&& startTime == 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 // 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 // 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 (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 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 == DataDirection.Ascending) endTime = null;
if (requestDirection == PageDirection.Descending) startTime = null; if (requestDirection == DataDirection.Descending) startTime = null;
} }
return (startTime, endTime, fromId); return (startTime, endTime, fromId);
} }
else // Time else // Time
{ {
DateTime? startTime = requestDirection == PageDirection.Descending ? null : ApplyTime(userFilterStartTime, paginationStartTime); DateTime? startTime = requestDirection == DataDirection.Descending ? null : ApplyTime(userFilterStartTime, paginationStartTime);
DateTime? endTime = (requestDirection == PageDirection.Ascending && paginationStartTime != null) ? null : ApplyTime(userFilterEndTime, paginationEndTime); DateTime? endTime = (requestDirection == DataDirection.Ascending && paginationStartTime != null) ? null : ApplyTime(userFilterEndTime, paginationEndTime);
if (maxTimePeriod.HasValue && endTime - startTime > maxTimePeriod.Value) if (maxTimePeriod.HasValue && endTime - startTime > maxTimePeriod.Value)
{ {
if (requestDirection == PageDirection.Ascending) if (requestDirection == DataDirection.Ascending)
endTime = startTime.Value.Add(maxTimePeriod.Value); endTime = startTime.Value.Add(maxTimePeriod.Value);
else else
startTime = endTime.Value.Add(-maxTimePeriod.Value); startTime = endTime.Value.Add(-maxTimePeriod.Value);

View File

@ -519,7 +519,7 @@ namespace CryptoExchange.Net.Objects
/// <param name="exchange">The exchange</param> /// <param name="exchange">The exchange</param>
/// <param name="tradeModes">Trade modes the result applies to</param> /// <param name="tradeModes">Trade modes the result applies to</param>
/// <returns></returns> /// <returns></returns>
public ExchangeWebResult<T> AsExchangeResult(string exchange, TradingMode[] tradeModes) public ExchangeWebResult<T> AsExchangeResult(string exchange, TradingMode[]? tradeModes)
{ {
return new ExchangeWebResult<T>(exchange, tradeModes, this); return new ExchangeWebResult<T>(exchange, tradeModes, this);
} }
@ -533,25 +533,11 @@ namespace CryptoExchange.Net.Objects
/// <param name="data">Data</param> /// <param name="data">Data</param>
/// <param name="nextPageToken">Next page token</param> /// <param name="nextPageToken">Next page token</param>
/// <returns></returns> /// <returns></returns>
public ExchangeWebResult<K> AsExchangeResult<K>(string exchange, TradingMode tradeMode, [AllowNull] K data, INextPageToken? nextPageToken = null) public ExchangeWebResult<K> AsExchangeResult<K>(string exchange, TradingMode tradeMode, [AllowNull] K data, PageRequest? nextPageToken = null)
{ {
return new ExchangeWebResult<K>(exchange, tradeMode, As<K>(data), nextPageToken); return new ExchangeWebResult<K>(exchange, tradeMode, As<K>(data), nextPageToken);
} }
/// <summary>
/// Copy the WebCallResult to an ExchangeWebResult of a new data type
/// </summary>
/// <typeparam name="K">The new type</typeparam>
/// <param name="exchange">The exchange</param>
/// <param name="tradeMode">Trade mode the result applies to</param>
/// <param name="data">Data</param>
/// <param name="nextPageToken">Next page token</param>
/// <returns></returns>
public ExchangeWebResult<K> AsExchangeResult<K>(string exchange, TradingMode tradeMode, [AllowNull] K data, PageRequest? nextPageRequest)
{
return new ExchangeWebResult<K>(exchange, tradeMode, As<K>(data), nextPageRequest);
}
/// <summary> /// <summary>
/// Copy the WebCallResult to an ExchangeWebResult of a new data type /// Copy the WebCallResult to an ExchangeWebResult of a new data type
/// </summary> /// </summary>
@ -561,7 +547,7 @@ namespace CryptoExchange.Net.Objects
/// <param name="data">Data</param> /// <param name="data">Data</param>
/// <param name="nextPageToken">Next page token</param> /// <param name="nextPageToken">Next page token</param>
/// <returns></returns> /// <returns></returns>
public ExchangeWebResult<K> AsExchangeResult<K>(string exchange, TradingMode[]? tradeModes, [AllowNull] K data, INextPageToken? nextPageToken = null) public ExchangeWebResult<K> AsExchangeResult<K>(string exchange, TradingMode[]? tradeModes, [AllowNull] K data, PageRequest? nextPageToken = null)
{ {
return new ExchangeWebResult<K>(exchange, tradeModes, As<K>(data), nextPageToken); return new ExchangeWebResult<K>(exchange, tradeModes, As<K>(data), nextPageToken);
} }

View File

@ -1,131 +1,131 @@
using System; //using System;
namespace CryptoExchange.Net.SharedApis //namespace CryptoExchange.Net.SharedApis
{ //{
/// <summary> // /// <summary>
/// A token which a request can use to retrieve the next page if there are more pages in the result set // /// A token which a request can use to retrieve the next page if there are more pages in the result set
/// </summary> // /// </summary>
public interface INextPageToken // public interface INextPageToken
{ // {
} // }
/// <summary> // /// <summary>
/// A datetime offset token // /// A datetime offset token
/// </summary> // /// </summary>
public record DateTimeToken: INextPageToken // public record DateTimeToken: INextPageToken
{ // {
/// <summary> // /// <summary>
/// Last result time // /// Last result time
/// </summary> // /// </summary>
public DateTime LastTime { get; set; } // public DateTime LastTime { get; set; }
/// <summary> // /// <summary>
/// ctor // /// ctor
/// </summary> // /// </summary>
public DateTimeToken(DateTime timestamp) // public DateTimeToken(DateTime timestamp)
{ // {
LastTime = timestamp; // LastTime = timestamp;
} // }
public DateTimeToken GetNextToken(DateTime nextTime) => this with { LastTime = nextTime }; // public DateTimeToken GetNextToken(DateTime nextTime) => this with { LastTime = nextTime };
} // }
/// <summary> // /// <summary>
/// A current page index token // /// A current page index token
/// </summary> // /// </summary>
public record PageToken: INextPageToken // public record PageToken: INextPageToken
{ // {
/// <summary> // /// <summary>
/// The next page index // /// The next page index
/// </summary> // /// </summary>
public int Page { get; set; } // public int Page { get; set; }
/// <summary> // /// <summary>
/// Page size // /// Page size
/// </summary> // /// </summary>
public int PageSize { get; set; } // public int PageSize { get; set; }
/// <summary> // /// <summary>
/// ctor // /// ctor
/// </summary> // /// </summary>
public PageToken(int page, int pageSize) // public PageToken(int page, int pageSize)
{ // {
Page = page; // Page = page;
PageSize = pageSize; // PageSize = pageSize;
} // }
public PageToken GetNextToken() => this with { Page = Page + 1 }; // public PageToken GetNextToken() => this with { Page = Page + 1 };
} // }
/// <summary> // /// <summary>
/// A id offset token // /// A id offset token
/// </summary> // /// </summary>
public record FromIdToken : INextPageToken // public record FromIdToken : INextPageToken
{ // {
/// <summary> // /// <summary>
/// The last id from previous result // /// The last id from previous result
/// </summary> // /// </summary>
public string FromToken { get; set; } // public string FromToken { get; set; }
/// <summary> // /// <summary>
/// ctor // /// ctor
/// </summary> // /// </summary>
public FromIdToken(string fromToken) // public FromIdToken(string fromToken)
{ // {
FromToken = fromToken; // FromToken = fromToken;
} // }
/// <summary> // /// <summary>
/// ctor // /// ctor
/// </summary> // /// </summary>
public FromIdToken(long fromToken) // public FromIdToken(long fromToken)
{ // {
FromToken = fromToken.ToString(); // FromToken = fromToken.ToString();
} // }
public FromIdToken GetNextToken(string nextToken) => this with { FromToken = nextToken }; // public FromIdToken GetNextToken(string nextToken) => this with { FromToken = nextToken };
public FromIdToken GetNextToken(long nextToken) => this with { FromToken = nextToken.ToString() }; // public FromIdToken GetNextToken(long nextToken) => this with { FromToken = nextToken.ToString() };
} // }
/// <summary> // /// <summary>
/// A cursor token // /// A cursor token
/// </summary> // /// </summary>
public record CursorToken : INextPageToken // public record CursorToken : INextPageToken
{ // {
/// <summary> // /// <summary>
/// The next page cursor // /// The next page cursor
/// </summary> // /// </summary>
public string Cursor { get; set; } // public string Cursor { get; set; }
/// <summary> // /// <summary>
/// ctor // /// ctor
/// </summary> // /// </summary>
public CursorToken(string cursor) // public CursorToken(string cursor)
{ // {
Cursor = cursor; // Cursor = cursor;
} // }
public CursorToken GetNextToken(string nextCursor) => this with { Cursor = nextCursor }; // public CursorToken GetNextToken(string nextCursor) => this with { Cursor = nextCursor };
} // }
/// <summary> // /// <summary>
/// A result offset token // /// A result offset token
/// </summary> // /// </summary>
public record OffsetToken : INextPageToken // public record OffsetToken : INextPageToken
{ // {
/// <summary> // /// <summary>
/// Offset in the result set // /// Offset in the result set
/// </summary> // /// </summary>
public int Offset { get; set; } // public int Offset { get; set; }
/// <summary> // /// <summary>
/// ctor // /// ctor
/// </summary> // /// </summary>
public OffsetToken(int offset) // public OffsetToken(int offset)
{ // {
Offset = offset; // Offset = offset;
} // }
public OffsetToken GetNextToken() => this with { Offset = Offset + Offset }; // public OffsetToken GetNextToken() => this with { Offset = Offset + Offset };
} // }
} //}

View File

@ -18,6 +18,6 @@ namespace CryptoExchange.Net.SharedApis
/// <param name="request">Request info</param> /// <param name="request">Request info</param>
/// <param name="nextPageToken">The pagination token from the previous request to continue pagination</param> /// <param name="nextPageToken">The pagination token from the previous request to continue pagination</param>
/// <param name="ct">Cancellation token</param> /// <param name="ct">Cancellation token</param>
Task<ExchangeWebResult<SharedFundingRate[]>> GetFundingRateHistoryAsync(GetFundingRateHistoryRequest request, INextPageToken? nextPageToken = null, CancellationToken ct = default); Task<ExchangeWebResult<SharedFundingRate[]>> GetFundingRateHistoryAsync(GetFundingRateHistoryRequest request, PageRequest? nextPageToken = null, CancellationToken ct = default);
} }
} }

View File

@ -80,7 +80,7 @@ namespace CryptoExchange.Net.SharedApis
/// <param name="request">Request info</param> /// <param name="request">Request info</param>
/// <param name="nextPageToken">The pagination token from the previous request to continue pagination</param> /// <param name="nextPageToken">The pagination token from the previous request to continue pagination</param>
/// <param name="ct">Cancellation token</param> /// <param name="ct">Cancellation token</param>
Task<ExchangeWebResult<SharedFuturesOrder[]>> GetClosedFuturesOrdersAsync(GetClosedOrdersRequest request, INextPageToken? nextPageToken = null, CancellationToken ct = default); Task<ExchangeWebResult<SharedFuturesOrder[]>> GetClosedFuturesOrdersAsync(GetClosedOrdersRequest request, PageRequest? nextPageToken = null, CancellationToken ct = default);
/// <summary> /// <summary>
/// Futures get order trades request options /// Futures get order trades request options
@ -103,7 +103,7 @@ namespace CryptoExchange.Net.SharedApis
/// <param name="request">Request info</param> /// <param name="request">Request info</param>
/// <param name="nextPageToken">The pagination token from the previous request to continue pagination</param> /// <param name="nextPageToken">The pagination token from the previous request to continue pagination</param>
/// <param name="ct">Cancellation token</param> /// <param name="ct">Cancellation token</param>
Task<ExchangeWebResult<SharedUserTrade[]>> GetFuturesUserTradesAsync(GetUserTradesRequest request, INextPageToken? nextPageToken = null, CancellationToken ct = default); Task<ExchangeWebResult<SharedUserTrade[]>> GetFuturesUserTradesAsync(GetUserTradesRequest request, PageRequest? nextPageToken = null, CancellationToken ct = default);
/// <summary> /// <summary>
/// Futures cancel order request options /// Futures cancel order request options

View File

@ -18,6 +18,6 @@ namespace CryptoExchange.Net.SharedApis
/// <param name="request">Request info</param> /// <param name="request">Request info</param>
/// <param name="nextPageToken">The pagination token from the previous request to continue pagination</param> /// <param name="nextPageToken">The pagination token from the previous request to continue pagination</param>
/// <param name="ct">Cancellation token</param> /// <param name="ct">Cancellation token</param>
Task<ExchangeWebResult<SharedFuturesKline[]>> GetIndexPriceKlinesAsync(GetKlinesRequest request, INextPageToken? nextPageToken = null, CancellationToken ct = default); Task<ExchangeWebResult<SharedFuturesKline[]>> GetIndexPriceKlinesAsync(GetKlinesRequest request, PageRequest? nextPageToken = null, CancellationToken ct = default);
} }
} }

View File

@ -18,6 +18,6 @@ namespace CryptoExchange.Net.SharedApis
/// <param name="request">Request info</param> /// <param name="request">Request info</param>
/// <param name="nextPageToken">The pagination token from the previous request to continue pagination</param> /// <param name="nextPageToken">The pagination token from the previous request to continue pagination</param>
/// <param name="ct">Cancellation token</param> /// <param name="ct">Cancellation token</param>
Task<ExchangeWebResult<SharedFuturesKline[]>> GetMarkPriceKlinesAsync(GetKlinesRequest request, INextPageToken? nextPageToken = null, CancellationToken ct = default); Task<ExchangeWebResult<SharedFuturesKline[]>> GetMarkPriceKlinesAsync(GetKlinesRequest request, PageRequest? nextPageToken = null, CancellationToken ct = default);
} }
} }

View File

@ -18,6 +18,6 @@ namespace CryptoExchange.Net.SharedApis
/// <param name="request">Request info</param> /// <param name="request">Request info</param>
/// <param name="nextPageToken">The pagination token from the previous request to continue pagination</param> /// <param name="nextPageToken">The pagination token from the previous request to continue pagination</param>
/// <param name="ct">Cancellation token</param> /// <param name="ct">Cancellation token</param>
Task<ExchangeWebResult<SharedPositionHistory[]>> GetPositionHistoryAsync(GetPositionHistoryRequest request, INextPageToken? nextPageToken = null, CancellationToken ct = default); Task<ExchangeWebResult<SharedPositionHistory[]>> GetPositionHistoryAsync(GetPositionHistoryRequest request, PageRequest? nextPageToken = null, CancellationToken ct = default);
} }
} }

View File

@ -33,6 +33,6 @@ namespace CryptoExchange.Net.SharedApis
/// <param name="nextPageToken">The pagination token from the previous request to continue pagination</param> /// <param name="nextPageToken">The pagination token from the previous request to continue pagination</param>
/// <param name="ct">Cancellation token</param> /// <param name="ct">Cancellation token</param>
/// <returns></returns> /// <returns></returns>
Task<ExchangeWebResult<SharedDeposit[]>> GetDepositsAsync(GetDepositsRequest request, INextPageToken? nextPageToken = null, CancellationToken ct = default); Task<ExchangeWebResult<SharedDeposit[]>> GetDepositsAsync(GetDepositsRequest request, PageRequest? nextPageToken = null, CancellationToken ct = default);
} }
} }

View File

@ -20,6 +20,6 @@ namespace CryptoExchange.Net.SharedApis
/// <param name="nextPageToken">The pagination token from the previous request to continue pagination</param> /// <param name="nextPageToken">The pagination token from the previous request to continue pagination</param>
/// <param name="ct">Cancellation token</param> /// <param name="ct">Cancellation token</param>
/// <returns></returns> /// <returns></returns>
Task<ExchangeWebResult<SharedKline[]>> GetKlinesAsync(GetKlinesRequest request, INextPageToken? nextPageToken = null, CancellationToken ct = default); Task<ExchangeWebResult<SharedKline[]>> GetKlinesAsync(GetKlinesRequest request, PageRequest? nextPageToken = null, CancellationToken ct = default);
} }
} }

View File

@ -20,6 +20,6 @@ namespace CryptoExchange.Net.SharedApis
/// <param name="nextPageToken">The pagination token from the previous request to continue pagination</param> /// <param name="nextPageToken">The pagination token from the previous request to continue pagination</param>
/// <param name="ct">Cancellation token</param> /// <param name="ct">Cancellation token</param>
/// <returns></returns> /// <returns></returns>
Task<ExchangeWebResult<SharedWithdrawal[]>> GetWithdrawalsAsync(GetWithdrawalsRequest request, INextPageToken? nextPageToken = null, CancellationToken ct = default); Task<ExchangeWebResult<SharedWithdrawal[]>> GetWithdrawalsAsync(GetWithdrawalsRequest request, PageRequest? nextPageToken = null, CancellationToken ct = default);
} }
} }

View File

@ -102,7 +102,7 @@ namespace CryptoExchange.Net.SharedApis
/// <param name="request">Request info</param> /// <param name="request">Request info</param>
/// <param name="nextPageToken">The pagination token from the previous request to continue pagination</param> /// <param name="nextPageToken">The pagination token from the previous request to continue pagination</param>
/// <param name="ct">Cancellation token</param> /// <param name="ct">Cancellation token</param>
Task<ExchangeWebResult<SharedUserTrade[]>> GetSpotUserTradesAsync(GetUserTradesRequest request, INextPageToken? nextPageToken = null, CancellationToken ct = default); Task<ExchangeWebResult<SharedUserTrade[]>> GetSpotUserTradesAsync(GetUserTradesRequest request, PageRequest? nextPageToken = null, CancellationToken ct = default);
/// <summary> /// <summary>
/// Spot cancel order request options /// Spot cancel order request options

View File

@ -23,11 +23,6 @@ namespace CryptoExchange.Net.SharedApis
/// </summary> /// </summary>
public TradingMode[]? DataTradeMode { get; } public TradingMode[]? DataTradeMode { get; }
/// <summary>
/// Token to retrieve the next page with
/// </summary>
public INextPageToken? NextPageToken { get; }
/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>
@ -51,63 +46,7 @@ namespace CryptoExchange.Net.SharedApis
string exchange, string exchange,
TradingMode dataTradeMode, TradingMode dataTradeMode,
WebCallResult<T> result, WebCallResult<T> result,
INextPageToken? nextPageToken = null) : PageRequest? 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;
}
/// <summary>
/// ctor
/// </summary>
public ExchangeWebResult(
string exchange,
TradingMode[]? dataTradeModes,
WebCallResult<T> 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;
}
/// <summary>
/// ctor
/// </summary>
public ExchangeWebResult(
string exchange,
TradingMode dataTradeMode,
WebCallResult<T> result,
PageRequest? nextPageToken) :
base(result.ResponseStatusCode, base(result.ResponseStatusCode,
result.HttpVersion, result.HttpVersion,
result.ResponseHeaders, result.ResponseHeaders,
@ -135,7 +74,7 @@ namespace CryptoExchange.Net.SharedApis
string exchange, string exchange,
TradingMode[]? dataTradeModes, TradingMode[]? dataTradeModes,
WebCallResult<T> result, WebCallResult<T> result,
PageRequest? nextPageRequest) : PageRequest? nextPageRequest = null) :
base(result.ResponseStatusCode, base(result.ResponseStatusCode,
result.HttpVersion, result.HttpVersion,
result.ResponseHeaders, result.ResponseHeaders,
@ -176,7 +115,7 @@ namespace CryptoExchange.Net.SharedApis
ResultDataSource dataSource, ResultDataSource dataSource,
[AllowNull] T data, [AllowNull] T data,
Error? error, Error? error,
INextPageToken? nextPageToken = null) : base( PageRequest? nextPageToken = null) : base(
code, code,
httpVersion, httpVersion,
responseHeaders, responseHeaders,
@ -194,7 +133,7 @@ namespace CryptoExchange.Net.SharedApis
{ {
DataTradeMode = dataTradeModes; DataTradeMode = dataTradeModes;
Exchange = exchange; Exchange = exchange;
NextPageToken = nextPageToken; NextPageRequest = nextPageToken;
} }
/// <summary> /// <summary>
@ -205,7 +144,7 @@ namespace CryptoExchange.Net.SharedApis
/// <returns></returns> /// <returns></returns>
public new ExchangeWebResult<K> As<K>([AllowNull] K data) public new ExchangeWebResult<K> As<K>([AllowNull] K data)
{ {
return new ExchangeWebResult<K>(Exchange, DataTradeMode, ResponseStatusCode, HttpVersion, ResponseHeaders, ResponseTime, ResponseLength, OriginalData, RequestId, RequestUrl, RequestBody, RequestMethod, RequestHeaders, DataSource, data, Error, NextPageToken); return new ExchangeWebResult<K>(Exchange, DataTradeMode, ResponseStatusCode, HttpVersion, ResponseHeaders, ResponseTime, ResponseLength, OriginalData, RequestId, RequestUrl, RequestBody, RequestMethod, RequestHeaders, DataSource, data, Error, NextPageRequest);
} }
/// <inheritdoc /> /// <inheritdoc />

View File

@ -8,23 +8,18 @@ namespace CryptoExchange.Net.SharedApis
/// </summary> /// </summary>
public class GetClosedOrdersOptions : PaginatedEndpointOptions<GetClosedOrdersRequest> public class GetClosedOrdersOptions : PaginatedEndpointOptions<GetClosedOrdersRequest>
{ {
/// <summary>
/// Whether the start/end time filter is supported
/// </summary>
public bool TimeFilterSupported { get; set; }
/// <summary> /// <summary>
/// ctor /// ctor
/// </summary> /// </summary>
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;
} }
/// <inheritdoc /> /// <inheritdoc />
public override Error? ValidateRequest(string exchange, GetClosedOrdersRequest request, TradingMode? tradingMode, TradingMode[] supportedApiTypes) 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 ArgumentError.Invalid(nameof(GetClosedOrdersRequest.StartTime), $"Time filter is not supported");
return base.ValidateRequest(exchange, request, tradingMode, supportedApiTypes); return base.ValidateRequest(exchange, request, tradingMode, supportedApiTypes);
@ -34,7 +29,7 @@ namespace CryptoExchange.Net.SharedApis
public override string ToString(string exchange) public override string ToString(string exchange)
{ {
var sb = new StringBuilder(base.ToString(exchange)); var sb = new StringBuilder(base.ToString(exchange));
sb.AppendLine($"Time filter supported: {TimeFilterSupported}"); sb.AppendLine($"Time filter supported: {TimePeriodFilterSupport}");
return sb.ToString(); return sb.ToString();
} }
} }

View File

@ -8,23 +8,18 @@ namespace CryptoExchange.Net.SharedApis
/// </summary> /// </summary>
public class GetDepositsOptions : PaginatedEndpointOptions<GetDepositsRequest> public class GetDepositsOptions : PaginatedEndpointOptions<GetDepositsRequest>
{ {
/// <summary>
/// Whether the start/end time filter is supported
/// </summary>
public bool TimeFilterSupported { get; set; }
/// <summary> /// <summary>
/// ctor /// ctor
/// </summary> /// </summary>
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;
} }
/// <inheritdoc /> /// <inheritdoc />
public override Error? ValidateRequest(string exchange, GetDepositsRequest request, TradingMode? tradingMode, TradingMode[] supportedApiTypes) 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 ArgumentError.Invalid(nameof(GetDepositsRequest.StartTime), $"Time filter is not supported");
return base.ValidateRequest(exchange, request, tradingMode, supportedApiTypes); return base.ValidateRequest(exchange, request, tradingMode, supportedApiTypes);
@ -34,7 +29,7 @@ namespace CryptoExchange.Net.SharedApis
public override string ToString(string exchange) public override string ToString(string exchange)
{ {
var sb = new StringBuilder(base.ToString(exchange)); var sb = new StringBuilder(base.ToString(exchange));
sb.AppendLine($"Time filter supported: {TimeFilterSupported}"); sb.AppendLine($"Time filter supported: {TimePeriodFilterSupport}");
return sb.ToString(); return sb.ToString();
} }
} }

View File

@ -1,4 +1,7 @@
namespace CryptoExchange.Net.SharedApis using CryptoExchange.Net.Objects;
using System.Text;
namespace CryptoExchange.Net.SharedApis
{ {
/// <summary> /// <summary>
/// Options for requesting funding rate history /// Options for requesting funding rate history
@ -8,8 +11,26 @@
/// <summary> /// <summary>
/// ctor /// ctor
/// </summary> /// </summary>
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)
{ {
} }
/// <inheritdoc />
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);
}
/// <inheritdoc />
public override string ToString(string exchange)
{
var sb = new StringBuilder(base.ToString(exchange));
sb.AppendLine($"Time filter supported: {TimePeriodFilterSupport}");
return sb.ToString();
}
} }
} }

View File

@ -26,7 +26,8 @@ namespace CryptoExchange.Net.SharedApis
/// <summary> /// <summary>
/// ctor /// ctor
/// </summary> /// </summary>
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[] SupportIntervals = new[]
{ {
@ -50,7 +51,8 @@ namespace CryptoExchange.Net.SharedApis
/// <summary> /// <summary>
/// ctor /// ctor
/// </summary> /// </summary>
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; SupportIntervals = intervals;
} }
@ -68,6 +70,9 @@ namespace CryptoExchange.Net.SharedApis
if (!IsSupported(request.Interval)) if (!IsSupported(request.Interval))
return ArgumentError.Invalid(nameof(GetKlinesRequest.Interval), "Interval not supported"); 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)) if (MaxAge.HasValue && request.StartTime < DateTime.UtcNow.Add(-MaxAge.Value))
return ArgumentError.Invalid(nameof(GetKlinesRequest.StartTime), $"Only the most recent {MaxAge} klines are available"); 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) public override string ToString(string exchange)
{ {
var sb = new StringBuilder(base.ToString(exchange)); var sb = new StringBuilder(base.ToString(exchange));
sb.AppendLine($"Time filter supported: {TimePeriodFilterSupport}");
sb.AppendLine($"Supported SharedKlineInterval values: {string.Join(", ", SupportIntervals)}"); sb.AppendLine($"Supported SharedKlineInterval values: {string.Join(", ", SupportIntervals)}");
if (MaxAge != null) if (MaxAge != null)
sb.AppendLine($"Max age of data: {MaxAge}"); sb.AppendLine($"Max age of data: {MaxAge}");

View File

@ -1,4 +1,7 @@
namespace CryptoExchange.Net.SharedApis using CryptoExchange.Net.Objects;
using System.Text;
namespace CryptoExchange.Net.SharedApis
{ {
/// <summary> /// <summary>
/// Options for requesting position history /// Options for requesting position history
@ -8,8 +11,26 @@
/// <summary> /// <summary>
/// ctor /// ctor
/// </summary> /// </summary>
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)
{ {
} }
/// <inheritdoc />
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);
}
/// <inheritdoc />
public override string ToString(string exchange)
{
var sb = new StringBuilder(base.ToString(exchange));
sb.AppendLine($"Time filter supported: {TimePeriodFilterSupport}");
return sb.ToString();
}
} }
} }

View File

@ -17,7 +17,8 @@ namespace CryptoExchange.Net.SharedApis
/// <summary> /// <summary>
/// ctor /// ctor
/// </summary> /// </summary>
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)
{ {
} }

View File

@ -8,23 +8,18 @@ namespace CryptoExchange.Net.SharedApis
/// </summary> /// </summary>
public class GetWithdrawalsOptions : PaginatedEndpointOptions<GetWithdrawalsRequest> public class GetWithdrawalsOptions : PaginatedEndpointOptions<GetWithdrawalsRequest>
{ {
/// <summary>
/// Whether the start/end time filter is supported
/// </summary>
public bool TimeFilterSupported { get; set; }
/// <summary> /// <summary>
/// ctor /// ctor
/// </summary> /// </summary>
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;
} }
/// <inheritdoc /> /// <inheritdoc />
public override Error? ValidateRequest(string exchange, GetWithdrawalsRequest request, TradingMode? tradingMode, TradingMode[] supportedApiTypes) 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 ArgumentError.Invalid(nameof(GetWithdrawalsRequest.StartTime), $"Time filter is not supported");
return base.ValidateRequest(exchange, request, tradingMode, supportedApiTypes); return base.ValidateRequest(exchange, request, tradingMode, supportedApiTypes);
@ -34,7 +29,7 @@ namespace CryptoExchange.Net.SharedApis
public override string ToString(string exchange) public override string ToString(string exchange)
{ {
var sb = new StringBuilder(base.ToString(exchange)); var sb = new StringBuilder(base.ToString(exchange));
sb.AppendLine($"Time filter supported: {TimeFilterSupported}"); sb.AppendLine($"Time filter supported: {TimePeriodFilterSupport}");
return sb.ToString(); return sb.ToString();
} }
} }

View File

@ -1,33 +0,0 @@
using System.Diagnostics.CodeAnalysis;
using System.Text;
namespace CryptoExchange.Net.SharedApis
{
/// <summary>
/// Options for paginated endpoints
/// </summary>
/// <typeparam name="T"></typeparam>
#if NET5_0_OR_GREATER
public class PageEndpointOptions<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)] T> : EndpointOptions<T> where T : SharedRequest
#else
public class PageEndpointOptions<T> : EndpointOptions<T> where T : SharedRequest
#endif
{
/// <summary>
/// ctor
/// </summary>
public PageEndpointOptions(bool needsAuthentication) : base(needsAuthentication)
{
}
/// <inheritdoc />
public override string ToString(string exchange)
{
var sb = new StringBuilder(base.ToString(exchange));
return sb.ToString();
}
}
}

View File

@ -13,13 +13,14 @@ namespace CryptoExchange.Net.SharedApis
public class PaginatedEndpointOptions<T> : EndpointOptions<T> where T : SharedRequest public class PaginatedEndpointOptions<T> : EndpointOptions<T> where T : SharedRequest
#endif #endif
{ {
///// <summary> /// <summary>
///// Type of pagination supported /// Whether ascending data retrieval and pagination is available
///// </summary> /// </summary>
//public SharedPaginationSupport PaginationSupport { get; } public bool SupportsAscending { get; set; }
/// <summary>
public bool SupportsAscendingPagination { get; set; } /// Whether ascending data retrieval and pagination is available
public bool SupportsDescendingPagination { get; set; } /// </summary>
public bool SupportsDescending { get; set; }
/// <summary> /// <summary>
/// Whether filtering based on start/end time is supported /// Whether filtering based on start/end time is supported
@ -34,8 +35,15 @@ namespace CryptoExchange.Net.SharedApis
/// <summary> /// <summary>
/// ctor /// ctor
/// </summary> /// </summary>
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; TimePeriodFilterSupport = timePeriodSupport;
MaxLimit = maxLimit; MaxLimit = maxLimit;
} }
@ -44,8 +52,8 @@ namespace CryptoExchange.Net.SharedApis
public override string ToString(string exchange) public override string ToString(string exchange)
{ {
var sb = new StringBuilder(base.ToString(exchange)); var sb = new StringBuilder(base.ToString(exchange));
sb.AppendLine($"Pagination ASC supported: {SupportsAscendingPagination}"); sb.AppendLine($"Ascending retrieval supported: {SupportsAscending}");
sb.AppendLine($"Pagination DESC supported: {SupportsDescendingPagination}"); sb.AppendLine($"Descending retrieval supported: {SupportsDescending}");
sb.AppendLine($"Time period filter support: {TimePeriodFilterSupport}"); sb.AppendLine($"Time period filter support: {TimePeriodFilterSupport}");
sb.AppendLine($"Max limit: {MaxLimit}"); sb.AppendLine($"Max limit: {MaxLimit}");
return sb.ToString(); return sb.ToString();

View File

@ -6,32 +6,37 @@ using System.Text;
namespace CryptoExchange.Net.SharedApis namespace CryptoExchange.Net.SharedApis
{ {
public enum PageDirection public enum DataDirection
{ {
Ascending, // Old to new Ascending, // Old to new
Descending // New to old 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 class PageRequest
{ {
public string? NextCursor { get; set; } public string? Cursor { get; set; }
public int? NextPage { get; set; } public int? Page { get; set; }
public int? NextOffset { get; set; } public int? Offset { get; set; }
public string? NextFromId { get; set; } public string? FromId { get; set; }
public DateTime? NextStartTime { get; set; } public DateTime? StartTime { get; set; }
public DateTime? NextEndTime { get; set; } public DateTime? EndTime { get; set; }
public static PageRequest FromNextCursor(string nextCursor) => new PageRequest { NextCursor = nextCursor }; public static PageRequest NextCursor(string nextCursor) => new PageRequest { Cursor = nextCursor };
public static PageRequest FromNextPage(int nextPage) => new PageRequest { NextPage = nextPage }; public static PageRequest NextPage(int nextPage) => new PageRequest { Page = nextPage };
public static PageRequest FromNextOffset(int nextOffset) => new PageRequest { NextOffset = nextOffset }; public static PageRequest NextOffset(int nextOffset) => new PageRequest { Offset = nextOffset };
public static PageRequest FromNextFromIdAsc(IEnumerable<long> idSelector) => new PageRequest { NextFromId = (idSelector.Max() + 1).ToString() }; public static PageRequest NextFromIdAsc(IEnumerable<long> idSelector) => new PageRequest { FromId = (idSelector.Max() + 1).ToString() };
public static PageRequest FromNextFromIdDesc(IEnumerable<long> idSelector) => new PageRequest { NextFromId = (idSelector.Min() - 1).ToString() }; public static PageRequest NextFromIdDesc(IEnumerable<long> idSelector) => new PageRequest { FromId = (idSelector.Min() - 1).ToString() };
public static PageRequest FromNextStartTimeAsc(IEnumerable<DateTime> timestampSelector) => new PageRequest { NextStartTime = timestampSelector.Max().AddMilliseconds(1) }; public static PageRequest NextStartTimeAsc(IEnumerable<DateTime> timestampSelector) => new PageRequest { StartTime = timestampSelector.Max().AddMilliseconds(1) };
public static PageRequest FromNextStartTimeDesc(IEnumerable<DateTime> timestampSelector) => new PageRequest { NextStartTime = timestampSelector.Min().AddMilliseconds(-1) }; public static PageRequest NextEndTimeDesc(IEnumerable<DateTime> timestampSelector) => new PageRequest { EndTime = timestampSelector.Min().AddMilliseconds(-1) };
public static PageRequest FromNextEndTimeAsc(IEnumerable<DateTime> timestampSelector) => new PageRequest { NextEndTime = timestampSelector.Max().AddMilliseconds(1) };
public static PageRequest FromNextEndTimeDesc(IEnumerable<DateTime> timestampSelector) => new PageRequest { NextEndTime = timestampSelector.Min().AddMilliseconds(-1) };
} }
} }

View File

@ -19,8 +19,10 @@ namespace CryptoExchange.Net.SharedApis
/// Max number of results /// Max number of results
/// </summary> /// </summary>
public int? Limit { get; } public int? Limit { get; }
/// <summary>
public PageDirection? Direction { get; set; } /// Data direction
/// </summary>
public DataDirection? Direction { get; set; }
/// <summary> /// <summary>
/// ctor /// ctor
@ -29,12 +31,14 @@ namespace CryptoExchange.Net.SharedApis
/// <param name="startTime">Filter by start time</param> /// <param name="startTime">Filter by start time</param>
/// <param name="endTime">Filter by end time</param> /// <param name="endTime">Filter by end time</param>
/// <param name="limit">Max number of results</param> /// <param name="limit">Max number of results</param>
/// <param name="direction">Data direction</param>
/// <param name="exchangeParameters">Exchange specific parameters</param> /// <param name="exchangeParameters">Exchange specific parameters</param>
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; StartTime = startTime;
EndTime = endTime; EndTime = endTime;
Limit = limit; Limit = limit;
Direction = direction;
} }
} }
} }

View File

@ -23,6 +23,10 @@ namespace CryptoExchange.Net.SharedApis
/// Max number of results /// Max number of results
/// </summary> /// </summary>
public int? Limit { get; } public int? Limit { get; }
/// <summary>
/// Data direction
/// </summary>
public DataDirection? Direction { get; set; }
/// <summary> /// <summary>
/// ctor /// ctor
@ -31,13 +35,15 @@ namespace CryptoExchange.Net.SharedApis
/// <param name="startTime">Filter by start time</param> /// <param name="startTime">Filter by start time</param>
/// <param name="endTime">Filter by end time</param> /// <param name="endTime">Filter by end time</param>
/// <param name="limit">Max number of results</param> /// <param name="limit">Max number of results</param>
/// <param name="direction">Data direction</param>
/// <param name="exchangeParameters">Exchange specific parameters</param> /// <param name="exchangeParameters">Exchange specific parameters</param>
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; Asset = asset;
StartTime = startTime; StartTime = startTime;
EndTime = endTime; EndTime = endTime;
Limit = limit; Limit = limit;
Direction = direction;
} }
} }
} }

View File

@ -19,6 +19,10 @@ namespace CryptoExchange.Net.SharedApis
/// Max number of results /// Max number of results
/// </summary> /// </summary>
public int? Limit { get; set; } public int? Limit { get; set; }
/// <summary>
/// Data direction
/// </summary>
public DataDirection? Direction { get; set; }
/// <summary> /// <summary>
/// ctor /// ctor
@ -27,12 +31,14 @@ namespace CryptoExchange.Net.SharedApis
/// <param name="startTime">Filter by start time</param> /// <param name="startTime">Filter by start time</param>
/// <param name="endTime">Filter by end time</param> /// <param name="endTime">Filter by end time</param>
/// <param name="limit">Max number of results</param> /// <param name="limit">Max number of results</param>
/// <param name="direction">Data direction</param>
/// <param name="exchangeParameters">Exchange specific parameters</param> /// <param name="exchangeParameters">Exchange specific parameters</param>
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; StartTime = startTime;
EndTime = endTime; EndTime = endTime;
Limit = limit; Limit = limit;
Direction = direction;
} }
} }
} }

View File

@ -23,6 +23,10 @@ namespace CryptoExchange.Net.SharedApis
/// Max number of results /// Max number of results
/// </summary> /// </summary>
public int? Limit { get; set; } public int? Limit { get; set; }
/// <summary>
/// Data direction
/// </summary>
public DataDirection? Direction { get; set; }
/// <summary> /// <summary>
/// ctor /// ctor
@ -32,13 +36,15 @@ namespace CryptoExchange.Net.SharedApis
/// <param name="startTime">Filter by start time</param> /// <param name="startTime">Filter by start time</param>
/// <param name="endTime">Filter by end time</param> /// <param name="endTime">Filter by end time</param>
/// <param name="limit">Max number of results</param> /// <param name="limit">Max number of results</param>
/// <param name="direction">Data direction</param>
/// <param name="exchangeParameters">Exchange specific parameters</param> /// <param name="exchangeParameters">Exchange specific parameters</param>
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; Interval = interval;
StartTime = startTime; StartTime = startTime;
EndTime = endTime; EndTime = endTime;
Limit = limit; Limit = limit;
Direction = direction;
} }
} }
} }

View File

@ -27,6 +27,10 @@ namespace CryptoExchange.Net.SharedApis
/// Max number of results /// Max number of results
/// </summary> /// </summary>
public int? Limit { get; set; } public int? Limit { get; set; }
/// <summary>
/// Data direction
/// </summary>
public DataDirection? Direction { get; set; }
/// <summary> /// <summary>
/// ctor /// ctor
@ -35,13 +39,15 @@ namespace CryptoExchange.Net.SharedApis
/// <param name="startTime">Filter by start time</param> /// <param name="startTime">Filter by start time</param>
/// <param name="endTime">Filter by end time</param> /// <param name="endTime">Filter by end time</param>
/// <param name="limit">Max number of results</param> /// <param name="limit">Max number of results</param>
/// <param name="direction">Data direction</param>
/// <param name="exchangeParameters">Exchange specific parameters</param> /// <param name="exchangeParameters">Exchange specific parameters</param>
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; Symbol = symbol;
StartTime = startTime; StartTime = startTime;
EndTime = endTime; EndTime = endTime;
Limit = limit; Limit = limit;
Direction = direction;
} }
/// <summary> /// <summary>
@ -51,13 +57,15 @@ namespace CryptoExchange.Net.SharedApis
/// <param name="startTime">Filter by start time</param> /// <param name="startTime">Filter by start time</param>
/// <param name="endTime">Filter by end time</param> /// <param name="endTime">Filter by end time</param>
/// <param name="limit">Max number of results</param> /// <param name="limit">Max number of results</param>
/// <param name="direction">Data direction</param>
/// <param name="exchangeParameters">Exchange specific parameters</param> /// <param name="exchangeParameters">Exchange specific parameters</param>
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; TradingMode = tradeMode;
StartTime = startTime; StartTime = startTime;
EndTime = endTime; EndTime = endTime;
Limit = limit; Limit = limit;
Direction = direction;
} }
} }
} }

View File

@ -19,8 +19,10 @@ namespace CryptoExchange.Net.SharedApis
/// Max number of results /// Max number of results
/// </summary> /// </summary>
public int? Limit { get; set; } public int? Limit { get; set; }
/// <summary>
public PageDirection? Direction { get; set; } /// Data direction
/// </summary>
public DataDirection? Direction { get; set; }
/// <summary> /// <summary>
/// ctor /// ctor
@ -29,12 +31,14 @@ namespace CryptoExchange.Net.SharedApis
/// <param name="startTime">Filter by start time</param> /// <param name="startTime">Filter by start time</param>
/// <param name="endTime">Filter by end time</param> /// <param name="endTime">Filter by end time</param>
/// <param name="limit">Max number of results</param> /// <param name="limit">Max number of results</param>
/// <param name="direction">Data direction</param>
/// <param name="exchangeParameters">Exchange specific parameters</param> /// <param name="exchangeParameters">Exchange specific parameters</param>
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; StartTime = startTime;
EndTime = endTime; EndTime = endTime;
Limit = limit; Limit = limit;
Direction = direction;
} }
} }
} }

View File

@ -19,6 +19,10 @@ namespace CryptoExchange.Net.SharedApis
/// Max number of results /// Max number of results
/// </summary> /// </summary>
public int? Limit { get; } public int? Limit { get; }
/// <summary>
/// Data direction
/// </summary>
public DataDirection? Direction { get; set; }
/// <summary> /// <summary>
/// ctor /// ctor
@ -27,12 +31,14 @@ namespace CryptoExchange.Net.SharedApis
/// <param name="startTime">Filter by start time</param> /// <param name="startTime">Filter by start time</param>
/// <param name="endTime">Filter by end time</param> /// <param name="endTime">Filter by end time</param>
/// <param name="limit">Max number of results</param> /// <param name="limit">Max number of results</param>
/// <param name="direction">Data direction</param>
/// <param name="exchangeParameters">Exchange specific parameters</param> /// <param name="exchangeParameters">Exchange specific parameters</param>
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; StartTime = startTime;
EndTime = endTime; EndTime = endTime;
Limit = limit; Limit = limit;
Direction = direction;
} }
} }
} }

View File

@ -23,6 +23,10 @@ namespace CryptoExchange.Net.SharedApis
/// Max number of results /// Max number of results
/// </summary> /// </summary>
public int? Limit { get; } public int? Limit { get; }
/// <summary>
/// Data direction
/// </summary>
public DataDirection? Direction { get; set; }
/// <summary> /// <summary>
/// ctor /// ctor
@ -31,13 +35,15 @@ namespace CryptoExchange.Net.SharedApis
/// <param name="startTime">Filter by start time</param> /// <param name="startTime">Filter by start time</param>
/// <param name="endTime">Filter by end time</param> /// <param name="endTime">Filter by end time</param>
/// <param name="limit">Max number of results</param> /// <param name="limit">Max number of results</param>
/// <param name="direction">Data direction</param>
/// <param name="exchangeParameters">Exchange specific parameters</param> /// <param name="exchangeParameters">Exchange specific parameters</param>
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; Asset = asset;
StartTime = startTime; StartTime = startTime;
EndTime = endTime; EndTime = endTime;
Limit = limit; Limit = limit;
Direction = direction;
} }
} }
} }