public async Task <BuiltTransactionInfo> GetOrBuildTransferTransaction(Guid operationId, BitcoinAddress fromAddress, PubKey fromAddressPubkey, BitcoinAddress toAddress, string assetId, Money amountToSend, bool includeFee) { var existingOperation = await _operationMetaRepository.Get(operationId); if (existingOperation != null) { var existingAmount = existingOperation.IncludeFee ? existingOperation.AmountSatoshi + existingOperation.FeeSatoshi : existingOperation.AmountSatoshi; if (existingOperation.FromAddress != fromAddress.ToString() || existingOperation.ToAddress != toAddress.ToString() || existingOperation.AssetId != assetId || existingOperation.IncludeFee != includeFee || existingAmount != amountToSend.Satoshi) { throw new BusinessException("Conflict in operation parameters", ErrorCode.Conflict); } return(await GetExistingTransaction(existingOperation.OperationId, existingOperation.Hash)); } var builtTransaction = await _transactionBuilder.GetTransferTransaction(fromAddress, fromAddressPubkey, toAddress, amountToSend, includeFee); var builtTransactionInfo = new BuiltTransactionInfo { TransactionHex = builtTransaction.TransactionData.ToHex(), UsedCoins = builtTransaction.UsedCoins }; var txHash = builtTransaction.TransactionData.GetHash().ToString(); await _transactionBlobStorage.AddOrReplaceTransaction(operationId, txHash, TransactionBlobType.Initial, builtTransactionInfo.ToJson(_network)); var operation = OperationMeta.Create(operationId, txHash, fromAddress.ToString(), toAddress.ToString(), assetId, builtTransaction.Amount.Satoshi, builtTransaction.Fee.Satoshi, includeFee); if (await _operationMetaRepository.TryInsert(operation)) { return(builtTransactionInfo); } existingOperation = await _operationMetaRepository.Get(operationId); return(await GetExistingTransaction(operationId, existingOperation.Hash)); }
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)); }