private async void ProcessNotifications() { while (!cancel.IsCancellationRequested) { try { var evt = (NewTransactionEvent)(await session.NextEventAsync(cancel)); if (evt.TransactionData.Confirmations > 0) { WaitConfirmations(evt.TransactionData.TransactionHash); } } catch (Exception e) { Log.Error("Failed to retrieve from websocket: \n" + e.ToString()); break; } } if (!cancel.IsCancellationRequested) { await LoadOps(this.lastBlockDeposits.ToString()); } }
private async Task MonitorClientForTriggers(ExplorerClient explorerClient, CancellationToken cancellationToken) { await explorerClient.WaitServerStartedAsync(cancellationToken); WebsocketNotificationSession notificationSession = null; while (!cancellationToken.IsCancellationRequested) { try { var summary = _nbXplorerSummaryProvider.GetSummary(explorerClient.CryptoCode); if (summary?.State != NBXplorerState.Ready) { await Task.Delay(TimeSpan.FromSeconds(10), cancellationToken); continue; } notificationSession = await explorerClient.CreateWebsocketNotificationSessionAsync(cancellationToken); await notificationSession.ListenNewBlockAsync(cancellationToken); await notificationSession.ListenAllTrackedSourceAsync(false, cancellationToken); while (!cancellationToken.IsCancellationRequested) { var evt = await notificationSession.NextEventAsync(cancellationToken); var factory = _derivationStrategyFactoryProvider.GetDerivationStrategyFactory( evt.CryptoCode); switch (evt) { case NewBlockEvent newBlockEvent: await _triggerDispatcher.DispatchTrigger(new NBXplorerNewBlockTrigger() { Data = new NBXplorerNewBlockTriggerData() { CryptoCode = evt.CryptoCode, Event = newBlockEvent } }); //we need to trigger transaction events for previous unconfirmed txs so that they are checked again and trigger respective actions var recipes = await _recipeManager.GetRecipes(new RecipesQuery() { Enabled = true, TriggerId = NBXplorerNewTransactionTrigger.Id }); foreach (var recipe in recipes) { var triggerParameters = recipe.RecipeTrigger.Get <NBXplorerNewTransactionTriggerParameters>(); if (triggerParameters.Transactions == null || !triggerParameters.Transactions.Any()) { continue; } var tasks = triggerParameters.Transactions.Select(result => (result, explorerClient.GetTransactionAsync(result.TransactionHash, cancellationToken))); await Task.WhenAll(tasks.Select(tuple => tuple.Item2)); foreach (var tx in tasks) { if (tx.Item1.Confirmations != tx.Item2.Result.Confirmations) { var walletService = new NBXplorerWalletService( recipe.RecipeTrigger.ExternalService, _nbXplorerPublicWalletProvider, _derivationSchemeParser, _derivationStrategyFactoryProvider, _nbXplorerClientProvider); await _triggerDispatcher.DispatchTrigger( new NBXplorerNewTransactionTrigger(explorerClient) { Data = new NBXplorerNewTransactionTriggerData() { CryptoCode = evt.CryptoCode, Event = new NewTransactionEvent() { CryptoCode = evt.CryptoCode, BlockId = newBlockEvent.Hash, TransactionData = tx.Item2.Result, TrackedSource = await walletService.ConstructTrackedSource() } } }); } } } break; case NewTransactionEvent newTransactionEvent: { await _triggerDispatcher.DispatchTrigger( new NBXplorerNewTransactionTrigger(explorerClient) { Data = new NBXplorerNewTransactionTriggerData() { CryptoCode = evt.CryptoCode, Event = newTransactionEvent } }); break; } case UnknownEvent unknownEvent: _logger.LogWarning( $"Received unknown message from NBXplorer ({unknownEvent.CryptoCode}), ID: {unknownEvent.EventId}"); break; } } } catch when(cancellationToken.IsCancellationRequested) { }