public async Task When_There_Is_Prior_Progress_A_Minimum_Starting_Block_Number_Will_Prevent_Processing_Earlier_Blocks()
        {
            var lastBlockProcessed = new BigInteger(5);
            var minBlock           = new BigInteger(10);

            var progressRepository = new InMemoryBlockchainProgressRepository(lastBlockProcessed);

            var mockRpcResponses = new BlockProcessingRpcMock(Web3Mock);

            mockRpcResponses.AddToGetBlockNumberRequestQueue(100);
            mockRpcResponses.SetupTransactionsWithReceipts(blockNumber: minBlock, numberOfTransactions: 2, logsPerTransaction: 2);

            var cancellationTokenSource = new CancellationTokenSource();
            var processedData           = new ProcessedBlockchainData();

            var blockProcessor = Web3.Processing.Blocks.CreateBlockProcessor(progressRepository, steps =>
            {
                //capture a block and then cancel
                steps.BlockStep.AddSynchronousProcessorHandler((block) => {
                    processedData.Blocks.Add(block);
                    cancellationTokenSource.Cancel();
                });
            }
                                                                             );


            await blockProcessor.ExecuteAsync(cancellationTokenSource.Token, minBlock);

            Assert.Single(processedData.Blocks);                                                 // one block processed
            Assert.Equal(minBlock, processedData.Blocks[0].Number.Value);                        // should have been the next block
            Assert.Equal(minBlock, await progressRepository.GetLastBlockNumberProcessedAsync()); // should have updated progress
        }
        public async Task When_There_Is_Prior_Progress_Processing_Should_Pick_Up_From_Where_It_Left_Off()
        {
            //pretend we have already completed block 1
            var lastBlockProcessed = new BigInteger(1);
            var nextBlockExpected  = lastBlockProcessed + 1;

            var progressRepository = new InMemoryBlockchainProgressRepository(lastBlockProcessed);

            var mockRpcResponses = new BlockProcessingRpcMock(Web3Mock);

            mockRpcResponses.AddToGetBlockNumberRequestQueue(100);
            mockRpcResponses.SetupTransactionsWithReceipts(blockNumber: nextBlockExpected, numberOfTransactions: 2, logsPerTransaction: 2);

            var processedData = new ProcessedBlockchainData();

            var cancellationTokenSource = new CancellationTokenSource();

            var blockProcessor = Web3.Processing.Blocks.CreateBlockProcessor(progressRepository, steps =>
            {
                //capture a block and then cancel
                steps.BlockStep.AddSynchronousProcessorHandler((block) => {
                    processedData.Blocks.Add(block);
                    cancellationTokenSource.Cancel();
                });
            }
                                                                             );

            await blockProcessor.ExecuteAsync(cancellationTokenSource.Token);

            Assert.Single(processedData.Blocks);                                                          // one block processed
            Assert.Equal(nextBlockExpected, processedData.Blocks[0].Number.Value);                        // should have been the next block
            Assert.Equal(nextBlockExpected, await progressRepository.GetLastBlockNumberProcessedAsync()); // should have updated progress
        }
        public async Task Will_Wait_For_Block_Confirmations_Before_Processing()
        {
            var        blockLastProcessed = new BigInteger(100);
            var        nextBlock          = blockLastProcessed + 1;
            const uint MIN_CONFIRMATIONS  = 12;

            var progressRepository = new InMemoryBlockchainProgressRepository(blockLastProcessed);

            var mockRpcResponses = new BlockProcessingRpcMock(Web3Mock);

            //when first asked - pretend the current block is behind the required confirmations
            mockRpcResponses.AddToGetBlockNumberRequestQueue(blockLastProcessed + MIN_CONFIRMATIONS);
            //the next time return an incremented block which is under the confirmation limit
            mockRpcResponses.AddToGetBlockNumberRequestQueue(nextBlock + MIN_CONFIRMATIONS);

            mockRpcResponses.SetupTransactionsWithReceipts(blockNumber: nextBlock, numberOfTransactions: 2, logsPerTransaction: 2);

            var cancellationTokenSource = new CancellationTokenSource();
            var processedData           = new ProcessedBlockchainData();

            var blockProcessor = Web3.Processing.Blocks.CreateBlockProcessor(progressRepository, steps =>
            {
                //capture a block and then cancel
                steps.BlockStep.AddSynchronousProcessorHandler((block) => {
                    processedData.Blocks.Add(block);
                    cancellationTokenSource.Cancel();
                });
            }
                                                                             , MIN_CONFIRMATIONS);


            await blockProcessor.ExecuteAsync(cancellationTokenSource.Token);

            Assert.Single(processedData.Blocks);                                                  //should have processed a single block before cancellation
            Assert.Equal(2, mockRpcResponses.BlockNumberRequestCount);                            //should have asked for latest block twice
            Assert.Equal(nextBlock, processedData.Blocks[0].Number.Value);                        // should have handled the expected block
            Assert.Equal(nextBlock, await progressRepository.GetLastBlockNumberProcessedAsync()); // should have updated progress
        }