public async Task <decimal?> UpdateBalance(string address) { if (await _observableWalletRepository.Get(address) != null) { var lastBlock = await _blockchainProvider.GetHeightAsync(); var unspentOutputs = (await _transactionOutputsService.GetUnspentOutputsAsync(address)) .ToList(); var blockHeightFromTxHash = new ConcurrentDictionary <UInt256, (string txHash, int blockHeight, string blockHash)>(); await unspentOutputs.Select(p => p.Reference.PrevHash).Distinct() .ForEachAsyncSemaphore(8, async txHash => { var tx = await _blockchainProvider.GetTransactionOrDefaultAsync(txHash.ToString().Substring(2)); if (tx == null) { throw new InvalidOperationException($"Unable to find transaction with hash {txHash}"); } blockHeightFromTxHash.TryAdd(txHash, tx.Value); }); var validatedUnspentOutputs = unspentOutputs .Where(p => { var tx = blockHeightFromTxHash[p.Reference.PrevHash]; if (tx.blockHash == null) // unconfirmed tx { return(false); } return(tx.blockHeight <= lastBlock); }).ToList(); var neoBalance = (decimal)validatedUnspentOutputs .Where(p => p.Output.AssetId == Utils.NeoToken) .Sum(p => p.Output.Value); var gasBalance = (decimal)validatedUnspentOutputs .Where(p => p.Output.AssetId == Utils.GasToken) .Sum(p => p.Output.Value); await Task.WhenAll(UpdateBalanceInRepo(lastBlock, address, neoBalance, Constants.Assets.Neo.AssetId), UpdateBalanceInRepo(lastBlock, address, gasBalance, Constants.Assets.Gas.AssetId));; } return(null); }
private async Task CheckTransaction(IUnconfirmedTransaction unconfirmedTx) { var operation = await _operationRepository.GetOrDefault(unconfirmedTx.OperationId); if (operation == null) { _log.Error(nameof(DetectTransactionsPeriodicalHandler), message: $"Aggregate for operation {unconfirmedTx.OperationId} not found"); return; } var blockchainTx = await _blockchainProvider.GetTransactionOrDefaultAsync(unconfirmedTx.TxHash); var isCompleted = blockchainTx?.blockHash != null; //once a tx included in a block means the tx is confirmed by the 7 consensus nodes and cannt be reversed var lastBlockHeight = await _blockchainProvider.GetHeightAsync(); var status = isCompleted ? BroadcastStatus.Completed : BroadcastStatus.InProgress; await _observableOperationRepository.InsertOrReplace(ObervableOperation.Create(operation, status, unconfirmedTx.TxHash, lastBlockHeight)); if (isCompleted) { var fromAddressBalance = await _walletBalanceService.UpdateBalance(operation.FromAddress); var toAddressBalance = await _walletBalanceService.UpdateBalance(operation.ToAddress); var operationCompletedLoggingContext = new { unconfirmedTx.OperationId, unconfirmedTx.TxHash, fromAddressBalance, toAddressBalance }; _log.Info("Transaction detected on blockchain", context: operationCompletedLoggingContext); await _unconfirmedTransactionRepository.DeleteIfExist(unconfirmedTx.OperationId); operation.OnDetectedOnBlockcain(DateTime.UtcNow); await _operationRepository.Save(operation); } }