mirror of
https://github.com/JKorf/CryptoExchange.Net
synced 2025-09-04 22:51:36 +00:00
Compare commits
No commits in common. "6156fb8154755a863f23a49c1dec918c3e4a7dfa" and "3e365f83c938b563b4c1c2d8a12481d250f5107c" have entirely different histories.
6156fb8154
...
3e365f83c9
@ -6,9 +6,9 @@
|
|||||||
<PackageId>CryptoExchange.Net.Protobuf</PackageId>
|
<PackageId>CryptoExchange.Net.Protobuf</PackageId>
|
||||||
<Authors>JKorf</Authors>
|
<Authors>JKorf</Authors>
|
||||||
<Description>Protobuf support for CryptoExchange.Net</Description>
|
<Description>Protobuf support for CryptoExchange.Net</Description>
|
||||||
<PackageVersion>9.5.0</PackageVersion>
|
<PackageVersion>9.4.0</PackageVersion>
|
||||||
<AssemblyVersion>9.5.0</AssemblyVersion>
|
<AssemblyVersion>9.4.0</AssemblyVersion>
|
||||||
<FileVersion>9.5.0</FileVersion>
|
<FileVersion>9.4.0</FileVersion>
|
||||||
<PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
|
<PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
|
||||||
<PackageTags>CryptoExchange;CryptoExchange.Net</PackageTags>
|
<PackageTags>CryptoExchange;CryptoExchange.Net</PackageTags>
|
||||||
<RepositoryType>git</RepositoryType>
|
<RepositoryType>git</RepositoryType>
|
||||||
@ -41,7 +41,9 @@
|
|||||||
<DocumentationFile>CryptoExchange.Net.Protobuf.xml</DocumentationFile>
|
<DocumentationFile>CryptoExchange.Net.Protobuf.xml</DocumentationFile>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="CryptoExchange.Net" Version="9.5.0" />
|
|
||||||
<PackageReference Include="protobuf-net" Version="3.2.56" />
|
<PackageReference Include="protobuf-net" Version="3.2.56" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\CryptoExchange.Net\CryptoExchange.Net.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
@ -5,9 +5,6 @@
|
|||||||
Protobuf support for CryptoExchange.Net.
|
Protobuf support for CryptoExchange.Net.
|
||||||
|
|
||||||
## Release notes
|
## Release notes
|
||||||
* Version 9.5.0 - 19 Aug 2025
|
|
||||||
* Updated CryptoExchange.Net version to 9.5.0
|
|
||||||
|
|
||||||
* Version 9.4.0 - 04 Aug 2025
|
* Version 9.4.0 - 04 Aug 2025
|
||||||
* Updated CryptoExchange.Net to version 9.4.0, see https://github.com/JKorf/CryptoExchange.Net/releases/
|
* Updated CryptoExchange.Net to version 9.4.0, see https://github.com/JKorf/CryptoExchange.Net/releases/
|
||||||
* Updated protobuf-net package version to 3.2.56
|
* Updated protobuf-net package version to 3.2.56
|
||||||
|
@ -182,7 +182,7 @@ namespace CryptoExchange.Net.UnitTests
|
|||||||
[TestCase("/sapi/test1", true)]
|
[TestCase("/sapi/test1", true)]
|
||||||
[TestCase("/sapi/test2", true)]
|
[TestCase("/sapi/test2", true)]
|
||||||
[TestCase("/api/test1", false)]
|
[TestCase("/api/test1", false)]
|
||||||
[TestCase("sapi/test1", true)]
|
[TestCase("sapi/test1", false)]
|
||||||
[TestCase("/sapi/", true)]
|
[TestCase("/sapi/", true)]
|
||||||
public async Task PartialEndpointRateLimiterEndpoints(string endpoint, bool expectLimiting)
|
public async Task PartialEndpointRateLimiterEndpoints(string endpoint, bool expectLimiting)
|
||||||
{
|
{
|
||||||
|
@ -78,10 +78,10 @@ namespace CryptoExchange.Net.UnitTests
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void ProcessRequest(RestApiClient apiClient, RestRequestConfiguration requestConfig)
|
public override void AuthenticateRequest(RestApiClient apiClient, Uri uri, HttpMethod method, ref IDictionary<string, object> uriParams, ref IDictionary<string, object> bodyParams, ref Dictionary<string, string> headers, bool auth, ArrayParametersSerialization arraySerialization, HttpMethodParameterPosition parameterPosition, RequestBodyFormat bodyFormat)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetKey() => _credentials.Key;
|
public string GetKey() => _credentials.Key;
|
||||||
public string GetSecret() => _credentials.Secret;
|
public string GetSecret() => _credentials.Secret;
|
||||||
}
|
}
|
||||||
|
@ -51,11 +51,30 @@ namespace CryptoExchange.Net.Authentication
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Authenticate a request
|
/// Authenticate a request. Output parameters should include the providedParameters input
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="apiClient">The Api client sending the request</param>
|
/// <param name="apiClient">The Api client sending the request</param>
|
||||||
/// <param name="requestConfig">The request configuration</param>
|
/// <param name="uri">The uri for the request</param>
|
||||||
public abstract void ProcessRequest(RestApiClient apiClient, RestRequestConfiguration requestConfig);
|
/// <param name="method">The method of the request</param>
|
||||||
|
/// <param name="auth">If the requests should be authenticated</param>
|
||||||
|
/// <param name="arraySerialization">Array serialization type</param>
|
||||||
|
/// <param name="requestBodyFormat">The formatting of the request body</param>
|
||||||
|
/// <param name="uriParameters">Parameters that need to be in the Uri of the request. Should include the provided parameters if they should go in the uri</param>
|
||||||
|
/// <param name="bodyParameters">Parameters that need to be in the body of the request. Should include the provided parameters if they should go in the body</param>
|
||||||
|
/// <param name="headers">The headers that should be send with the request</param>
|
||||||
|
/// <param name="parameterPosition">The position where the providedParameters should go</param>
|
||||||
|
public abstract void AuthenticateRequest(
|
||||||
|
RestApiClient apiClient,
|
||||||
|
Uri uri,
|
||||||
|
HttpMethod method,
|
||||||
|
ref IDictionary<string, object>? uriParameters,
|
||||||
|
ref IDictionary<string, object>? bodyParameters,
|
||||||
|
ref Dictionary<string, string>? headers,
|
||||||
|
bool auth,
|
||||||
|
ArrayParametersSerialization arraySerialization,
|
||||||
|
HttpMethodParameterPosition parameterPosition,
|
||||||
|
RequestBodyFormat requestBodyFormat
|
||||||
|
);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// SHA256 sign the data and return the bytes
|
/// SHA256 sign the data and return the bytes
|
||||||
|
@ -55,7 +55,7 @@ namespace CryptoExchange.Net.Clients
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Request headers to be sent with each request
|
/// Request headers to be sent with each request
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected Dictionary<string, string> StandardRequestHeaders { get; set; } = [];
|
protected Dictionary<string, string>? StandardRequestHeaders { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Whether parameters need to be ordered
|
/// Whether parameters need to be ordered
|
||||||
@ -364,58 +364,74 @@ namespace CryptoExchange.Net.Clients
|
|||||||
ParameterCollection? bodyParameters,
|
ParameterCollection? bodyParameters,
|
||||||
Dictionary<string, string>? additionalHeaders)
|
Dictionary<string, string>? additionalHeaders)
|
||||||
{
|
{
|
||||||
var requestConfiguration = new RestRequestConfiguration(
|
var uriParams = uriParameters == null ? null : CreateParameterDictionary(uriParameters);
|
||||||
definition,
|
var bodyParams = bodyParameters == null ? null : CreateParameterDictionary(bodyParameters);
|
||||||
baseAddress,
|
|
||||||
uriParameters == null ? new Dictionary<string, object>() : CreateParameterDictionary(uriParameters),
|
|
||||||
bodyParameters == null ? new Dictionary<string, object>() : CreateParameterDictionary(bodyParameters),
|
|
||||||
new Dictionary<string, string>(additionalHeaders ?? []),
|
|
||||||
definition.ArraySerialization ?? ArraySerialization,
|
|
||||||
definition.ParameterPosition ?? ParameterPositions[definition.Method],
|
|
||||||
definition.RequestBodyFormat ?? RequestBodyFormat);
|
|
||||||
|
|
||||||
try
|
var uri = new Uri(baseAddress.AppendPath(definition.Path));
|
||||||
{
|
var arraySerialization = definition.ArraySerialization ?? ArraySerialization;
|
||||||
AuthenticationProvider?.ProcessRequest(this, requestConfiguration);
|
var bodyFormat = definition.RequestBodyFormat ?? RequestBodyFormat;
|
||||||
}
|
var parameterPosition = definition.ParameterPosition ?? ParameterPositions[definition.Method];
|
||||||
catch (Exception ex)
|
|
||||||
{
|
Dictionary<string, string>? headers = null;
|
||||||
throw new Exception("Failed to authenticate request, make sure your API credentials are correct", ex);
|
if (AuthenticationProvider != null)
|
||||||
}
|
{
|
||||||
|
try
|
||||||
var queryString = requestConfiguration.GetQueryString(true);
|
{
|
||||||
if (!string.IsNullOrEmpty(queryString) && !queryString.StartsWith("?"))
|
AuthenticationProvider.AuthenticateRequest(
|
||||||
queryString = $"?{queryString}";
|
this,
|
||||||
|
uri,
|
||||||
|
definition.Method,
|
||||||
|
ref uriParams,
|
||||||
|
ref bodyParams,
|
||||||
|
ref headers,
|
||||||
|
definition.Authenticated,
|
||||||
|
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 (uriParams != null)
|
||||||
|
uri = uri.SetParameters(uriParams, arraySerialization);
|
||||||
|
|
||||||
var uri = new Uri(baseAddress.AppendPath(definition.Path) + queryString);
|
|
||||||
var request = RequestFactory.Create(definition.Method, uri, requestId);
|
var request = RequestFactory.Create(definition.Method, uri, requestId);
|
||||||
request.Accept = Constants.JsonContentHeader;
|
request.Accept = Constants.JsonContentHeader;
|
||||||
|
|
||||||
foreach (var header in requestConfiguration.Headers)
|
if (headers != null)
|
||||||
request.AddHeader(header.Key, header.Value);
|
|
||||||
|
|
||||||
foreach (var header in StandardRequestHeaders)
|
|
||||||
{
|
{
|
||||||
// Only add it if it isn't overwritten
|
foreach (var header in headers)
|
||||||
if (!requestConfiguration.Headers.ContainsKey(header.Key))
|
|
||||||
request.AddHeader(header.Key, header.Value);
|
request.AddHeader(header.Key, header.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (requestConfiguration.ParameterPosition == HttpMethodParameterPosition.InBody)
|
if (additionalHeaders != null)
|
||||||
{
|
{
|
||||||
var contentType = requestConfiguration.BodyFormat == RequestBodyFormat.Json ? Constants.JsonContentHeader : Constants.FormContentHeader;
|
foreach (var header in additionalHeaders)
|
||||||
var bodyContent = requestConfiguration.GetBodyContent();
|
request.AddHeader(header.Key, header.Value);
|
||||||
if (bodyContent != null)
|
}
|
||||||
|
|
||||||
|
if (StandardRequestHeaders != null)
|
||||||
|
{
|
||||||
|
foreach (var header in StandardRequestHeaders)
|
||||||
{
|
{
|
||||||
request.SetContent(bodyContent, contentType);
|
// 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 (bodyParams != null && bodyParams.Count != 0)
|
||||||
|
WriteParamBody(request, bodyParams, contentType);
|
||||||
else
|
else
|
||||||
{
|
request.SetContent(RequestBodyEmptyContent, contentType);
|
||||||
if (requestConfiguration.BodyParameters != null && requestConfiguration.BodyParameters.Count != 0)
|
|
||||||
WriteParamBody(request, requestConfiguration.BodyParameters, contentType);
|
|
||||||
else
|
|
||||||
request.SetContent(RequestBodyEmptyContent, contentType);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return request;
|
return request;
|
||||||
|
@ -6,9 +6,9 @@
|
|||||||
<PackageId>CryptoExchange.Net</PackageId>
|
<PackageId>CryptoExchange.Net</PackageId>
|
||||||
<Authors>JKorf</Authors>
|
<Authors>JKorf</Authors>
|
||||||
<Description>CryptoExchange.Net is a base library which is used to implement different cryptocurrency (exchange) API's. It provides a standardized way of implementing different API's, which results in a very similar experience for users of the API implementations.</Description>
|
<Description>CryptoExchange.Net is a base library which is used to implement different cryptocurrency (exchange) API's. It provides a standardized way of implementing different API's, which results in a very similar experience for users of the API implementations.</Description>
|
||||||
<PackageVersion>9.5.0</PackageVersion>
|
<PackageVersion>9.4.0</PackageVersion>
|
||||||
<AssemblyVersion>9.5.0</AssemblyVersion>
|
<AssemblyVersion>9.4.0</AssemblyVersion>
|
||||||
<FileVersion>9.5.0</FileVersion>
|
<FileVersion>9.4.0</FileVersion>
|
||||||
<PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
|
<PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
|
||||||
<PackageTags>OKX;OKX.Net;Mexc;Mexc.Net;Kucoin;Kucoin.Net;Kraken;Kraken.Net;Huobi;Huobi.Net;CoinEx;CoinEx.Net;Bybit;Bybit.Net;Bitget;Bitget.Net;Bitfinex;Bitfinex.Net;Binance;Binance.Net;CryptoCurrency;CryptoCurrency Exchange;CryptoExchange.Net</PackageTags>
|
<PackageTags>OKX;OKX.Net;Mexc;Mexc.Net;Kucoin;Kucoin.Net;Kraken;Kraken.Net;Huobi;Huobi.Net;CoinEx;CoinEx.Net;Bybit;Bybit.Net;Bitget;Bitget.Net;Bitfinex;Bitfinex.Net;Binance;Binance.Net;CryptoCurrency;CryptoCurrency Exchange;CryptoExchange.Net</PackageTags>
|
||||||
<RepositoryType>git</RepositoryType>
|
<RepositoryType>git</RepositoryType>
|
||||||
|
@ -76,9 +76,6 @@ namespace CryptoExchange.Net.Objects
|
|||||||
{
|
{
|
||||||
Path = path;
|
Path = path;
|
||||||
Method = method;
|
Method = method;
|
||||||
|
|
||||||
if (!Path.StartsWith("/"))
|
|
||||||
Path = $"/{Path}";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
@ -1,124 +0,0 @@
|
|||||||
using System.Collections.Generic;
|
|
||||||
using System.Net.Http;
|
|
||||||
|
|
||||||
namespace CryptoExchange.Net.Objects
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Rest request configuration
|
|
||||||
/// </summary>
|
|
||||||
public class RestRequestConfiguration
|
|
||||||
{
|
|
||||||
private string? _bodyContent;
|
|
||||||
private string? _queryString;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Http method
|
|
||||||
/// </summary>
|
|
||||||
public HttpMethod Method { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
/// Whether the request needs authentication
|
|
||||||
/// </summary>
|
|
||||||
public bool Authenticated { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
/// Base address for the request
|
|
||||||
/// </summary>
|
|
||||||
public string BaseAddress { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
/// The request path
|
|
||||||
/// </summary>
|
|
||||||
public string Path { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
/// Query parameters
|
|
||||||
/// </summary>
|
|
||||||
public IDictionary<string, object> QueryParameters { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
/// Body parameters
|
|
||||||
/// </summary>
|
|
||||||
public IDictionary<string, object> BodyParameters { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
/// Request headers
|
|
||||||
/// </summary>
|
|
||||||
public IDictionary<string, string> Headers { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
/// Array serialization type
|
|
||||||
/// </summary>
|
|
||||||
public ArrayParametersSerialization ArraySerialization { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
/// Position of the parameters
|
|
||||||
/// </summary>
|
|
||||||
public HttpMethodParameterPosition ParameterPosition { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
/// Body format
|
|
||||||
/// </summary>
|
|
||||||
public RequestBodyFormat BodyFormat { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// ctor
|
|
||||||
/// </summary>
|
|
||||||
public RestRequestConfiguration(
|
|
||||||
RequestDefinition requestDefinition,
|
|
||||||
string baseAddress,
|
|
||||||
IDictionary<string, object> queryParams,
|
|
||||||
IDictionary<string, object> bodyParams,
|
|
||||||
IDictionary<string, string> headers,
|
|
||||||
ArrayParametersSerialization arraySerialization,
|
|
||||||
HttpMethodParameterPosition parametersPosition,
|
|
||||||
RequestBodyFormat bodyFormat)
|
|
||||||
{
|
|
||||||
Method = requestDefinition.Method;
|
|
||||||
Authenticated = requestDefinition.Authenticated;
|
|
||||||
Path = requestDefinition.Path;
|
|
||||||
BaseAddress = baseAddress;
|
|
||||||
QueryParameters = queryParams;
|
|
||||||
BodyParameters = bodyParams;
|
|
||||||
Headers = headers;
|
|
||||||
ArraySerialization = arraySerialization;
|
|
||||||
ParameterPosition = parametersPosition;
|
|
||||||
BodyFormat = bodyFormat;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Get the parameter collection based on the ParameterPosition
|
|
||||||
/// </summary>
|
|
||||||
public IDictionary<string, object> GetPositionParameters()
|
|
||||||
{
|
|
||||||
if (ParameterPosition == HttpMethodParameterPosition.InBody)
|
|
||||||
return BodyParameters;
|
|
||||||
|
|
||||||
return QueryParameters;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Get the query string. If it's not previously set it will return a newly formatted query string. If previously set return that.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="urlEncode">Whether to URL encode the parameter string if creating new</param>
|
|
||||||
public string GetQueryString(bool urlEncode = true)
|
|
||||||
{
|
|
||||||
return _queryString ?? QueryParameters.CreateParamString(urlEncode, ArraySerialization);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Set the query string of the request. Will be returned by subsequent <see cref="GetQueryString" /> calls
|
|
||||||
/// </summary>
|
|
||||||
public void SetQueryString(string value)
|
|
||||||
{
|
|
||||||
_queryString = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Get the body content if it's previously set
|
|
||||||
/// </summary>
|
|
||||||
public string? GetBodyContent()
|
|
||||||
{
|
|
||||||
return _bodyContent;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Set the body content for the request
|
|
||||||
/// </summary>
|
|
||||||
public void SetBodyContent(string content)
|
|
||||||
{
|
|
||||||
_bodyContent = content;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -128,27 +128,23 @@ namespace CryptoExchange.Net.Testing
|
|||||||
var uriParams = client.ParameterPositions[method] == HttpMethodParameterPosition.InUri ? client.CreateParameterDictionary(parameters) : null;
|
var uriParams = client.ParameterPositions[method] == HttpMethodParameterPosition.InUri ? client.CreateParameterDictionary(parameters) : null;
|
||||||
var bodyParams = client.ParameterPositions[method] == HttpMethodParameterPosition.InBody ? client.CreateParameterDictionary(parameters) : null;
|
var bodyParams = client.ParameterPositions[method] == HttpMethodParameterPosition.InBody ? client.CreateParameterDictionary(parameters) : null;
|
||||||
|
|
||||||
var requestDefinition = new RestRequestConfiguration(
|
var headers = new Dictionary<string, string>();
|
||||||
new RequestDefinition(path, method)
|
|
||||||
{
|
|
||||||
Authenticated = true
|
|
||||||
},
|
|
||||||
host,
|
|
||||||
uriParams ?? new Dictionary<string, object>(),
|
|
||||||
bodyParams ?? new Dictionary<string, object>(),
|
|
||||||
new Dictionary<string, string>(),
|
|
||||||
client.ArraySerialization,
|
|
||||||
client.ParameterPositions[method],
|
|
||||||
client.RequestBodyFormat
|
|
||||||
);
|
|
||||||
|
|
||||||
authProvider.TimeProvider = new TestAuthTimeProvider(time ?? new DateTime(2024, 01, 01, 0, 0, 0, DateTimeKind.Utc));
|
authProvider.TimeProvider = new TestAuthTimeProvider(time ?? new DateTime(2024, 01, 01, 0, 0, 0, DateTimeKind.Utc));
|
||||||
authProvider.ProcessRequest(
|
authProvider.AuthenticateRequest(
|
||||||
client,
|
client,
|
||||||
requestDefinition
|
new Uri(host.AppendPath(path)),
|
||||||
|
method,
|
||||||
|
ref uriParams,
|
||||||
|
ref bodyParams,
|
||||||
|
ref headers,
|
||||||
|
true,
|
||||||
|
client.ArraySerialization,
|
||||||
|
client.ParameterPositions[method],
|
||||||
|
client.RequestBodyFormat
|
||||||
);
|
);
|
||||||
|
|
||||||
var signature = getSignature(requestDefinition.QueryParameters, requestDefinition.BodyParameters, requestDefinition.Headers);
|
var signature = getSignature(uriParams, bodyParams, headers);
|
||||||
|
|
||||||
if (!string.Equals(signature, expectedSignature, compareCase ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase))
|
if (!string.Equals(signature, expectedSignature, compareCase ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase))
|
||||||
throw new Exception($"Signatures do not match. Expected: {expectedSignature}, Actual: {signature}");
|
throw new Exception($"Signatures do not match. Expected: {expectedSignature}, Actual: {signature}");
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<Router AppAssembly="@typeof(Program).Assembly">
|
<Router AppAssembly="@typeof(Program).Assembly" PreferExactMatches="@true">
|
||||||
<Found Context="routeData">
|
<Found Context="routeData">
|
||||||
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
|
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
|
||||||
</Found>
|
</Found>
|
||||||
|
10
README.md
10
README.md
@ -59,16 +59,6 @@ Make a one time donation in a crypto currency of your choice. If you prefer to d
|
|||||||
Alternatively, sponsor me on Github using [Github Sponsors](https://github.com/sponsors/JKorf).
|
Alternatively, sponsor me on Github using [Github Sponsors](https://github.com/sponsors/JKorf).
|
||||||
|
|
||||||
## Release notes
|
## Release notes
|
||||||
* Version 9.5.0 - 19 Aug 2025
|
|
||||||
* Added better error handling support
|
|
||||||
* Added ErrorDescription, ErrorType and IsTransient to Error object
|
|
||||||
* Added ErrorCode in favor of Code
|
|
||||||
* Updated some error messages
|
|
||||||
* Refactored RestApiClient request authentication and AuthenticationProvider to prevent duplicate query string / body serialization
|
|
||||||
* Fixed IOrderBookSocketClient Shared interface not getting registered in DI
|
|
||||||
* Fixed response type in websocket queries not interested in the response
|
|
||||||
* Fixed timing issue in query response processing
|
|
||||||
|
|
||||||
* Version 9.4.0 - 04 Aug 2025
|
* Version 9.4.0 - 04 Aug 2025
|
||||||
* Updated Shared symbol requests/subscriptions to allow multiple symbols in one call if supported
|
* Updated Shared symbol requests/subscriptions to allow multiple symbols in one call if supported
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user