public async Task BroadCastTransactionAsync(Guid operationId, Transaction tx) { var operation = await _operationMetaRepository.GetAsync(operationId); if (operation == null) { throw new BusinessException("Operation not found", ErrorCode.BadInputParameter); } if (await _operationEventRepository.ExistAsync(operationId, OperationEventType.Broadcasted)) { throw new BusinessException("Transaction already brodcasted", ErrorCode.TransactionAlreadyBroadcasted); } var hash = tx.GetHash().ToString(); await _transactionBlobStorage.AddOrReplaceTransactionAsync(operationId, hash, TransactionBlobType.BeforeBroadcast, tx.ToHex()); var lastBlockHeight = await _blockChainProvider.GetLastBlockHeightAsync(); await _blockChainProvider.BroadCastTransactionAsync(tx); await _observableOperationRepository.InsertOrReplaceAsync(ObervableOperation.Create(operation, BroadcastStatus.InProgress, hash, lastBlockHeight)); await _unconfirmedTransactionRepository.InsertOrReplaceAsync( UnconfirmedTransaction.Create(operationId, hash)); await _transactionOutputsService.CompleteTxOutputs(operationId, tx); await _operationEventRepository.InsertIfNotExistAsync(OperationEvent.Create(operationId, OperationEventType.Broadcasted)); }
public async Task <BuiltTransactionInfo> GetOrBuildTransferTransactionAsync(Guid operationId, IList <OperationInput> inputs, IList <OperationOutput> outputs, OperationType operationType, string assetId, bool includeFee) { var existingOperation = await _operationMetaRepository.GetAsync(operationId); if (existingOperation != null) { if (!OperationMetaComparer.Compare(existingOperation, inputs, outputs, assetId, includeFee)) { throw new BusinessException("Conflict in operation parameters", ErrorCode.Conflict); } return(await GetExistingTransaction(existingOperation.OperationId, existingOperation.Hash)); } IBuiltTransaction builtTransaction; switch (operationType) { case OperationType.Single: builtTransaction = await _transactionBuilder.GetTransferTransactionAsync(inputs.Single(), outputs.Single(), includeFee); break; case OperationType.ManyInputs: builtTransaction = await _transactionBuilder.GetManyInputsTransferTransactionAsync(inputs, outputs.Single(), includeFee); break; case OperationType.ManyOutputs: builtTransaction = await _transactionBuilder.GetManyOutputsTransferTransactionAsync(inputs.Single(), outputs, includeFee); break; default: throw new ArgumentOutOfRangeException(nameof(operationType)); } var builtTransactionInfo = new BuiltTransactionInfo { TransactionHex = builtTransaction.TransactionData.ToHex(), UsedCoins = builtTransaction.UsedCoins }; await _transactionOutputsService.AddInternalOutputs(operationId, builtTransaction.TransactionData.Outputs.AsCoins()); var txHash = builtTransaction.TransactionData.GetHash().ToString(); await _transactionBlobStorage.AddOrReplaceTransactionAsync(operationId, txHash, TransactionBlobType.Initial, builtTransactionInfo.ToJson(_network)); var operation = OperationMeta.Create(operationId, txHash, inputs, outputs, assetId, builtTransaction.Fee.Satoshi, includeFee); if (await _operationMetaRepository.TryInsertAsync(operation)) { return(builtTransactionInfo); } existingOperation = await _operationMetaRepository.GetAsync(operationId); return(await GetExistingTransaction(operationId, existingOperation.Hash)); }