Skip to content

Commit 29fc5af

Browse files
authored
CryptoExchange.Net 9.0.0 Release (#12)
* Updated library versions * Added RateLimitUpdated event * Added dynamic ApiEnvironments support * Added GenerateClientOrderId method to ExchangeRestClient * Added additional methods to ExchangeRestClient/ExchangeSocketClient for easier access * Added support for Native AOT compilation * Added IBookTickerRestClient Shared implementations * Added ISpotTriggerOrderRestClient Shared implementations * Added ISpotOrderClientIdClient Shared implementations * Added IFuturesTriggerOrderRestClient Shared implementations * Added IFuturesOrderClientIdClient Shared implementations * Added IFuturesTpSlRestClient Shared implementations * Split clients into different partial classes per topic
1 parent 1e5f018 commit 29fc5af

File tree

63 files changed

+5867
-2841
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

63 files changed

+5867
-2841
lines changed

.github/ISSUE_TEMPLATE/bug_report.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,11 @@ What endpoints and subscriptions are called.
1515

1616
**Expected behavior**
1717
A clear and concise description of what you expected to happen.
18+
19+
**Additional info**
20+
If the issue is with a specific endpoint please provide:
21+
response.RequestBody:
22+
If possible enable the `options.OutputOriginalData` client options and provide:
23+
response.OriginalData:
24+
25+
If available provide related logging:

.github/workflows/dotnet.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ jobs:
1616
- name: Setup .NET
1717
uses: actions/setup-dotnet@v1
1818
with:
19-
dotnet-version: 8.0.x
19+
dotnet-version: 9.0.x
2020
- name: Set GitHub package source
2121
run: dotnet nuget add source --username JKorf --password ${{ secrets.GITHUB_TOKEN }} --store-password-in-clear-text --name github "https://nuget.pkg.github.com/JKorf/index.json"
2222
- name: Restore dependencies
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
using CryptoExchange.Net.SharedApis;
2+
using System;
3+
using System.Collections.Generic;
4+
using System.Linq;
5+
using System.Text;
6+
using System.Threading.Tasks;
7+
using System.Threading;
8+
using CryptoExchange.Net.Objects;
9+
10+
namespace CryptoClients.Net
11+
{
12+
/// <inheritdoc />
13+
public partial class ExchangeRestClient
14+
{
15+
16+
/// <inheritdoc />
17+
public IEnumerable<IAssetsRestClient> GetAssetsClients() => _sharedClients.OfType<IAssetsRestClient>();
18+
/// <inheritdoc />
19+
public IAssetsRestClient? GetAssetClient(string exchange) => GetAssetsClients().SingleOrDefault(s => s.Exchange == exchange);
20+
21+
#region Get Assets
22+
23+
/// <inheritdoc />
24+
public async Task<ExchangeWebResult<SharedAsset[]>> GetAssetsAsync(string exchange, GetAssetsRequest request, CancellationToken ct = default)
25+
{
26+
var result = await Task.WhenAll(GetAssetsIntAsync(request, new[] { exchange }, ct)).ConfigureAwait(false);
27+
return result.SingleOrDefault() ?? new ExchangeWebResult<SharedAsset[]>(exchange, new InvalidOperationError($"Request not supported for {exchange}"));
28+
}
29+
30+
/// <inheritdoc />
31+
public async Task<ExchangeWebResult<SharedAsset[]>[]> GetAssetsAsync(GetAssetsRequest request, IEnumerable<string>? exchanges = null, CancellationToken ct = default)
32+
{
33+
return await Task.WhenAll(GetAssetsIntAsync(request, exchanges, ct)).ConfigureAwait(false);
34+
}
35+
36+
/// <inheritdoc />
37+
public IAsyncEnumerable<ExchangeWebResult<SharedAsset[]>> GetAssetsAsyncEnumerable(GetAssetsRequest request, IEnumerable<string>? exchanges = null, CancellationToken ct = default)
38+
{
39+
return GetAssetsIntAsync(request, exchanges, ct).ParallelEnumerateAsync();
40+
}
41+
42+
private IEnumerable<Task<ExchangeWebResult<SharedAsset[]>>> GetAssetsIntAsync(GetAssetsRequest request, IEnumerable<string>? exchanges, CancellationToken ct)
43+
{
44+
var clients = GetAssetsClients();
45+
if (exchanges != null)
46+
clients = clients.Where(c => exchanges.Contains(c.Exchange, StringComparer.InvariantCultureIgnoreCase));
47+
48+
var tasks = clients.Where(x => x.GetAssetsOptions.Supported).Select(x => x.GetAssetsAsync(request, ct));
49+
return tasks;
50+
}
51+
52+
#endregion
53+
54+
#region Get Asset
55+
56+
/// <inheritdoc />
57+
public async Task<ExchangeWebResult<SharedAsset>> GetAssetAsync(string exchange, GetAssetRequest request, CancellationToken ct = default)
58+
{
59+
var result = await Task.WhenAll(GetAssetIntAsync(request, new[] { exchange }, ct)).ConfigureAwait(false);
60+
return result.SingleOrDefault() ?? new ExchangeWebResult<SharedAsset>(exchange, new InvalidOperationError($"Request not supported for {exchange}"));
61+
}
62+
63+
/// <inheritdoc />
64+
public async Task<ExchangeWebResult<SharedAsset>[]> GetAssetAsync(GetAssetRequest request, IEnumerable<string>? exchanges = null, CancellationToken ct = default)
65+
{
66+
return await Task.WhenAll(GetAssetIntAsync(request, exchanges, ct)).ConfigureAwait(false);
67+
}
68+
69+
/// <inheritdoc />
70+
public IAsyncEnumerable<ExchangeWebResult<SharedAsset>> GetAssetAsyncEnumerable(GetAssetRequest request, IEnumerable<string>? exchanges = null, CancellationToken ct = default)
71+
{
72+
return GetAssetIntAsync(request, exchanges, ct).ParallelEnumerateAsync();
73+
}
74+
75+
private IEnumerable<Task<ExchangeWebResult<SharedAsset>>> GetAssetIntAsync(GetAssetRequest request, IEnumerable<string>? exchanges, CancellationToken ct)
76+
{
77+
var clients = GetAssetsClients();
78+
if (exchanges != null)
79+
clients = clients.Where(c => exchanges.Contains(c.Exchange, StringComparer.InvariantCultureIgnoreCase));
80+
81+
var tasks = clients.Where(x => x.GetAssetOptions.Supported).Select(x => x.GetAssetAsync(request, ct));
82+
return tasks;
83+
}
84+
85+
#endregion
86+
87+
}
88+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
using CryptoExchange.Net.Objects;
2+
using CryptoExchange.Net.SharedApis;
3+
using System;
4+
using System.Collections.Generic;
5+
using System.Linq;
6+
using System.Threading;
7+
using System.Threading.Tasks;
8+
9+
namespace CryptoClients.Net
10+
{
11+
/// <inheritdoc />
12+
public partial class ExchangeRestClient
13+
{
14+
/// <inheritdoc />
15+
public IEnumerable<IBalanceRestClient> GetBalancesClients() => _sharedClients.OfType<IBalanceRestClient>();
16+
/// <inheritdoc />
17+
public IEnumerable<IBalanceRestClient> GetBalancesClients(TradingMode api) => _sharedClients.OfType<IBalanceRestClient>().Where(s => s.SupportedTradingModes.Contains(api));
18+
/// <inheritdoc />
19+
public IBalanceRestClient? GetBalancesClient(TradingMode api, string exchange) => _sharedClients.OfType<IBalanceRestClient>().SingleOrDefault(s => s.SupportedTradingModes.Contains(api) && s.Exchange == exchange);
20+
21+
22+
#region Get Balances
23+
24+
/// <inheritdoc />
25+
public async Task<ExchangeWebResult<SharedBalance[]>> GetBalancesAsync(string exchange, GetBalancesRequest request, CancellationToken ct = default)
26+
{
27+
var result = await Task.WhenAll(GetBalancesIntAsync(request, new[] { exchange }, ct)).ConfigureAwait(false);
28+
return result.SingleOrDefault() ?? new ExchangeWebResult<SharedBalance[]>(exchange, new InvalidOperationError($"Request not supported for {exchange}"));
29+
}
30+
31+
/// <inheritdoc />
32+
public async Task<ExchangeWebResult<SharedBalance[]>[]> GetBalancesAsync(GetBalancesRequest request, IEnumerable<string>? exchanges = null, CancellationToken ct = default)
33+
{
34+
return await Task.WhenAll(GetBalancesIntAsync(request, exchanges, ct)).ConfigureAwait(false);
35+
}
36+
37+
/// <inheritdoc />
38+
public IAsyncEnumerable<ExchangeWebResult<SharedBalance[]>> GetBalancesAsyncEnumerable(GetBalancesRequest request, IEnumerable<string>? exchanges = null, CancellationToken ct = default)
39+
{
40+
return GetBalancesIntAsync(request, exchanges, ct).ParallelEnumerateAsync();
41+
}
42+
43+
private IEnumerable<Task<ExchangeWebResult<SharedBalance[]>>> GetBalancesIntAsync(GetBalancesRequest request, IEnumerable<string>? exchanges, CancellationToken ct)
44+
{
45+
var clients = GetBalancesClients().Where(x => request.TradingMode == null ? true : x.SupportedTradingModes.Contains(request.TradingMode.Value));
46+
if (exchanges != null)
47+
clients = clients.Where(c => exchanges.Contains(c.Exchange, StringComparer.InvariantCultureIgnoreCase));
48+
49+
var tasks = clients.Where(x => x.GetBalancesOptions.Supported).Select(x => x.GetBalancesAsync(request, ct));
50+
return tasks;
51+
}
52+
53+
#endregion
54+
}
55+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
using CryptoExchange.Net.Objects;
2+
using CryptoExchange.Net.SharedApis;
3+
using System;
4+
using System.Collections.Generic;
5+
using System.Linq;
6+
using System.Threading;
7+
using System.Threading.Tasks;
8+
9+
namespace CryptoClients.Net
10+
{
11+
/// <inheritdoc />
12+
public partial class ExchangeRestClient
13+
{
14+
/// <inheritdoc />
15+
public IEnumerable<IBookTickerRestClient> GetBookTickerClients() => _sharedClients.OfType<IBookTickerRestClient>();
16+
/// <inheritdoc />
17+
public IEnumerable<IBookTickerRestClient> GetBookTickerClients(TradingMode api) => _sharedClients.OfType<IBookTickerRestClient>().Where(s => s.SupportedTradingModes.Contains(api));
18+
/// <inheritdoc />
19+
public IBookTickerRestClient? GetBookTickerClient(TradingMode api, string exchange) => _sharedClients.OfType<IBookTickerRestClient>().SingleOrDefault(s => s.SupportedTradingModes.Contains(api) && s.Exchange == exchange);
20+
21+
22+
#region Get Book Tickers
23+
24+
/// <inheritdoc />
25+
public async Task<ExchangeWebResult<SharedBookTicker>> GetBookTickerAsync(string exchange, GetBookTickerRequest request, CancellationToken ct = default)
26+
{
27+
var result = await Task.WhenAll(GetBookTickersInt(request, new[] { exchange }, ct)).ConfigureAwait(false);
28+
return result.SingleOrDefault() ?? new ExchangeWebResult<SharedBookTicker>(exchange, new InvalidOperationError($"Request not supported for {exchange}"));
29+
}
30+
31+
/// <inheritdoc />
32+
public async Task<ExchangeWebResult<SharedBookTicker>[]> GetBookTickersAsync(GetBookTickerRequest request, IEnumerable<string>? exchanges = null, CancellationToken ct = default)
33+
{
34+
return await Task.WhenAll(GetBookTickersInt(request, exchanges, ct)).ConfigureAwait(false);
35+
}
36+
37+
/// <inheritdoc />
38+
public IAsyncEnumerable<ExchangeWebResult<SharedBookTicker>> GetBookTickersAsyncEnumerable(GetBookTickerRequest request, IEnumerable<string>? exchanges = null, CancellationToken ct = default)
39+
{
40+
return GetBookTickersInt(request, exchanges, ct).ParallelEnumerateAsync();
41+
}
42+
43+
private IEnumerable<Task<ExchangeWebResult<SharedBookTicker>>> GetBookTickersInt(GetBookTickerRequest request, IEnumerable<string>? exchanges, CancellationToken ct)
44+
{
45+
var clients = GetBookTickerClients().Where(x => x.SupportedTradingModes.Contains(request.Symbol.TradingMode));
46+
if (exchanges != null)
47+
clients = clients.Where(c => exchanges.Contains(c.Exchange, StringComparer.InvariantCultureIgnoreCase));
48+
49+
var tasks = clients.Where(x => x.GetBookTickerOptions.Supported).Select(x => x.GetBookTickerAsync(request, ct));
50+
return tasks;
51+
}
52+
53+
#endregion
54+
55+
}
56+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
using CryptoExchange.Net.Objects;
2+
using CryptoExchange.Net.SharedApis;
3+
using System;
4+
using System.Collections.Generic;
5+
using System.Linq;
6+
using System.Threading;
7+
using System.Threading.Tasks;
8+
9+
namespace CryptoClients.Net
10+
{
11+
/// <inheritdoc />
12+
public partial class ExchangeRestClient
13+
{
14+
/// <inheritdoc />
15+
public IEnumerable<IDepositRestClient> GetDepositsClients() => _sharedClients.OfType<IDepositRestClient>();
16+
/// <inheritdoc />
17+
public IDepositRestClient? GetDepositsClient(string exchange) => GetDepositsClients().SingleOrDefault(s => s.Exchange == exchange);
18+
19+
#region Get Deposits
20+
21+
/// <inheritdoc />
22+
public async Task<ExchangeWebResult<SharedDeposit[]>> GetDepositsAsync(string exchange, GetDepositsRequest request, CancellationToken ct = default)
23+
{
24+
var result = await Task.WhenAll(GetDepositsInt(request, new[] { exchange }, ct)).ConfigureAwait(false);
25+
return result.SingleOrDefault() ?? new ExchangeWebResult<SharedDeposit[]>(exchange, new InvalidOperationError($"Request not supported for {exchange}"));
26+
}
27+
28+
/// <inheritdoc />
29+
public async Task<ExchangeWebResult<SharedDeposit[]>[]> GetDepositsAsync(GetDepositsRequest request, IEnumerable<string>? exchanges = null, CancellationToken ct = default)
30+
{
31+
return await Task.WhenAll(GetDepositsInt(request, exchanges, ct)).ConfigureAwait(false);
32+
}
33+
34+
/// <inheritdoc />
35+
public IAsyncEnumerable<ExchangeWebResult<SharedDeposit[]>> GetDepositsAsyncEnumerable(GetDepositsRequest request, IEnumerable<string>? exchanges = null, CancellationToken ct = default)
36+
{
37+
return GetDepositsInt(request, exchanges, ct).ParallelEnumerateAsync();
38+
}
39+
40+
private IEnumerable<Task<ExchangeWebResult<SharedDeposit[]>>> GetDepositsInt(GetDepositsRequest request, IEnumerable<string>? exchanges, CancellationToken ct)
41+
{
42+
var clients = GetDepositsClients();
43+
if (exchanges != null)
44+
clients = clients.Where(c => exchanges.Contains(c.Exchange, StringComparer.InvariantCultureIgnoreCase));
45+
46+
var tasks = clients.Where(x => x.GetDepositsOptions.Supported).Select(x => x.GetDepositsAsync(request, null, ct));
47+
return tasks;
48+
}
49+
50+
#endregion
51+
}
52+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
using CryptoExchange.Net.Objects;
2+
using CryptoExchange.Net.SharedApis;
3+
using System;
4+
using System.Collections.Generic;
5+
using System.Linq;
6+
using System.Threading;
7+
using System.Threading.Tasks;
8+
9+
namespace CryptoClients.Net
10+
{
11+
/// <inheritdoc />
12+
public partial class ExchangeRestClient
13+
{
14+
/// <inheritdoc />
15+
public IEnumerable<IFeeRestClient> GetFeeClients() => _sharedClients.OfType<IFeeRestClient>();
16+
/// <inheritdoc />
17+
public IEnumerable<IFeeRestClient> GetFeeClients(TradingMode api) => _sharedClients.OfType<IFeeRestClient>().Where(s => s.SupportedTradingModes.Contains(api));
18+
/// <inheritdoc />
19+
public IFeeRestClient? GetFeeClient(TradingMode api, string exchange) => _sharedClients.OfType<IFeeRestClient>().SingleOrDefault(s => s.SupportedTradingModes.Contains(api) && s.Exchange == exchange);
20+
21+
#region Get Fees
22+
23+
/// <inheritdoc />
24+
public async Task<ExchangeWebResult<SharedFee>> GetFeesAsync(string exchange, GetFeeRequest request, CancellationToken ct = default)
25+
{
26+
var result = await Task.WhenAll(GetFeesInt(request, new[] { exchange }, ct)).ConfigureAwait(false);
27+
return result.SingleOrDefault() ?? new ExchangeWebResult<SharedFee>(exchange, new InvalidOperationError($"Request not supported for {exchange}"));
28+
}
29+
30+
/// <inheritdoc />
31+
public async Task<ExchangeWebResult<SharedFee>[]> GetFeesAsync(GetFeeRequest request, IEnumerable<string>? exchanges = null, CancellationToken ct = default)
32+
{
33+
return await Task.WhenAll(GetFeesInt(request, exchanges, ct)).ConfigureAwait(false);
34+
}
35+
36+
/// <inheritdoc />
37+
public IAsyncEnumerable<ExchangeWebResult<SharedFee>> GetFeesAsyncEnumerable(GetFeeRequest request, IEnumerable<string>? exchanges = null, CancellationToken ct = default)
38+
{
39+
return GetFeesInt(request, exchanges, ct).ParallelEnumerateAsync();
40+
}
41+
42+
private IEnumerable<Task<ExchangeWebResult<SharedFee>>> GetFeesInt(GetFeeRequest request, IEnumerable<string>? exchanges, CancellationToken ct)
43+
{
44+
var clients = GetFeeClients().Where(x => x.SupportedTradingModes.Contains(request.Symbol.TradingMode));
45+
if (exchanges != null)
46+
clients = clients.Where(c => exchanges.Contains(c.Exchange, StringComparer.InvariantCultureIgnoreCase));
47+
48+
var tasks = clients.Where(x => x.GetFeeOptions.Supported).Select(x => x.GetFeesAsync(request, ct));
49+
return tasks;
50+
}
51+
52+
#endregion
53+
}
54+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
using CryptoExchange.Net.Objects;
2+
using CryptoExchange.Net.SharedApis;
3+
using System;
4+
using System.Collections.Generic;
5+
using System.Linq;
6+
using System.Threading;
7+
using System.Threading.Tasks;
8+
9+
namespace CryptoClients.Net
10+
{
11+
/// <inheritdoc />
12+
public partial class ExchangeRestClient
13+
{
14+
/// <inheritdoc />
15+
public IEnumerable<IFundingRateRestClient> GetFundingRateClients() => _sharedClients.OfType<IFundingRateRestClient>();
16+
/// <inheritdoc />
17+
public IEnumerable<IFundingRateRestClient> GetFundingRateClients(TradingMode api) => _sharedClients.OfType<IFundingRateRestClient>().Where(s => s.SupportedTradingModes.Contains(api));
18+
/// <inheritdoc />
19+
public IFundingRateRestClient? GetFundingRateClient(TradingMode api, string exchange) => _sharedClients.OfType<IFundingRateRestClient>().SingleOrDefault(s => s.SupportedTradingModes.Contains(api) && s.Exchange == exchange);
20+
21+
#region Get Funding Rate History
22+
23+
/// <inheritdoc />
24+
public async Task<ExchangeWebResult<SharedFundingRate[]>> GetFundingRateHistoryAsync(string exchange, GetFundingRateHistoryRequest request, CancellationToken ct = default)
25+
{
26+
var result = await Task.WhenAll(GetFundingRateHistoryInt(request, new[] { exchange }, ct)).ConfigureAwait(false);
27+
return result.SingleOrDefault() ?? new ExchangeWebResult<SharedFundingRate[]>(exchange, new InvalidOperationError($"Request not supported for {exchange}"));
28+
}
29+
30+
/// <inheritdoc />
31+
public async Task<ExchangeWebResult<SharedFundingRate[]>[]> GetFundingRateHistoryAsync(GetFundingRateHistoryRequest request, IEnumerable<string>? exchanges = null, CancellationToken ct = default)
32+
{
33+
return await Task.WhenAll(GetFundingRateHistoryInt(request, exchanges, ct)).ConfigureAwait(false);
34+
}
35+
36+
/// <inheritdoc />
37+
public IAsyncEnumerable<ExchangeWebResult<SharedFundingRate[]>> GetFundingRateHistoryAsyncEnumerable(GetFundingRateHistoryRequest request, IEnumerable<string>? exchanges = null, CancellationToken ct = default)
38+
{
39+
return GetFundingRateHistoryInt(request, exchanges, ct).ParallelEnumerateAsync();
40+
}
41+
42+
private IEnumerable<Task<ExchangeWebResult<SharedFundingRate[]>>> GetFundingRateHistoryInt(GetFundingRateHistoryRequest request, IEnumerable<string>? exchanges, CancellationToken ct)
43+
{
44+
var clients = GetFundingRateClients().Where(x => x.SupportedTradingModes.Contains(request.Symbol.TradingMode));
45+
if (exchanges != null)
46+
clients = clients.Where(c => exchanges.Contains(c.Exchange, StringComparer.InvariantCultureIgnoreCase));
47+
48+
var tasks = clients.Where(x => x.GetFundingRateHistoryOptions.Supported).Select(x => x.GetFundingRateHistoryAsync(request, null, ct));
49+
return tasks;
50+
}
51+
52+
#endregion
53+
54+
}
55+
}

0 commit comments

Comments
 (0)