public async Task BroadCastTransaction(Guid operationId, Transaction tx)
        {
            var operation = await _operationMetaRepository.Get(operationId);

            if (operation == null)
            {
                throw new BusinessException("Operation not found", ErrorCode.BadInputParameter);
            }

            if (await _operationEventRepository.Exist(operationId, OperationEventType.Broadcasted))
            {
                throw new BusinessException("Transaction already brodcasted", ErrorCode.TransactionAlreadyBroadcasted);
            }
            var hash = tx.GetHash().ToString();
            await _transactionBlobStorage.AddOrReplaceTransaction(operationId, hash, TransactionBlobType.BeforeBroadcast, tx.ToHex());

            var lastBlockHeight = await _blockChainProvider.GetLastBlockHeight();

            await _blockChainProvider.BroadCastTransaction(tx);

            await _observableOperationRepository.InsertOrReplace(ObervableOperation.Create(operation, BroadcastStatus.InProgress, hash, lastBlockHeight));

            await _unconfirmedTransactionRepository.InsertOrReplace(UnconfirmedTransaction.Create(operationId, hash));

            await _operationEventRepository.InsertIfNotExist(OperationEvent.Create(operationId, OperationEventType.Broadcasted));

            await _spentOutputRepository.InsertSpentOutputs(operationId, tx.Inputs.Select(i => new Output(i.PrevOut)));
        }
        private async Task CheckUnconfirmedTransaction(IUnconfirmedTransaction unconfirmedTransaction)
        {
            var operationMeta = await _operationMetaRepository.GetAsync(unconfirmedTransaction.OperationId);

            if (operationMeta == null)
            {
                _log.Warning(unconfirmedTransaction.ToJson(), "OperationMeta not found");

                return;
            }

            var confirmationCount = await _blockChainProvider.GetTxConfirmationCountAsync(unconfirmedTransaction.TxHash);

            var isCompleted = confirmationCount >= _confirmationsSettings.MinConfirmationsToDetectOperation;

            ;
            if (isCompleted)
            {
                //Force update balances
                var fromAddressUpdatedBalance = await operationMeta.Inputs.SelectAsync(async o => await _walletBalanceService.UpdateBtcBalanceAsync(o.Address,
                                                                                                                                                    _confirmationsSettings.MinConfirmationsToDetectOperation))
                ;

                var toAddressUpdatedBalance = await operationMeta.Outputs.SelectAsync(async o =>
                                                                                      await _walletBalanceService.UpdateBtcBalanceAsync(o.Address,
                                                                                                                                        _confirmationsSettings.MinConfirmationsToDetectOperation));


                var operationCompletedLoggingContext = new
                {
                    unconfirmedTransaction.OperationId,
                    unconfirmedTransaction.TxHash,
                    fromAddressUpdatedBalance,
                    toAddressUpdatedBalance
                };

                await _operationEventRepository.InsertIfNotExistAsync(OperationEvent.Create(
                                                                          unconfirmedTransaction.OperationId,
                                                                          OperationEventType.DetectedOnBlockChain, operationCompletedLoggingContext));

                _log.Info(operationCompletedLoggingContext.ToJson(), "Operation completed");


                await _unconfirmedTransactionRepository.DeleteIfExistAsync(unconfirmedTransaction.OperationId);
            }

            var status = isCompleted
                ? BroadcastStatus.Completed
                : BroadcastStatus.InProgress;

            var lastBlockHeight = await _blockChainProvider.GetLastBlockHeightAsync();

            await _observableOperationRepository.InsertOrReplaceAsync(ObervableOperation.Create(operationMeta, status,
                                                                                                unconfirmedTransaction.TxHash,
                                                                                                lastBlockHeight));
        }
Beispiel #3
0
        public async Task DetectUnconfirmedTransactions()
        {
            var unconfirmedTxs = await _unconfirmedTransactionRepository.GetAll();

            foreach (var unconfirmedTransaction in unconfirmedTxs)
            {
                var operationMeta = await _operationMetaRepository.Get(unconfirmedTransaction.OperationId);

                if (operationMeta == null)
                {
                    await _log.WriteWarningAsync(nameof(UpdateObservableOperations), nameof(DetectUnconfirmedTransactions),
                                                 unconfirmedTransaction.ToJson(), "OperationMeta not found");

                    continue;
                }

                var confirmationCount = await _blockChainProvider.GetTxConfirmationCount(unconfirmedTransaction.TxHash);

                var isCompleted = confirmationCount >= _confirmationsSettings.MinConfirmationsToDetectOperation;
                ;
                if (isCompleted)
                {
                    //Force update balances
                    var fromAddressUpdatedBalance = await _walletBalanceService.UpdateBalance(operationMeta.FromAddress);

                    var toAddressUpdatedBalance = await _walletBalanceService.UpdateBalance(operationMeta.ToAddress);


                    var operationCompletedLoggingContext = new
                    {
                        unconfirmedTransaction.OperationId,
                        unconfirmedTransaction.TxHash,
                        fromAddressUpdatedBalance,
                        toAddressUpdatedBalance
                    };

                    await _operationEventRepository.InsertIfNotExist(OperationEvent.Create(unconfirmedTransaction.OperationId,
                                                                                           OperationEventType.DetectedOnBlockChain, operationCompletedLoggingContext));

                    await _log.WriteInfoAsync(nameof(UpdateBalanceFunctions), nameof(DetectUnconfirmedTransactions),
                                              operationCompletedLoggingContext.ToJson(),
                                              "Operation completed");


                    await _unconfirmedTransactionRepository.DeleteIfExist(unconfirmedTransaction.OperationId);
                }

                var status = isCompleted
                    ? BroadcastStatus.Completed
                    : BroadcastStatus.InProgress;

                await _observableOperationRepository.InsertOrReplace(ObervableOperation.Create(operationMeta, status,
                                                                                               unconfirmedTransaction.TxHash));
            }
        }