public async Task <CommandResult> CreateReport([FromBody] BlockTransactionsReportsRequest input)
        {
            if (!ModelState.IsValid)
            {
                return(CommandResultBuilder.Fail(ModelState.GetErrorsList().ToArray()));
            }

            if (!input.Blocks.Any())
            {
                return(CommandResultBuilder.Fail("0 block count"));
            }

            if (input.Blocks.Length > _bcnReportsSettings.MaxBlockCountPerCommand)
            {
                return(CommandResultBuilder.Fail($"Maximum block count per request exceeded: {_bcnReportsSettings.MaxBlockCountPerCommand}"));
            }

            var blockExistence = (await input.Blocks.SelectAsync(IsBlock)).ToList();

            if (blockExistence.Any(p => !p.exists))
            {
                var notFoundBlocks = blockExistence.Where(p => !p.exists).Select(p => p.block);
                return(CommandResultBuilder.Fail($"Blocks {string.Join(", ", notFoundBlocks)} not found"));
            }

            await _commandProducer.CreateCommand(input.Blocks, input.Email);

            foreach (var block in input.Blocks)
            {
                await _reportMetadataRepository.InsertOrReplace(ReportMetadata.Create(block, queuedAt: DateTime.UtcNow));
            }


            return(CommandResultBuilder.Ok());
        }
        public async Task <CommandResult> CreateRangeReport([FromQuery] int minBlock, [FromQuery] int maxBlock, [FromQuery] int batch = 1)
        {
            var list = Enumerable.Range(minBlock, maxBlock - minBlock + 1);

            foreach (var enumerable in list.Batch(batch))
            {
                await _commandProducer.CreateCommand(enumerable.Select(p => p.ToString()), null);

                foreach (var block in enumerable)
                {
                    await _reportMetadataRepository.InsertOrReplace(ReportMetadata.Create(block.ToString(), queuedAt: DateTime.UtcNow));
                }
            }


            return(CommandResultBuilder.Ok());
        }
        public async Task <CommandResult> CreateReport([FromBody] AddressTransactionsReportsRequest input)
        {
            if (!ModelState.IsValid)
            {
                return(CommandResultBuilder.Fail(ModelState.GetErrorsList().ToArray()));
            }

            if (!BitcoinAddressHelper.IsAddress(input.BitcoinAddress, _bcnReportsSettings.UsedNetwork()))
            {
                return(CommandResultBuilder.Fail("Invalid base58 address string."));
            }

            await _addressTransactionsReportMetadataRepository.InsertOrReplace(ReportMetadata.Create(input.BitcoinAddress, queuedAt: DateTime.UtcNow));

            await _commandProducer.CreateCommand(input.BitcoinAddress, input.Email);

            return(CommandResultBuilder.Ok());
        }
        public async Task<CommandResult> CreateReport([FromBody]AssetTransactionsReportsRequest input)
        {
            if (!ModelState.IsValid)
            {
                return CommandResultBuilder.Fail(ModelState.GetErrorsList().ToArray());
            }

            var assetDefinitions = await _assetDefinitionService.GetAssetDefinitionsAsync();

            if (!assetDefinitions.ContainsKey(input.Asset))
            {
                return CommandResultBuilder.Fail("Asset not found");
            }

            var asset = assetDefinitions[input.Asset];
            var assetId = asset.AssetIds.First();

            await _reportMetadataRepository.InsertOrReplace(ReportMetadata.Create(assetId, queuedAt: DateTime.UtcNow));
            await _commandProducer.CreateCommand(assetId, input.Email);
            
            return CommandResultBuilder.Ok();
        }