mirror of
https://github.com/JKorf/CryptoExchange.Net
synced 2025-08-31 12:42:00 +00:00
Compare commits
7 Commits
3e365f83c9
...
6156fb8154
Author | SHA1 | Date | |
---|---|---|---|
|
6156fb8154 | ||
|
f2753aed1e | ||
|
e33d826381 | ||
|
364aa4d324 | ||
|
455b332757 | ||
|
876b895645 | ||
|
daf7ed9fe6 |
@ -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.4.0</PackageVersion>
|
<PackageVersion>9.5.0</PackageVersion>
|
||||||
<AssemblyVersion>9.4.0</AssemblyVersion>
|
<AssemblyVersion>9.5.0</AssemblyVersion>
|
||||||
<FileVersion>9.4.0</FileVersion>
|
<FileVersion>9.5.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,9 +41,7 @@
|
|||||||
<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,6 +5,9 @@
|
|||||||
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", false)]
|
[TestCase("sapi/test1", true)]
|
||||||
[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 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 override void ProcessRequest(RestApiClient apiClient, RestRequestConfiguration requestConfig)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetKey() => _credentials.Key;
|
public string GetKey() => _credentials.Key;
|
||||||
public string GetSecret() => _credentials.Secret;
|
public string GetSecret() => _credentials.Secret;
|
||||||
}
|
}
|
||||||
|
@ -51,30 +51,11 @@ namespace CryptoExchange.Net.Authentication
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Authenticate a request. Output parameters should include the providedParameters input
|
/// Authenticate a request
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="apiClient">The Api client sending the request</param>
|
/// <param name="apiClient">The Api client sending the request</param>
|
||||||
/// <param name="uri">The uri for the request</param>
|
/// <param name="requestConfig">The request configuration</param>
|
||||||
/// <param name="method">The method of the request</param>
|
public abstract void ProcessRequest(RestApiClient apiClient, RestRequestConfiguration requestConfig);
|
||||||
/// <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,74 +364,58 @@ namespace CryptoExchange.Net.Clients
|
|||||||
ParameterCollection? bodyParameters,
|
ParameterCollection? bodyParameters,
|
||||||
Dictionary<string, string>? additionalHeaders)
|
Dictionary<string, string>? additionalHeaders)
|
||||||
{
|
{
|
||||||
var uriParams = uriParameters == null ? null : CreateParameterDictionary(uriParameters);
|
var requestConfiguration = new RestRequestConfiguration(
|
||||||
var bodyParams = bodyParameters == null ? null : CreateParameterDictionary(bodyParameters);
|
definition,
|
||||||
|
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);
|
||||||
|
|
||||||
var uri = new Uri(baseAddress.AppendPath(definition.Path));
|
try
|
||||||
var arraySerialization = definition.ArraySerialization ?? ArraySerialization;
|
|
||||||
var bodyFormat = definition.RequestBodyFormat ?? RequestBodyFormat;
|
|
||||||
var parameterPosition = definition.ParameterPosition ?? ParameterPositions[definition.Method];
|
|
||||||
|
|
||||||
Dictionary<string, string>? headers = null;
|
|
||||||
if (AuthenticationProvider != null)
|
|
||||||
{
|
{
|
||||||
try
|
AuthenticationProvider?.ProcessRequest(this, requestConfiguration);
|
||||||
{
|
|
||||||
AuthenticationProvider.AuthenticateRequest(
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
throw new Exception("Failed to authenticate request, make sure your API credentials are correct", ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
var queryString = requestConfiguration.GetQueryString(true);
|
||||||
|
if (!string.IsNullOrEmpty(queryString) && !queryString.StartsWith("?"))
|
||||||
|
queryString = $"?{queryString}";
|
||||||
|
|
||||||
// Add the auth parameters to the uri, start with a new URI to be able to sort the parameters including the auth parameters
|
var uri = new Uri(baseAddress.AppendPath(definition.Path) + queryString);
|
||||||
if (uriParams != null)
|
|
||||||
uri = uri.SetParameters(uriParams, arraySerialization);
|
|
||||||
|
|
||||||
var request = RequestFactory.Create(definition.Method, uri, requestId);
|
var request = RequestFactory.Create(definition.Method, uri, requestId);
|
||||||
request.Accept = Constants.JsonContentHeader;
|
request.Accept = Constants.JsonContentHeader;
|
||||||
|
|
||||||
if (headers != null)
|
foreach (var header in requestConfiguration.Headers)
|
||||||
{
|
request.AddHeader(header.Key, header.Value);
|
||||||
foreach (var header in headers)
|
|
||||||
request.AddHeader(header.Key, header.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (additionalHeaders != null)
|
foreach (var header in StandardRequestHeaders)
|
||||||
{
|
{
|
||||||
foreach (var header in additionalHeaders)
|
// Only add it if it isn't overwritten
|
||||||
|
if (!requestConfiguration.Headers.ContainsKey(header.Key))
|
||||||
request.AddHeader(header.Key, header.Value);
|
request.AddHeader(header.Key, header.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (StandardRequestHeaders != null)
|
if (requestConfiguration.ParameterPosition == HttpMethodParameterPosition.InBody)
|
||||||
{
|
{
|
||||||
foreach (var header in StandardRequestHeaders)
|
var contentType = requestConfiguration.BodyFormat == RequestBodyFormat.Json ? Constants.JsonContentHeader : Constants.FormContentHeader;
|
||||||
|
var bodyContent = requestConfiguration.GetBodyContent();
|
||||||
|
if (bodyContent != null)
|
||||||
{
|
{
|
||||||
// Only add it if it isn't overwritten
|
request.SetContent(bodyContent, contentType);
|
||||||
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.4.0</PackageVersion>
|
<PackageVersion>9.5.0</PackageVersion>
|
||||||
<AssemblyVersion>9.4.0</AssemblyVersion>
|
<AssemblyVersion>9.5.0</AssemblyVersion>
|
||||||
<FileVersion>9.4.0</FileVersion>
|
<FileVersion>9.5.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,6 +76,9 @@ namespace CryptoExchange.Net.Objects
|
|||||||
{
|
{
|
||||||
Path = path;
|
Path = path;
|
||||||
Method = method;
|
Method = method;
|
||||||
|
|
||||||
|
if (!Path.StartsWith("/"))
|
||||||
|
Path = $"/{Path}";
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
124
CryptoExchange.Net/Objects/RestRequestConfiguration.cs
Normal file
124
CryptoExchange.Net/Objects/RestRequestConfiguration.cs
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
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,23 +128,27 @@ 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 headers = new Dictionary<string, string>();
|
var requestDefinition = new RestRequestConfiguration(
|
||||||
|
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.AuthenticateRequest(
|
authProvider.ProcessRequest(
|
||||||
client,
|
client,
|
||||||
new Uri(host.AppendPath(path)),
|
requestDefinition
|
||||||
method,
|
|
||||||
ref uriParams,
|
|
||||||
ref bodyParams,
|
|
||||||
ref headers,
|
|
||||||
true,
|
|
||||||
client.ArraySerialization,
|
|
||||||
client.ParameterPositions[method],
|
|
||||||
client.RequestBodyFormat
|
|
||||||
);
|
);
|
||||||
|
|
||||||
var signature = getSignature(uriParams, bodyParams, headers);
|
var signature = getSignature(requestDefinition.QueryParameters, requestDefinition.BodyParameters, requestDefinition.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" PreferExactMatches="@true">
|
<Router AppAssembly="@typeof(Program).Assembly">
|
||||||
<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,6 +59,16 @@ 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