using CryptoExchange.Net.Objects; using CryptoExchange.Net.Objects.Sockets; using Microsoft.Extensions.DependencyInjection; using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Threading; using System.Threading.Tasks; namespace CryptoExchange.Net.SharedApis { /// /// Shared interfaces utilities /// public static class SharedUtils { /// /// Get client information including supported features /// public static SharedClientInfo GetClientInfo(PlatformInfo platformInfo, ISharedApi client) { return new SharedClientInfo { Exchange = client.Exchange, TypeName = client.GetType().Name, SupportedEnvironments = platformInfo.SupportedEnvironments, SupportedTradingModes = client.SupportedTradingModes, CentralizationType = platformInfo.CentralizationType, Transport = client.Transport, Authenticated = client.Authenticated, Capabilities = client.Capabilities.Where(x => x.Supported).ToArray() }; } /// /// Apply symbols request filter for asset type and trading mode /// public static T[] ApplySymbolFilter(T[] symbols, GetSymbolsRequest request) where T : SharedSpotSymbol { IEnumerable resultData = symbols; if (request.TradingMode != null) resultData = resultData.Where(x => x.TradingMode == request.TradingMode); if (request.BaseAssetType != null) resultData = resultData.Where(x => x.BaseAssetType == request.BaseAssetType); if (request.QuoteAssetType != null) resultData = resultData.Where(x => x.QuoteAssetType == request.QuoteAssetType); if (request.BaseAssetSubType != null) resultData = resultData.Where(x => x.BaseAssetSubType == request.BaseAssetSubType); if (request.QuoteAssetSubType != null) resultData = resultData.Where(x => x.QuoteAssetSubType == request.QuoteAssetSubType); return resultData.ToArray(); } /// /// Register Shared API client in DI container /// public static IServiceCollection RegisterSharedApiClient< TSharedApiClient, #if NET5_0_OR_GREATER [DynamicallyAccessedMembers( DynamicallyAccessedMemberTypes.PublicConstructors)] #endif TImplementation >(this IServiceCollection services, Action> configure) where TImplementation : class, TSharedApiClient where TSharedApiClient : class, ISharedApiClientBase { services.AddTransient(); services.AddTransient( serviceProvider => serviceProvider.GetRequiredService()); var builder = new SharedApiClientRegistrationBuilder(services); configure(builder); builder.RegisterTransportAgnosticCapabilities(); return services; } /// /// Execute GetAssetAsync for all capabilities in parallel and return results as they arrive /// public static IAsyncEnumerable> ExecuteAllAsync( this IEnumerable> capabilities, GetAssetRequest request, CancellationToken ct = default) { return capabilities .Select(x => x.Capability.GetAssetAsync(request, ct)) .ParallelEnumerateAsync(); } /// /// Execute GetAssetAsync for all capabilities in parallel and return results as they arrive /// public static IAsyncEnumerable> ExecuteAllAsync( this IEnumerable> capabilities, GetAssetRequest request, CancellationToken ct = default) { return capabilities .Select(x => x.Capability.GetAssetAsync(request, ct)) .ParallelEnumerateAsync(); } /// /// Execute GetAllAssetsAsync for all capabilities in parallel and return results as they arrive /// public static IAsyncEnumerable> ExecuteAllAsync( this IEnumerable> capabilities, GetAssetsRequest request, CancellationToken ct = default) { return capabilities .Select(x => x.Capability.GetAllAssetsAsync(request, ct)) .ParallelEnumerateAsync(); } /// /// Execute GetAllAssetsAsync for all capabilities in parallel and return results as they arrive /// public static IAsyncEnumerable> ExecuteAllAsync( this IEnumerable> capabilities, GetAssetsRequest request, CancellationToken ct = default) { return capabilities .Select(x => x.Capability.GetAllAssetsAsync(request, ct)) .ParallelEnumerateAsync(); } /// /// Execute GetBalancesAsync for all capabilities in parallel and return results as they arrive /// public static IAsyncEnumerable> ExecuteAllAsync( this IEnumerable> capabilities, GetBalancesRequest request, CancellationToken ct = default) { return capabilities .Select(x => x.Capability.GetBalancesAsync(request, ct)) .ParallelEnumerateAsync(); } /// /// Execute GetBalancesAsync for all capabilities in parallel and return results as they arrive /// public static IAsyncEnumerable> ExecuteAllAsync( this IEnumerable> capabilities, GetBalancesRequest request, CancellationToken ct = default) { return capabilities .Select(x => x.Capability.GetBalancesAsync(request, ct)) .ParallelEnumerateAsync(); } /// /// Execute GetFeesAsync for all capabilities in parallel and return results as they arrive /// public static IAsyncEnumerable> ExecuteAllAsync( this IEnumerable> capabilities, GetFeeRequest request, CancellationToken ct = default) { return capabilities .Select(x => x.Capability.GetFeesAsync(request, ct)) .ParallelEnumerateAsync(); } /// /// Execute GetFeesAsync for all capabilities in parallel and return results as they arrive /// public static IAsyncEnumerable> ExecuteAllAsync( this IEnumerable> capabilities, GetFeeRequest request, CancellationToken ct = default) { return capabilities .Select(x => x.Capability.GetFeesAsync(request, ct)) .ParallelEnumerateAsync(); } /// /// Execute GetFundingInfoAsync for all capabilities in parallel and return results as they arrive /// public static IAsyncEnumerable> ExecuteAllAsync( this IEnumerable> capabilities, GetFundingInfoRequest request, CancellationToken ct = default) { return capabilities .Select(x => x.Capability.GetFundingInfoAsync(request, ct)) .ParallelEnumerateAsync(); } /// /// Execute GetFundingInfoAsync for all capabilities in parallel and return results as they arrive /// public static IAsyncEnumerable> ExecuteAllAsync( this IEnumerable> capabilities, GetFundingInfoRequest request, CancellationToken ct = default) { return capabilities .Select(x => x.Capability.GetFundingInfoAsync(request, ct)) .ParallelEnumerateAsync(); } /// /// Execute GetIndexPriceAsync for all capabilities in parallel and return results as they arrive /// public static IAsyncEnumerable> ExecuteAllAsync( this IEnumerable> capabilities, GetIndexPriceRequest request, CancellationToken ct = default) { return capabilities .Select(x => x.Capability.GetIndexPriceAsync(request, ct)) .ParallelEnumerateAsync(); } /// /// Execute GetIndexPriceAsync for all capabilities in parallel and return results as they arrive /// public static IAsyncEnumerable> ExecuteAllAsync( this IEnumerable> capabilities, GetIndexPriceRequest request, CancellationToken ct = default) { return capabilities .Select(x => x.Capability.GetIndexPriceAsync(request, ct)) .ParallelEnumerateAsync(); } /// /// Execute GetMarkPriceAsync for all capabilities in parallel and return results as they arrive /// public static IAsyncEnumerable> ExecuteAllAsync( this IEnumerable> capabilities, GetMarkPriceRequest request, CancellationToken ct = default) { return capabilities .Select(x => x.Capability.GetMarkPriceAsync(request, ct)) .ParallelEnumerateAsync(); } /// /// Execute GetMarkPriceAsync for all capabilities in parallel and return results as they arrive /// public static IAsyncEnumerable> ExecuteAllAsync( this IEnumerable> capabilities, GetMarkPriceRequest request, CancellationToken ct = default) { return capabilities .Select(x => x.Capability.GetMarkPriceAsync(request, ct)) .ParallelEnumerateAsync(); } /// /// Execute GetAllMarkPricesAsync for all capabilities in parallel and return results as they arrive /// public static IAsyncEnumerable> ExecuteAllAsync( this IEnumerable> capabilities, GetAllMarkPricesRequest request, CancellationToken ct = default) { return capabilities .Select(x => x.Capability.GetAllMarkPricesAsync(request, ct)) .ParallelEnumerateAsync(); } /// /// Execute GetAllMarkPricesAsync for all capabilities in parallel and return results as they arrive /// public static IAsyncEnumerable> ExecuteAllAsync( this IEnumerable> capabilities, GetAllMarkPricesRequest request, CancellationToken ct = default) { return capabilities .Select(x => x.Capability.GetAllMarkPricesAsync(request, ct)) .ParallelEnumerateAsync(); } /// /// Execute GetAllIndexPricesAsync for all capabilities in parallel and return results as they arrive /// public static IAsyncEnumerable> ExecuteAllAsync( this IEnumerable> capabilities, GetAllIndexPricesRequest request, CancellationToken ct = default) { return capabilities .Select(x => x.Capability.GetAllIndexPricesAsync(request, ct)) .ParallelEnumerateAsync(); } /// /// Execute GetAllIndexPricesAsync for all capabilities in parallel and return results as they arrive /// public static IAsyncEnumerable> ExecuteAllAsync( this IEnumerable> capabilities, GetAllIndexPricesRequest request, CancellationToken ct = default) { return capabilities .Select(x => x.Capability.GetAllIndexPricesAsync(request, ct)) .ParallelEnumerateAsync(); } /// /// Execute GetLeverageAsync for all capabilities in parallel and return results as they arrive /// public static IAsyncEnumerable> ExecuteAllAsync( this IEnumerable> capabilities, GetLeverageRequest request, CancellationToken ct = default) { return capabilities .Select(x => x.Capability.GetLeverageAsync(request, ct)) .ParallelEnumerateAsync(); } /// /// Execute GetLeverageAsync for all capabilities in parallel and return results as they arrive /// public static IAsyncEnumerable> ExecuteAllAsync( this IEnumerable> capabilities, GetLeverageRequest request, CancellationToken ct = default) { return capabilities .Select(x => x.Capability.GetLeverageAsync(request, ct)) .ParallelEnumerateAsync(); } /// /// Execute GetLeverageTiersAsync for all capabilities in parallel and return results as they arrive /// public static IAsyncEnumerable> ExecuteAllAsync( this IEnumerable> capabilities, GetLeverageTiersRequest request, CancellationToken ct = default) { return capabilities .Select(x => x.Capability.GetLeverageTiersAsync(request, ct)) .ParallelEnumerateAsync(); } /// /// Execute GetLeverageTiersAsync for all capabilities in parallel and return results as they arrive /// public static IAsyncEnumerable> ExecuteAllAsync( this IEnumerable> capabilities, GetLeverageTiersRequest request, CancellationToken ct = default) { return capabilities .Select(x => x.Capability.GetLeverageTiersAsync(request, ct)) .ParallelEnumerateAsync(); } /// /// Execute GetOpenInterestAsync for all capabilities in parallel and return results as they arrive /// public static IAsyncEnumerable> ExecuteAllAsync( this IEnumerable> capabilities, GetOpenInterestRequest request, CancellationToken ct = default) { return capabilities .Select(x => x.Capability.GetOpenInterestAsync(request, ct)) .ParallelEnumerateAsync(); } /// /// Execute GetOpenInterestAsync for all capabilities in parallel and return results as they arrive /// public static IAsyncEnumerable> ExecuteAllAsync( this IEnumerable> capabilities, GetOpenInterestRequest request, CancellationToken ct = default) { return capabilities .Select(x => x.Capability.GetOpenInterestAsync(request, ct)) .ParallelEnumerateAsync(); } /// /// Execute GetBookTickerAsync for all capabilities in parallel and return results as they arrive /// public static IAsyncEnumerable> ExecuteAllAsync( this IEnumerable> capabilities, GetBookTickerRequest request, CancellationToken ct = default) { return capabilities .Select(x => x.Capability.GetBookTickerAsync(request, ct)) .ParallelEnumerateAsync(); } /// /// Execute GetBookTickerAsync for all capabilities in parallel and return results as they arrive /// public static IAsyncEnumerable> ExecuteAllAsync( this IEnumerable> capabilities, GetBookTickerRequest request, CancellationToken ct = default) { return capabilities .Select(x => x.Capability.GetBookTickerAsync(request, ct)) .ParallelEnumerateAsync(); } /// /// Execute GetOrderBookAsync for all capabilities in parallel and return results as they arrive /// public static IAsyncEnumerable> ExecuteAllAsync( this IEnumerable> capabilities, GetOrderBookRequest request, CancellationToken ct = default) { return capabilities .Select(x => x.Capability.GetOrderBookAsync(request, ct)) .ParallelEnumerateAsync(); } /// /// Execute GetOrderBookAsync for all capabilities in parallel and return results as they arrive /// public static IAsyncEnumerable> ExecuteAllAsync( this IEnumerable> capabilities, GetOrderBookRequest request, CancellationToken ct = default) { return capabilities .Select(x => x.Capability.GetOrderBookAsync(request, ct)) .ParallelEnumerateAsync(); } /// /// Execute GetPositionModeAsync for all capabilities in parallel and return results as they arrive /// public static IAsyncEnumerable> ExecuteAllAsync( this IEnumerable> capabilities, GetPositionModeRequest request, CancellationToken ct = default) { return capabilities .Select(x => x.Capability.GetPositionModeAsync(request, ct)) .ParallelEnumerateAsync(); } /// /// Execute GetPositionModeAsync for all capabilities in parallel and return results as they arrive /// public static IAsyncEnumerable> ExecuteAllAsync( this IEnumerable> capabilities, GetPositionModeRequest request, CancellationToken ct = default) { return capabilities .Select(x => x.Capability.GetPositionModeAsync(request, ct)) .ParallelEnumerateAsync(); } /// /// Execute GetPositionsAsync for all capabilities in parallel and return results as they arrive /// public static IAsyncEnumerable> ExecuteAllAsync( this IEnumerable> capabilities, GetPositionsRequest request, CancellationToken ct = default) { return capabilities .Select(x => x.Capability.GetPositionsAsync(request, ct)) .ParallelEnumerateAsync(); } /// /// Execute GetPositionsAsync for all capabilities in parallel and return results as they arrive /// public static IAsyncEnumerable> ExecuteAllAsync( this IEnumerable> capabilities, GetPositionsRequest request, CancellationToken ct = default) { return capabilities .Select(x => x.Capability.GetPositionsAsync(request, ct)) .ParallelEnumerateAsync(); } /// /// Execute GetSpotSymbolsAsync for all capabilities in parallel and return results as they arrive /// public static IAsyncEnumerable> ExecuteAllAsync( this IEnumerable> capabilities, GetSymbolsRequest request, CancellationToken ct = default) { return capabilities .Select(x => x.Capability.GetSpotSymbolsAsync(request, ct)) .ParallelEnumerateAsync(); } /// /// Execute GetSpotSymbolsAsync for all capabilities in parallel and return results as they arrive /// public static IAsyncEnumerable> ExecuteAllAsync( this IEnumerable> capabilities, GetSymbolsRequest request, CancellationToken ct = default) { return capabilities .Select(x => x.Capability.GetSpotSymbolsAsync(request, ct)) .ParallelEnumerateAsync(); } /// /// Execute GetFuturesSymbolsAsync for all capabilities in parallel and return results as they arrive /// public static IAsyncEnumerable> ExecuteAllAsync( this IEnumerable> capabilities, GetSymbolsRequest request, CancellationToken ct = default) { return capabilities .Select(x => x.Capability.GetFuturesSymbolsAsync(request, ct)) .ParallelEnumerateAsync(); } /// /// Execute GetFuturesSymbolsAsync for all capabilities in parallel and return results as they arrive /// public static IAsyncEnumerable> ExecuteAllAsync( this IEnumerable> capabilities, GetSymbolsRequest request, CancellationToken ct = default) { return capabilities .Select(x => x.Capability.GetFuturesSymbolsAsync(request, ct)) .ParallelEnumerateAsync(); } /// /// Execute GetTickerAsync for all capabilities in parallel and return results as they arrive /// public static IAsyncEnumerable> ExecuteAllAsync( this IEnumerable> capabilities, GetTickerRequest request, CancellationToken ct = default) { return capabilities .Select(x => x.Capability.GetTickerAsync(request, ct)) .ParallelEnumerateAsync(); } /// /// Execute GetTickerAsync for all capabilities in parallel and return results as they arrive /// public static IAsyncEnumerable> ExecuteAllAsync( this IEnumerable> capabilities, GetTickerRequest request, CancellationToken ct = default) { return capabilities .Select(x => x.Capability.GetTickerAsync(request, ct)) .ParallelEnumerateAsync(); } /// /// Execute GetAllTickersAsync for all capabilities in parallel and return results as they arrive /// public static IAsyncEnumerable> ExecuteAllAsync( this IEnumerable> capabilities, GetTickersRequest request, CancellationToken ct = default) { return capabilities .Select(x => x.Capability.GetAllTickersAsync(request, ct)) .ParallelEnumerateAsync(); } /// /// Execute GetAllTickersAsync for all capabilities in parallel and return results as they arrive /// public static IAsyncEnumerable> ExecuteAllAsync( this IEnumerable> capabilities, GetTickersRequest request, CancellationToken ct = default) { return capabilities .Select(x => x.Capability.GetAllTickersAsync(request, ct)) .ParallelEnumerateAsync(); } /// /// Execute GetRecentTradesAsync for all capabilities in parallel and return results as they arrive /// public static IAsyncEnumerable> ExecuteAllAsync( this IEnumerable> capabilities, GetRecentTradesRequest request, CancellationToken ct = default) { return capabilities .Select(x => x.Capability.GetRecentTradesAsync(request, ct)) .ParallelEnumerateAsync(); } /// /// Execute GetRecentTradesAsync for all capabilities in parallel and return results as they arrive /// public static IAsyncEnumerable> ExecuteAllAsync( this IEnumerable> capabilities, GetRecentTradesRequest request, CancellationToken ct = default) { return capabilities .Select(x => x.Capability.GetRecentTradesAsync(request, ct)) .ParallelEnumerateAsync(); } /// /// Subscribe to trade updates for all capabilities in parallel and return results as they arrive /// public static IAsyncEnumerable> SubscribeAllAsync( this IEnumerable> capabilities, SubscribeTradeRequest request, Action> onData, CancellationToken ct = default) { return capabilities .Select(x => x.Capability.SubscribeToTradeUpdatesAsync(request, onData, ct)) .ParallelEnumerateAsync(); } /// /// Subscribe to balance updates for all capabilities in parallel and return results as they arrive /// public static IAsyncEnumerable> SubscribeAllAsync( this IEnumerable> capabilities, SubscribeBalancesRequest request, Action> onData, CancellationToken ct = default) { return capabilities .Select(x => x.Capability.SubscribeToBalanceUpdatesAsync(request, onData, ct)) .ParallelEnumerateAsync(); } /// /// Subscribe to index price updates for all capabilities in parallel and return results as they arrive /// public static IAsyncEnumerable> SubscribeAllAsync( this IEnumerable> capabilities, SubscribeIndexPriceRequest request, Action> onData, CancellationToken ct = default) { return capabilities .Select(x => x.Capability.SubscribeToIndexPriceUpdatesAsync(request, onData, ct)) .ParallelEnumerateAsync(); } /// /// Subscribe to funding info updates for all capabilities in parallel and return results as they arrive /// public static IAsyncEnumerable> SubscribeAllAsync( this IEnumerable> capabilities, SubscribeFundingInfoRequest request, Action> onData, CancellationToken ct = default) { return capabilities .Select(x => x.Capability.SubscribeToFundingInfoUpdatesAsync(request, onData, ct)) .ParallelEnumerateAsync(); } /// /// Subscribe to kline updates for all capabilities in parallel and return results as they arrive /// public static IAsyncEnumerable> SubscribeAllAsync( this IEnumerable> capabilities, SubscribeKlineRequest request, Action> onData, CancellationToken ct = default) { return capabilities .Select(x => x.Capability.SubscribeToKlineUpdatesAsync(request, onData, ct)) .ParallelEnumerateAsync(); } /// /// Subscribe to mark price updates for all capabilities in parallel and return results as they arrive /// public static IAsyncEnumerable> SubscribeAllAsync( this IEnumerable> capabilities, SubscribeMarkPriceRequest request, Action> onData, CancellationToken ct = default) { return capabilities .Select(x => x.Capability.SubscribeToMarkPriceUpdatesAsync(request, onData, ct)) .ParallelEnumerateAsync(); } /// /// Subscribe to order book updates for all capabilities in parallel and return results as they arrive /// public static IAsyncEnumerable> SubscribeAllAsync( this IEnumerable> capabilities, SubscribeOrderBookRequest request, Action> onData, CancellationToken ct = default) { return capabilities .Select(x => x.Capability.SubscribeToOrderBookUpdatesAsync(request, onData, ct)) .ParallelEnumerateAsync(); } /// /// Subscribe to incremental order book updates for all capabilities in parallel and return results as they arrive /// public static IAsyncEnumerable> SubscribeAllAsync( this IEnumerable> capabilities, SubscribeOrderBookRequest request, Action> onData, CancellationToken ct = default) { return capabilities .Select(x => x.Capability.SubscribeToIncrementalOrderBookUpdatesAsync(request, onData, ct)) .ParallelEnumerateAsync(); } /// /// Subscribe to futures order updates for all capabilities in parallel and return results as they arrive /// public static IAsyncEnumerable> SubscribeAllAsync( this IEnumerable> capabilities, SubscribeFuturesOrderRequest request, Action> onData, CancellationToken ct = default) { return capabilities .Select(x => x.Capability.SubscribeToFuturesOrderUpdatesAsync(request, onData, ct)) .ParallelEnumerateAsync(); } /// /// Subscribe to spot order updates for all capabilities in parallel and return results as they arrive /// public static IAsyncEnumerable> SubscribeAllAsync( this IEnumerable> capabilities, SubscribeSpotOrderRequest request, Action> onData, CancellationToken ct = default) { return capabilities .Select(x => x.Capability.SubscribeToSpotOrderUpdatesAsync(request, onData, ct)) .ParallelEnumerateAsync(); } /// /// Subscribe to position updates for all capabilities in parallel and return results as they arrive /// public static IAsyncEnumerable> SubscribeAllAsync( this IEnumerable> capabilities, SubscribePositionRequest request, Action> onData, CancellationToken ct = default) { return capabilities .Select(x => x.Capability.SubscribeToPositionUpdatesAsync(request, onData, ct)) .ParallelEnumerateAsync(); } /// /// Subscribe to ticker updates for all capabilities in parallel and return results as they arrive /// public static IAsyncEnumerable> SubscribeAllAsync( this IEnumerable> capabilities, SubscribeTickerRequest request, Action> onData, CancellationToken ct = default) { return capabilities .Select(x => x.Capability.SubscribeToTickerUpdatesAsync(request, onData, ct)) .ParallelEnumerateAsync(); } /// /// Subscribe to all ticker updates for all capabilities in parallel and return results as they arrive /// public static IAsyncEnumerable> SubscribeAllAsync( this IEnumerable> capabilities, SubscribeAllTickersRequest request, Action> onData, CancellationToken ct = default) { return capabilities .Select(x => x.Capability.SubscribeToAllTickersUpdatesAsync(request, onData, ct)) .ParallelEnumerateAsync(); } /// /// Subscribe to user trade updates for all capabilities in parallel and return results as they arrive /// public static IAsyncEnumerable> SubscribeAllAsync( this IEnumerable> capabilities, SubscribeUserTradeRequest request, Action> onData, CancellationToken ct = default) { return capabilities .Select(x => x.Capability.SubscribeToUserTradeUpdatesAsync(request, onData, ct)) .ParallelEnumerateAsync(); } /// /// Wait for all results from an IAsyncEnumerable and return them as an array /// public static async Task WaitAllAsync(this IAsyncEnumerable enumerable) { var result = new List(); await foreach (var itemResult in enumerable.ConfigureAwait(false)) result.Add(itemResult); return result.ToArray(); } } }