From ac33b5e96edc0fdfd75bb018d43f79f2fcd1b20d Mon Sep 17 00:00:00 2001 From: JKorf Date: Wed, 17 Apr 2024 16:54:26 +0200 Subject: [PATCH] Futures rate limiting --- .../FuturesApi/KucoinRestClientFuturesApi.cs | 13 ++-- .../KucoinRestClientFuturesApiAccount.cs | 60 ++++++++++++------- .../KucoinRestClientFuturesApiExchangeData.cs | 47 ++++++++++----- .../KucoinRestClientFuturesApiTrading.cs | 35 +++++++---- .../KucoinSocketClientFuturesApi.cs | 6 +- .../SpotApi/KucoinRestClientSpotApiAccount.cs | 2 +- .../IKucoinRestClientFuturesApiAccount.cs | 9 --- Kucoin.Net/Kucoin.Net.xml | 12 ---- docs/index.html | 2 +- 9 files changed, 105 insertions(+), 81 deletions(-) diff --git a/Kucoin.Net/Clients/FuturesApi/KucoinRestClientFuturesApi.cs b/Kucoin.Net/Clients/FuturesApi/KucoinRestClientFuturesApi.cs index fd78c421..540abfc4 100644 --- a/Kucoin.Net/Clients/FuturesApi/KucoinRestClientFuturesApi.cs +++ b/Kucoin.Net/Clients/FuturesApi/KucoinRestClientFuturesApi.cs @@ -66,9 +66,9 @@ internal KucoinRestClientFuturesApi(ILogger logger, HttpClient? httpClient, Kuco protected override AuthenticationProvider CreateAuthenticationProvider(ApiCredentials credentials) => new KucoinAuthenticationProvider((KucoinApiCredentials)credentials); - internal async Task Execute(Uri uri, HttpMethod method, CancellationToken ct, Dictionary? parameters = null, bool signed = false, HttpMethodParameterPosition? parameterPosition = null) + internal async Task SendAsync(RequestDefinition definition, ParameterCollection? parameters, CancellationToken cancellationToken, int? weight = null) { - var result = await SendRequestAsync>(uri, method, ct, parameters, signed, parameterPosition: parameterPosition, requestWeight: 0).ConfigureAwait(false); + var result = await base.SendAsync(BaseAddress, definition, parameters, cancellationToken, null, weight).ConfigureAwait(false); if (!result) return result.AsDatalessError(result.Error!); @@ -78,9 +78,9 @@ internal async Task Execute(Uri uri, HttpMethod method, Cancellat return result.AsDataless(); } - internal async Task> Execute(Uri uri, HttpMethod method, CancellationToken ct, Dictionary? parameters = null, bool signed = false, HttpMethodParameterPosition? parameterPosition = null) + internal async Task> SendAsync(RequestDefinition definition, ParameterCollection? parameters, CancellationToken cancellationToken, int? weight = null) { - var result = await SendRequestAsync>(uri, method, ct, parameters, signed, parameterPosition: parameterPosition, requestWeight: 0).ConfigureAwait(false); + var result = await base.SendAsync>(BaseAddress, definition, parameters, cancellationToken, null, weight).ConfigureAwait(false); if (!result) return result.AsError(result.Error!); @@ -90,11 +90,6 @@ internal async Task> Execute(Uri uri, HttpMethod method, Can return result.As(result.Data.Data); } - internal Uri GetUri(string path, int apiVersion = 1) - { - return new Uri(BaseAddress.AppendPath("api").AppendPath("v" + apiVersion, path)); - } - /// protected override Task> GetServerTimestampAsync() => ExchangeData.GetServerTimeAsync(); diff --git a/Kucoin.Net/Clients/FuturesApi/KucoinRestClientFuturesApiAccount.cs b/Kucoin.Net/Clients/FuturesApi/KucoinRestClientFuturesApiAccount.cs index 0c79488d..3fa615b7 100644 --- a/Kucoin.Net/Clients/FuturesApi/KucoinRestClientFuturesApiAccount.cs +++ b/Kucoin.Net/Clients/FuturesApi/KucoinRestClientFuturesApiAccount.cs @@ -20,6 +20,7 @@ namespace Kucoin.Net.Clients.FuturesApi /// public class KucoinRestClientFuturesApiAccount : IKucoinRestClientFuturesApiAccount { + private static readonly RequestDefinitionCache _definitions = new(); private readonly KucoinRestClientFuturesApi _baseClient; internal KucoinRestClientFuturesApiAccount(KucoinRestClientFuturesApi baseClient) @@ -33,7 +34,8 @@ public async Task> GetAccountOverviewAsync( { var parameters = new ParameterCollection(); parameters.AddOptionalParameter("currency", asset); - return await _baseClient.Execute(_baseClient.GetUri("account-overview"), HttpMethod.Get, ct, parameters, true).ConfigureAwait(false); + var request = _definitions.GetOrCreate(HttpMethod.Get, $"api/v1/account-overview", KucoinExchange.RateLimiter.FuturesRest, 5, true); + return await _baseClient.SendAsync(request, parameters, ct).ConfigureAwait(false); } /// @@ -47,7 +49,8 @@ public async Task> parameters.AddOptionalParameter("offset", offset?.ToString(CultureInfo.InvariantCulture)); parameters.AddOptionalParameter("maxCount", pageSize?.ToString(CultureInfo.InvariantCulture)); parameters.AddOptionalParameter("forward", forward); - return await _baseClient.Execute>(_baseClient.GetUri("transaction-history"), HttpMethod.Get, ct, parameters, true).ConfigureAwait(false); + var request = _definitions.GetOrCreate(HttpMethod.Get, $"api/v1/transaction-history", KucoinExchange.RateLimiter.ManagementRest, 2, true); + return await _baseClient.SendAsync>(request, parameters, ct).ConfigureAwait(false); } #endregion @@ -62,7 +65,8 @@ public async Task> TransferToMainAccountAsyn parameters.AddParameter("currency", asset); parameters.AddParameter("amount", quantity.ToString(CultureInfo.InvariantCulture)); parameters.AddParameter("recAccountType", EnumConverter.GetString(receiveAccountType)); - return await _baseClient.Execute(_baseClient.GetUri("transfer-out", 3), HttpMethod.Post, ct, parameters, true).ConfigureAwait(false); + var request = _definitions.GetOrCreate(HttpMethod.Post, $"api/v3/transfer-out", KucoinExchange.RateLimiter.ManagementRest, 20, true); + return await _baseClient.SendAsync(request, parameters, ct).ConfigureAwait(false); } /// @@ -75,7 +79,8 @@ public async Task TransferToFuturesAccountAsync(string asset, dec parameters.AddParameter("currency", asset); parameters.AddParameter("amount", quantity.ToString(CultureInfo.InvariantCulture)); parameters.AddParameter("payAccountType", EnumConverter.GetString(payAccountType)); - return await _baseClient.Execute(_baseClient.GetUri("transfer-in", 3), HttpMethod.Post, ct, parameters, true).ConfigureAwait(false); + var request = _definitions.GetOrCreate(HttpMethod.Post, $"api/v1/transfer-in", KucoinExchange.RateLimiter.ManagementRest, 20, true); + return await _baseClient.SendAsync(request, parameters, ct).ConfigureAwait(false); } /// @@ -88,16 +93,10 @@ public async Task>> GetTransferToM parameters.AddOptionalParameter("currentPage", currentPage); parameters.AddOptionalParameter("pageSize", pageSize); parameters.AddOptionalParameter("status", EnumConverter.GetString(status)); - return await _baseClient.Execute>(_baseClient.GetUri("transfer-list"), HttpMethod.Get, ct, parameters, true).ConfigureAwait(false); + var request = _definitions.GetOrCreate(HttpMethod.Get, $"api/v1/transfer-list", KucoinExchange.RateLimiter.ManagementRest, 20, true); + return await _baseClient.SendAsync>(request, parameters, ct).ConfigureAwait(false); } - /// - public async Task CancelTransferToMainAccountAsync(string applyId, CancellationToken ct = default) - { - var parameters = new ParameterCollection(); - parameters.AddParameter("applyId", applyId); - return await _baseClient.Execute(_baseClient.GetUri("cancel/transfer-out", 1), HttpMethod.Delete, ct, parameters, true).ConfigureAwait(false); - } #endregion #region Positions @@ -107,7 +106,8 @@ public async Task> GetPositionAsync(string symbol, { var parameters = new ParameterCollection(); parameters.AddParameter("symbol", symbol); - return await _baseClient.Execute(_baseClient.GetUri("position"), HttpMethod.Get, ct, parameters, true).ConfigureAwait(false); + var request = _definitions.GetOrCreate(HttpMethod.Get, $"api/v1/position", KucoinExchange.RateLimiter.FuturesRest, 2, true); + return await _baseClient.SendAsync(request, parameters, ct).ConfigureAwait(false); } /// @@ -115,7 +115,8 @@ public async Task>> GetPositionsAsync( { var parameters = new ParameterCollection(); parameters.AddOptionalParameter("currency", asset); - return await _baseClient.Execute>(_baseClient.GetUri("positions"), HttpMethod.Get, ct, parameters, signed: true).ConfigureAwait(false); + var request = _definitions.GetOrCreate(HttpMethod.Get, $"api/v1/positions", KucoinExchange.RateLimiter.FuturesRest, 2, true); + return await _baseClient.SendAsync>(request, parameters, ct).ConfigureAwait(false); } /// @@ -124,7 +125,8 @@ public async Task ToggleAutoDepositMarginAsync(string symbol, boo var parameters = new ParameterCollection(); parameters.AddParameter("symbol", symbol); parameters.AddParameter("status", enabled.ToString()); - return await _baseClient.Execute(_baseClient.GetUri("position/margin/auto-deposit-status"), HttpMethod.Post, ct, parameters, true).ConfigureAwait(false); + var request = _definitions.GetOrCreate(HttpMethod.Post, $"api/v1/position/margin/auto-deposit-status", KucoinExchange.RateLimiter.FuturesRest, 4, true); + return await _baseClient.SendAsync(request, parameters, ct).ConfigureAwait(false); } /// @@ -134,7 +136,8 @@ public async Task AddMarginAsync(string symbol, decimal quantity, parameters.AddParameter("symbol", symbol); parameters.AddParameter("bizNo", clientId ?? Convert.ToBase64String(Guid.NewGuid().ToByteArray())); parameters.AddParameter("margin", quantity.ToString(CultureInfo.InvariantCulture)); - return await _baseClient.Execute(_baseClient.GetUri("position/margin/deposit-margin"), HttpMethod.Post, ct, parameters, true).ConfigureAwait(false); + var request = _definitions.GetOrCreate(HttpMethod.Post, $"api/v1/position/margin/deposit-margin", KucoinExchange.RateLimiter.FuturesRest, 4, true); + return await _baseClient.SendAsync(request, parameters, ct).ConfigureAwait(false); } #endregion @@ -151,7 +154,8 @@ public async Task>> GetFu parameters.AddOptionalParameter("offset", offset?.ToString(CultureInfo.InvariantCulture)); parameters.AddOptionalParameter("maxCount", pageSize?.ToString(CultureInfo.InvariantCulture)); parameters.AddOptionalParameter("forward", forward); - return await _baseClient.Execute>(_baseClient.GetUri("funding-history"), HttpMethod.Get, ct, parameters, true).ConfigureAwait(false); + var request = _definitions.GetOrCreate(HttpMethod.Get, $"api/v1/funding-history", KucoinExchange.RateLimiter.FuturesRest, 5, true); + return await _baseClient.SendAsync>(request, parameters, ct).ConfigureAwait(false); } #endregion @@ -162,18 +166,20 @@ public async Task> GetOpenOrderValueAsync(st { var parameters = new ParameterCollection(); parameters.AddParameter("symbol", symbol); - return await _baseClient.Execute(_baseClient.GetUri("openOrderStatistics"), HttpMethod.Get, ct, parameters, true).ConfigureAwait(false); + var request = _definitions.GetOrCreate(HttpMethod.Get, $"api/v1/openOrderStatistics", KucoinExchange.RateLimiter.FuturesRest, 10, true); + return await _baseClient.SendAsync(request, parameters, ct).ConfigureAwait(false); } #endregion #region Get Risk Limit Level /// - public async Task>> GetRiskLimitLevelAsync(string symbol, CancellationToken ct = default) + public async Task>> GetRiskLimitLevelAsync(string symbol, CancellationToken ct = default) { var parameters = new ParameterCollection(); parameters.AddParameter("symbol", symbol); - return await _baseClient.Execute>(_baseClient.GetUri("contracts/risk-limit/" + symbol), HttpMethod.Get, ct, parameters, true).ConfigureAwait(false); + var request = _definitions.GetOrCreate(HttpMethod.Get, $"api/v1/contracts/risk-limit/" + symbol, KucoinExchange.RateLimiter.FuturesRest, 5, true); + return await _baseClient.SendAsync>(request, parameters, ct).ConfigureAwait(false); } #endregion @@ -185,16 +191,24 @@ public async Task> SetRiskLimitLevelAsync(string symbol, int var parameters = new ParameterCollection(); parameters.AddParameter("symbol", symbol); parameters.AddParameter("level", level); - return await _baseClient.Execute(_baseClient.GetUri("position/risk-limit-level/change"), HttpMethod.Post, ct, parameters, true).ConfigureAwait(false); + var request = _definitions.GetOrCreate(HttpMethod.Post, $"api/v1/position/risk-limit-level/change", KucoinExchange.RateLimiter.FuturesRest, 4, true); + return await _baseClient.SendAsync(request, parameters, ct).ConfigureAwait(false); } #endregion #region Websocket token - internal async Task> GetWebsocketToken(bool authenticated, CancellationToken ct = default) + internal async Task> GetWebsocketTokenPublicAsync(CancellationToken ct = default) + { + var request = _definitions.GetOrCreate(HttpMethod.Post, $"api/v1/bullet-public", KucoinExchange.RateLimiter.PublicRest, 10, false); + return await _baseClient.SendAsync(request, null, ct).ConfigureAwait(false); + } + + internal async Task> GetWebsocketTokenPrivateAsync(CancellationToken ct = default) { - return await _baseClient.Execute(_baseClient.GetUri(authenticated ? "bullet-private" : "bullet-public"), method: HttpMethod.Post, ct, signed: authenticated).ConfigureAwait(false); + var request = _definitions.GetOrCreate(HttpMethod.Post, $"api/v1/bullet-private", KucoinExchange.RateLimiter.FuturesRest, 10, true); + return await _baseClient.SendAsync(request, null, ct).ConfigureAwait(false); } #endregion diff --git a/Kucoin.Net/Clients/FuturesApi/KucoinRestClientFuturesApiExchangeData.cs b/Kucoin.Net/Clients/FuturesApi/KucoinRestClientFuturesApiExchangeData.cs index 310529b8..e37f88c5 100644 --- a/Kucoin.Net/Clients/FuturesApi/KucoinRestClientFuturesApiExchangeData.cs +++ b/Kucoin.Net/Clients/FuturesApi/KucoinRestClientFuturesApiExchangeData.cs @@ -13,12 +13,14 @@ using Kucoin.Net.Objects.Models.Futures; using Kucoin.Net.Objects.Models.Spot; using Kucoin.Net.Interfaces.Clients.FuturesApi; +using System.Security.Cryptography; namespace Kucoin.Net.Clients.FuturesApi { /// public class KucoinRestClientFuturesApiExchangeData : IKucoinRestClientFuturesApiExchangeData { + private static readonly RequestDefinitionCache _definitions = new(); private readonly KucoinRestClientFuturesApi _baseClient; internal KucoinRestClientFuturesApiExchangeData(KucoinRestClientFuturesApi baseClient) @@ -31,13 +33,15 @@ internal KucoinRestClientFuturesApiExchangeData(KucoinRestClientFuturesApi baseC /// public async Task>> GetOpenContractsAsync(CancellationToken ct = default) { - return await _baseClient.Execute>(_baseClient.GetUri("contracts/active"), HttpMethod.Get, ct).ConfigureAwait(false); + var request = _definitions.GetOrCreate(HttpMethod.Get, $"api/v1/contracts/active", KucoinExchange.RateLimiter.PublicRest, 3); + return await _baseClient.SendAsync>(request, null, ct).ConfigureAwait(false); } /// public async Task> GetContractAsync(string symbol, CancellationToken ct = default) { - return await _baseClient.Execute(_baseClient.GetUri("contracts/" + symbol), HttpMethod.Get, ct).ConfigureAwait(false); + var request = _definitions.GetOrCreate(HttpMethod.Get, $"api/v1/contracts/" + symbol, KucoinExchange.RateLimiter.PublicRest, 3); + return await _baseClient.SendAsync(request, null, ct).ConfigureAwait(false); } #endregion @@ -49,7 +53,8 @@ public async Task> GetTickerAsync(string symbol { var parameters = new ParameterCollection(); parameters.AddParameter("symbol", symbol); - return await _baseClient.Execute(_baseClient.GetUri("ticker"), HttpMethod.Get, ct, parameters).ConfigureAwait(false); + var request = _definitions.GetOrCreate(HttpMethod.Get, $"api/v1/ticker", KucoinExchange.RateLimiter.PublicRest, 2); + return await _baseClient.SendAsync(request, parameters, ct).ConfigureAwait(false); } #endregion @@ -61,7 +66,8 @@ public async Task> GetAggregatedFullOrderBookAsyn { var parameters = new ParameterCollection(); parameters.AddParameter("symbol", symbol); - return await _baseClient.Execute(_baseClient.GetUri("level2/snapshot"), HttpMethod.Get, ct, parameters).ConfigureAwait(false); + var request = _definitions.GetOrCreate(HttpMethod.Get, $"api/v1/level2/snapshot", KucoinExchange.RateLimiter.PublicRest, 3); + return await _baseClient.SendAsync(request, parameters, ct).ConfigureAwait(false); } /// @@ -71,7 +77,10 @@ public async Task> GetAggregatedPartialOrderBookA var parameters = new ParameterCollection(); parameters.AddParameter("symbol", symbol); - return await _baseClient.Execute(_baseClient.GetUri("level2/depth" + depth), HttpMethod.Get, ct, parameters).ConfigureAwait(false); + + var weight = depth == 20 ? 5 : 10; + var request = _definitions.GetOrCreate(HttpMethod.Get, $"api/v1/level2/depth" + depth, KucoinExchange.RateLimiter.PublicRest, weight); + return await _baseClient.SendAsync(request, parameters, ct, weight).ConfigureAwait(false); } #endregion @@ -83,7 +92,8 @@ public async Task>> GetTradeHistor { var parameters = new ParameterCollection(); parameters.AddParameter("symbol", symbol); - return await _baseClient.Execute>(_baseClient.GetUri("trade/history"), HttpMethod.Get, ct, parameters).ConfigureAwait(false); + var request = _definitions.GetOrCreate(HttpMethod.Get, $"api/v1/trade/history", KucoinExchange.RateLimiter.PublicRest, 5); + return await _baseClient.SendAsync>(request, parameters, ct).ConfigureAwait(false); } #endregion @@ -100,7 +110,8 @@ public async Task>> G parameters.AddOptionalParameter("offset", offset?.ToString(CultureInfo.InvariantCulture)); parameters.AddOptionalParameter("maxCount", pageSize?.ToString(CultureInfo.InvariantCulture)); parameters.AddOptionalParameter("forward", forward); - return await _baseClient.Execute>(_baseClient.GetUri("interest/query"), HttpMethod.Get, ct, parameters, true).ConfigureAwait(false); + var request = _definitions.GetOrCreate(HttpMethod.Get, $"api/v1/interest/query", KucoinExchange.RateLimiter.PublicRest, 5); + return await _baseClient.SendAsync>(request, parameters, ct).ConfigureAwait(false); } /// @@ -113,13 +124,15 @@ public async Task>> GetIndexLis parameters.AddOptionalParameter("offset", offset?.ToString(CultureInfo.InvariantCulture)); parameters.AddOptionalParameter("maxCount", pageSize?.ToString(CultureInfo.InvariantCulture)); parameters.AddOptionalParameter("forward", forward); - return await _baseClient.Execute>(_baseClient.GetUri("index/query"), HttpMethod.Get, ct, parameters, true).ConfigureAwait(false); + var request = _definitions.GetOrCreate(HttpMethod.Get, $"api/v1/index/query", KucoinExchange.RateLimiter.PublicRest, 2); + return await _baseClient.SendAsync>(request, parameters, ct).ConfigureAwait(false); } /// public async Task> GetCurrentMarkPriceAsync(string symbol, CancellationToken ct = default) { - return await _baseClient.Execute(_baseClient.GetUri($"mark-price/{symbol}/current"), HttpMethod.Get, ct).ConfigureAwait(false); + var request = _definitions.GetOrCreate(HttpMethod.Get, $"api/v1/mark-price/{symbol}/current", KucoinExchange.RateLimiter.PublicRest, 3); + return await _baseClient.SendAsync(request, null, ct).ConfigureAwait(false); } /// @@ -132,13 +145,15 @@ public async Task>> GetP parameters.AddOptionalParameter("offset", offset?.ToString(CultureInfo.InvariantCulture)); parameters.AddOptionalParameter("maxCount", pageSize?.ToString(CultureInfo.InvariantCulture)); parameters.AddOptionalParameter("forward", forward); - return await _baseClient.Execute>(_baseClient.GetUri("premium/query"), HttpMethod.Get, ct, parameters, true).ConfigureAwait(false); + var request = _definitions.GetOrCreate(HttpMethod.Get, $"api/v1/premium/query", KucoinExchange.RateLimiter.PublicRest, 3); + return await _baseClient.SendAsync>(request, parameters, ct).ConfigureAwait(false); } /// public async Task> GetCurrentFundingRateAsync(string symbol, CancellationToken ct = default) { - return await _baseClient.Execute(_baseClient.GetUri($"funding-rate/{symbol}/current"), HttpMethod.Get, ct).ConfigureAwait(false); + var request = _definitions.GetOrCreate(HttpMethod.Get, $"api/v1/funding-rate/{symbol}/current", KucoinExchange.RateLimiter.PublicRest, 2); + return await _baseClient.SendAsync(request, null, ct).ConfigureAwait(false); } #endregion @@ -148,7 +163,8 @@ public async Task> GetCurrentFundingRateAsync(s /// public async Task> GetServerTimeAsync(CancellationToken ct = default) { - var result = await _baseClient.Execute(_baseClient.GetUri("timestamp"), HttpMethod.Get, ct).ConfigureAwait(false); + var request = _definitions.GetOrCreate(HttpMethod.Get, $"api/v1/timestamp", KucoinExchange.RateLimiter.PublicRest, 2); + var result = await _baseClient.SendAsync(request, null, ct).ConfigureAwait(false); return result.As(result ? new DateTime(1970, 1, 1).AddMilliseconds(result.Data) : default); } @@ -159,7 +175,8 @@ public async Task> GetServerTimeAsync(CancellationToken /// public async Task> GetServiceStatusAsync(CancellationToken ct = default) { - return await _baseClient.Execute(_baseClient.GetUri("status"), HttpMethod.Get, ct).ConfigureAwait(false); + var request = _definitions.GetOrCreate(HttpMethod.Get, $"api/v1/status", KucoinExchange.RateLimiter.PublicRest, 4); + return await _baseClient.SendAsync(request, null, ct).ConfigureAwait(false); } #endregion @@ -174,7 +191,9 @@ public async Task>> GetKlinesAsync parameters.AddParameter("granularity", JsonConvert.SerializeObject(interval, new FuturesKlineIntervalConverter(false))); parameters.AddOptionalParameter("from", DateTimeConverter.ConvertToMilliseconds(startTime)); parameters.AddOptionalParameter("to", DateTimeConverter.ConvertToMilliseconds(endTime)); - return await _baseClient.Execute>(_baseClient.GetUri("kline/query"), HttpMethod.Get, ct, parameters).ConfigureAwait(false); + + var request = _definitions.GetOrCreate(HttpMethod.Get, $"api/v1/kline/query", KucoinExchange.RateLimiter.PublicRest, 3); + return await _baseClient.SendAsync>(request, null, ct).ConfigureAwait(false); } #endregion diff --git a/Kucoin.Net/Clients/FuturesApi/KucoinRestClientFuturesApiTrading.cs b/Kucoin.Net/Clients/FuturesApi/KucoinRestClientFuturesApiTrading.cs index e1733597..6068cda7 100644 --- a/Kucoin.Net/Clients/FuturesApi/KucoinRestClientFuturesApiTrading.cs +++ b/Kucoin.Net/Clients/FuturesApi/KucoinRestClientFuturesApiTrading.cs @@ -14,12 +14,14 @@ using Kucoin.Net.Objects.Models.Spot; using CryptoExchange.Net.Converters; using Kucoin.Net.Interfaces.Clients.FuturesApi; +using System.Security.Cryptography; namespace Kucoin.Net.Clients.FuturesApi { /// public class KucoinRestClientFuturesApiTrading : IKucoinRestClientFuturesApiTrading { + private static readonly RequestDefinitionCache _definitions = new(); private readonly KucoinRestClientFuturesApi _baseClient; internal KucoinRestClientFuturesApiTrading(KucoinRestClientFuturesApi baseClient) @@ -75,13 +77,15 @@ public async Task> PlaceOrderAsync( parameters.AddOptionalParameter("iceberg", iceberg); parameters.AddOptionalParameter("visibleSize", visibleSize?.ToString()); - return await _baseClient.Execute(_baseClient.GetUri("orders", 1), HttpMethod.Post, ct, parameters, true).ConfigureAwait(false); + var request = _definitions.GetOrCreate(HttpMethod.Post, $"api/v1/orders", KucoinExchange.RateLimiter.FuturesRest, 2, true); + return await _baseClient.SendAsync(request, parameters, ct).ConfigureAwait(false); } /// public async Task> CancelOrderAsync(string orderId, CancellationToken ct = default) { - return await _baseClient.Execute(_baseClient.GetUri("orders/" + orderId, 1), HttpMethod.Delete, ct, signed: true).ConfigureAwait(false); + var request = _definitions.GetOrCreate(HttpMethod.Delete, $"api/v1/orders/" + orderId, KucoinExchange.RateLimiter.FuturesRest, 1, true); + return await _baseClient.SendAsync(request, null, ct).ConfigureAwait(false); } /// @@ -89,7 +93,8 @@ public async Task> CancelAllOrdersAsync(stri { var parameters = new ParameterCollection(); parameters.AddOptionalParameter("symbol", symbol); - return await _baseClient.Execute(_baseClient.GetUri("orders", 1), HttpMethod.Delete, ct, parameters, true).ConfigureAwait(false); + var request = _definitions.GetOrCreate(HttpMethod.Delete, $"api/v1/orders", KucoinExchange.RateLimiter.FuturesRest, 30, true); + return await _baseClient.SendAsync(request, parameters, ct).ConfigureAwait(false); } @@ -98,7 +103,8 @@ public async Task> CancelAllStopOrdersAsync( { var parameters = new ParameterCollection(); parameters.AddOptionalParameter("symbol", symbol); - return await _baseClient.Execute(_baseClient.GetUri("stopOrders", 1), HttpMethod.Delete, ct, parameters, true).ConfigureAwait(false); + var request = _definitions.GetOrCreate(HttpMethod.Delete, $"api/v1/stopOrders", KucoinExchange.RateLimiter.FuturesRest, 15, true); + return await _baseClient.SendAsync(request, parameters, ct).ConfigureAwait(false); } /// @@ -113,7 +119,8 @@ public async Task>> GetOrdersA parameters.AddOptionalParameter("endAt", DateTimeConverter.ConvertToMilliseconds(endTime)); parameters.AddOptionalParameter("currentPage", currentPage); parameters.AddOptionalParameter("pageSize", pageSize); - return await _baseClient.Execute>(_baseClient.GetUri("orders"), HttpMethod.Get, ct, parameters, true).ConfigureAwait(false); + var request = _definitions.GetOrCreate(HttpMethod.Get, $"api/v1/orders", KucoinExchange.RateLimiter.FuturesRest, 2, true); + return await _baseClient.SendAsync>(request, parameters, ct).ConfigureAwait(false); } @@ -128,7 +135,8 @@ public async Task>> GetUntrigg parameters.AddOptionalParameter("endAt", DateTimeConverter.ConvertToMilliseconds(endTime)); parameters.AddOptionalParameter("currentPage", currentPage); parameters.AddOptionalParameter("pageSize", pageSize); - return await _baseClient.Execute>(_baseClient.GetUri("stopOrders"), HttpMethod.Get, ct, parameters, true).ConfigureAwait(false); + var request = _definitions.GetOrCreate(HttpMethod.Get, $"api/v1/stopOrders", KucoinExchange.RateLimiter.FuturesRest, 6, true); + return await _baseClient.SendAsync>(request, parameters, ct).ConfigureAwait(false); } /// @@ -136,13 +144,15 @@ public async Task>> GetClosedOrder { var parameters = new ParameterCollection(); parameters.AddOptionalParameter("symbol", symbol); - return await _baseClient.Execute>(_baseClient.GetUri("recentDoneOrders"), HttpMethod.Get, ct, parameters, signed: true).ConfigureAwait(false); + var request = _definitions.GetOrCreate(HttpMethod.Get, $"api/v1/recentDoneOrders", KucoinExchange.RateLimiter.FuturesRest, 5, true); + return await _baseClient.SendAsync>(request, parameters, ct).ConfigureAwait(false); } /// public async Task> GetOrderAsync(string orderId, CancellationToken ct = default) { - return await _baseClient.Execute(_baseClient.GetUri("orders/" + orderId), HttpMethod.Get, ct, signed: true).ConfigureAwait(false); + var request = _definitions.GetOrCreate(HttpMethod.Get, $"api/v1/orders/" + orderId, KucoinExchange.RateLimiter.FuturesRest, 5, true); + return await _baseClient.SendAsync(request, null, ct).ConfigureAwait(false); } /// @@ -150,7 +160,8 @@ public async Task> GetOrderByClientOrderIdAsyn { var parameters = new ParameterCollection(); parameters.AddOptionalParameter("clientOid", clientOrderId); - return await _baseClient.Execute(_baseClient.GetUri("orders/byClientOid"), HttpMethod.Get, ct, parameters, true).ConfigureAwait(false); + var request = _definitions.GetOrCreate(HttpMethod.Get, $"api/v1/orders/byClientOid", KucoinExchange.RateLimiter.FuturesRest, 5, true); + return await _baseClient.SendAsync(request, parameters, ct).ConfigureAwait(false); } #endregion @@ -168,13 +179,15 @@ public async Task>> GetUse parameters.AddOptionalParameter("endAt", DateTimeConverter.ConvertToMilliseconds(endTime)); parameters.AddOptionalParameter("currentPage", currentPage); parameters.AddOptionalParameter("pageSize", pageSize); - return await _baseClient.Execute>(_baseClient.GetUri("fills"), HttpMethod.Get, ct, parameters, true).ConfigureAwait(false); + var request = _definitions.GetOrCreate(HttpMethod.Get, $"api/v1/fills", KucoinExchange.RateLimiter.FuturesRest, 5, true); + return await _baseClient.SendAsync>(request, parameters, ct).ConfigureAwait(false); } /// public async Task>> GetRecentUserTradesAsync(CancellationToken ct = default) { - return await _baseClient.Execute>(_baseClient.GetUri("recentFills"), HttpMethod.Get, ct, signed: true).ConfigureAwait(false); + var request = _definitions.GetOrCreate(HttpMethod.Get, $"api/v1/recentFills", KucoinExchange.RateLimiter.FuturesRest, 3, true); + return await _baseClient.SendAsync>(request, null, ct).ConfigureAwait(false); } #endregion diff --git a/Kucoin.Net/Clients/FuturesApi/KucoinSocketClientFuturesApi.cs b/Kucoin.Net/Clients/FuturesApi/KucoinSocketClientFuturesApi.cs index 410fc738..fb6ea2e9 100644 --- a/Kucoin.Net/Clients/FuturesApi/KucoinSocketClientFuturesApi.cs +++ b/Kucoin.Net/Clients/FuturesApi/KucoinSocketClientFuturesApi.cs @@ -194,7 +194,11 @@ public async Task> SubscribeToPositionUpdatesAsyn options.ApiCredentials = apiCredentials; })) { - WebCallResult tokenResult = await ((KucoinRestClientFuturesApiAccount)restClient.FuturesApi.Account).GetWebsocketToken(authenticated).ConfigureAwait(false); + WebCallResult tokenResult; + if (authenticated) + tokenResult = await ((KucoinRestClientFuturesApiAccount)restClient.FuturesApi.Account).GetWebsocketTokenPrivateAsync().ConfigureAwait(false); + else + tokenResult = await ((KucoinRestClientFuturesApiAccount)restClient.FuturesApi.Account).GetWebsocketTokenPublicAsync().ConfigureAwait(false); if (!tokenResult) return tokenResult.As(null); diff --git a/Kucoin.Net/Clients/SpotApi/KucoinRestClientSpotApiAccount.cs b/Kucoin.Net/Clients/SpotApi/KucoinRestClientSpotApiAccount.cs index 48c3010f..0c4cca45 100644 --- a/Kucoin.Net/Clients/SpotApi/KucoinRestClientSpotApiAccount.cs +++ b/Kucoin.Net/Clients/SpotApi/KucoinRestClientSpotApiAccount.cs @@ -349,7 +349,7 @@ internal async Task> GetWebsocketTokenPublicAsync(Can internal async Task> GetWebsocketTokenPrivateAsync(CancellationToken ct = default) { - var request = _definitions.GetOrCreate(HttpMethod.Post, $"api/v1/bullet-private", KucoinExchange.RateLimiter.PublicRest, 10, true); + var request = _definitions.GetOrCreate(HttpMethod.Post, $"api/v1/bullet-private", KucoinExchange.RateLimiter.SpotRest, 10, true); return await _baseClient.SendAsync(request, null, ct).ConfigureAwait(false); } } diff --git a/Kucoin.Net/Interfaces/Clients/FuturesApi/IKucoinRestClientFuturesApiAccount.cs b/Kucoin.Net/Interfaces/Clients/FuturesApi/IKucoinRestClientFuturesApiAccount.cs index 41fe0510..bb51b9fa 100644 --- a/Kucoin.Net/Interfaces/Clients/FuturesApi/IKucoinRestClientFuturesApiAccount.cs +++ b/Kucoin.Net/Interfaces/Clients/FuturesApi/IKucoinRestClientFuturesApiAccount.cs @@ -60,15 +60,6 @@ public interface IKucoinRestClientFuturesApiAccount /// Task TransferToFuturesAccountAsync(string asset, decimal quantity, AccountType payAccountType, CancellationToken ct = default); - /// - /// Cancel a transfer from futures account to main account - /// - /// - /// Transfer id to cancel - /// Cancellation token - /// Withdrawal id - Task CancelTransferToMainAccountAsync(string applyId, CancellationToken ct = default); - /// /// Get transfer to main account history /// diff --git a/Kucoin.Net/Kucoin.Net.xml b/Kucoin.Net/Kucoin.Net.xml index 40be4a02..ca06cbd2 100644 --- a/Kucoin.Net/Kucoin.Net.xml +++ b/Kucoin.Net/Kucoin.Net.xml @@ -70,9 +70,6 @@ - - - @@ -2024,15 +2021,6 @@ Cancellation token - - - Cancel a transfer from futures account to main account - - - Transfer id to cancel - Cancellation token - Withdrawal id - Get transfer to main account history diff --git a/docs/index.html b/docs/index.html index dc8e90f8..91b60649 100644 --- a/docs/index.html +++ b/docs/index.html @@ -186,7 +186,7 @@

API Access

Rate limiting

-

By default a rate limiter is enabled which makes sure the server rate limits aren't exceeded. For more info on what the rate limits for the Kucoin API are see the Spot API docs. Currently client side rate limiting is only implemented for the Spot API. Note that rate limiting is only implemented to prevent going over the request rate limit, it does not apply for order limits.

+

By default a rate limiter is enabled which makes sure the server rate limits aren't exceeded. For more info on what the rate limits for the Kucoin API are see the Spot API docs. Note that rate limiting is only implemented to prevent going over the request rate limit, it does not apply for order limits.

Whether client ratelimiting is enabled in the library and what the behaviour should be when the limit is reached can be controlled with the RatelimiterEnabled and RateLimitingBehaviour client options

services.AddKucoin(x =>
     x.RatelimiterEnabled = true;