mirror of
https://github.com/JKorf/CryptoExchange.Net.git
synced 2026-08-12 17:03:10 +00:00
Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| fde8d6353b | |||
| 41b996168a | |||
| b26f8fb900 | |||
| bdbbc61d86 | |||
| d64e200f2f |
@@ -0,0 +1,23 @@
|
||||
name: Publish Nuget
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
- name: Setup .NET SDK
|
||||
uses: actions/setup-dotnet@v1
|
||||
- name: Build
|
||||
run: dotnet build -c Release
|
||||
- name: Test
|
||||
run: dotnet test -c Release --no-build
|
||||
- name: Pack nugets
|
||||
run: dotnet pack -c Release --no-build --include-symbols -p:PackageVersion=${{github.event.release.name}} --output .
|
||||
- name: Push Package to NuGet
|
||||
run: dotnet nuget push "*.nupkg" --api-key ${{secrets.nuget_api_key}} --source https://api.nuget.org/v3/index.json
|
||||
@@ -21,7 +21,7 @@ namespace CryptoExchange.Net.Authentication
|
||||
/// <summary>
|
||||
/// Provided credentials
|
||||
/// </summary>
|
||||
protected readonly ApiCredentials _credentials;
|
||||
protected internal readonly ApiCredentials _credentials;
|
||||
|
||||
/// <summary>
|
||||
/// Byte representation of the secret
|
||||
|
||||
@@ -235,7 +235,7 @@ namespace CryptoExchange.Net.Clients
|
||||
|
||||
if (ClientOptions.RateLimiterEnabled)
|
||||
{
|
||||
var limitResult = await definition.RateLimitGate.ProcessAsync(_logger, requestId, RateLimitItemType.Request, definition, baseAddress, ApiOptions.ApiCredentials?.Key ?? ClientOptions.ApiCredentials?.Key, requestWeight, ClientOptions.RateLimitingBehaviour, cancellationToken).ConfigureAwait(false);
|
||||
var limitResult = await definition.RateLimitGate.ProcessAsync(_logger, requestId, RateLimitItemType.Request, definition, baseAddress, AuthenticationProvider?._credentials.Key, requestWeight, ClientOptions.RateLimitingBehaviour, cancellationToken).ConfigureAwait(false);
|
||||
if (!limitResult)
|
||||
return new CallResult(limitResult.Error!);
|
||||
}
|
||||
@@ -249,7 +249,7 @@ namespace CryptoExchange.Net.Clients
|
||||
|
||||
if (ClientOptions.RateLimiterEnabled)
|
||||
{
|
||||
var limitResult = await definition.RateLimitGate.ProcessSingleAsync(_logger, requestId, RateLimitItemType.Request, definition, baseAddress, ApiOptions.ApiCredentials?.Key ?? ClientOptions.ApiCredentials?.Key, requestWeight, ClientOptions.RateLimitingBehaviour, cancellationToken).ConfigureAwait(false);
|
||||
var limitResult = await definition.RateLimitGate.ProcessSingleAsync(_logger, requestId, RateLimitItemType.Request, definition, baseAddress, AuthenticationProvider?._credentials.Key, requestWeight, ClientOptions.RateLimitingBehaviour, cancellationToken).ConfigureAwait(false);
|
||||
if (!limitResult)
|
||||
return new CallResult(limitResult.Error!);
|
||||
}
|
||||
@@ -513,7 +513,7 @@ namespace CryptoExchange.Net.Clients
|
||||
|
||||
if (ClientOptions.RateLimiterEnabled)
|
||||
{
|
||||
var limitResult = await gate.ProcessAsync(_logger, requestId, RateLimitItemType.Request, new RequestDefinition(uri.AbsolutePath.TrimStart('/'), method) { Authenticated = signed }, uri.Host, ApiOptions.ApiCredentials?.Key ?? ClientOptions.ApiCredentials?.Key, requestWeight, ClientOptions.RateLimitingBehaviour, cancellationToken).ConfigureAwait(false);
|
||||
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, cancellationToken).ConfigureAwait(false);
|
||||
if (!limitResult)
|
||||
return new CallResult<IRequest>(limitResult.Error!);
|
||||
}
|
||||
|
||||
@@ -6,9 +6,9 @@
|
||||
<PackageId>CryptoExchange.Net</PackageId>
|
||||
<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>
|
||||
<PackageVersion>7.5.0</PackageVersion>
|
||||
<AssemblyVersion>7.5.0</AssemblyVersion>
|
||||
<FileVersion>7.5.0</FileVersion>
|
||||
<PackageVersion>7.5.1</PackageVersion>
|
||||
<AssemblyVersion>7.5.1</AssemblyVersion>
|
||||
<FileVersion>7.5.1</FileVersion>
|
||||
<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</PackageTags>
|
||||
<RepositoryType>git</RepositoryType>
|
||||
|
||||
@@ -5,6 +5,7 @@ using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text.Json.Nodes;
|
||||
using CryptoExchange.Net.Converters;
|
||||
using CryptoExchange.Net.Converters.JsonNet;
|
||||
using Newtonsoft.Json;
|
||||
@@ -257,6 +258,64 @@ namespace CryptoExchange.Net.Testing.Comparers
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(propValue.Type == JTokenType.Array)
|
||||
{
|
||||
var jObjs = (JArray)propValue;
|
||||
if (propertyValue is IEnumerable list)
|
||||
{
|
||||
var enumerator = list.GetEnumerator();
|
||||
foreach (var jObj in jObjs)
|
||||
{
|
||||
enumerator.MoveNext();
|
||||
if (jObj.Type == JTokenType.Object)
|
||||
{
|
||||
foreach (var subProp in ((JObject)jObj).Properties())
|
||||
{
|
||||
if (ignoreProperties?.Contains(subProp.Name) == true)
|
||||
continue;
|
||||
CheckObject(method, subProp, enumerator.Current, ignoreProperties!);
|
||||
}
|
||||
}
|
||||
else if (jObj.Type == JTokenType.Array)
|
||||
{
|
||||
var resultObj = enumerator.Current;
|
||||
var resultProps = resultObj.GetType().GetProperties().Select(p => (p, p.GetCustomAttributes(typeof(ArrayPropertyAttribute), true).Cast<ArrayPropertyAttribute>().SingleOrDefault()));
|
||||
var arrayConverterProperty = resultObj.GetType().GetCustomAttributes(typeof(JsonConverterAttribute), true).FirstOrDefault();
|
||||
var jsonConverter = ((JsonConverterAttribute)arrayConverterProperty!).ConverterType;
|
||||
if (jsonConverter != typeof(ArrayConverter))
|
||||
// Not array converter?
|
||||
continue;
|
||||
|
||||
int i = 0;
|
||||
foreach (var item in jObj.Values())
|
||||
{
|
||||
var arrayProp = resultProps.SingleOrDefault(p => p.Item2!.Index == i).p;
|
||||
if (arrayProp != null)
|
||||
CheckPropertyValue(method, item, arrayProp.GetValue(resultObj), arrayProp.PropertyType, arrayProp.Name, "Array index " + i, ignoreProperties!);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var value = enumerator.Current;
|
||||
if (value == default && ((JValue)jObj).Type != JTokenType.Null)
|
||||
throw new Exception($"{method}: Array has no value while input json array has value {jObj}");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var resultProps = propertyValue.GetType().GetProperties().Select(p => (p, p.GetCustomAttributes(typeof(ArrayPropertyAttribute), true).Cast<ArrayPropertyAttribute>().SingleOrDefault()));
|
||||
int i = 0;
|
||||
foreach (var item in jObjs.Values())
|
||||
{
|
||||
var arrayProp = resultProps.SingleOrDefault(p => p.Item2!.Index == i).p;
|
||||
if (arrayProp != null)
|
||||
CheckPropertyValue(method, item, arrayProp.GetValue(propertyValue), arrayProp.PropertyType, arrayProp.Name, "Array index " + i, ignoreProperties!);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CheckValues(method, propertyName!, propertyType, (JValue)propValue, propertyValue);
|
||||
@@ -278,7 +337,7 @@ namespace CryptoExchange.Net.Testing.Comparers
|
||||
if (time != DateTimeConverter.ParseFromString(jsonValue.Value<string>()!))
|
||||
throw new Exception($"{method}: {property} not equal: {jsonValue.Value<decimal>()} vs {time}");
|
||||
}
|
||||
else if (propertyType.IsEnum)
|
||||
else if (propertyType.IsEnum || Nullable.GetUnderlyingType(propertyType)?.IsEnum == true)
|
||||
{
|
||||
// TODO enum comparing
|
||||
}
|
||||
@@ -305,7 +364,10 @@ namespace CryptoExchange.Net.Testing.Comparers
|
||||
}
|
||||
else if (jsonValue.Type == JTokenType.Boolean)
|
||||
{
|
||||
if (jsonValue.Value<bool>() != (bool)objectValue)
|
||||
if (objectValue is bool boolVal && jsonValue.Value<bool>() != boolVal)
|
||||
throw new Exception($"{method}: {property} not equal: {jsonValue.Value<bool>()} vs {(bool)objectValue}");
|
||||
|
||||
if (jsonValue.Value<bool>() != bool.Parse(objectValue.ToString()))
|
||||
throw new Exception($"{method}: {property} not equal: {jsonValue.Value<bool>()} vs {(bool)objectValue}");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ namespace CryptoExchange.Net.Testing.Implementations
|
||||
{
|
||||
internal class TestRequest : IRequest
|
||||
{
|
||||
private readonly Dictionary<string, IEnumerable<string>> _headers = new Dictionary<string, IEnumerable<string>>();
|
||||
private readonly TestResponse _response;
|
||||
|
||||
public string Accept { set { } }
|
||||
@@ -31,9 +32,10 @@ namespace CryptoExchange.Net.Testing.Implementations
|
||||
|
||||
public void AddHeader(string key, string value)
|
||||
{
|
||||
_headers.Add(key, new[] { value });
|
||||
}
|
||||
|
||||
public Dictionary<string, IEnumerable<string>> GetHeaders() => new();
|
||||
public Dictionary<string, IEnumerable<string>> GetHeaders() => _headers;
|
||||
|
||||
public Task<IResponse> GetResponseAsync(CancellationToken cancellationToken) => Task.FromResult<IResponse>(_response);
|
||||
|
||||
|
||||
@@ -170,8 +170,9 @@ namespace CryptoExchange.Net.Testing
|
||||
var expectedMethod = reader.ReadLine();
|
||||
var expectedPath = reader.ReadLine();
|
||||
var expectedAuth = bool.Parse(reader.ReadLine()!);
|
||||
var response = reader.ReadToEnd();
|
||||
|
||||
TestHelpers.ConfigureRestClient(_client, "", System.Net.HttpStatusCode.OK);
|
||||
TestHelpers.ConfigureRestClient(_client, response, System.Net.HttpStatusCode.OK);
|
||||
var result = await methodInvoke(_client).ConfigureAwait(false);
|
||||
|
||||
// Check request/response properties
|
||||
|
||||
@@ -45,6 +45,9 @@ 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).
|
||||
|
||||
## Release notes
|
||||
* Version 7.5.1 - 03 May 2024
|
||||
* Some small improvements in unit testing components
|
||||
|
||||
* Version 7.5.0 - 01 May 2024
|
||||
* Added testing implementations
|
||||
* Small refactor AuthenticationProvider to allow better testing
|
||||
|
||||
Reference in New Issue
Block a user