mirror of
https://github.com/JKorf/CryptoExchange.Net.git
synced 2026-10-21 02:20:56 +00:00
Compare commits
5 Commits
45a42fb028
...
b9f93cb3fe
| Author | SHA1 | Date | |
|---|---|---|---|
| b9f93cb3fe | |||
| 15f7ba32e1 | |||
| a34684cd31 | |||
| e5da147ba8 | |||
| 404d62ee5c |
@@ -33,12 +33,12 @@ namespace CryptoExchange.Net.UnitTests
|
|||||||
|
|
||||||
for (var i = 0; i < requests + 1; i++)
|
for (var i = 0; i < requests + 1; i++)
|
||||||
{
|
{
|
||||||
var result1 = await rateLimiter.ProcessAsync(new TraceLogger(), 1, RateLimitItemType.Request, requestDefinition, "123", 1, RateLimitingBehaviour.Wait, null, default);
|
var result1 = await rateLimiter.ProcessAsync(new TraceLogger(), 1, RateLimitItemType.Request, requestDefinition, "123", 1, RateLimitingBehaviour.Wait, null, 1, default);
|
||||||
Assert.That(i == requests ? triggered : !triggered);
|
Assert.That(i == requests ? triggered : !triggered);
|
||||||
}
|
}
|
||||||
triggered = false;
|
triggered = false;
|
||||||
await Task.Delay((int)Math.Round(perSeconds * 1000) + 10);
|
await Task.Delay((int)Math.Round(perSeconds * 1000) + 10);
|
||||||
var result2 = await rateLimiter.ProcessAsync(new TraceLogger(), 1, RateLimitItemType.Request, requestDefinition, "123", 1, RateLimitingBehaviour.Wait, null, default);
|
var result2 = await rateLimiter.ProcessAsync(new TraceLogger(), 1, RateLimitItemType.Request, requestDefinition, "123", 1, RateLimitingBehaviour.Wait, null, 1, default);
|
||||||
Assert.That(!triggered);
|
Assert.That(!triggered);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,7 +58,7 @@ namespace CryptoExchange.Net.UnitTests
|
|||||||
rateLimiter.RateLimitTriggered += (x) => { evnt = x; };
|
rateLimiter.RateLimitTriggered += (x) => { evnt = x; };
|
||||||
for (var i = 0; i < 2; i++)
|
for (var i = 0; i < 2; i++)
|
||||||
{
|
{
|
||||||
var result1 = await rateLimiter.ProcessAsync(new TraceLogger(), 1, RateLimitItemType.Request, requestDefinition, "123", 1, RateLimitingBehaviour.Wait, null, default);
|
var result1 = await rateLimiter.ProcessAsync(new TraceLogger(), 1, RateLimitItemType.Request, requestDefinition, "123", 1, RateLimitingBehaviour.Wait, null, 1, default);
|
||||||
bool expected = i == 1 ? expectLimiting ? evnt?.DelayTime > TimeSpan.Zero : evnt == null : evnt == null;
|
bool expected = i == 1 ? expectLimiting ? evnt?.DelayTime > TimeSpan.Zero : evnt == null : evnt == null;
|
||||||
Assert.That(expected);
|
Assert.That(expected);
|
||||||
}
|
}
|
||||||
@@ -79,9 +79,9 @@ namespace CryptoExchange.Net.UnitTests
|
|||||||
RateLimitEvent? evnt = null;
|
RateLimitEvent? evnt = null;
|
||||||
rateLimiter.RateLimitTriggered += (x) => { evnt = x; };
|
rateLimiter.RateLimitTriggered += (x) => { evnt = x; };
|
||||||
|
|
||||||
var result1 = await rateLimiter.ProcessAsync(new TraceLogger(), 1, RateLimitItemType.Request, requestDefinition1, "123", 1, RateLimitingBehaviour.Wait, null, default);
|
var result1 = await rateLimiter.ProcessAsync(new TraceLogger(), 1, RateLimitItemType.Request, requestDefinition1, "123", 1, RateLimitingBehaviour.Wait, null, 1, default);
|
||||||
Assert.That(evnt == null);
|
Assert.That(evnt == null);
|
||||||
var result2 = await rateLimiter.ProcessAsync(new TraceLogger(), 1, RateLimitItemType.Request, requestDefinition2, "123", 1, RateLimitingBehaviour.Wait, null, default);
|
var result2 = await rateLimiter.ProcessAsync(new TraceLogger(), 1, RateLimitItemType.Request, requestDefinition2, "123", 1, RateLimitingBehaviour.Wait, null, 1, default);
|
||||||
Assert.That(expectLimiting ? evnt != null : evnt == null);
|
Assert.That(expectLimiting ? evnt != null : evnt == null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,12 +100,12 @@ namespace CryptoExchange.Net.UnitTests
|
|||||||
|
|
||||||
for (var i = 0; i < requests + 1; i++)
|
for (var i = 0; i < requests + 1; i++)
|
||||||
{
|
{
|
||||||
var result1 = await rateLimiter.ProcessAsync(new TraceLogger(), 1, RateLimitItemType.Request, requestDefinition, "123", 1, RateLimitingBehaviour.Wait, null, default);
|
var result1 = await rateLimiter.ProcessAsync(new TraceLogger(), 1, RateLimitItemType.Request, requestDefinition, "123", 1, RateLimitingBehaviour.Wait, null, 1, default);
|
||||||
Assert.That(i == requests ? triggered : !triggered);
|
Assert.That(i == requests ? triggered : !triggered);
|
||||||
}
|
}
|
||||||
triggered = false;
|
triggered = false;
|
||||||
await Task.Delay((int)Math.Round(perSeconds * 1000) + 10);
|
await Task.Delay((int)Math.Round(perSeconds * 1000) + 10);
|
||||||
var result2 = await rateLimiter.ProcessAsync(new TraceLogger(), 1, RateLimitItemType.Request, requestDefinition, "123", 1, RateLimitingBehaviour.Wait, null, default);
|
var result2 = await rateLimiter.ProcessAsync(new TraceLogger(), 1, RateLimitItemType.Request, requestDefinition, "123", 1, RateLimitingBehaviour.Wait, null, 1, default);
|
||||||
Assert.That(!triggered);
|
Assert.That(!triggered);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -123,7 +123,7 @@ namespace CryptoExchange.Net.UnitTests
|
|||||||
rateLimiter.RateLimitTriggered += (x) => { evnt = x; };
|
rateLimiter.RateLimitTriggered += (x) => { evnt = x; };
|
||||||
for (var i = 0; i < 2; i++)
|
for (var i = 0; i < 2; i++)
|
||||||
{
|
{
|
||||||
var result1 = await rateLimiter.ProcessAsync(new TraceLogger(), 1, RateLimitItemType.Request, requestDefinition, "123", 1, RateLimitingBehaviour.Wait, null, default);
|
var result1 = await rateLimiter.ProcessAsync(new TraceLogger(), 1, RateLimitItemType.Request, requestDefinition, "123", 1, RateLimitingBehaviour.Wait, null, 1, default);
|
||||||
bool expected = i == 1 ? expectLimited ? evnt?.DelayTime > TimeSpan.Zero : evnt == null : evnt == null;
|
bool expected = i == 1 ? expectLimited ? evnt?.DelayTime > TimeSpan.Zero : evnt == null : evnt == null;
|
||||||
Assert.That(expected);
|
Assert.That(expected);
|
||||||
}
|
}
|
||||||
@@ -143,7 +143,7 @@ namespace CryptoExchange.Net.UnitTests
|
|||||||
rateLimiter.RateLimitTriggered += (x) => { evnt = x; };
|
rateLimiter.RateLimitTriggered += (x) => { evnt = x; };
|
||||||
for (var i = 0; i < 2; i++)
|
for (var i = 0; i < 2; i++)
|
||||||
{
|
{
|
||||||
var result1 = await rateLimiter.ProcessAsync(new TraceLogger(), 1, RateLimitItemType.Request, requestDefinition, "123", 1, RateLimitingBehaviour.Wait, null, default);
|
var result1 = await rateLimiter.ProcessAsync(new TraceLogger(), 1, RateLimitItemType.Request, requestDefinition, "123", 1, RateLimitingBehaviour.Wait, null, 1, default);
|
||||||
bool expected = i == 1 ? expectLimited ? evnt?.DelayTime > TimeSpan.Zero : evnt == null : evnt == null;
|
bool expected = i == 1 ? expectLimited ? evnt?.DelayTime > TimeSpan.Zero : evnt == null : evnt == null;
|
||||||
Assert.That(expected);
|
Assert.That(expected);
|
||||||
}
|
}
|
||||||
@@ -166,9 +166,9 @@ namespace CryptoExchange.Net.UnitTests
|
|||||||
RateLimitEvent? evnt = null;
|
RateLimitEvent? evnt = null;
|
||||||
rateLimiter.RateLimitTriggered += (x) => { evnt = x; };
|
rateLimiter.RateLimitTriggered += (x) => { evnt = x; };
|
||||||
|
|
||||||
var result1 = await rateLimiter.ProcessAsync(new TraceLogger(), 1, RateLimitItemType.Request, requestDefinition1, key1, 1, RateLimitingBehaviour.Wait, null, default);
|
var result1 = await rateLimiter.ProcessAsync(new TraceLogger(), 1, RateLimitItemType.Request, requestDefinition1, key1, 1, RateLimitingBehaviour.Wait, null, 1, default);
|
||||||
Assert.That(evnt == null);
|
Assert.That(evnt == null);
|
||||||
var result2 = await rateLimiter.ProcessAsync(new TraceLogger(), 1, RateLimitItemType.Request, requestDefinition2, key2, 1, RateLimitingBehaviour.Wait, null, default);
|
var result2 = await rateLimiter.ProcessAsync(new TraceLogger(), 1, RateLimitItemType.Request, requestDefinition2, key2, 1, RateLimitingBehaviour.Wait, null, 1, default);
|
||||||
Assert.That(expectLimited ? evnt != null : evnt == null);
|
Assert.That(expectLimited ? evnt != null : evnt == null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -185,9 +185,9 @@ namespace CryptoExchange.Net.UnitTests
|
|||||||
RateLimitEvent? evnt = null;
|
RateLimitEvent? evnt = null;
|
||||||
rateLimiter.RateLimitTriggered += (x) => { evnt = x; };
|
rateLimiter.RateLimitTriggered += (x) => { evnt = x; };
|
||||||
|
|
||||||
var result1 = await rateLimiter.ProcessAsync(new TraceLogger(), 1, RateLimitItemType.Request, requestDefinition1, "123", 1, RateLimitingBehaviour.Wait, null, default);
|
var result1 = await rateLimiter.ProcessAsync(new TraceLogger(), 1, RateLimitItemType.Request, requestDefinition1, "123", 1, RateLimitingBehaviour.Wait, null, 1, default);
|
||||||
Assert.That(evnt == null);
|
Assert.That(evnt == null);
|
||||||
var result2 = await rateLimiter.ProcessAsync(new TraceLogger(), 1, RateLimitItemType.Request, requestDefinition2, null, 1, RateLimitingBehaviour.Wait, null, default);
|
var result2 = await rateLimiter.ProcessAsync(new TraceLogger(), 1, RateLimitItemType.Request, requestDefinition2, null, 1, RateLimitingBehaviour.Wait, null, 1, default);
|
||||||
Assert.That(expectLimited ? evnt != null : evnt == null);
|
Assert.That(expectLimited ? evnt != null : evnt == null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -205,9 +205,9 @@ namespace CryptoExchange.Net.UnitTests
|
|||||||
RateLimitEvent? evnt = null;
|
RateLimitEvent? evnt = null;
|
||||||
rateLimiter.RateLimitTriggered += (x) => { evnt = x; };
|
rateLimiter.RateLimitTriggered += (x) => { evnt = x; };
|
||||||
|
|
||||||
var result1 = await rateLimiter.ProcessAsync(new TraceLogger(), 1, RateLimitItemType.Request, requestDefinition1, "123", 1, RateLimitingBehaviour.Wait, null, default);
|
var result1 = await rateLimiter.ProcessAsync(new TraceLogger(), 1, RateLimitItemType.Request, requestDefinition1, "123", 1, RateLimitingBehaviour.Wait, null, 1, default);
|
||||||
Assert.That(evnt == null);
|
Assert.That(evnt == null);
|
||||||
var result2 = await rateLimiter.ProcessAsync(new TraceLogger(), 1, RateLimitItemType.Request, requestDefinition2, "123", 1, RateLimitingBehaviour.Wait, null, default);
|
var result2 = await rateLimiter.ProcessAsync(new TraceLogger(), 1, RateLimitItemType.Request, requestDefinition2, "123", 1, RateLimitingBehaviour.Wait, null, 1, default);
|
||||||
Assert.That(expectLimited ? evnt != null : evnt == null);
|
Assert.That(expectLimited ? evnt != null : evnt == null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -222,9 +222,9 @@ namespace CryptoExchange.Net.UnitTests
|
|||||||
RateLimitEvent? evnt = null;
|
RateLimitEvent? evnt = null;
|
||||||
rateLimiter.RateLimitTriggered += (x) => { evnt = x; };
|
rateLimiter.RateLimitTriggered += (x) => { evnt = x; };
|
||||||
|
|
||||||
var result1 = await rateLimiter.ProcessAsync(new TraceLogger(), 1, RateLimitItemType.Connection, new RequestDefinition(host1, "1", HttpMethod.Get), "123", 1, RateLimitingBehaviour.Wait, null, default);
|
var result1 = await rateLimiter.ProcessAsync(new TraceLogger(), 1, RateLimitItemType.Connection, new RequestDefinition(host1, "1", HttpMethod.Get), "123", 1, RateLimitingBehaviour.Wait, null, 1, default);
|
||||||
Assert.That(evnt == null);
|
Assert.That(evnt == null);
|
||||||
var result2 = await rateLimiter.ProcessAsync(new TraceLogger(), 1, RateLimitItemType.Connection, new RequestDefinition(host2, "1", HttpMethod.Get), "123", 1, RateLimitingBehaviour.Wait, null, default);
|
var result2 = await rateLimiter.ProcessAsync(new TraceLogger(), 1, RateLimitItemType.Connection, new RequestDefinition(host2, "1", HttpMethod.Get), "123", 1, RateLimitingBehaviour.Wait, null, 1, default);
|
||||||
Assert.That(expectLimited ? evnt != null : evnt == null);
|
Assert.That(expectLimited ? evnt != null : evnt == null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -238,8 +238,8 @@ namespace CryptoExchange.Net.UnitTests
|
|||||||
rateLimiter.RateLimitTriggered += (x) => { evnt = x; };
|
rateLimiter.RateLimitTriggered += (x) => { evnt = x; };
|
||||||
var ct = new CancellationTokenSource(TimeSpan.FromSeconds(0.2));
|
var ct = new CancellationTokenSource(TimeSpan.FromSeconds(0.2));
|
||||||
|
|
||||||
var result1 = await rateLimiter.ProcessAsync(new TraceLogger(), 1, RateLimitItemType.Connection, new RequestDefinition("https://test.com", "1", HttpMethod.Get), "123", 1, RateLimitingBehaviour.Wait, null, ct.Token);
|
var result1 = await rateLimiter.ProcessAsync(new TraceLogger(), 1, RateLimitItemType.Connection, new RequestDefinition("https://test.com", "1", HttpMethod.Get), "123", 1, RateLimitingBehaviour.Wait, null, 1, ct.Token);
|
||||||
var result2 = await rateLimiter.ProcessAsync(new TraceLogger(), 1, RateLimitItemType.Connection, new RequestDefinition("https://test.com", "1", HttpMethod.Get), "123", 1, RateLimitingBehaviour.Wait, null, ct.Token);
|
var result2 = await rateLimiter.ProcessAsync(new TraceLogger(), 1, RateLimitItemType.Connection, new RequestDefinition("https://test.com", "1", HttpMethod.Get), "123", 1, RateLimitingBehaviour.Wait, null, 1, ct.Token);
|
||||||
Assert.That(result2.Error, Is.TypeOf<CancellationRequestedError>());
|
Assert.That(result2.Error, Is.TypeOf<CancellationRequestedError>());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -257,9 +257,9 @@ namespace CryptoExchange.Net.UnitTests
|
|||||||
var ct = new CancellationTokenSource(TimeSpan.FromSeconds(0.2));
|
var ct = new CancellationTokenSource(TimeSpan.FromSeconds(0.2));
|
||||||
|
|
||||||
// act
|
// act
|
||||||
var result1 = await rateLimiter.ProcessAsync(new TraceLogger(), 1, RateLimitItemType.Request, definition, null, 1, RateLimitingBehaviour.Fail, null, ct.Token);
|
var result1 = await rateLimiter.ProcessAsync(new TraceLogger(), 1, RateLimitItemType.Request, definition, null, 1, RateLimitingBehaviour.Fail, null, 1, ct.Token);
|
||||||
await rateLimiter.ResetAsync(RateLimitItemType.Request, definition, null, null, null, default);
|
await rateLimiter.ResetAsync(RateLimitItemType.Request, definition, null, null, null, default);
|
||||||
var result2 = await rateLimiter.ProcessAsync(new TraceLogger(), 1, RateLimitItemType.Request, definition, null, 1, RateLimitingBehaviour.Fail, null, ct.Token);
|
var result2 = await rateLimiter.ProcessAsync(new TraceLogger(), 1, RateLimitItemType.Request, definition, null, 1, RateLimitingBehaviour.Fail, null, 1, ct.Token);
|
||||||
|
|
||||||
// assert
|
// assert
|
||||||
Assert.That(evnt, Is.Null);
|
Assert.That(evnt, Is.Null);
|
||||||
@@ -279,10 +279,10 @@ namespace CryptoExchange.Net.UnitTests
|
|||||||
rateLimiter.RateLimitTriggered += (x) => { evnt = x; };
|
rateLimiter.RateLimitTriggered += (x) => { evnt = x; };
|
||||||
|
|
||||||
// act
|
// act
|
||||||
var result1 = await rateLimiter.ProcessAsync(new TraceLogger(), 1, RateLimitItemType.Request, definition1, null, 1, RateLimitingBehaviour.Fail, null, default);
|
var result1 = await rateLimiter.ProcessAsync(new TraceLogger(), 1, RateLimitItemType.Request, definition1, null, 1, RateLimitingBehaviour.Fail, null, 1, default);
|
||||||
var result2 = await rateLimiter.ProcessAsync(new TraceLogger(), 1, RateLimitItemType.Request, definition2, null, 1, RateLimitingBehaviour.Fail, null, default);
|
var result2 = await rateLimiter.ProcessAsync(new TraceLogger(), 1, RateLimitItemType.Request, definition2, null, 1, RateLimitingBehaviour.Fail, null, 1, default);
|
||||||
await rateLimiter.ResetAsync(RateLimitItemType.Request, definition1, null, null, null, default);
|
await rateLimiter.ResetAsync(RateLimitItemType.Request, definition1, null, null, null, default);
|
||||||
var result3 = await rateLimiter.ProcessAsync(new TraceLogger(), 1, RateLimitItemType.Request, definition2, null, 1, RateLimitingBehaviour.Fail, null, default);
|
var result3 = await rateLimiter.ProcessAsync(new TraceLogger(), 1, RateLimitItemType.Request, definition2, null, 1, RateLimitingBehaviour.Fail, null, 1, default);
|
||||||
|
|
||||||
// assert
|
// assert
|
||||||
Assert.That(evnt, Is.Not.Null);
|
Assert.That(evnt, Is.Not.Null);
|
||||||
@@ -321,5 +321,48 @@ namespace CryptoExchange.Net.UnitTests
|
|||||||
// assert
|
// assert
|
||||||
Assert.That(evnt != null, Is.EqualTo(expectLimited));
|
Assert.That(evnt != null, Is.EqualTo(expectLimited));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[TestCase(RateLimitWindowType.Fixed)]
|
||||||
|
[TestCase(RateLimitWindowType.FixedAfterFirst)]
|
||||||
|
[TestCase(RateLimitWindowType.Sliding)]
|
||||||
|
[TestCase(RateLimitWindowType.Decay)]
|
||||||
|
public async Task LowerThreshold_ReservesCapacityForFullThreshold(RateLimitWindowType windowType)
|
||||||
|
{
|
||||||
|
var gate = new RateLimitGate("Test");
|
||||||
|
gate.AddGuard(new RateLimitGuard(
|
||||||
|
RateLimitGuard.PerHost,
|
||||||
|
new LimitItemTypeFilter(RateLimitItemType.Request),
|
||||||
|
10,
|
||||||
|
TimeSpan.FromHours(1),
|
||||||
|
windowType,
|
||||||
|
decayPerTimeSpan: 1));
|
||||||
|
|
||||||
|
var definition = new RequestDefinition(
|
||||||
|
"https://test.com", "/ticker", HttpMethod.Get);
|
||||||
|
var logger = new TraceLogger();
|
||||||
|
|
||||||
|
for (var i = 0; i < 8; i++)
|
||||||
|
{
|
||||||
|
var result = await gate.ProcessAsync(
|
||||||
|
logger, i, RateLimitItemType.Request, definition, null, 1,
|
||||||
|
RateLimitingBehaviour.Fail, null, 0.8, default);
|
||||||
|
Assert.That(result.Success, Is.True);
|
||||||
|
}
|
||||||
|
|
||||||
|
var marketData = await gate.ProcessAsync(
|
||||||
|
logger, 9, RateLimitItemType.Request, definition, null, 1,
|
||||||
|
RateLimitingBehaviour.Fail, null, 0.8, default);
|
||||||
|
Assert.That(marketData.Error, Is.TypeOf<ClientRateLimitError>());
|
||||||
|
|
||||||
|
var order = await gate.ProcessAsync(
|
||||||
|
logger, 10, RateLimitItemType.Request, definition, null, 2,
|
||||||
|
RateLimitingBehaviour.Fail, null, 1.0, default);
|
||||||
|
Assert.That(order.Success, Is.True);
|
||||||
|
|
||||||
|
var overHardLimit = await gate.ProcessAsync(
|
||||||
|
logger, 11, RateLimitItemType.Request, definition, null, 1,
|
||||||
|
RateLimitingBehaviour.Fail, null, 1.0, default);
|
||||||
|
Assert.That(overHardLimit.Error, Is.TypeOf<ClientRateLimitError>());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
|
using CryptoExchange.Net.Interfaces.Clients;
|
||||||
|
using CryptoExchange.Net.RateLimiting;
|
||||||
using CryptoExchange.Net.SharedApis;
|
using CryptoExchange.Net.SharedApis;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace CryptoExchange.Net.UnitTests
|
namespace CryptoExchange.Net.UnitTests
|
||||||
{
|
{
|
||||||
@@ -189,6 +193,24 @@ namespace CryptoExchange.Net.UnitTests
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private sealed class TestApiClient : IBaseApiClient
|
||||||
|
{
|
||||||
|
public string Exchange => "TestExchange";
|
||||||
|
public string BaseAddress => "https://test.invalid";
|
||||||
|
|
||||||
|
public string FormatSymbol(
|
||||||
|
string baseAsset,
|
||||||
|
string quoteAsset,
|
||||||
|
TradingMode tradingMode,
|
||||||
|
DateTime? deliverDate = null)
|
||||||
|
=> $"{baseAsset}{quoteAsset}";
|
||||||
|
|
||||||
|
public Task<TResult> WithRateLimitAdmissionAsync<TResult>(
|
||||||
|
RateLimitAdmission admission,
|
||||||
|
Func<Task<TResult>> operation)
|
||||||
|
=> operation();
|
||||||
|
}
|
||||||
|
|
||||||
private interface ITestRestCapability : ITestCapability, ISharedRest
|
private interface ITestRestCapability : ITestCapability, ISharedRest
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -236,7 +258,7 @@ namespace CryptoExchange.Net.UnitTests
|
|||||||
TradingMode[]? applicableTradingModes)
|
TradingMode[]? applicableTradingModes)
|
||||||
: base(
|
: base(
|
||||||
SharedTransport.Rest,
|
SharedTransport.Rest,
|
||||||
"TestExchange",
|
new TestApiClient(),
|
||||||
apiTradingModes,
|
apiTradingModes,
|
||||||
() => false,
|
() => false,
|
||||||
(baseAsset, quoteAsset, tradingMode, deliverDate) => $"{baseAsset}{quoteAsset}")
|
(baseAsset, quoteAsset, tradingMode, deliverDate) => $"{baseAsset}{quoteAsset}")
|
||||||
@@ -258,7 +280,7 @@ namespace CryptoExchange.Net.UnitTests
|
|||||||
public TestOptionsHost(TradingMode[] apiTradingModes, CapabilityOptions capabilityOptions)
|
public TestOptionsHost(TradingMode[] apiTradingModes, CapabilityOptions capabilityOptions)
|
||||||
: base(
|
: base(
|
||||||
SharedTransport.Rest,
|
SharedTransport.Rest,
|
||||||
"TestExchange",
|
new TestApiClient(),
|
||||||
apiTradingModes,
|
apiTradingModes,
|
||||||
() => false,
|
() => false,
|
||||||
(baseAsset, quoteAsset, tradingMode, deliverDate) => $"{baseAsset}{quoteAsset}")
|
(baseAsset, quoteAsset, tradingMode, deliverDate) => $"{baseAsset}{quoteAsset}")
|
||||||
@@ -274,7 +296,7 @@ namespace CryptoExchange.Net.UnitTests
|
|||||||
protected TestTransportSharedApi(SharedTransport transport)
|
protected TestTransportSharedApi(SharedTransport transport)
|
||||||
: base(
|
: base(
|
||||||
transport,
|
transport,
|
||||||
"TestExchange",
|
new TestApiClient(),
|
||||||
[TradingMode.Spot],
|
[TradingMode.Spot],
|
||||||
() => false,
|
() => false,
|
||||||
(baseAsset, quoteAsset, tradingMode, deliverDate) => $"{baseAsset}{quoteAsset}")
|
(baseAsset, quoteAsset, tradingMode, deliverDate) => $"{baseAsset}{quoteAsset}")
|
||||||
|
|||||||
@@ -1,10 +1,13 @@
|
|||||||
using System;
|
|
||||||
using CryptoExchange.Net.Interfaces.Clients;
|
using CryptoExchange.Net.Interfaces.Clients;
|
||||||
using CryptoExchange.Net.Objects.Errors;
|
using CryptoExchange.Net.Objects.Errors;
|
||||||
using CryptoExchange.Net.Objects.Options;
|
using CryptoExchange.Net.Objects.Options;
|
||||||
|
using CryptoExchange.Net.RateLimiting;
|
||||||
using CryptoExchange.Net.SharedApis;
|
using CryptoExchange.Net.SharedApis;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Microsoft.Extensions.Logging.Abstractions;
|
using Microsoft.Extensions.Logging.Abstractions;
|
||||||
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace CryptoExchange.Net.Clients
|
namespace CryptoExchange.Net.Clients
|
||||||
{
|
{
|
||||||
@@ -78,6 +81,11 @@ namespace CryptoExchange.Net.Clients
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
protected internal virtual ErrorMapping ErrorMapping { get; } = new ErrorMapping([]);
|
protected internal virtual ErrorMapping ErrorMapping { get; } = new ErrorMapping([]);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Current rate limit admission override
|
||||||
|
/// </summary>
|
||||||
|
protected readonly AsyncLocal<RateLimitAdmission?> AdmissionOverride = new();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ctor
|
/// ctor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -122,6 +130,29 @@ namespace CryptoExchange.Net.Clients
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public ErrorInfo GetErrorInfo(string code, string? message = null) => ErrorMapping.GetErrorInfo(code.ToString(), message);
|
public ErrorInfo GetErrorInfo(string code, string? message = null) => ErrorMapping.GetErrorInfo(code.ToString(), message);
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public async Task<TResult> WithRateLimitAdmissionAsync<TResult>(
|
||||||
|
RateLimitAdmission admission,
|
||||||
|
Func<Task<TResult>> operation)
|
||||||
|
{
|
||||||
|
if (admission == null)
|
||||||
|
throw new ArgumentNullException(nameof(admission));
|
||||||
|
if (operation == null)
|
||||||
|
throw new ArgumentNullException(nameof(operation));
|
||||||
|
|
||||||
|
var previous = AdmissionOverride.Value;
|
||||||
|
AdmissionOverride.Value = admission;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return await operation().ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
AdmissionOverride.Value = previous;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Dispose
|
/// Dispose
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -350,6 +350,9 @@ namespace CryptoExchange.Net.Clients
|
|||||||
|
|
||||||
if (ClientOptions.RateLimiterEnabled)
|
if (ClientOptions.RateLimiterEnabled)
|
||||||
{
|
{
|
||||||
|
var admissionOverride = AdmissionOverride.Value ?? ClientOptions.RateLimitAdmission?.Invoke(definition, requestWeight);
|
||||||
|
var rateRatio = admissionOverride?.MaxUtilizationRatio ?? 1.0;
|
||||||
|
|
||||||
var limitResult = await definition.RateLimitGate.ProcessAsync(
|
var limitResult = await definition.RateLimitGate.ProcessAsync(
|
||||||
_logger,
|
_logger,
|
||||||
requestId,
|
requestId,
|
||||||
@@ -359,6 +362,7 @@ namespace CryptoExchange.Net.Clients
|
|||||||
requestWeight,
|
requestWeight,
|
||||||
ClientOptions.RateLimitingBehaviour,
|
ClientOptions.RateLimitingBehaviour,
|
||||||
rateLimitKeySuffix + ClientOptions.RateLimitGroup,
|
rateLimitKeySuffix + ClientOptions.RateLimitGroup,
|
||||||
|
rateRatio,
|
||||||
cancellationToken).ConfigureAwait(false);
|
cancellationToken).ConfigureAwait(false);
|
||||||
if (!limitResult.Success)
|
if (!limitResult.Success)
|
||||||
return limitResult.Error!;
|
return limitResult.Error!;
|
||||||
@@ -374,6 +378,9 @@ namespace CryptoExchange.Net.Clients
|
|||||||
if (ClientOptions.RateLimiterEnabled)
|
if (ClientOptions.RateLimiterEnabled)
|
||||||
{
|
{
|
||||||
var singleRequestWeight = weightSingleLimiter ?? 1;
|
var singleRequestWeight = weightSingleLimiter ?? 1;
|
||||||
|
var admissionOverride = AdmissionOverride.Value ?? ClientOptions.RateLimitAdmission?.Invoke(definition, singleRequestWeight);
|
||||||
|
var rateRatio = admissionOverride?.MaxUtilizationRatio ?? 1.0;
|
||||||
|
|
||||||
var limitResult = await definition.RateLimitGate.ProcessSingleAsync(
|
var limitResult = await definition.RateLimitGate.ProcessSingleAsync(
|
||||||
_logger,
|
_logger,
|
||||||
requestId,
|
requestId,
|
||||||
@@ -384,6 +391,7 @@ namespace CryptoExchange.Net.Clients
|
|||||||
singleRequestWeight,
|
singleRequestWeight,
|
||||||
ClientOptions.RateLimitingBehaviour,
|
ClientOptions.RateLimitingBehaviour,
|
||||||
rateLimitKeySuffix,
|
rateLimitKeySuffix,
|
||||||
|
rateRatio,
|
||||||
cancellationToken).ConfigureAwait(false);
|
cancellationToken).ConfigureAwait(false);
|
||||||
if (!limitResult.Success)
|
if (!limitResult.Success)
|
||||||
return limitResult.Error!;
|
return limitResult.Error!;
|
||||||
|
|||||||
@@ -858,6 +858,8 @@ namespace CryptoExchange.Net.Clients
|
|||||||
ReconnectInterval = ClientOptions.ReconnectInterval,
|
ReconnectInterval = ClientOptions.ReconnectInterval,
|
||||||
RateLimiter = ClientOptions.RateLimiterEnabled ? RateLimiter : null,
|
RateLimiter = ClientOptions.RateLimiterEnabled ? RateLimiter : null,
|
||||||
RateLimitingBehavior = ClientOptions.RateLimitingBehaviour,
|
RateLimitingBehavior = ClientOptions.RateLimitingBehaviour,
|
||||||
|
RateLimitAdmissionCallbackOptions = (def, weight) => ClientOptions.RateLimitAdmission?.Invoke(def, weight),
|
||||||
|
RateLimitAdmissionCallbackRequest = () => AdmissionOverride.Value,
|
||||||
Proxy = ClientOptions.Proxy,
|
Proxy = ClientOptions.Proxy,
|
||||||
Timeout = ApiOptions.SocketNoDataTimeout ?? ClientOptions.SocketNoDataTimeout,
|
Timeout = ApiOptions.SocketNoDataTimeout ?? ClientOptions.SocketNoDataTimeout,
|
||||||
ReceiveBufferSize = ClientOptions.ReceiveBufferSize,
|
ReceiveBufferSize = ClientOptions.ReceiveBufferSize,
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
using CryptoExchange.Net.Interfaces;
|
using CryptoExchange.Net.Clients;
|
||||||
|
using CryptoExchange.Net.Interfaces;
|
||||||
|
using CryptoExchange.Net.Interfaces.Clients;
|
||||||
using CryptoExchange.Net.Objects;
|
using CryptoExchange.Net.Objects;
|
||||||
|
using CryptoExchange.Net.RateLimiting;
|
||||||
using CryptoExchange.Net.SharedApis;
|
using CryptoExchange.Net.SharedApis;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using System;
|
using System;
|
||||||
@@ -11,6 +14,7 @@ using System.IO.Compression;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using System.Web;
|
using System.Web;
|
||||||
|
|
||||||
namespace CryptoExchange.Net
|
namespace CryptoExchange.Net
|
||||||
@@ -146,25 +150,42 @@ namespace CryptoExchange.Net
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static string ToFormData(this IDictionary<string, object> parameters)
|
public static string ToFormData(this IDictionary<string, object> parameters)
|
||||||
{
|
{
|
||||||
var formData = HttpUtility.ParseQueryString(string.Empty);
|
var result = new StringBuilder();
|
||||||
|
var first = true;
|
||||||
|
|
||||||
|
void Append(string key, object value)
|
||||||
|
{
|
||||||
|
if (!first)
|
||||||
|
result.Append('&');
|
||||||
|
first = false;
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(key))
|
||||||
|
{
|
||||||
|
result.Append(HttpUtility.UrlEncode(key, Encoding.UTF8));
|
||||||
|
result.Append('=');
|
||||||
|
}
|
||||||
|
|
||||||
|
var text = string.Format(CultureInfo.InvariantCulture, "{0}", value);
|
||||||
|
result.Append(HttpUtility.UrlEncode(text, Encoding.UTF8));
|
||||||
|
}
|
||||||
|
|
||||||
foreach (var kvp in parameters)
|
foreach (var kvp in parameters)
|
||||||
{
|
{
|
||||||
if (kvp.Value is null)
|
if (kvp.Value is null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (kvp.Value.GetType().IsArray)
|
if (kvp.Value is Array array)
|
||||||
{
|
{
|
||||||
var array = (Array)kvp.Value;
|
|
||||||
foreach (var value in array)
|
foreach (var value in array)
|
||||||
formData.Add(kvp.Key, string.Format(CultureInfo.InvariantCulture, "{0}", value));
|
Append(kvp.Key, value);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
formData.Add(kvp.Key, string.Format(CultureInfo.InvariantCulture, "{0}", kvp.Value));
|
Append(kvp.Key, kvp.Value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return formData.ToString()!;
|
return result.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -493,6 +514,41 @@ namespace CryptoExchange.Net
|
|||||||
|
|
||||||
return bytes;
|
return bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Execute an operation with a specific rate limit admission rule
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="client">Client</param>
|
||||||
|
/// <param name="admission">Rate limit admission rule</param>
|
||||||
|
/// <param name="operation">Operation to execute</param>
|
||||||
|
public static Task<TResult> WithRateLimitAdmissionAsync<TClient, TResult>(
|
||||||
|
this TClient client,
|
||||||
|
RateLimitAdmission admission,
|
||||||
|
Func<TClient, Task<TResult>> operation)
|
||||||
|
where TClient : IRateLimitAdmissionClient
|
||||||
|
{
|
||||||
|
return client.WithRateLimitAdmissionAsync(
|
||||||
|
admission,
|
||||||
|
() => operation(client));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Return the task results in the form of an IAsyncEnumerable, returning the first completed task first
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">Type of task result</typeparam>
|
||||||
|
/// <param name="tasks">Task list</param>
|
||||||
|
public static async IAsyncEnumerable<T> ParallelEnumerateAsync<T>(this IEnumerable<Task<T>> tasks)
|
||||||
|
{
|
||||||
|
var remaining = new List<Task<T>>(tasks);
|
||||||
|
|
||||||
|
while (remaining.Count != 0)
|
||||||
|
{
|
||||||
|
var task = await Task.WhenAny(remaining).ConfigureAwait(false);
|
||||||
|
remaining.Remove(task);
|
||||||
|
yield return await task.ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
using CryptoExchange.Net.Authentication;
|
using CryptoExchange.Net.SharedApis;
|
||||||
using CryptoExchange.Net.Objects.Options;
|
|
||||||
using CryptoExchange.Net.SharedApis;
|
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace CryptoExchange.Net.Interfaces.Clients
|
namespace CryptoExchange.Net.Interfaces.Clients
|
||||||
@@ -8,7 +6,7 @@ namespace CryptoExchange.Net.Interfaces.Clients
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Base api client
|
/// Base api client
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IBaseApiClient
|
public interface IBaseApiClient : IRateLimitAdmissionClient
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Exchange name
|
/// Exchange name
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
using CryptoExchange.Net.RateLimiting;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace CryptoExchange.Net.Interfaces
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A client supporting rate limit admission rules
|
||||||
|
/// </summary>
|
||||||
|
public interface IRateLimitAdmissionClient
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Execute an operation with a specific rate limit admission rule
|
||||||
|
/// </summary>
|
||||||
|
Task<TResult> WithRateLimitAdmissionAsync<TResult>(
|
||||||
|
RateLimitAdmission admission,
|
||||||
|
Func<Task<TResult>> operation);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
using CryptoExchange.Net.Authentication;
|
using CryptoExchange.Net.Authentication;
|
||||||
|
using CryptoExchange.Net.RateLimiting;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace CryptoExchange.Net.Objects.Options
|
namespace CryptoExchange.Net.Objects.Options
|
||||||
@@ -41,6 +42,12 @@ namespace CryptoExchange.Net.Objects.Options
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public RateLimitingBehaviour RateLimitingBehaviour { get; set; } = RateLimitingBehaviour.Wait;
|
public RateLimitingBehaviour RateLimitingBehaviour { get; set; } = RateLimitingBehaviour.Wait;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A delegate receiving the request definition and the request weight that can be used to determine whether a request should be admitted or rejected based
|
||||||
|
/// on the request definition and the current rate limit usage ratio. This allows for custom rate limiting logic to be implemented.
|
||||||
|
/// </summary>
|
||||||
|
public Func<RequestDefinition, int, RateLimitAdmission>? RateLimitAdmission { get; set; }
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -75,6 +75,7 @@ namespace CryptoExchange.Net.Objects.Options
|
|||||||
item.RateLimiterEnabled = RateLimiterEnabled;
|
item.RateLimiterEnabled = RateLimiterEnabled;
|
||||||
item.RateLimitingBehaviour = RateLimitingBehaviour;
|
item.RateLimitingBehaviour = RateLimitingBehaviour;
|
||||||
item.RateLimitGroup = RateLimitGroup;
|
item.RateLimitGroup = RateLimitGroup;
|
||||||
|
item.RateLimitAdmission = RateLimitAdmission;
|
||||||
item.CachingEnabled = CachingEnabled;
|
item.CachingEnabled = CachingEnabled;
|
||||||
item.CachingMaxAge = CachingMaxAge;
|
item.CachingMaxAge = CachingMaxAge;
|
||||||
item.HttpVersion = HttpVersion;
|
item.HttpVersion = HttpVersion;
|
||||||
|
|||||||
@@ -105,6 +105,7 @@ namespace CryptoExchange.Net.Objects.Options
|
|||||||
item.RateLimitingBehaviour = RateLimitingBehaviour;
|
item.RateLimitingBehaviour = RateLimitingBehaviour;
|
||||||
item.RateLimiterEnabled = RateLimiterEnabled;
|
item.RateLimiterEnabled = RateLimiterEnabled;
|
||||||
item.RateLimitGroup = RateLimitGroup;
|
item.RateLimitGroup = RateLimitGroup;
|
||||||
|
item.RateLimitAdmission = RateLimitAdmission;
|
||||||
item.ReceiveBufferSize = ReceiveBufferSize;
|
item.ReceiveBufferSize = ReceiveBufferSize;
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,4 +40,16 @@ public interface ICallResult<T> : ICallResult
|
|||||||
/// The result data, only available when Success = true
|
/// The result data, only available when Success = true
|
||||||
/// </summary>
|
/// </summary>
|
||||||
T? Data { get; }
|
T? Data { get; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Exchange call result
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">Result data type</typeparam>
|
||||||
|
public interface IExchangeCallResult<T> : ICallResult, ICallResult<T>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Exchange name
|
||||||
|
/// </summary>
|
||||||
|
public string Exchange { get; set; }
|
||||||
}
|
}
|
||||||
@@ -79,7 +79,7 @@ namespace CryptoExchange.Net.Objects
|
|||||||
/// HTTP call result
|
/// HTTP call result
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="T">Result data type</typeparam>
|
/// <typeparam name="T">Result data type</typeparam>
|
||||||
public interface IHttpResult<T> : IHttpResult, ICallResult<T>
|
public interface IHttpResult<T> : IHttpResult, IExchangeCallResult<T>
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ namespace CryptoExchange.Net.Objects
|
|||||||
/// WebSocket call result
|
/// WebSocket call result
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="T">Data result type</typeparam>
|
/// <typeparam name="T">Data result type</typeparam>
|
||||||
public interface IWebSocketResult<T> : IWebSocketResult, ICallResult<T>
|
public interface IWebSocketResult<T> : IWebSocketResult, IExchangeCallResult<T>
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using CryptoExchange.Net.RateLimiting.Interfaces;
|
using CryptoExchange.Net.RateLimiting;
|
||||||
|
using CryptoExchange.Net.RateLimiting.Interfaces;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
@@ -64,6 +65,17 @@ namespace CryptoExchange.Net.Objects.Sockets
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public RateLimitingBehaviour RateLimitingBehavior { get; set; }
|
public RateLimitingBehaviour RateLimitingBehavior { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A delegate receiving the request definition and the request weight that can be used to determine whether a request should be admitted or rejected based
|
||||||
|
/// on the request definition and the current rate limit usage ratio. This allows for custom rate limiting logic to be implemented.
|
||||||
|
/// </summary>
|
||||||
|
public Func<RequestDefinition, int, RateLimitAdmission?>? RateLimitAdmissionCallbackOptions { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A delegate for retrieving the current rate limit admission decision for a specific request. This allows for custom rate limiting logic to be implemented.
|
||||||
|
/// </summary>
|
||||||
|
public Func<RateLimitAdmission?>? RateLimitAdmissionCallbackRequest { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Encoding for sending/receiving data
|
/// Encoding for sending/receiving data
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -104,7 +104,7 @@ namespace CryptoExchange.Net.RateLimiting.Guards
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public LimitCheck Check(RateLimitItemType type, RequestDefinition definition, string? apiKey, int requestWeight, string? keySuffix)
|
public LimitCheck Check(RateLimitItemType type, RequestDefinition definition, string? apiKey, int requestWeight, string? keySuffix, double allowedRateRatio)
|
||||||
{
|
{
|
||||||
foreach (var filter in _filters)
|
foreach (var filter in _filters)
|
||||||
{
|
{
|
||||||
@@ -127,7 +127,7 @@ namespace CryptoExchange.Net.RateLimiting.Guards
|
|||||||
_trackers.Add(key, tracker);
|
_trackers.Add(key, tracker);
|
||||||
}
|
}
|
||||||
|
|
||||||
var delay = tracker.GetWaitTime(requestWeight);
|
var delay = tracker.GetWaitTime(requestWeight, allowedRateRatio);
|
||||||
if (delay == default)
|
if (delay == default)
|
||||||
return LimitCheck.NotNeeded(Limit, TimeSpan, tracker.Current);
|
return LimitCheck.NotNeeded(Limit, TimeSpan, tracker.Current);
|
||||||
|
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ namespace CryptoExchange.Net.RateLimiting.Guards
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public LimitCheck Check(RateLimitItemType type, RequestDefinition definition, string? apiKey, int requestWeight, string? keySuffix)
|
public LimitCheck Check(RateLimitItemType type, RequestDefinition definition, string? apiKey, int requestWeight, string? keySuffix, double allowedRateRatio)
|
||||||
{
|
{
|
||||||
if (type != Type)
|
if (type != Type)
|
||||||
return LimitCheck.NotApplicable;
|
return LimitCheck.NotApplicable;
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ namespace CryptoExchange.Net.RateLimiting.Guards
|
|||||||
public string Name => "EndpointLimitGuard";
|
public string Name => "EndpointLimitGuard";
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public string Description => $"Limit requests to endpoint";
|
public string Description => _windowType == RateLimitWindowType.Decay ? $"Endpoint limit of {_limit} with a decay rate of {_decayRate}" : $"Limit of {_limit} per {_period}";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ctor
|
/// ctor
|
||||||
@@ -53,7 +53,7 @@ namespace CryptoExchange.Net.RateLimiting.Guards
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public LimitCheck Check(RateLimitItemType type, RequestDefinition definition, string? apiKey, int requestWeight, string? keySuffix)
|
public LimitCheck Check(RateLimitItemType type, RequestDefinition definition, string? apiKey, int requestWeight, string? keySuffix, double allowedRateRatio)
|
||||||
{
|
{
|
||||||
var key = _keySelector(definition, apiKey) + keySuffix;
|
var key = _keySelector(definition, apiKey) + keySuffix;
|
||||||
if (!_trackers.TryGetValue(key, out var tracker))
|
if (!_trackers.TryGetValue(key, out var tracker))
|
||||||
@@ -62,7 +62,7 @@ namespace CryptoExchange.Net.RateLimiting.Guards
|
|||||||
_trackers.Add(key, tracker);
|
_trackers.Add(key, tracker);
|
||||||
}
|
}
|
||||||
|
|
||||||
var delay = tracker.GetWaitTime(requestWeight);
|
var delay = tracker.GetWaitTime(requestWeight, allowedRateRatio);
|
||||||
if (delay == default)
|
if (delay == default)
|
||||||
return LimitCheck.NotNeeded(_limit, _period, tracker.Current);
|
return LimitCheck.NotNeeded(_limit, _period, tracker.Current);
|
||||||
|
|
||||||
|
|||||||
@@ -53,9 +53,20 @@ namespace CryptoExchange.Net.RateLimiting.Interfaces
|
|||||||
/// <param name="requestWeight">Request weight</param>
|
/// <param name="requestWeight">Request weight</param>
|
||||||
/// <param name="behaviour">Behaviour when rate limit is hit</param>
|
/// <param name="behaviour">Behaviour when rate limit is hit</param>
|
||||||
/// <param name="keySuffix">An additional optional suffix for the key selector. Can be used to make rate limiting work based on parameters.</param>
|
/// <param name="keySuffix">An additional optional suffix for the key selector. Can be used to make rate limiting work based on parameters.</param>
|
||||||
/// <param name="ct">Cancelation token</param>
|
/// <param name="allowedRateRatio">The allowed rate ratio</param>
|
||||||
|
/// <param name="ct">Cancellation token</param>
|
||||||
/// <returns>Error if RateLimitingBehaviour is Fail and rate limit is hit</returns>
|
/// <returns>Error if RateLimitingBehaviour is Fail and rate limit is hit</returns>
|
||||||
ValueTask<CallResult> ProcessAsync(ILogger logger, int itemId, RateLimitItemType type, RequestDefinition definition, string? apiKey, int requestWeight, RateLimitingBehaviour behaviour, string? keySuffix, CancellationToken ct);
|
ValueTask<CallResult> ProcessAsync(
|
||||||
|
ILogger logger,
|
||||||
|
int itemId,
|
||||||
|
RateLimitItemType type,
|
||||||
|
RequestDefinition definition,
|
||||||
|
string? apiKey,
|
||||||
|
int requestWeight,
|
||||||
|
RateLimitingBehaviour behaviour,
|
||||||
|
string? keySuffix,
|
||||||
|
double allowedRateRatio,
|
||||||
|
CancellationToken ct);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Enforces the rate limit as defined in the request definition. When a rate limit is hit will wait for the rate limit to pass if RateLimitingBehaviour is Wait, or return an error if it is set to Fail
|
/// Enforces the rate limit as defined in the request definition. When a rate limit is hit will wait for the rate limit to pass if RateLimitingBehaviour is Wait, or return an error if it is set to Fail
|
||||||
@@ -69,9 +80,21 @@ namespace CryptoExchange.Net.RateLimiting.Interfaces
|
|||||||
/// <param name="behaviour">Behaviour when rate limit is hit</param>
|
/// <param name="behaviour">Behaviour when rate limit is hit</param>
|
||||||
/// <param name="requestWeight">The weight to apply to the limit guard</param>
|
/// <param name="requestWeight">The weight to apply to the limit guard</param>
|
||||||
/// <param name="keySuffix">An additional optional suffix for the key selector. Can be used to make rate limiting work based on parameters.</param>
|
/// <param name="keySuffix">An additional optional suffix for the key selector. Can be used to make rate limiting work based on parameters.</param>
|
||||||
|
/// <param name="allowedRateRatio">The allowed rate ratio</param>
|
||||||
/// <param name="ct">Cancelation token</param>
|
/// <param name="ct">Cancelation token</param>
|
||||||
/// <returns>Error if RateLimitingBehaviour is Fail and rate limit is hit</returns>
|
/// <returns>Error if RateLimitingBehaviour is Fail and rate limit is hit</returns>
|
||||||
ValueTask<CallResult> ProcessSingleAsync(ILogger logger, int itemId, IRateLimitGuard guard, RateLimitItemType type, RequestDefinition definition, string? apiKey, int requestWeight, RateLimitingBehaviour behaviour, string? keySuffix, CancellationToken ct);
|
ValueTask<CallResult> ProcessSingleAsync(
|
||||||
|
ILogger logger,
|
||||||
|
int itemId,
|
||||||
|
IRateLimitGuard guard,
|
||||||
|
RateLimitItemType type,
|
||||||
|
RequestDefinition definition,
|
||||||
|
string? apiKey,
|
||||||
|
int requestWeight,
|
||||||
|
RateLimitingBehaviour behaviour,
|
||||||
|
string? keySuffix,
|
||||||
|
double allowedRateRatio,
|
||||||
|
CancellationToken ct);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Reset the limit for the specified parameters
|
/// Reset the limit for the specified parameters
|
||||||
|
|||||||
@@ -25,8 +25,9 @@ namespace CryptoExchange.Net.RateLimiting.Interfaces
|
|||||||
/// <param name="apiKey">The API key</param>
|
/// <param name="apiKey">The API key</param>
|
||||||
/// <param name="requestWeight">The request weight</param>
|
/// <param name="requestWeight">The request weight</param>
|
||||||
/// <param name="keySuffix">An additional optional suffix for the key selector. Can be used to make rate limiting work based on parameters.</param>
|
/// <param name="keySuffix">An additional optional suffix for the key selector. Can be used to make rate limiting work based on parameters.</param>
|
||||||
|
/// <param name="allowedRateRatio">The allowed rate ratio</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
LimitCheck Check(RateLimitItemType type, RequestDefinition definition, string? apiKey, int requestWeight, string? keySuffix);
|
LimitCheck Check(RateLimitItemType type, RequestDefinition definition, string? apiKey, int requestWeight, string? keySuffix, double allowedRateRatio);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Apply the request to this guard with the specified weight
|
/// Apply the request to this guard with the specified weight
|
||||||
|
|||||||
@@ -22,9 +22,7 @@ namespace CryptoExchange.Net.RateLimiting.Interfaces
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get the time to wait to fit the weight
|
/// Get the time to wait to fit the weight
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="weight"></param>
|
TimeSpan GetWaitTime(int weight, double allowedRateRatio);
|
||||||
/// <returns></returns>
|
|
||||||
TimeSpan GetWaitTime(int weight);
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Register the weight in this window
|
/// Register the weight in this window
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace CryptoExchange.Net.RateLimiting
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Rate limit admission decision result
|
||||||
|
/// </summary>
|
||||||
|
public record RateLimitAdmission
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Value ratio between 0 and 1
|
||||||
|
/// </summary>
|
||||||
|
public double MaxUtilizationRatio { get; }
|
||||||
|
|
||||||
|
private RateLimitAdmission(double maxUtilizationValue) {
|
||||||
|
if (maxUtilizationValue <= 0 || maxUtilizationValue > 1)
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(maxUtilizationValue), "Max utilization value must be bigger than 0 and less than or equal to 1");
|
||||||
|
|
||||||
|
MaxUtilizationRatio = maxUtilizationValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Only allow the request when below a certain ratio of the rate limit, for example 0.5 means it can use a max of 50% of the rate limit,
|
||||||
|
/// 1 means it's allowed to use the full rate limit.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">0.5 means a max use 50% of the rate limit, 1 means the request is allowed to use the full rate limit</param>
|
||||||
|
public static RateLimitAdmission WithMaxUtilizationRatio(double value)
|
||||||
|
=> new RateLimitAdmission(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -37,14 +37,24 @@ namespace CryptoExchange.Net.RateLimiting
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public async ValueTask<CallResult> ProcessAsync(ILogger logger, int itemId, RateLimitItemType type, RequestDefinition definition, string? apiKey, int requestWeight, RateLimitingBehaviour rateLimitingBehaviour, string? keySuffix, CancellationToken ct)
|
public async ValueTask<CallResult> ProcessAsync(
|
||||||
|
ILogger logger,
|
||||||
|
int itemId,
|
||||||
|
RateLimitItemType type,
|
||||||
|
RequestDefinition definition,
|
||||||
|
string? apiKey,
|
||||||
|
int requestWeight,
|
||||||
|
RateLimitingBehaviour rateLimitingBehaviour,
|
||||||
|
string? keySuffix,
|
||||||
|
double allowedRateRatio,
|
||||||
|
CancellationToken ct)
|
||||||
{
|
{
|
||||||
await _semaphore.WaitAsync(ct).ConfigureAwait(false);
|
await _semaphore.WaitAsync(ct).ConfigureAwait(false);
|
||||||
bool release = true;
|
bool release = true;
|
||||||
_waitingCount++;
|
_waitingCount++;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return await CheckGuardsAsync(_guards, logger, itemId, type, definition, apiKey, requestWeight, rateLimitingBehaviour, keySuffix, ct).ConfigureAwait(false);
|
return await CheckGuardsAsync(_guards, logger, itemId, type, definition, apiKey, requestWeight, rateLimitingBehaviour, keySuffix, allowedRateRatio, ct).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
catch (TaskCanceledException tce)
|
catch (TaskCanceledException tce)
|
||||||
{
|
{
|
||||||
@@ -71,6 +81,7 @@ namespace CryptoExchange.Net.RateLimiting
|
|||||||
int requestWeight,
|
int requestWeight,
|
||||||
RateLimitingBehaviour rateLimitingBehaviour,
|
RateLimitingBehaviour rateLimitingBehaviour,
|
||||||
string? keySuffix,
|
string? keySuffix,
|
||||||
|
double allowedRateRatio,
|
||||||
CancellationToken ct)
|
CancellationToken ct)
|
||||||
{
|
{
|
||||||
await _semaphore.WaitAsync(ct).ConfigureAwait(false);
|
await _semaphore.WaitAsync(ct).ConfigureAwait(false);
|
||||||
@@ -78,7 +89,7 @@ namespace CryptoExchange.Net.RateLimiting
|
|||||||
_waitingCount++;
|
_waitingCount++;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return await CheckGuardsAsync(new IRateLimitGuard[] { guard }, logger, itemId, type, definition, apiKey, requestWeight, rateLimitingBehaviour, keySuffix, ct).ConfigureAwait(false);
|
return await CheckGuardsAsync(new IRateLimitGuard[] { guard }, logger, itemId, type, definition, apiKey, requestWeight, rateLimitingBehaviour, keySuffix, allowedRateRatio, ct).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
catch (TaskCanceledException tce)
|
catch (TaskCanceledException tce)
|
||||||
{
|
{
|
||||||
@@ -94,12 +105,23 @@ namespace CryptoExchange.Net.RateLimiting
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async ValueTask<CallResult> CheckGuardsAsync(IEnumerable<IRateLimitGuard> guards, ILogger logger, int itemId, RateLimitItemType type, RequestDefinition definition, string? apiKey, int requestWeight, RateLimitingBehaviour rateLimitingBehaviour, string? keySuffix, CancellationToken ct)
|
private async ValueTask<CallResult> CheckGuardsAsync(
|
||||||
|
IEnumerable<IRateLimitGuard> guards,
|
||||||
|
ILogger logger,
|
||||||
|
int itemId,
|
||||||
|
RateLimitItemType type,
|
||||||
|
RequestDefinition definition,
|
||||||
|
string? apiKey,
|
||||||
|
int requestWeight,
|
||||||
|
RateLimitingBehaviour rateLimitingBehaviour,
|
||||||
|
string? keySuffix,
|
||||||
|
double allowedRateRatio,
|
||||||
|
CancellationToken ct)
|
||||||
{
|
{
|
||||||
foreach (var guard in guards)
|
foreach (var guard in guards)
|
||||||
{
|
{
|
||||||
// Check if a wait is needed for this guard
|
// Check if a wait is needed for this guard
|
||||||
var result = guard.Check(type, definition, apiKey, requestWeight, keySuffix);
|
var result = guard.Check(type, definition, apiKey, requestWeight, keySuffix, allowedRateRatio);
|
||||||
if (result.Delay != TimeSpan.Zero && rateLimitingBehaviour == RateLimitingBehaviour.Fail)
|
if (result.Delay != TimeSpan.Zero && rateLimitingBehaviour == RateLimitingBehaviour.Fail)
|
||||||
{
|
{
|
||||||
// Delay is needed and limit behaviour is to fail the request
|
// Delay is needed and limit behaviour is to fail the request
|
||||||
@@ -109,7 +131,10 @@ namespace CryptoExchange.Net.RateLimiting
|
|||||||
logger.RateLimitRequestFailed(itemId, definition.Path, guard.Name, guard.Description);
|
logger.RateLimitRequestFailed(itemId, definition.Path, guard.Name, guard.Description);
|
||||||
|
|
||||||
RateLimitTriggered?.Invoke(new RateLimitEvent(itemId, _name, guard.Description, definition, result.Current, requestWeight, result.Limit, result.Period, result.Delay, rateLimitingBehaviour));
|
RateLimitTriggered?.Invoke(new RateLimitEvent(itemId, _name, guard.Description, definition, result.Current, requestWeight, result.Limit, result.Period, result.Delay, rateLimitingBehaviour));
|
||||||
return CallResult.Fail(new ClientRateLimitError($"Rate limit check failed on guard {guard.Name}; {guard.Description}"));
|
var errorMsg = $"Rate limit check failed on guard {guard.Name}; {guard.Description}";
|
||||||
|
if (allowedRateRatio < 1)
|
||||||
|
errorMsg += $" with allowed ratio {allowedRateRatio}";
|
||||||
|
return CallResult.Fail(new ClientRateLimitError(errorMsg));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result.Delay != TimeSpan.Zero)
|
if (result.Delay != TimeSpan.Zero)
|
||||||
@@ -117,7 +142,14 @@ namespace CryptoExchange.Net.RateLimiting
|
|||||||
// Delay is needed and limit behaviour is to wait for the request to be under the limit
|
// Delay is needed and limit behaviour is to wait for the request to be under the limit
|
||||||
_semaphore.Release();
|
_semaphore.Release();
|
||||||
|
|
||||||
var description = result.Limit == null ? guard.Description : $"{guard.Description}, Request weight: {requestWeight}, Current: {result.Current}, Limit: {result.Limit}, requests now being limited: {_waitingCount}";
|
var description =
|
||||||
|
result.Limit == null
|
||||||
|
? guard.Description
|
||||||
|
: $"{guard.Description}, Request weight: {requestWeight}," +
|
||||||
|
$" Current: {result.Current}" +
|
||||||
|
$", Limit: {result.Limit}" +
|
||||||
|
(allowedRateRatio < 1 ? $", Allowed ratio: {allowedRateRatio}" : "") +
|
||||||
|
$", requests now being limited: {_waitingCount}";
|
||||||
if (type == RateLimitItemType.Connection)
|
if (type == RateLimitItemType.Connection)
|
||||||
logger.RateLimitDelayingConnection(itemId, result.Delay, guard.Name, description);
|
logger.RateLimitDelayingConnection(itemId, result.Delay, guard.Name, description);
|
||||||
else
|
else
|
||||||
@@ -126,7 +158,7 @@ namespace CryptoExchange.Net.RateLimiting
|
|||||||
RateLimitTriggered?.Invoke(new RateLimitEvent(itemId, _name, guard.Description, definition, result.Current, requestWeight, result.Limit, result.Period, result.Delay, rateLimitingBehaviour));
|
RateLimitTriggered?.Invoke(new RateLimitEvent(itemId, _name, guard.Description, definition, result.Current, requestWeight, result.Limit, result.Period, result.Delay, rateLimitingBehaviour));
|
||||||
await Task.Delay((int)result.Delay.TotalMilliseconds + 1, ct).ConfigureAwait(false);
|
await Task.Delay((int)result.Delay.TotalMilliseconds + 1, ct).ConfigureAwait(false);
|
||||||
await _semaphore.WaitAsync(ct).ConfigureAwait(false);
|
await _semaphore.WaitAsync(ct).ConfigureAwait(false);
|
||||||
return await CheckGuardsAsync(guards, logger, itemId, type, definition, apiKey, requestWeight, rateLimitingBehaviour, keySuffix, ct).ConfigureAwait(false);
|
return await CheckGuardsAsync(guards, logger, itemId, type, definition, apiKey, requestWeight, rateLimitingBehaviour, keySuffix, allowedRateRatio, ct).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -41,22 +41,31 @@ namespace CryptoExchange.Net.RateLimiting.Trackers
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public TimeSpan GetWaitTime(int weight)
|
public TimeSpan GetWaitTime(int weight, double allowedRateRatio)
|
||||||
{
|
{
|
||||||
// Decrease the counter based on the last update time and decay rate
|
// Decrease the counter based on the last update time and decay rate
|
||||||
DecreaseCounter(DateTime.UtcNow);
|
DecreaseCounter(DateTime.UtcNow);
|
||||||
|
|
||||||
if (Current + weight > Limit)
|
if ((Current + weight) / (double)Limit > allowedRateRatio)
|
||||||
{
|
{
|
||||||
// The weight would cause the rate limit to be passed
|
// The weight would cause the rate limit to be passed
|
||||||
if (Current == 0)
|
if (Current == 0)
|
||||||
{
|
{
|
||||||
throw new Exception("Request limit reached without any prior request. " +
|
if (allowedRateRatio < 1)
|
||||||
$"This request can never execute with the current rate limiter. Request weight: {weight}, RateLimit: {Limit}");
|
{
|
||||||
|
throw new Exception("Request limit reached max utilization. " +
|
||||||
|
$"This request can never execute with the current rate limiter configuration. Request weight: {weight}, RateLimit: {Limit}, " +
|
||||||
|
$"Request ratio: {(Current + weight) / (double)Limit}, AllowedRateRatio: {allowedRateRatio}");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new Exception("Request limit reached without any prior request. " +
|
||||||
|
$"This request can never execute with the current rate limiter. Request weight: {weight}, RateLimit: {Limit}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determine the time to wait before this weight can be applied without going over the rate limit
|
// Determine the time to wait before this weight can be applied without going over the rate limit
|
||||||
return DetermineWaitTime(weight);
|
return DetermineWaitTime(weight, allowedRateRatio);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Weight can fit without going over limit
|
// Weight can fit without going over limit
|
||||||
@@ -90,10 +99,11 @@ namespace CryptoExchange.Net.RateLimiting.Trackers
|
|||||||
/// Determine the time to wait before the weight would fit
|
/// Determine the time to wait before the weight would fit
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="requestWeight"></param>
|
/// <param name="requestWeight"></param>
|
||||||
|
/// <param name="allowedRateRatio"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
private TimeSpan DetermineWaitTime(int requestWeight)
|
private TimeSpan DetermineWaitTime(int requestWeight, double allowedRateRatio)
|
||||||
{
|
{
|
||||||
var weightToRemove = Math.Max(Current - (Limit - requestWeight), 0);
|
var weightToRemove = Math.Max(Current + requestWeight - Limit * allowedRateRatio, 0);
|
||||||
var result = TimeSpan.FromMilliseconds(Math.Ceiling(weightToRemove / DecreaseRate) * TimePeriod.TotalMilliseconds);
|
var result = TimeSpan.FromMilliseconds(Math.Ceiling(weightToRemove / DecreaseRate) * TimePeriod.TotalMilliseconds);
|
||||||
if (result < TimeSpan.Zero)
|
if (result < TimeSpan.Zero)
|
||||||
return TimeSpan.Zero;
|
return TimeSpan.Zero;
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ namespace CryptoExchange.Net.RateLimiting.Trackers
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public TimeSpan GetWaitTime(int weight)
|
public TimeSpan GetWaitTime(int weight, double allowedRateRatio)
|
||||||
{
|
{
|
||||||
// Remove requests no longer in time period from the history
|
// Remove requests no longer in time period from the history
|
||||||
var checkTime = DateTime.UtcNow;
|
var checkTime = DateTime.UtcNow;
|
||||||
@@ -63,13 +63,22 @@ namespace CryptoExchange.Net.RateLimiting.Trackers
|
|||||||
if (Current == 0)
|
if (Current == 0)
|
||||||
_nextReset = null;
|
_nextReset = null;
|
||||||
|
|
||||||
if (Current + weight > Limit)
|
if ((Current + weight) / (double)Limit > allowedRateRatio)
|
||||||
{
|
{
|
||||||
// The weight would cause the rate limit to be passed
|
// The weight would cause the rate limit to be passed
|
||||||
if (Current == 0)
|
if (Current == 0)
|
||||||
{
|
{
|
||||||
throw new Exception("Request limit reached without any prior request. " +
|
if (allowedRateRatio < 1)
|
||||||
$"This request can never execute with the current rate limiter. Request weight: {weight}, RateLimit: {Limit}");
|
{
|
||||||
|
throw new Exception("Request limit reached max utilization. " +
|
||||||
|
$"This request can never execute with the current rate limiter configuration. Request weight: {weight}, RateLimit: {Limit}, " +
|
||||||
|
$"Request ratio: {(Current + weight) / (double)Limit}, AllowedRateRatio: {allowedRateRatio}");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new Exception("Request limit reached without any prior request. " +
|
||||||
|
$"This request can never execute with the current rate limiter. Request weight: {weight}, RateLimit: {Limit}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determine the time to wait before this weight can be applied without going over the rate limit
|
// Determine the time to wait before this weight can be applied without going over the rate limit
|
||||||
|
|||||||
@@ -52,19 +52,28 @@ namespace CryptoExchange.Net.RateLimiting.Trackers
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public TimeSpan GetWaitTime(int weight)
|
public TimeSpan GetWaitTime(int weight, double allowedRateRatio)
|
||||||
{
|
{
|
||||||
// Remove requests no longer in time period from the history
|
// Remove requests no longer in time period from the history
|
||||||
var checkTime = DateTime.UtcNow;
|
var checkTime = DateTime.UtcNow;
|
||||||
RemoveBefore(checkTime.AddTicks(-(checkTime.Ticks % TimePeriod.Ticks)));
|
RemoveBefore(checkTime.AddTicks(-(checkTime.Ticks % TimePeriod.Ticks)));
|
||||||
|
|
||||||
if (Current + weight > Limit)
|
if ((Current + weight) / (double)Limit > allowedRateRatio)
|
||||||
{
|
{
|
||||||
// The weight would cause the rate limit to be passed
|
// The weight would cause the rate limit to be passed
|
||||||
if (Current == 0)
|
if (Current == 0)
|
||||||
{
|
{
|
||||||
throw new Exception("Request limit reached without any prior request. " +
|
if (allowedRateRatio < 1)
|
||||||
$"This request can never execute with the current rate limiter. Request weight: {weight}, RateLimit: {Limit}");
|
{
|
||||||
|
throw new Exception("Request limit reached max utilization. " +
|
||||||
|
$"This request can never execute with the current rate limiter configuration. Request weight: {weight}, RateLimit: {Limit}, " +
|
||||||
|
$"Request ratio: {(Current + weight) / (double)Limit}, AllowedRateRatio: {allowedRateRatio}");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new Exception("Request limit reached without any prior request. " +
|
||||||
|
$"This request can never execute with the current rate limiter. Request weight: {weight}, RateLimit: {Limit}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determine the time to wait before this weight can be applied without going over the rate limit
|
// Determine the time to wait before this weight can be applied without going over the rate limit
|
||||||
|
|||||||
@@ -53,22 +53,31 @@ namespace CryptoExchange.Net.RateLimiting.Trackers
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public TimeSpan GetWaitTime(int weight)
|
public TimeSpan GetWaitTime(int weight, double allowedRateRatio)
|
||||||
{
|
{
|
||||||
// Remove requests no longer in time period from the history
|
// Remove requests no longer in time period from the history
|
||||||
RemoveBefore(DateTime.UtcNow - TimePeriod);
|
RemoveBefore(DateTime.UtcNow - TimePeriod);
|
||||||
|
|
||||||
if (Current + weight > Limit)
|
if ((Current + weight) / (double)Limit > allowedRateRatio)
|
||||||
{
|
{
|
||||||
// The weight would cause the rate limit to be passed
|
// The weight would cause the rate limit to be passed
|
||||||
if (Current == 0)
|
if (Current == 0)
|
||||||
{
|
{
|
||||||
throw new Exception("Request limit reached without any prior request. " +
|
if (allowedRateRatio < 1)
|
||||||
$"This request can never execute with the current rate limiter. Request weight: {weight}, RateLimit: {Limit}");
|
{
|
||||||
|
throw new Exception("Request limit reached max utilization. " +
|
||||||
|
$"This request can never execute with the current rate limiter configuration. Request weight: {weight}, RateLimit: {Limit}, " +
|
||||||
|
$"Request ratio: {(Current + weight) / (double)Limit}, AllowedRateRatio: {allowedRateRatio}");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new Exception("Request limit reached without any prior request. " +
|
||||||
|
$"This request can never execute with the current rate limiter. Request weight: {weight}, RateLimit: {Limit}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determine the time to wait before this weight can be applied without going over the rate limit
|
// Determine the time to wait before this weight can be applied without going over the rate limit
|
||||||
return DetermineWaitTime(weight);
|
return DetermineWaitTime(weight, allowedRateRatio);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Weight can fit without going over limit
|
// Weight can fit without going over limit
|
||||||
@@ -108,9 +117,9 @@ namespace CryptoExchange.Net.RateLimiting.Trackers
|
|||||||
/// Determine the time to wait before the weight would fit
|
/// Determine the time to wait before the weight would fit
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
private TimeSpan DetermineWaitTime(int requestWeight)
|
private TimeSpan DetermineWaitTime(int requestWeight, double allowedRateRatio)
|
||||||
{
|
{
|
||||||
var weightToRemove = Math.Max(Current - (Limit - requestWeight), 0);
|
var weightToRemove = Math.Max(Current + requestWeight - Limit * allowedRateRatio, 0);
|
||||||
var removedWeight = 0;
|
var removedWeight = 0;
|
||||||
for (var i = 0; i < _entries.Count; i++)
|
for (var i = 0; i < _entries.Count; i++)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
using CryptoExchange.Net.Clients;
|
using CryptoExchange.Net.Clients;
|
||||||
|
using CryptoExchange.Net.Interfaces.Clients;
|
||||||
|
using CryptoExchange.Net.RateLimiting;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace CryptoExchange.Net.SharedApis
|
namespace CryptoExchange.Net.SharedApis
|
||||||
{
|
{
|
||||||
@@ -12,7 +15,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
{
|
{
|
||||||
private readonly Func<string, string, TradingMode, DateTime?, string> _symbolFormatter;
|
private readonly Func<string, string, TradingMode, DateTime?, string> _symbolFormatter;
|
||||||
private readonly Func<bool> _authDelegate;
|
private readonly Func<bool> _authDelegate;
|
||||||
|
private readonly IBaseApiClient _apiClient;
|
||||||
private IReadOnlyCollection<CapabilityOptions> _capabilities = Array.Empty<CapabilityOptions>();
|
private IReadOnlyCollection<CapabilityOptions> _capabilities = Array.Empty<CapabilityOptions>();
|
||||||
IReadOnlyCollection<CapabilityOptions> ISharedApi.Capabilities => _capabilities;
|
IReadOnlyCollection<CapabilityOptions> ISharedApi.Capabilities => _capabilities;
|
||||||
|
|
||||||
@@ -33,16 +36,17 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public SharedApiBase(
|
public SharedApiBase(
|
||||||
SharedTransport transport,
|
SharedTransport transport,
|
||||||
string exchange,
|
IBaseApiClient apiClient,
|
||||||
TradingMode[] supportedTradingModes,
|
TradingMode[] supportedTradingModes,
|
||||||
Func<bool> authenticated,
|
Func<bool> authenticated,
|
||||||
Func<string, string, TradingMode, DateTime?, string> formatSymbol)
|
Func<string, string, TradingMode, DateTime?, string> formatSymbol)
|
||||||
{
|
{
|
||||||
Transport = transport;
|
_apiClient = apiClient;
|
||||||
Exchange = exchange;
|
|
||||||
SupportedTradingModes = supportedTradingModes;
|
|
||||||
_authDelegate = authenticated;
|
_authDelegate = authenticated;
|
||||||
_symbolFormatter = formatSymbol;
|
_symbolFormatter = formatSymbol;
|
||||||
|
Transport = transport;
|
||||||
|
Exchange = apiClient.Exchange;
|
||||||
|
SupportedTradingModes = supportedTradingModes;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@@ -64,6 +68,12 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public void ResetDefaultExchangeParameters() => ExchangeParameters.ResetStaticExchangeParameters(Exchange);
|
public void ResetDefaultExchangeParameters() => ExchangeParameters.ResetStaticExchangeParameters(Exchange);
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public Task<TResult> WithRateLimitAdmissionAsync<TResult>(
|
||||||
|
RateLimitAdmission admission,
|
||||||
|
Func<Task<TResult>> operation)
|
||||||
|
=> _apiClient.WithRateLimitAdmissionAsync(admission, operation);
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public abstract SharedClientInfo Discover();
|
public abstract SharedClientInfo Discover();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
namespace CryptoExchange.Net.SharedApis
|
namespace CryptoExchange.Net.SharedApis
|
||||||
{
|
{
|
||||||
@@ -76,5 +77,83 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
|
|
||||||
return services;
|
return services;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Execute GetTickerAsync for all capabilities in parallel and return results as they arrive
|
||||||
|
/// </summary>
|
||||||
|
public static IAsyncEnumerable<HttpResult<SharedTicker>> ExecuteAllAsync(
|
||||||
|
this IEnumerable<SharedCapabilityResolution<IGetTickerRest>> capabilities,
|
||||||
|
GetTickerRequest request,
|
||||||
|
CancellationToken ct = default)
|
||||||
|
{
|
||||||
|
return capabilities
|
||||||
|
.Select(x => x.Capability.GetTickerAsync(request, ct))
|
||||||
|
.ParallelEnumerateAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Execute GetAllTickersAsync for all capabilities in parallel and return results as they arrive
|
||||||
|
/// </summary>
|
||||||
|
public static IAsyncEnumerable<HttpResult<SharedTicker[]>> ExecuteAllAsync(
|
||||||
|
this IEnumerable<SharedCapabilityResolution<IGetAllTickersRest>> capabilities,
|
||||||
|
GetTickersRequest request,
|
||||||
|
CancellationToken ct = default)
|
||||||
|
{
|
||||||
|
return capabilities
|
||||||
|
.Select(x => x.Capability.GetAllTickersAsync(request, ct))
|
||||||
|
.ParallelEnumerateAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Execute GetAssetAsync for all capabilities in parallel and return results as they arrive
|
||||||
|
/// </summary>
|
||||||
|
public static IAsyncEnumerable<HttpResult<SharedAsset>> ExecuteAllAsync(
|
||||||
|
this IEnumerable<SharedCapabilityResolution<IGetAssetRest>> capabilities,
|
||||||
|
GetAssetRequest request,
|
||||||
|
CancellationToken ct = default)
|
||||||
|
{
|
||||||
|
return capabilities
|
||||||
|
.Select(x => x.Capability.GetAssetAsync(request, ct))
|
||||||
|
.ParallelEnumerateAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Execute GetAllAssetsAsync for all capabilities in parallel and return results as they arrive
|
||||||
|
/// </summary>
|
||||||
|
public static IAsyncEnumerable<HttpResult<SharedAsset[]>> ExecuteAllAsync(
|
||||||
|
this IEnumerable<SharedCapabilityResolution<IGetAllAssetsRest>> capabilities,
|
||||||
|
GetAssetsRequest request,
|
||||||
|
CancellationToken ct = default)
|
||||||
|
{
|
||||||
|
return capabilities
|
||||||
|
.Select(x => x.Capability.GetAllAssetsAsync(request, ct))
|
||||||
|
.ParallelEnumerateAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Execute GetAllBalancesAsync for all capabilities in parallel and return results as they arrive
|
||||||
|
/// </summary>
|
||||||
|
public static IAsyncEnumerable<HttpResult<SharedBalance[]>> ExecuteAllAsync(
|
||||||
|
this IEnumerable<SharedCapabilityResolution<IGetBalancesRest>> capabilities,
|
||||||
|
GetBalancesRequest request,
|
||||||
|
CancellationToken ct = default)
|
||||||
|
{
|
||||||
|
return capabilities
|
||||||
|
.Select(x => x.Capability.GetBalancesAsync(request, ct))
|
||||||
|
.ParallelEnumerateAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Execute GetAllBalancesAsync for all capabilities in parallel and return results as they arrive
|
||||||
|
/// </summary>
|
||||||
|
public static IAsyncEnumerable<ICallResult<SharedBalance[]>> ExecuteAllAsync(
|
||||||
|
this IEnumerable<SharedCapabilityResolution<IGetBalances>> capabilities,
|
||||||
|
GetBalancesRequest request,
|
||||||
|
CancellationToken ct = default)
|
||||||
|
{
|
||||||
|
return capabilities
|
||||||
|
.Select(x => x.Capability.GetBalancesAsync(request, ct))
|
||||||
|
.ParallelEnumerateAsync();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="request">Request info</param>
|
/// <param name="request">Request info</param>
|
||||||
/// <param name="ct">Cancellation token</param>
|
/// <param name="ct">Cancellation token</param>
|
||||||
Task<ICallResult<SharedAsset[]>> GetAllAssetsAsync(GetAssetsRequest request, CancellationToken ct = default);
|
Task<IExchangeCallResult<SharedAsset[]>> GetAllAssetsAsync(GetAssetsRequest request, CancellationToken ct = default);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="request">Request info</param>
|
/// <param name="request">Request info</param>
|
||||||
/// <param name="ct">Cancellation token</param>
|
/// <param name="ct">Cancellation token</param>
|
||||||
Task<ICallResult<SharedAsset>> GetAssetAsync(GetAssetRequest request, CancellationToken ct = default);
|
Task<IExchangeCallResult<SharedAsset>> GetAssetAsync(GetAssetRequest request, CancellationToken ct = default);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// <param name="request">Request info</param>
|
/// <param name="request">Request info</param>
|
||||||
/// <param name="ct">Cancellation token</param>
|
/// <param name="ct">Cancellation token</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<ICallResult<SharedBalance[]>> GetBalancesAsync(GetBalancesRequest request, CancellationToken ct = default);
|
Task<IExchangeCallResult<SharedBalance[]>> GetBalancesAsync(GetBalancesRequest request, CancellationToken ct = default);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
+1
-1
@@ -25,7 +25,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// <param name="request">Request info</param>
|
/// <param name="request">Request info</param>
|
||||||
/// <param name="ct">Cancellation token</param>
|
/// <param name="ct">Cancellation token</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<ICallResult<SharedDepositAddress[]>> GetDepositAddressesAsync(GetDepositAddressesRequest request, CancellationToken ct = default);
|
Task<IExchangeCallResult<SharedDepositAddress[]>> GetDepositAddressesAsync(GetDepositAddressesRequest request, CancellationToken ct = default);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// <param name="nextPageToken">The pagination request from the previous request result <see cref="HttpResult{T}.NextPageRequest"/> property to continue pagination</param>
|
/// <param name="nextPageToken">The pagination request from the previous request result <see cref="HttpResult{T}.NextPageRequest"/> property to continue pagination</param>
|
||||||
/// <param name="ct">Cancellation token</param>
|
/// <param name="ct">Cancellation token</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<ICallResult<SharedDeposit[]>> GetDepositHistoryAsync(GetDepositsRequest request, PageRequest? nextPageToken = null, CancellationToken ct = default);
|
Task<IExchangeCallResult<SharedDeposit[]>> GetDepositHistoryAsync(GetDepositsRequest request, PageRequest? nextPageToken = null, CancellationToken ct = default);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="request">Request info</param>
|
/// <param name="request">Request info</param>
|
||||||
/// <param name="ct">Cancellation token</param>
|
/// <param name="ct">Cancellation token</param>
|
||||||
Task<ICallResult<SharedFee>> GetFeesAsync(GetFeeRequest request, CancellationToken ct = default);
|
Task<IExchangeCallResult<SharedFee>> GetFeesAsync(GetFeeRequest request, CancellationToken ct = default);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="request">Request info</param>
|
/// <param name="request">Request info</param>
|
||||||
/// <param name="ct">Cancellation token</param>
|
/// <param name="ct">Cancellation token</param>
|
||||||
Task<ICallResult<SharedFundingInfo>> GetFundingInfoAsync(GetFundingInfoRequest request, CancellationToken ct = default);
|
Task<IExchangeCallResult<SharedFundingInfo>> GetFundingInfoAsync(GetFundingInfoRequest request, CancellationToken ct = default);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
+1
-1
@@ -25,7 +25,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// <param name="request">Request info</param>
|
/// <param name="request">Request info</param>
|
||||||
/// <param name="nextPageToken">The pagination request from the previous request result <see cref="HttpResult{T}.NextPageRequest"/> property to continue pagination</param>
|
/// <param name="nextPageToken">The pagination request from the previous request result <see cref="HttpResult{T}.NextPageRequest"/> property to continue pagination</param>
|
||||||
/// <param name="ct">Cancellation token</param>
|
/// <param name="ct">Cancellation token</param>
|
||||||
Task<ICallResult<SharedFundingRate[]>> GetFundingRateHistoryAsync(GetFundingRateHistoryRequest request, PageRequest? nextPageToken = null, CancellationToken ct = default);
|
Task<IExchangeCallResult<SharedFundingRate[]>> GetFundingRateHistoryAsync(GetFundingRateHistoryRequest request, PageRequest? nextPageToken = null, CancellationToken ct = default);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
+1
-1
@@ -25,7 +25,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// <param name="request">Request info</param>
|
/// <param name="request">Request info</param>
|
||||||
/// <param name="nextPageToken">The pagination request from the previous request result <see cref="HttpResult{T}.NextPageRequest"/> property to continue pagination</param>
|
/// <param name="nextPageToken">The pagination request from the previous request result <see cref="HttpResult{T}.NextPageRequest"/> property to continue pagination</param>
|
||||||
/// <param name="ct">Cancellation token</param>
|
/// <param name="ct">Cancellation token</param>
|
||||||
Task<ICallResult<SharedFundingFee[]>> GetUserFundingHistoryAsync(GetUserFundingHistoryRequest request, PageRequest? nextPageToken = null, CancellationToken ct = default);
|
Task<IExchangeCallResult<SharedFundingFee[]>> GetUserFundingHistoryAsync(GetUserFundingHistoryRequest request, PageRequest? nextPageToken = null, CancellationToken ct = default);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -1,12 +1,15 @@
|
|||||||
using System;
|
using CryptoExchange.Net.Interfaces;
|
||||||
|
using CryptoExchange.Net.RateLimiting;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace CryptoExchange.Net.SharedApis
|
namespace CryptoExchange.Net.SharedApis
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Shared API
|
/// Shared API
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface ISharedApi
|
public interface ISharedApi : IRateLimitAdmissionClient
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Name of the exchange
|
/// Name of the exchange
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="request">Request info</param>
|
/// <param name="request">Request info</param>
|
||||||
/// <param name="ct">Cancellation token</param>
|
/// <param name="ct">Cancellation token</param>
|
||||||
Task<ICallResult<SharedIndexPrice[]>> GetAllIndexPricesAsync(GetAllIndexPricesRequest request, CancellationToken ct = default);
|
Task<IExchangeCallResult<SharedIndexPrice[]>> GetAllIndexPricesAsync(GetAllIndexPricesRequest request, CancellationToken ct = default);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="request">Request info</param>
|
/// <param name="request">Request info</param>
|
||||||
/// <param name="ct">Cancellation token</param>
|
/// <param name="ct">Cancellation token</param>
|
||||||
Task<ICallResult<SharedIndexPrice>> GetIndexPriceAsync(GetIndexPriceRequest request, CancellationToken ct = default);
|
Task<IExchangeCallResult<SharedIndexPrice>> GetIndexPriceAsync(GetIndexPriceRequest request, CancellationToken ct = default);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
+1
-1
@@ -25,7 +25,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// <param name="request">Request info</param>
|
/// <param name="request">Request info</param>
|
||||||
/// <param name="nextPageToken">The pagination request from the previous request result <see cref="HttpResult{T}.NextPageRequest"/> property to continue pagination</param>
|
/// <param name="nextPageToken">The pagination request from the previous request result <see cref="HttpResult{T}.NextPageRequest"/> property to continue pagination</param>
|
||||||
/// <param name="ct">Cancellation token</param>
|
/// <param name="ct">Cancellation token</param>
|
||||||
Task<ICallResult<SharedFuturesKline[]>> GetIndexPriceKlinesAsync(GetKlinesRequest request, PageRequest? nextPageToken = null, CancellationToken ct = default);
|
Task<IExchangeCallResult<SharedFuturesKline[]>> GetIndexPriceKlinesAsync(GetKlinesRequest request, PageRequest? nextPageToken = null, CancellationToken ct = default);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
+1
-1
@@ -25,7 +25,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// <param name="request">Request info</param>
|
/// <param name="request">Request info</param>
|
||||||
/// <param name="nextPageToken">The pagination request from the previous request result <see cref="HttpResult{T}.NextPageRequest"/> property to continue pagination</param>
|
/// <param name="nextPageToken">The pagination request from the previous request result <see cref="HttpResult{T}.NextPageRequest"/> property to continue pagination</param>
|
||||||
/// <param name="ct">Cancellation token</param>
|
/// <param name="ct">Cancellation token</param>
|
||||||
Task<ICallResult<SharedFuturesKline[]>> GetMarkPriceKlinesAsync(GetKlinesRequest request, PageRequest? nextPageToken = null, CancellationToken ct = default);
|
Task<IExchangeCallResult<SharedFuturesKline[]>> GetMarkPriceKlinesAsync(GetKlinesRequest request, PageRequest? nextPageToken = null, CancellationToken ct = default);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// <param name="nextPageToken">The pagination request from the previous request result <see cref="HttpResult{T}.NextPageRequest"/> property to continue pagination</param>
|
/// <param name="nextPageToken">The pagination request from the previous request result <see cref="HttpResult{T}.NextPageRequest"/> property to continue pagination</param>
|
||||||
/// <param name="ct">Cancellation token</param>
|
/// <param name="ct">Cancellation token</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<ICallResult<SharedKline[]>> GetKlinesAsync(GetKlinesRequest request, PageRequest? nextPageToken = null, CancellationToken ct = default);
|
Task<IExchangeCallResult<SharedKline[]>> GetKlinesAsync(GetKlinesRequest request, PageRequest? nextPageToken = null, CancellationToken ct = default);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// <param name="request">Request info</param>
|
/// <param name="request">Request info</param>
|
||||||
/// <param name="nextPageToken">The pagination request from the previous request result <see cref="HttpResult{T}.NextPageRequest"/> property to continue pagination</param>
|
/// <param name="nextPageToken">The pagination request from the previous request result <see cref="HttpResult{T}.NextPageRequest"/> property to continue pagination</param>
|
||||||
/// <param name="ct">Cancellation token</param>
|
/// <param name="ct">Cancellation token</param>
|
||||||
Task<ICallResult<SharedLedgerEntry[]>> GetLedgerAsync(GetLedgerRequest request, PageRequest? nextPageToken = null, CancellationToken ct = default);
|
Task<IExchangeCallResult<SharedLedgerEntry[]>> GetLedgerAsync(GetLedgerRequest request, PageRequest? nextPageToken = null, CancellationToken ct = default);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="request">Request info</param>
|
/// <param name="request">Request info</param>
|
||||||
/// <param name="ct">Cancellation token</param>
|
/// <param name="ct">Cancellation token</param>
|
||||||
Task<ICallResult<SharedLeverage>> GetLeverageAsync(GetLeverageRequest request, CancellationToken ct = default);
|
Task<IExchangeCallResult<SharedLeverage>> GetLeverageAsync(GetLeverageRequest request, CancellationToken ct = default);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="request">Request info</param>
|
/// <param name="request">Request info</param>
|
||||||
/// <param name="ct">Cancellation token</param>
|
/// <param name="ct">Cancellation token</param>
|
||||||
Task<ICallResult<SharedLeverageTier[]>> GetLeverageTiersAsync(GetLeverageTiersRequest request, CancellationToken ct = default);
|
Task<IExchangeCallResult<SharedLeverageTier[]>> GetLeverageTiersAsync(GetLeverageTiersRequest request, CancellationToken ct = default);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="request">Request info</param>
|
/// <param name="request">Request info</param>
|
||||||
/// <param name="ct">Cancellation token</param>
|
/// <param name="ct">Cancellation token</param>
|
||||||
Task<ICallResult<SharedLeverage>> SetLeverageAsync(SetLeverageRequest request, CancellationToken ct = default);
|
Task<IExchangeCallResult<SharedLeverage>> SetLeverageAsync(SetLeverageRequest request, CancellationToken ct = default);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="request">Request info</param>
|
/// <param name="request">Request info</param>
|
||||||
/// <param name="ct">Cancellation token</param>
|
/// <param name="ct">Cancellation token</param>
|
||||||
Task<ICallResult<SharedMarkPrice[]>> GetAllMarkPricesAsync(GetAllMarkPricesRequest request, CancellationToken ct = default);
|
Task<IExchangeCallResult<SharedMarkPrice[]>> GetAllMarkPricesAsync(GetAllMarkPricesRequest request, CancellationToken ct = default);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="request">Request info</param>
|
/// <param name="request">Request info</param>
|
||||||
/// <param name="ct">Cancellation token</param>
|
/// <param name="ct">Cancellation token</param>
|
||||||
Task<ICallResult<SharedMarkPrice>> GetMarkPriceAsync(GetMarkPriceRequest request, CancellationToken ct = default);
|
Task<IExchangeCallResult<SharedMarkPrice>> GetMarkPriceAsync(GetMarkPriceRequest request, CancellationToken ct = default);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="request">Request info</param>
|
/// <param name="request">Request info</param>
|
||||||
/// <param name="ct">Cancellation token</param>
|
/// <param name="ct">Cancellation token</param>
|
||||||
Task<ICallResult<SharedOpenInterest>> GetOpenInterestAsync(GetOpenInterestRequest request, CancellationToken ct = default);
|
Task<IExchangeCallResult<SharedOpenInterest>> GetOpenInterestAsync(GetOpenInterestRequest request, CancellationToken ct = default);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// <param name="request">Request info</param>
|
/// <param name="request">Request info</param>
|
||||||
/// <param name="ct">Cancellation token</param>
|
/// <param name="ct">Cancellation token</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<ICallResult<SharedBookTicker>> GetBookTickerAsync(GetBookTickerRequest request, CancellationToken ct = default);
|
Task<IExchangeCallResult<SharedBookTicker>> GetBookTickerAsync(GetBookTickerRequest request, CancellationToken ct = default);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// <param name="request">Request info</param>
|
/// <param name="request">Request info</param>
|
||||||
/// <param name="ct">Cancellation token</param>
|
/// <param name="ct">Cancellation token</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<ICallResult<SharedOrderBook>> GetOrderBookAsync(GetOrderBookRequest request, CancellationToken ct = default);
|
Task<IExchangeCallResult<SharedOrderBook>> GetOrderBookAsync(GetOrderBookRequest request, CancellationToken ct = default);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
+1
-1
@@ -23,7 +23,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="request">Request info</param>
|
/// <param name="request">Request info</param>
|
||||||
/// <param name="ct">Cancellation token</param>
|
/// <param name="ct">Cancellation token</param>
|
||||||
Task<ICallResult> CancelAllFuturesOrdersAsync(CancelAllOrdersRequest request, CancellationToken ct = default);
|
Task<IExchangeCallResult> CancelAllFuturesOrdersAsync(CancelAllOrdersRequest request, CancellationToken ct = default);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
+1
-1
@@ -23,7 +23,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="request">Request info</param>
|
/// <param name="request">Request info</param>
|
||||||
/// <param name="ct">Cancellation token</param>
|
/// <param name="ct">Cancellation token</param>
|
||||||
Task<ICallResult> CancelAllFuturesSymbolOrdersAsync(CancelAllSymbolOrdersRequest request, CancellationToken ct = default);
|
Task<IExchangeCallResult> CancelAllFuturesSymbolOrdersAsync(CancelAllSymbolOrdersRequest request, CancellationToken ct = default);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
+1
-1
@@ -23,7 +23,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="request">Request info</param>
|
/// <param name="request">Request info</param>
|
||||||
/// <param name="ct">Cancellation token</param>
|
/// <param name="ct">Cancellation token</param>
|
||||||
Task<ICallResult<SharedId>> CancelFuturesOrderAsync(CancelOrderRequest request, CancellationToken ct = default);
|
Task<IExchangeCallResult<SharedId>> CancelFuturesOrderAsync(CancelOrderRequest request, CancellationToken ct = default);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
+1
-1
@@ -23,7 +23,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="request">Request info</param>
|
/// <param name="request">Request info</param>
|
||||||
/// <param name="ct">Cancellation token</param>
|
/// <param name="ct">Cancellation token</param>
|
||||||
Task<ICallResult<SharedId>> CancelFuturesOrderByClientOrderIdAsync(CancelOrderRequest request, CancellationToken ct = default);
|
Task<IExchangeCallResult<SharedId>> CancelFuturesOrderByClientOrderIdAsync(CancelOrderRequest request, CancellationToken ct = default);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
+1
-1
@@ -24,7 +24,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="request">Request info</param>
|
/// <param name="request">Request info</param>
|
||||||
/// <param name="ct">Cancellation token</param>
|
/// <param name="ct">Cancellation token</param>
|
||||||
Task<ICallResult<SharedId>> EditFuturesOrderAsync(
|
Task<IExchangeCallResult<SharedId>> EditFuturesOrderAsync(
|
||||||
EditOrderRequest request,
|
EditOrderRequest request,
|
||||||
CancellationToken ct = default);
|
CancellationToken ct = default);
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -23,7 +23,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="request">Request info</param>
|
/// <param name="request">Request info</param>
|
||||||
/// <param name="ct">Cancellation token</param>
|
/// <param name="ct">Cancellation token</param>
|
||||||
Task<ICallResult<SharedId>> EditFuturesOrderByClientOrderIdAsync(EditOrderRequest request, CancellationToken ct = default);
|
Task<IExchangeCallResult<SharedId>> EditFuturesOrderByClientOrderIdAsync(EditOrderRequest request, CancellationToken ct = default);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
+1
-1
@@ -25,7 +25,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// <param name="request">Request info</param>
|
/// <param name="request">Request info</param>
|
||||||
/// <param name="nextPageToken">The pagination request from the previous request result <see cref="HttpResult{T}.NextPageRequest"/> property to continue pagination</param>
|
/// <param name="nextPageToken">The pagination request from the previous request result <see cref="HttpResult{T}.NextPageRequest"/> property to continue pagination</param>
|
||||||
/// <param name="ct">Cancellation token</param>
|
/// <param name="ct">Cancellation token</param>
|
||||||
Task<ICallResult<SharedFuturesOrder[]>> GetClosedFuturesOrdersAsync(GetClosedOrdersRequest request, PageRequest? nextPageToken = null, CancellationToken ct = default);
|
Task<IExchangeCallResult<SharedFuturesOrder[]>> GetClosedFuturesOrdersAsync(GetClosedOrdersRequest request, PageRequest? nextPageToken = null, CancellationToken ct = default);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="request">Request info</param>
|
/// <param name="request">Request info</param>
|
||||||
/// <param name="ct">Cancellation token</param>
|
/// <param name="ct">Cancellation token</param>
|
||||||
Task<ICallResult<SharedFuturesOrder>> GetFuturesOrderAsync(GetOrderRequest request, CancellationToken ct = default);
|
Task<IExchangeCallResult<SharedFuturesOrder>> GetFuturesOrderAsync(GetOrderRequest request, CancellationToken ct = default);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
+1
-1
@@ -24,7 +24,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="request">Request info</param>
|
/// <param name="request">Request info</param>
|
||||||
/// <param name="ct">Cancellation token</param>
|
/// <param name="ct">Cancellation token</param>
|
||||||
Task<ICallResult<SharedFuturesOrder>> GetFuturesOrderByClientOrderIdAsync(GetOrderRequest request, CancellationToken ct = default);
|
Task<IExchangeCallResult<SharedFuturesOrder>> GetFuturesOrderByClientOrderIdAsync(GetOrderRequest request, CancellationToken ct = default);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
+1
-1
@@ -23,7 +23,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="request">Request info</param>
|
/// <param name="request">Request info</param>
|
||||||
/// <param name="ct">Cancellation token</param>
|
/// <param name="ct">Cancellation token</param>
|
||||||
Task<ICallResult<SharedFuturesOrder[]>> GetOpenFuturesOrdersAsync(GetOpenOrdersRequest request, CancellationToken ct = default);
|
Task<IExchangeCallResult<SharedFuturesOrder[]>> GetOpenFuturesOrdersAsync(GetOpenOrdersRequest request, CancellationToken ct = default);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
+1
-1
@@ -51,7 +51,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="request">Request info</param>
|
/// <param name="request">Request info</param>
|
||||||
/// <param name="ct">Cancellation token</param>
|
/// <param name="ct">Cancellation token</param>
|
||||||
Task<ICallResult<SharedId>> PlaceFuturesOrderAsync(PlaceFuturesOrderRequest request, CancellationToken ct = default);
|
Task<IExchangeCallResult<SharedId>> PlaceFuturesOrderAsync(PlaceFuturesOrderRequest request, CancellationToken ct = default);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
+1
-1
@@ -59,7 +59,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="request">Request info</param>
|
/// <param name="request">Request info</param>
|
||||||
/// <param name="ct">Cancellation token</param>
|
/// <param name="ct">Cancellation token</param>
|
||||||
Task<ICallResult<CallResult<SharedId>[]>> PlaceMultipleFuturesOrdersAsync(
|
Task<IExchangeCallResult<CallResult<SharedId>[]>> PlaceMultipleFuturesOrdersAsync(
|
||||||
PlaceMultipleFuturesOrdersRequest request,
|
PlaceMultipleFuturesOrdersRequest request,
|
||||||
CancellationToken ct = default);
|
CancellationToken ct = default);
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -23,7 +23,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="request">Request info</param>
|
/// <param name="request">Request info</param>
|
||||||
/// <param name="ct">Cancellation token</param>
|
/// <param name="ct">Cancellation token</param>
|
||||||
Task<ICallResult> CancelAllSpotOrdersAsync(CancelAllOrdersRequest request, CancellationToken ct = default);
|
Task<IExchangeCallResult> CancelAllSpotOrdersAsync(CancelAllOrdersRequest request, CancellationToken ct = default);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
+1
-1
@@ -23,7 +23,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="request">Request info</param>
|
/// <param name="request">Request info</param>
|
||||||
/// <param name="ct">Cancellation token</param>
|
/// <param name="ct">Cancellation token</param>
|
||||||
Task<ICallResult> CancelAllSpotSymbolOrdersAsync(CancelAllSymbolOrdersRequest request, CancellationToken ct = default);
|
Task<IExchangeCallResult> CancelAllSpotSymbolOrdersAsync(CancelAllSymbolOrdersRequest request, CancellationToken ct = default);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="request">Request info</param>
|
/// <param name="request">Request info</param>
|
||||||
/// <param name="ct">Cancellation token</param>
|
/// <param name="ct">Cancellation token</param>
|
||||||
Task<ICallResult<SharedId>> CancelSpotOrderAsync(CancelOrderRequest request, CancellationToken ct = default);
|
Task<IExchangeCallResult<SharedId>> CancelSpotOrderAsync(CancelOrderRequest request, CancellationToken ct = default);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
+1
-1
@@ -23,7 +23,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="request">Request info</param>
|
/// <param name="request">Request info</param>
|
||||||
/// <param name="ct">Cancellation token</param>
|
/// <param name="ct">Cancellation token</param>
|
||||||
Task<ICallResult<SharedId>> CancelSpotOrderByClientOrderIdAsync(CancelOrderRequest request, CancellationToken ct = default);
|
Task<IExchangeCallResult<SharedId>> CancelSpotOrderByClientOrderIdAsync(CancelOrderRequest request, CancellationToken ct = default);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="request">Request info</param>
|
/// <param name="request">Request info</param>
|
||||||
/// <param name="ct">Cancellation token</param>
|
/// <param name="ct">Cancellation token</param>
|
||||||
Task<ICallResult<SharedId>> EditSpotOrderAsync(
|
Task<IExchangeCallResult<SharedId>> EditSpotOrderAsync(
|
||||||
EditOrderRequest request,
|
EditOrderRequest request,
|
||||||
CancellationToken ct = default);
|
CancellationToken ct = default);
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -23,7 +23,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="request">Request info</param>
|
/// <param name="request">Request info</param>
|
||||||
/// <param name="ct">Cancellation token</param>
|
/// <param name="ct">Cancellation token</param>
|
||||||
Task<ICallResult<SharedId>> EditSpotOrderByClientOrderIdAsync(EditOrderRequest request, CancellationToken ct = default);
|
Task<IExchangeCallResult<SharedId>> EditSpotOrderByClientOrderIdAsync(EditOrderRequest request, CancellationToken ct = default);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
+1
-1
@@ -25,7 +25,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// <param name="request">Request info</param>
|
/// <param name="request">Request info</param>
|
||||||
/// <param name="nextPageToken">The pagination request from the previous request result <see cref="HttpResult{T}.NextPageRequest"/> property to continue pagination</param>
|
/// <param name="nextPageToken">The pagination request from the previous request result <see cref="HttpResult{T}.NextPageRequest"/> property to continue pagination</param>
|
||||||
/// <param name="ct">Cancellation token</param>
|
/// <param name="ct">Cancellation token</param>
|
||||||
Task<ICallResult<SharedSpotOrder[]>> GetClosedSpotOrdersAsync(GetClosedOrdersRequest request, PageRequest? nextPageToken = null, CancellationToken ct = default);
|
Task<IExchangeCallResult<SharedSpotOrder[]>> GetClosedSpotOrdersAsync(GetClosedOrdersRequest request, PageRequest? nextPageToken = null, CancellationToken ct = default);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
+1
-1
@@ -23,7 +23,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="request">Request info</param>
|
/// <param name="request">Request info</param>
|
||||||
/// <param name="ct">Cancellation token</param>
|
/// <param name="ct">Cancellation token</param>
|
||||||
Task<ICallResult<SharedSpotOrder[]>> GetOpenSpotOrdersAsync(GetOpenOrdersRequest request, CancellationToken ct = default);
|
Task<IExchangeCallResult<SharedSpotOrder[]>> GetOpenSpotOrdersAsync(GetOpenOrdersRequest request, CancellationToken ct = default);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="request">Request info</param>
|
/// <param name="request">Request info</param>
|
||||||
/// <param name="ct">Cancellation token</param>
|
/// <param name="ct">Cancellation token</param>
|
||||||
Task<ICallResult<SharedSpotOrder>> GetSpotOrderAsync(GetOrderRequest request, CancellationToken ct = default);
|
Task<IExchangeCallResult<SharedSpotOrder>> GetSpotOrderAsync(GetOrderRequest request, CancellationToken ct = default);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
+1
-1
@@ -24,7 +24,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="request">Request info</param>
|
/// <param name="request">Request info</param>
|
||||||
/// <param name="ct">Cancellation token</param>
|
/// <param name="ct">Cancellation token</param>
|
||||||
Task<ICallResult<SharedSpotOrder>> GetSpotOrderByClientOrderIdAsync(GetOrderRequest request, CancellationToken ct = default);
|
Task<IExchangeCallResult<SharedSpotOrder>> GetSpotOrderByClientOrderIdAsync(GetOrderRequest request, CancellationToken ct = default);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -59,7 +59,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="request">Request info</param>
|
/// <param name="request">Request info</param>
|
||||||
/// <param name="ct">Cancellation token</param>
|
/// <param name="ct">Cancellation token</param>
|
||||||
Task<ICallResult<CallResult<SharedId>[]>> PlaceMultipleSpotOrdersAsync(
|
Task<IExchangeCallResult<CallResult<SharedId>[]>> PlaceMultipleSpotOrdersAsync(
|
||||||
PlaceMultipleSpotOrdersRequest request,
|
PlaceMultipleSpotOrdersRequest request,
|
||||||
CancellationToken ct = default);
|
CancellationToken ct = default);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="request">Request info</param>
|
/// <param name="request">Request info</param>
|
||||||
/// <param name="ct">Cancellation token</param>
|
/// <param name="ct">Cancellation token</param>
|
||||||
Task<ICallResult<SharedId>> PlaceSpotOrderAsync(
|
Task<IExchangeCallResult<SharedId>> PlaceSpotOrderAsync(
|
||||||
PlaceSpotOrderRequest request,
|
PlaceSpotOrderRequest request,
|
||||||
CancellationToken ct = default);
|
CancellationToken ct = default);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="request">Request info</param>
|
/// <param name="request">Request info</param>
|
||||||
/// <param name="ct">Cancellation token</param>
|
/// <param name="ct">Cancellation token</param>
|
||||||
Task<ICallResult<SharedPositionModeResult>> GetPositionModeAsync(GetPositionModeRequest request, CancellationToken ct = default);
|
Task<IExchangeCallResult<SharedPositionModeResult>> GetPositionModeAsync(GetPositionModeRequest request, CancellationToken ct = default);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="request">Request info</param>
|
/// <param name="request">Request info</param>
|
||||||
/// <param name="ct">Cancellation token</param>
|
/// <param name="ct">Cancellation token</param>
|
||||||
Task<ICallResult<SharedPositionModeResult>> SetPositionModeAsync(SetPositionModeRequest request, CancellationToken ct = default);
|
Task<IExchangeCallResult<SharedPositionModeResult>> SetPositionModeAsync(SetPositionModeRequest request, CancellationToken ct = default);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// <param name="request">Request info</param>
|
/// <param name="request">Request info</param>
|
||||||
/// <param name="ct">Cancellation token</param>
|
/// <param name="ct">Cancellation token</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<ICallResult<SharedId>> CloseFullPositionAsync(CloseFullPositionRequest request, CancellationToken ct = default);
|
Task<IExchangeCallResult<SharedId>> CloseFullPositionAsync(CloseFullPositionRequest request, CancellationToken ct = default);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
+1
-1
@@ -25,7 +25,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// <param name="request">Request info</param>
|
/// <param name="request">Request info</param>
|
||||||
/// <param name="nextPageToken">The pagination request from the previous request result <see cref="HttpResult{T}.NextPageRequest"/> property to continue pagination</param>
|
/// <param name="nextPageToken">The pagination request from the previous request result <see cref="HttpResult{T}.NextPageRequest"/> property to continue pagination</param>
|
||||||
/// <param name="ct">Cancellation token</param>
|
/// <param name="ct">Cancellation token</param>
|
||||||
Task<ICallResult<SharedPositionHistory[]>> GetPositionHistoryAsync(GetPositionHistoryRequest request, PageRequest? nextPageToken = null, CancellationToken ct = default);
|
Task<IExchangeCallResult<SharedPositionHistory[]>> GetPositionHistoryAsync(GetPositionHistoryRequest request, PageRequest? nextPageToken = null, CancellationToken ct = default);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="request">Request info</param>
|
/// <param name="request">Request info</param>
|
||||||
/// <param name="ct">Cancellation token</param>
|
/// <param name="ct">Cancellation token</param>
|
||||||
Task<ICallResult<SharedPosition[]>> GetPositionsAsync(GetPositionsRequest request, CancellationToken ct = default);
|
Task<IExchangeCallResult<SharedPosition[]>> GetPositionsAsync(GetPositionsRequest request, CancellationToken ct = default);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// Get all futures symbols for a specific base asset
|
/// Get all futures symbols for a specific base asset
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="baseAsset">Asset, for example `ETH`</param>
|
/// <param name="baseAsset">Asset, for example `ETH`</param>
|
||||||
Task<ExchangeCallResult<SharedSymbol[]>> GetFuturesSymbolsForBaseAssetAsync(string baseAsset);
|
Task<IExchangeCallResult<SharedSymbol[]>> GetFuturesSymbolsForBaseAssetAsync(string baseAsset);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets whether the client supports a futures symbol
|
/// Gets whether the client supports a futures symbol
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// Gets whether the client supports a spot symbol
|
/// Gets whether the client supports a spot symbol
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="symbol">The symbol</param>
|
/// <param name="symbol">The symbol</param>
|
||||||
Task<ExchangeCallResult<bool>> SupportsSpotSymbolAsync(SharedSymbol symbol);
|
Task<IExchangeCallResult<bool>> SupportsSpotSymbolAsync(SharedSymbol symbol);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets whether the client supports a spot symbol
|
/// Gets whether the client supports a spot symbol
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="request">Request info</param>
|
/// <param name="request">Request info</param>
|
||||||
/// <param name="ct">Cancellation token</param>
|
/// <param name="ct">Cancellation token</param>
|
||||||
Task<ICallResult<SharedTicker[]>> GetAllTickersAsync(GetTickersRequest request, CancellationToken ct = default);
|
Task<IExchangeCallResult<SharedTicker[]>> GetAllTickersAsync(GetTickersRequest request, CancellationToken ct = default);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="request">Request info</param>
|
/// <param name="request">Request info</param>
|
||||||
/// <param name="ct">Cancellation token</param>
|
/// <param name="ct">Cancellation token</param>
|
||||||
Task<ICallResult<SharedTicker>> GetTickerAsync(GetTickerRequest request, CancellationToken ct = default);
|
Task<IExchangeCallResult<SharedTicker>> GetTickerAsync(GetTickerRequest request, CancellationToken ct = default);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// <param name="request">Request info</param>
|
/// <param name="request">Request info</param>
|
||||||
/// <param name="ct">Cancellation token</param>
|
/// <param name="ct">Cancellation token</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<ICallResult<bool>> CancelFuturesTpSlAsync(CancelTpSlRequest request, CancellationToken ct = default);
|
Task<IExchangeCallResult<bool>> CancelFuturesTpSlAsync(CancelTpSlRequest request, CancellationToken ct = default);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// <param name="request">Request info</param>
|
/// <param name="request">Request info</param>
|
||||||
/// <param name="ct">Cancellation token</param>
|
/// <param name="ct">Cancellation token</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<ICallResult<SharedId>> SetFuturesTpSlAsync(SetTpSlRequest request, CancellationToken ct = default);
|
Task<IExchangeCallResult<SharedId>> SetFuturesTpSlAsync(SetTpSlRequest request, CancellationToken ct = default);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// <param name="request">Request info</param>
|
/// <param name="request">Request info</param>
|
||||||
/// <param name="ct">Cancellation token</param>
|
/// <param name="ct">Cancellation token</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<ICallResult<SharedTrade[]>> GetRecentTradesAsync(GetRecentTradesRequest request, CancellationToken ct = default);
|
Task<IExchangeCallResult<SharedTrade[]>> GetRecentTradesAsync(GetRecentTradesRequest request, CancellationToken ct = default);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// <param name="nextPageToken">The pagination request from the previous request result <see cref="HttpResult{T}.NextPageRequest"/> property to continue pagination</param>
|
/// <param name="nextPageToken">The pagination request from the previous request result <see cref="HttpResult{T}.NextPageRequest"/> property to continue pagination</param>
|
||||||
/// <param name="ct">Cancellation token</param>
|
/// <param name="ct">Cancellation token</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<ICallResult<SharedTrade[]>> GetTradeHistoryAsync(GetTradeHistoryRequest request, PageRequest? nextPageToken = null, CancellationToken ct = default);
|
Task<IExchangeCallResult<SharedTrade[]>> GetTradeHistoryAsync(GetTradeHistoryRequest request, PageRequest? nextPageToken = null, CancellationToken ct = default);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
+1
-1
@@ -25,7 +25,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// <param name="request">Request info</param>
|
/// <param name="request">Request info</param>
|
||||||
/// <param name="nextPageToken">The pagination request from the previous request result <see cref="HttpResult{T}.NextPageRequest"/> property to continue pagination</param>
|
/// <param name="nextPageToken">The pagination request from the previous request result <see cref="HttpResult{T}.NextPageRequest"/> property to continue pagination</param>
|
||||||
/// <param name="ct">Cancellation token</param>
|
/// <param name="ct">Cancellation token</param>
|
||||||
Task<ICallResult<SharedTransfer[]>> GetTransferHistoryAsync(GetTransferHistoryRequest request, PageRequest? nextPageToken = null, CancellationToken ct = default);
|
Task<IExchangeCallResult<SharedTransfer[]>> GetTransferHistoryAsync(GetTransferHistoryRequest request, PageRequest? nextPageToken = null, CancellationToken ct = default);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="request">Request info</param>
|
/// <param name="request">Request info</param>
|
||||||
/// <param name="ct">Cancellation token</param>
|
/// <param name="ct">Cancellation token</param>
|
||||||
Task<ICallResult<SharedId>> TransferAsync(TransferRequest request, CancellationToken ct = default);
|
Task<IExchangeCallResult<SharedId>> TransferAsync(TransferRequest request, CancellationToken ct = default);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
+1
-1
@@ -23,7 +23,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="request">Request info</param>
|
/// <param name="request">Request info</param>
|
||||||
/// <param name="ct">Cancellation token</param>
|
/// <param name="ct">Cancellation token</param>
|
||||||
Task<ICallResult<SharedId>> CancelFuturesTriggerOrderAsync(CancelOrderRequest request, CancellationToken ct = default);
|
Task<IExchangeCallResult<SharedId>> CancelFuturesTriggerOrderAsync(CancelOrderRequest request, CancellationToken ct = default);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
+1
-1
@@ -23,7 +23,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="request">Request info</param>
|
/// <param name="request">Request info</param>
|
||||||
/// <param name="ct">Cancellation token</param>
|
/// <param name="ct">Cancellation token</param>
|
||||||
Task<ICallResult<SharedFuturesTriggerOrder>> GetFuturesTriggerOrderAsync(GetOrderRequest request, CancellationToken ct = default);
|
Task<IExchangeCallResultSharedFuturesTriggerOrder>> GetFuturesTriggerOrderAsync(GetOrderRequest request, CancellationToken ct = default);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
+1
-1
@@ -25,7 +25,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// <param name="request">Request info</param>
|
/// <param name="request">Request info</param>
|
||||||
/// <param name="ct">Cancellation token</param>
|
/// <param name="ct">Cancellation token</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<ICallResult<SharedId>> PlaceFuturesTriggerOrderAsync(PlaceFuturesTriggerOrderRequest request, CancellationToken ct = default);
|
Task<IExchangeCallResult<SharedId>> PlaceFuturesTriggerOrderAsync(PlaceFuturesTriggerOrderRequest request, CancellationToken ct = default);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
+1
-1
@@ -23,7 +23,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="request">Request info</param>
|
/// <param name="request">Request info</param>
|
||||||
/// <param name="ct">Cancellation token</param>
|
/// <param name="ct">Cancellation token</param>
|
||||||
Task<ICallResult<SharedId>> CancelSpotTriggerOrderAsync(CancelOrderRequest request, CancellationToken ct = default);
|
Task<IExchangeCallResult<SharedId>> CancelSpotTriggerOrderAsync(CancelOrderRequest request, CancellationToken ct = default);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
+1
-1
@@ -23,7 +23,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="request">Request info</param>
|
/// <param name="request">Request info</param>
|
||||||
/// <param name="ct">Cancellation token</param>
|
/// <param name="ct">Cancellation token</param>
|
||||||
Task<ICallResult<SharedSpotTriggerOrder>> GetSpotTriggerOrderAsync(GetOrderRequest request, CancellationToken ct = default);
|
Task<IExchangeCallResult<SharedSpotTriggerOrder>> GetSpotTriggerOrderAsync(GetOrderRequest request, CancellationToken ct = default);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
+1
-1
@@ -25,7 +25,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// <param name="request">Request info</param>
|
/// <param name="request">Request info</param>
|
||||||
/// <param name="ct">Cancellation token</param>
|
/// <param name="ct">Cancellation token</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<ICallResult<SharedId>> PlaceSpotTriggerOrderAsync(PlaceSpotTriggerOrderRequest request, CancellationToken ct = default);
|
Task<IExchangeCallResult<SharedId>> PlaceSpotTriggerOrderAsync(PlaceSpotTriggerOrderRequest request, CancellationToken ct = default);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -23,7 +23,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="request">Request info</param>
|
/// <param name="request">Request info</param>
|
||||||
/// <param name="ct">Cancellation token</param>
|
/// <param name="ct">Cancellation token</param>
|
||||||
Task<ICallResult<SharedUserTrade[]>> GetFuturesOrderTradesAsync(GetOrderTradesRequest request, CancellationToken ct = default);
|
Task<IExchangeCallResult<SharedUserTrade[]>> GetFuturesOrderTradesAsync(GetOrderTradesRequest request, CancellationToken ct = default);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
+1
-1
@@ -25,7 +25,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// <param name="request">Request info</param>
|
/// <param name="request">Request info</param>
|
||||||
/// <param name="nextPageToken">The pagination request from the previous request result <see cref="HttpResult{T}.NextPageRequest"/> property to continue pagination</param>
|
/// <param name="nextPageToken">The pagination request from the previous request result <see cref="HttpResult{T}.NextPageRequest"/> property to continue pagination</param>
|
||||||
/// <param name="ct">Cancellation token</param>
|
/// <param name="ct">Cancellation token</param>
|
||||||
Task<ICallResult<SharedUserTrade[]>> GetFuturesUserTradeHistoryAsync(GetUserTradesRequest request, PageRequest? nextPageToken = null, CancellationToken ct = default);
|
Task<IExchangeCallResult<SharedUserTrade[]>> GetFuturesUserTradeHistoryAsync(GetUserTradesRequest request, PageRequest? nextPageToken = null, CancellationToken ct = default);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user