public async Task OneEvent()
        {
            const string INDEX_NAME = "transfer-logs";

            //surround with "using" so that anything in a buffer is sent on dispose
            using (var azureSearchService = new AzureSearchService(AzureSearchServiceName, _azureSearchApiKey))
            {
                try
                {
                    //setup
                    var index = await azureSearchService.CreateIndexForEventLogAsync <TransferEvent_ERC20>(INDEX_NAME);

                    var indexer = azureSearchService.CreateIndexerForEventLog <TransferEvent_ERC20>(index.Name, documentsPerBatch: 1);

                    var web3 = new Web3.Web3(BlockchainUrl);
                    var blockchainProcessor     = web3.Processing.Logs.CreateProcessor <TransferEvent_ERC20>((transfer) => indexer.IndexAsync(transfer));
                    var cancellationTokenSource = new CancellationTokenSource();

                    //execute
                    await blockchainProcessor.ExecuteAsync(3146694, cancellationTokenSource.Token, 3146684);

                    //assert
                    await Task.Delay(5000); // allow time to index

                    Assert.Equal(19, await azureSearchService.CountDocumentsAsync(INDEX_NAME));
                }
                finally
                {
                    await azureSearchService.DeleteIndexAsync(INDEX_NAME);
                }
            }
        }
        public async Task OneEventWithMapping()
        {
            const string INDEX_NAME = "one-event-with-mapping";

            using (var azureSearchService = new AzureSearchService(AzureSearchServiceName, _azureSearchApiKey))
            {
                try
                {
                    //setup

                    //create a definition of an index -
                    //it describes the fields, key and data types
                    //at this stage - it is only an in-memory schema
                    var index = CreateAzureIndexDefinition(INDEX_NAME);

                    //create the index in azure
                    index = await azureSearchService.CreateIndexAsync(index);

                    // create a processor for a specific event and map to a custom DTO for the search
                    var indexer = azureSearchService.CreateIndexerForEventLog <TransferEvent_ERC20, CustomTransferSearchDocumentDto>(
                        index.Name,
                        (e) =>
                        new CustomTransferSearchDocumentDto
                    {
                        From        = e.Event.From,
                        To          = e.Event.To,
                        Value       = e.Event.Value.ToString(),
                        BlockNumber = e.Log.BlockNumber.Value.ToString(),
                        TxHash      = e.Log.TransactionHash,
                        LogAddress  = e.Log.Address,
                        LogIndex    = (int)e.Log.LogIndex.Value,
                        DocumentKey = $"{e.Log.TransactionHash}_{e.Log.LogIndex.Value}"
                    },
                        documentsPerBatch: 1);

                    var web3 = new Web3.Web3(BlockchainUrl);
                    var blockchainProcessor = web3.Processing.Logs.CreateProcessor <TransferEvent_ERC20>(
                        transfer => indexer.IndexAsync(transfer));

                    var cancellationTokenSource = new CancellationTokenSource();

                    //execute
                    await blockchainProcessor.ExecuteAsync(3146694, cancellationTokenSource.Token, 3146684);

                    //assert
                    await Task.Delay(5000); // allow time to index

                    Assert.Equal(19, await azureSearchService.CountDocumentsAsync(INDEX_NAME));
                }
                finally
                {
                    await azureSearchService.DeleteIndexAsync(INDEX_NAME);
                }
            }
        }
        public async Task AnEventAndItsTransaction()
        {
            const string EVENT_INDEX_NAME    = "transfer-logs-related";
            const string FUNCTION_INDEX_NAME = "related-transfer-functions";

            //surround with "using" so that anything in a buffer is sent on dispose
            using (var azureSearchService = new AzureSearchService(AzureSearchServiceName, _azureSearchApiKey))
            {
                try
                {
                    //setup
                    var transferEventIndex = await azureSearchService.CreateIndexForEventLogAsync <TransferEvent_ERC20>(EVENT_INDEX_NAME);

                    var transferFunctionIndex = await azureSearchService.CreateIndexForFunctionMessageAsync <TransferFunction>(FUNCTION_INDEX_NAME);

                    var transferIndexer         = azureSearchService.CreateIndexerForEventLog <TransferEvent_ERC20>(transferEventIndex.Name);
                    var transferFunctionIndexer = azureSearchService.CreateIndexerForFunctionMessage <TransferFunction>(transferFunctionIndex.Name);

                    //this handler ensures the transaction is a Transfer and invokes the indexer
                    var transferFunctionProcessorHandler = transferFunctionIndexer.CreateProcessorHandler();

                    var web3 = new Web3.Web3(BlockchainUrl);

                    var blockchainProcessor = web3.Processing.Logs.CreateProcessor <TransferEvent_ERC20>(async(log) => {
                        await transferIndexer.IndexAsync(log);
                        var transactionWithReceipt = await web3.Eth.GetTransactionReceiptVO(log.Log.BlockNumber, log.Log.TransactionHash).ConfigureAwait(false);

                        await transferFunctionProcessorHandler.ExecuteAsync(transactionWithReceipt);
                    });

                    var cancellationTokenSource = new CancellationTokenSource();

                    //execute
                    await blockchainProcessor.ExecuteAsync(3146694, cancellationTokenSource.Token, 3146684);

                    //assert
                    await Task.Delay(5000); // allow time to index

                    Assert.Equal(19, await azureSearchService.CountDocumentsAsync(EVENT_INDEX_NAME));
                    Assert.Equal(3, await azureSearchService.CountDocumentsAsync(FUNCTION_INDEX_NAME));
                }
                finally
                {
                    await azureSearchService.DeleteIndexAsync(EVENT_INDEX_NAME);

                    await azureSearchService.DeleteIndexAsync(FUNCTION_INDEX_NAME);
                }
            }
        }