private static void RegisterImplementationServices <TAppSettings>(
            IServiceCollection services,
            TransactionsExecutorServiceOptions <TAppSettings> options,
            IReloadingManager <TAppSettings> settings)

            where TAppSettings : class, ITransactionsExecutorSettings <BaseTransactionsExecutorDbSettings>
        {
            services.AddTransient(s => options.AddressValidatorFactory(new ServiceFactoryContext <TAppSettings>(s, settings)));
            services.AddTransient(s => options.HealthProviderFactory(new ServiceFactoryContext <TAppSettings>(s, settings)));
            services.AddTransient(s => options.BlockchainInfoProviderFactory(new ServiceFactoryContext <TAppSettings>(s, settings)));
            services.AddTransient <IDependenciesInfoProvider>(s =>
            {
                var impl = options.DependenciesInfoProviderFactory(new ServiceFactoryContext <TAppSettings>(s, settings));

                return(new CachedDependenciesInfoProviderDecorator
                       (
                           impl,
                           s.GetRequiredService <LongLiveInMemoryCache>(),
                           settings.CurrentValue.DependenciesInfoCacheExpirationPeriod
                       ));
            });
            services.AddTransient(s => options.TransferAmountTransactionsEstimatorFactory(new ServiceFactoryContext <TAppSettings>(s, settings)));
            services.AddTransient(s => options.TransferCoinsTransactionsEstimatorFactory(new ServiceFactoryContext <TAppSettings>(s, settings)));
            services.AddTransient(s => options.TransferAmountTransactionsBuilderFactory(new ServiceFactoryContext <TAppSettings>(s, settings)));
            services.AddTransient(s => options.TransferCoinsTransactionsBuilderFactory(new ServiceFactoryContext <TAppSettings>(s, settings)));
            services.AddTransient(s => options.TransactionBroadcasterFactory(new ServiceFactoryContext <TAppSettings>(s, settings)));
            services.AddTransient(s => options.AddressFormatsProviderFactory(new ServiceFactoryContext <TAppSettings>(s, settings)));
            services.AddTransient(s => options.TransactionsStateProviderFactory(new ServiceFactoryContext <TAppSettings>(s, settings)));
        }
        private static void RegisterCommonServices <TAppSettings>(
            IServiceCollection services,
            IReloadingManager <TAppSettings> settings,
            TransactionsExecutorServiceOptions <TAppSettings> options)

            where TAppSettings : class, ITransactionsExecutorSettings <BaseTransactionsExecutorDbSettings>
        {
            services.AddTransient <IStartupManager, StartupManager>();

            services.AddSingleton <IHealthMonitor>(s => new HealthMonitor(
                                                       s.GetRequiredService <ILogFactory>(),
                                                       s.GetRequiredService <IHealthProvider>(),
                                                       settings.CurrentValue.HealthMonitoringPeriod
                                                       ));

            services.AddSingleton(s =>
                                  options.RawObjectsReadOnlyRepositoryFactory(options.IntegrationName.CamelToKebab(),
                                                                              new ServiceFactoryContext <TAppSettings>(s, settings)));

            services.AddSingleton(s => new LongLiveInMemoryCache());
        }
        private static TransactionsExecutorServiceOptions <TAppSettings> GetOptions <TAppSettings>(
            Action <TransactionsExecutorServiceOptions <TAppSettings> > configureOptions)

            where TAppSettings : class, ITransactionsExecutorSettings <BaseTransactionsExecutorDbSettings>
        {
            var options = new TransactionsExecutorServiceOptions <TAppSettings>();

            configureOptions(options);

            if (string.IsNullOrWhiteSpace(options.IntegrationName))
            {
                throw new InvalidOperationException($"{nameof(options)}.{nameof(options.IntegrationName)} is required.");
            }

            if (options.AddressValidatorFactory == null)
            {
                throw new InvalidOperationException(
                          $"{nameof(options)}.{nameof(options.AddressValidatorFactory)} is required.");
            }

            if (options.HealthProviderFactory == null)
            {
                throw new InvalidOperationException($"{nameof(options)}.{nameof(options.HealthProviderFactory)} is required.");
            }

            if (options.BlockchainInfoProviderFactory == null)
            {
                throw new InvalidOperationException(
                          $"{nameof(options)}.{nameof(options.BlockchainInfoProviderFactory)} is required.");
            }

            if (options.DependenciesInfoProviderFactory == null)
            {
                throw new InvalidOperationException(
                          $"{nameof(options)}.{nameof(options.DependenciesInfoProviderFactory)} is required.");
            }

            if (options.TransferAmountTransactionsEstimatorFactory == null)
            {
                throw new InvalidOperationException(
                          $"{nameof(options)}.{nameof(options.TransferAmountTransactionsEstimatorFactory)} is required.");
            }

            if (options.TransferCoinsTransactionsEstimatorFactory == null)
            {
                throw new InvalidOperationException(
                          $"{nameof(options)}.{nameof(options.TransferCoinsTransactionsEstimatorFactory)} is required.");
            }

            if (options.TransactionBroadcasterFactory == null)
            {
                throw new InvalidOperationException(
                          $"{nameof(options)}.{nameof(options.TransactionBroadcasterFactory)} is required.");
            }

            if (options.TransferAmountTransactionsBuilderFactory == null)
            {
                throw new InvalidOperationException(
                          $"{nameof(options)}.{nameof(options.TransferAmountTransactionsBuilderFactory)} is required.");
            }

            if (options.TransferCoinsTransactionsBuilderFactory == null)
            {
                throw new InvalidOperationException(
                          $"{nameof(options)}.{nameof(options.TransferCoinsTransactionsBuilderFactory)} is required.");
            }

            if (options.AddressFormatsProviderFactory == null)
            {
                throw new InvalidOperationException(
                          $"{nameof(options)}.{nameof(options.AddressFormatsProviderFactory)} is required.");
            }

            if (options.TransactionsStateProviderFactory == null)
            {
                throw new InvalidOperationException(
                          $"{nameof(options)}.{nameof(options.TransactionsStateProviderFactory)} is required.");
            }

            return(options);
        }