diff --git a/CryptoExchange.Net/Interfaces/IRateLimiter.cs b/CryptoExchange.Net/Interfaces/IRateLimiter.cs
index 735f3ec..df6b494 100644
--- a/CryptoExchange.Net/Interfaces/IRateLimiter.cs
+++ b/CryptoExchange.Net/Interfaces/IRateLimiter.cs
@@ -1,4 +1,4 @@
-using CryptoExchange.Net.Objects;
+using CryptoExchange.Net.Objects;
namespace CryptoExchange.Net.Interfaces
{
@@ -13,7 +13,8 @@ namespace CryptoExchange.Net.Interfaces
///
///
///
+ ///
///
- CallResult LimitRequest(RestClient client, string url, RateLimitingBehaviour limitBehaviour);
+ CallResult LimitRequest(RestClient client, string url, RateLimitingBehaviour limitBehaviour, int credits=1);
}
}
diff --git a/CryptoExchange.Net/RateLimiter/RateLimiterAPIKey.cs b/CryptoExchange.Net/RateLimiter/RateLimiterAPIKey.cs
index 0b2dddf..8bfe2f6 100644
--- a/CryptoExchange.Net/RateLimiter/RateLimiterAPIKey.cs
+++ b/CryptoExchange.Net/RateLimiter/RateLimiterAPIKey.cs
@@ -34,7 +34,7 @@ namespace CryptoExchange.Net.RateLimiter
}
///
- public CallResult LimitRequest(RestClient client, string url, RateLimitingBehaviour limitBehaviour)
+ public CallResult LimitRequest(RestClient client, string url, RateLimitingBehaviour limitBehaviour, int credits = 1)
{
if(client.authProvider?.Credentials?.Key == null)
return new CallResult(0, null);
diff --git a/CryptoExchange.Net/RateLimiter/RateLimiterCredit.cs b/CryptoExchange.Net/RateLimiter/RateLimiterCredit.cs
new file mode 100644
index 0000000..ef6cc2b
--- /dev/null
+++ b/CryptoExchange.Net/RateLimiter/RateLimiterCredit.cs
@@ -0,0 +1,65 @@
+using CryptoExchange.Net.Interfaces;
+using CryptoExchange.Net.Objects;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Threading;
+
+namespace CryptoExchange.Net.RateLimiter
+{
+ ///
+ /// Limits the amount of requests per time period to a certain limit, counts the total amount of requests.
+ ///
+ public class RateLimiterCredit : IRateLimiter
+ {
+ internal List history = new List();
+
+ private readonly int limit;
+ private readonly TimeSpan perTimePeriod;
+ private readonly object requestLock = new object();
+
+ ///
+ /// Create a new RateLimiterTotal. This rate limiter limits the amount of requests per time period to a certain limit, counts the total amount of requests.
+ ///
+ /// The amount to limit to
+ /// The time period over which the limit counts
+ public RateLimiterCredit(int limit, TimeSpan perTimePeriod)
+ {
+ this.limit = limit;
+ this.perTimePeriod = perTimePeriod;
+ }
+
+ ///
+ public CallResult LimitRequest(RestClient client, string url, RateLimitingBehaviour limitBehaviour, int credits = 1)
+ {
+ var sw = Stopwatch.StartNew();
+ lock (requestLock)
+ {
+ sw.Stop();
+ double waitTime = 0;
+ var checkTime = DateTime.UtcNow;
+ history.RemoveAll(d => d < checkTime - perTimePeriod);
+
+ if (history.Count >= limit)
+ {
+ waitTime = (history.First() - (checkTime - perTimePeriod)).TotalMilliseconds;
+ if (waitTime > 0)
+ {
+ if (limitBehaviour == RateLimitingBehaviour.Fail)
+ return new CallResult(waitTime, new RateLimitError($"total limit of {limit} reached"));
+
+ Thread.Sleep(Convert.ToInt32(waitTime));
+ waitTime += sw.ElapsedMilliseconds;
+ }
+ }
+
+ for (int i = 1; i <= credits; i++)
+ history.Add(DateTime.UtcNow);
+
+ history.Sort();
+ return new CallResult(waitTime, null);
+ }
+ }
+ }
+}
diff --git a/CryptoExchange.Net/RateLimiter/RateLimiterPerEndpoint.cs b/CryptoExchange.Net/RateLimiter/RateLimiterPerEndpoint.cs
index fb62900..f137ae3 100644
--- a/CryptoExchange.Net/RateLimiter/RateLimiterPerEndpoint.cs
+++ b/CryptoExchange.Net/RateLimiter/RateLimiterPerEndpoint.cs
@@ -30,7 +30,7 @@ namespace CryptoExchange.Net.RateLimiter
}
///
- public CallResult LimitRequest(RestClient client, string url, RateLimitingBehaviour limitingBehaviour)
+ public CallResult LimitRequest(RestClient client, string url, RateLimitingBehaviour limitingBehaviour, int credits = 1)
{
int waitTime;
RateLimitObject rlo;
diff --git a/CryptoExchange.Net/RateLimiter/RateLimiterTotal.cs b/CryptoExchange.Net/RateLimiter/RateLimiterTotal.cs
index 85919e6..a5d1792 100644
--- a/CryptoExchange.Net/RateLimiter/RateLimiterTotal.cs
+++ b/CryptoExchange.Net/RateLimiter/RateLimiterTotal.cs
@@ -31,7 +31,7 @@ namespace CryptoExchange.Net.RateLimiter
}
///
- public CallResult LimitRequest(RestClient client, string url, RateLimitingBehaviour limitBehaviour)
+ public CallResult LimitRequest(RestClient client, string url, RateLimitingBehaviour limitBehaviour, int credits = 1)
{
var sw = Stopwatch.StartNew();
lock (requestLock)
diff --git a/CryptoExchange.Net/RestClient.cs b/CryptoExchange.Net/RestClient.cs
index d3372fa..bc8bdd5 100644
--- a/CryptoExchange.Net/RestClient.cs
+++ b/CryptoExchange.Net/RestClient.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
@@ -172,7 +172,7 @@ namespace CryptoExchange.Net
///
[return: NotNull]
protected virtual async Task> SendRequest(Uri uri, HttpMethod method, CancellationToken cancellationToken,
- Dictionary? parameters = null, bool signed = false, bool checkResult = true, PostParameters? postPosition = null, ArrayParametersSerialization? arraySerialization = null) where T : class
+ Dictionary? parameters = null, bool signed = false, bool checkResult = true, PostParameters? postPosition = null, ArrayParametersSerialization? arraySerialization = null, int credits=1) where T : class
{
var requestId = NextId();
log.Write(LogVerbosity.Debug, $"[{requestId}] Creating request for " + uri);
@@ -185,7 +185,7 @@ namespace CryptoExchange.Net
var request = ConstructRequest(uri, method, parameters, signed, postPosition ?? postParametersPosition, arraySerialization ?? this.arraySerialization, requestId);
foreach (var limiter in RateLimiters)
{
- var limitResult = limiter.LimitRequest(this, uri.AbsolutePath, RateLimitBehaviour);
+ var limitResult = limiter.LimitRequest(this, uri.AbsolutePath, RateLimitBehaviour, credits);
if (!limitResult.Success)
{
log.Write(LogVerbosity.Debug, $"[{requestId}] Request {uri.AbsolutePath} failed because of rate limit");