diff --git a/CryptoExchange.Net/Clients/RestApiClient.cs b/CryptoExchange.Net/Clients/RestApiClient.cs
index 3c22555..4d4504a 100644
--- a/CryptoExchange.Net/Clients/RestApiClient.cs
+++ b/CryptoExchange.Net/Clients/RestApiClient.cs
@@ -437,215 +437,6 @@ namespace CryptoExchange.Net.Clients
return request;
}
- ///
- /// Execute a request to the uri and returns if it was successful
- ///
- /// The uri to send the request to
- /// The method of the request
- /// Cancellation token
- /// The parameters of the request
- /// Whether or not the request should be authenticated
- /// The format of the body content
- /// Where the parameters should be placed, overwrites the value set in the client
- /// How array parameters should be serialized, overwrites the value set in the client
- /// Credits used for the request
- /// Additional headers to send with the request
- /// The ratelimit gate to use
- ///
- [return: NotNull]
- protected virtual async Task SendRequestAsync(
- Uri uri,
- HttpMethod method,
- CancellationToken cancellationToken,
- Dictionary? parameters = null,
- bool signed = false,
- RequestBodyFormat? requestBodyFormat = null,
- HttpMethodParameterPosition? parameterPosition = null,
- ArrayParametersSerialization? arraySerialization = null,
- int requestWeight = 1,
- Dictionary? additionalHeaders = null,
- IRateLimitGate? gate = null)
- {
- int currentTry = 0;
- while (true)
- {
- currentTry++;
- var request = await PrepareRequestAsync(uri, method, cancellationToken, parameters, signed, requestBodyFormat, parameterPosition, arraySerialization, requestWeight, additionalHeaders, gate).ConfigureAwait(false);
- if (!request)
- return new WebCallResult(request.Error!);
-
- var result = await GetResponseAsync(request.Data, gate, cancellationToken).ConfigureAwait(false);
- if (!result)
- _logger.RestApiErrorReceived(result.RequestId, result.ResponseStatusCode, (long)Math.Floor(result.ResponseTime!.Value.TotalMilliseconds), result.Error?.ToString());
- else
- _logger.RestApiResponseReceived(result.RequestId, result.ResponseStatusCode, (long)Math.Floor(result.ResponseTime!.Value.TotalMilliseconds), OutputOriginalData ? result.OriginalData : "[Data only available when OutputOriginal = true]");
-
- if (await ShouldRetryRequestAsync(gate, result, currentTry).ConfigureAwait(false))
- continue;
-
- return result.AsDataless();
- }
- }
-
- ///
- /// Execute a request to the uri and deserialize the response into the provided type parameter
- ///
- /// The type to deserialize into
- /// The uri to send the request to
- /// The method of the request
- /// Cancellation token
- /// The parameters of the request
- /// Whether or not the request should be authenticated
- /// The format of the body content
- /// Where the parameters should be placed, overwrites the value set in the client
- /// How array parameters should be serialized, overwrites the value set in the client
- /// Credits used for the request
- /// Additional headers to send with the request
- /// The ratelimit gate to use
- /// Whether caching should be prevented for this request
- ///
- [return: NotNull]
- protected virtual async Task> SendRequestAsync(
- Uri uri,
- HttpMethod method,
- CancellationToken cancellationToken,
- Dictionary? parameters = null,
- bool signed = false,
- RequestBodyFormat? requestBodyFormat = null,
- HttpMethodParameterPosition? parameterPosition = null,
- ArrayParametersSerialization? arraySerialization = null,
- int requestWeight = 1,
- Dictionary? additionalHeaders = null,
- IRateLimitGate? gate = null,
- bool preventCaching = false
- ) where T : class
- {
- var key = uri.ToString() + method + signed + parameters?.ToFormData();
- if (ShouldCache(method) && !preventCaching)
- {
- _logger.CheckingCache(key);
- var cachedValue = _cache.Get(key, ClientOptions.CachingMaxAge);
- if (cachedValue != null)
- {
- _logger.CacheHit(key);
- var original = (WebCallResult)cachedValue;
- return original.Cached();
- }
-
- _logger.CacheNotHit(key);
- }
-
- int currentTry = 0;
- while (true)
- {
- currentTry++;
- var request = await PrepareRequestAsync(uri, method, cancellationToken, parameters, signed, requestBodyFormat, parameterPosition, arraySerialization, requestWeight, additionalHeaders, gate).ConfigureAwait(false);
- if (!request)
- return new WebCallResult(request.Error!);
-
- var result = await GetResponseAsync(request.Data, gate, cancellationToken).ConfigureAwait(false);
- if (!result)
- _logger.RestApiErrorReceived(result.RequestId, result.ResponseStatusCode, (long)Math.Floor(result.ResponseTime!.Value.TotalMilliseconds), result.Error?.ToString());
- else
- _logger.RestApiResponseReceived(result.RequestId, result.ResponseStatusCode, (long)Math.Floor(result.ResponseTime!.Value.TotalMilliseconds), OutputOriginalData ? result.OriginalData : "[Data only available when OutputOriginal = true]");
-
- if (await ShouldRetryRequestAsync(gate, result, currentTry).ConfigureAwait(false))
- continue;
-
- if (result.Success &&
- ShouldCache(method) &&
- !preventCaching)
- {
- _cache.Add(key, result);
- }
-
- return result;
- }
- }
-
- ///
- /// Prepares a request to be sent to the server
- ///
- /// The uri to send the request to
- /// The method of the request
- /// Cancellation token
- /// The parameters of the request
- /// Whether or not the request should be authenticated
- /// The format of the body content
- /// Where the parameters should be placed, overwrites the value set in the client
- /// How array parameters should be serialized, overwrites the value set in the client
- /// Credits used for the request
- /// Additional headers to send with the request
- /// The rate limit gate to use
- ///
- protected virtual async Task> PrepareRequestAsync(
- Uri uri,
- HttpMethod method,
- CancellationToken cancellationToken,
- Dictionary? parameters = null,
- bool signed = false,
- RequestBodyFormat? requestBodyFormat = null,
- HttpMethodParameterPosition? parameterPosition = null,
- ArrayParametersSerialization? arraySerialization = null,
- int requestWeight = 1,
- Dictionary? additionalHeaders = null,
- IRateLimitGate? gate = null)
- {
- var requestId = ExchangeHelpers.NextId();
-
- if (signed)
- {
- if (AuthenticationProvider == null)
- {
- _logger.RestApiNoApiCredentials(requestId, uri.AbsolutePath);
- return new CallResult(new NoApiCredentialsError());
- }
-
- var syncTask = SyncTimeAsync();
- var timeSyncInfo = GetTimeSyncInfo();
-
- if (timeSyncInfo != null && timeSyncInfo.TimeSyncState.LastSyncTime == default)
- {
- // Initially with first request we'll need to wait for the time syncing, if it's not the first request we can just continue
- var syncTimeResult = await syncTask.ConfigureAwait(false);
- if (!syncTimeResult)
- {
- _logger.RestApiFailedToSyncTime(requestId, syncTimeResult.Error!.ToString());
- return syncTimeResult.As(default);
- }
- }
- }
-
- if (requestWeight != 0)
- {
- if (gate == null)
- throw new Exception("Ratelimit gate not set when request weight is not 0");
-
- if (ClientOptions.RateLimiterEnabled)
- {
- var limitResult = await gate.ProcessAsync(_logger, requestId, RateLimitItemType.Request, new RequestDefinition(uri.AbsolutePath.TrimStart('/'), method) { Authenticated = signed }, uri.Host, AuthenticationProvider?._credentials.Key, requestWeight, ClientOptions.RateLimitingBehaviour, null, cancellationToken).ConfigureAwait(false);
- if (!limitResult)
- return new CallResult(limitResult.Error!);
- }
- }
-
- _logger.RestApiCreatingRequest(requestId, uri);
- var paramsPosition = parameterPosition ?? ParameterPositions[method];
- var request = ConstructRequest(uri, method, parameters?.OrderBy(p => p.Key).ToDictionary(p => p.Key, p => p.Value), signed, paramsPosition, arraySerialization ?? ArraySerialization, requestBodyFormat ?? RequestBodyFormat, requestId, additionalHeaders);
-
- string? paramString = "";
- if (paramsPosition == HttpMethodParameterPosition.InBody)
- paramString = $" with request body '{request.Content}'";
-
- var headers = request.GetHeaders();
- if (headers.Length != 0)
- paramString += " with headers " + string.Join(", ", headers.Select(h => h.Key + $"=[{string.Join(",", h.Value)}]"));
-
- TotalRequestsMade++;
- _logger.RestApiSendingRequest(requestId, method, signed ? "signed": "", request.Uri, paramString);
- return new CallResult(request);
- }
-
///
/// Executes the request and returns the result deserialized into the type parameter class
///
@@ -804,112 +595,6 @@ namespace CryptoExchange.Net.Clients
return false;
}
- ///
- /// Creates a request object
- ///
- /// The uri to send the request to
- /// The method of the request
- /// The parameters of the request
- /// Whether or not the request should be authenticated
- /// Where the parameters should be placed
- /// How array parameters should be serialized
- /// Format of the body content
- /// Unique id of a request
- /// Additional headers to send with the request
- ///
- protected virtual IRequest ConstructRequest(
- Uri uri,
- HttpMethod method,
- Dictionary? parameters,
- bool signed,
- HttpMethodParameterPosition parameterPosition,
- ArrayParametersSerialization arraySerialization,
- RequestBodyFormat bodyFormat,
- int requestId,
- Dictionary? additionalHeaders)
- {
- parameters ??= new Dictionary();
-
- for (var i = 0; i < parameters.Count; i++)
- {
- var kvp = parameters.ElementAt(i);
- if (kvp.Value is Func delegateValue)
- parameters[kvp.Key] = delegateValue();
- }
-
- if (parameterPosition == HttpMethodParameterPosition.InUri)
- {
- foreach (var parameter in parameters)
- uri = uri.AddQueryParameter(parameter.Key, parameter.Value.ToString()!);
- }
-
- var headers = new Dictionary();
- var uriParameters = parameterPosition == HttpMethodParameterPosition.InUri ? CreateParameterDictionary(parameters) : null;
- var bodyParameters = parameterPosition == HttpMethodParameterPosition.InBody ? CreateParameterDictionary(parameters) : null;
- if (AuthenticationProvider != null)
- {
- try
- {
- AuthenticationProvider.AuthenticateRequest(
- this,
- uri,
- method,
- ref uriParameters,
- ref bodyParameters,
- ref headers,
- signed,
- arraySerialization,
- parameterPosition,
- bodyFormat
- );
- }
- catch (Exception ex)
- {
- throw new Exception("Failed to authenticate request, make sure your API credentials are correct", ex);
- }
- }
-
- // Add the auth parameters to the uri, start with a new URI to be able to sort the parameters including the auth parameters
- if (uriParameters != null)
- uri = uri.SetParameters(uriParameters, arraySerialization);
-
- var request = RequestFactory.Create(method, uri, requestId);
- request.Accept = Constants.JsonContentHeader;
-
- if (headers != null)
- {
- foreach (var header in headers)
- request.AddHeader(header.Key, header.Value);
- }
-
- if (additionalHeaders != null)
- {
- foreach (var header in additionalHeaders)
- request.AddHeader(header.Key, header.Value);
- }
-
- if (StandardRequestHeaders != null)
- {
- foreach (var header in StandardRequestHeaders)
- {
- // Only add it if it isn't overwritten
- if (additionalHeaders?.ContainsKey(header.Key) != true)
- request.AddHeader(header.Key, header.Value);
- }
- }
-
- if (parameterPosition == HttpMethodParameterPosition.InBody)
- {
- var contentType = bodyFormat == RequestBodyFormat.Json ? Constants.JsonContentHeader : Constants.FormContentHeader;
- if (bodyParameters?.Any() == true)
- WriteParamBody(request, bodyParameters, contentType);
- else
- request.SetContent(RequestBodyEmptyContent, contentType);
- }
-
- return request;
- }
-
///
/// Writes the parameters of the request to the request object body
///
@@ -1049,9 +734,5 @@ namespace CryptoExchange.Net.Clients
=> ClientOptions.CachingEnabled
&& definition.Method == HttpMethod.Get
&& !definition.PreventCaching;
-
- private bool ShouldCache(HttpMethod method)
- => ClientOptions.CachingEnabled
- && method == HttpMethod.Get;
}
}