Ejemplo n.º 1
0
        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));
        }
Ejemplo n.º 2
0
        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));
        }