コード例 #1
0
        public async Task <string> GetOrBuildTransferTransaction(Guid operationId,
                                                                 BitcoinAddress fromAddress,
                                                                 PubKey fromAddressPubkey,
                                                                 BitcoinAddress toAddress,
                                                                 string assetId,
                                                                 Money amountToSend,
                                                                 bool includeFee)
        {
            if (await _operationMetaRepository.Exist(operationId))
            {
                return(await _transactionBlobStorage.GetTransaction(operationId, TransactionBlobType.Initial));
            }

            var buildedTransaction = await _transactionBuilder.GetTransferTransaction(fromAddress, fromAddressPubkey, toAddress, amountToSend, includeFee);

            var transactionContext =
                Serializer.ToString((tx: buildedTransaction.TransactionData, spentCoins: buildedTransaction.SpentCoins));

            await _transactionBlobStorage.AddOrReplaceTransaction(operationId,
                                                                  TransactionBlobType.Initial,
                                                                  transactionContext);

            var operation = OperationMeta.Create(operationId, fromAddress.ToString(), toAddress.ToString(), assetId,
                                                 buildedTransaction.Amount.Satoshi, buildedTransaction.Fee.Satoshi, includeFee);
            await _operationMetaRepository.Insert(operation);

            return(transactionContext);
        }
コード例 #2
0
        public async Task <Transaction> GetOrBuildTransferTransaction(Guid operationId,
                                                                      BitcoinAddress fromAddress,
                                                                      PubKey fromAddressPubkey,
                                                                      BitcoinAddress toAddress,
                                                                      string assetId,
                                                                      Money amountToSend,
                                                                      bool includeFee)
        {
            if (await _operationMetaRepository.Exist(operationId))
            {
                var alreadyBuildedTransaction = await _transactionBlobStorage.GetTransaction(operationId, TransactionBlobType.Initial);

                return(Transaction.Parse(alreadyBuildedTransaction));
            }

            var buildedTransaction = await _transactionBuilder.GetTransferTransaction(fromAddress, fromAddressPubkey, toAddress, amountToSend, includeFee);

            await _transactionBlobStorage.AddOrReplaceTransaction(operationId, TransactionBlobType.Initial,
                                                                  buildedTransaction.TransactionData.ToHex());

            var operation = OperationMeta.Create(operationId, fromAddress.ToString(), toAddress.ToString(), assetId,
                                                 buildedTransaction.Amount.Satoshi, buildedTransaction.Fee.Satoshi, includeFee);
            await _operationMetaRepository.Insert(operation);

            return(buildedTransaction.TransactionData);
        }
コード例 #3
0
        public async Task BroadcastTransaction(BroadcastingTransaction transaction, QueueTriggeringContext context)
        {
            try
            {
                var signedByClientTr = await _transactionBlobStorage.GetTransaction(transaction.TransactionId, TransactionBlobType.Initial);

                var signedByExchangeTr = await _exchangeSignatureApi.SignTransaction(signedByClientTr);

                if (!await _settingsRepository.Get(Constants.CanBeBroadcastedSetting, true))
                {
                    await _transactionBlobStorage.AddOrReplaceTransaction(transaction.TransactionId, TransactionBlobType.Signed, signedByExchangeTr);

                    context.MoveMessageToPoison(transaction.ToJson());
                    return;
                }

                var tr = new Transaction(signedByExchangeTr);
                await _broadcastService.BroadcastTransaction(transaction.TransactionId, tr);

                if (transaction.TransactionCommandType == TransactionCommandType.SegwitTransferToHotwallet)
                {
                    _cqrsEngine.PublishEvent(new CashinCompletedEvent {
                        OperationId = transaction.TransactionId, TxHash = tr.GetHash().ToString()
                    }, BitcoinBoundedContext.Name);
                }

                if (transaction.TransactionCommandType == TransactionCommandType.Transfer)
                {
                    _cqrsEngine.PublishEvent(new CashoutCompletedEvent {
                        OperationId = transaction.TransactionId, TxHash = tr.GetHash().ToString()
                    }, BitcoinBoundedContext.Name);
                }
            }
            catch (RPCException e)
            {
                if (e.Message != transaction.LastError)
                {
                    await _logger.WriteWarningAsync("BroadcastingTransactionFunction", "BroadcastTransaction", $"Id: [{transaction.TransactionId}]", $"Message: {e.Message} Code:{e.RPCCode} CodeMessage:{e.RPCCodeMessage}");
                }

                transaction.LastError = e.Message;

                var unacceptableTx = _unacceptableTxErrors.Any(o => e.Message.Contains(o));

                if (transaction.DequeueCount >= _settings.MaxDequeueCount || unacceptableTx)
                {
                    context.MoveMessageToPoison();
                }
                else
                {
                    transaction.DequeueCount++;
                    context.MoveMessageToEnd(transaction.ToJson());
                    context.SetCountQueueBasedDelay(_settings.MaxQueueDelay, 200);
                }
            }
        }
コード例 #4
0
        public async Task Monitor(FeeReserveMonitoringMessage message, QueueTriggeringContext context)
        {
            if (await _broadcastedTransactionBlob.IsBroadcasted(message.TransactionId))
            {
                return;
            }

            if (DateTime.UtcNow - message.PutDateTime > TimeSpan.FromSeconds(_settings.FeeReservePeriodSeconds))
            {
                await _logger.WriteInfoAsync("FeeReserveMonitoringFunction", "Monitor", message.ToJson(), "Free reserved fee");

                await _transactionSignRequestRepository.InvalidateTransactionId(message.TransactionId);

                await Task.Delay(3000);

                if (await _broadcastedTransactionBlob.IsBroadcasted(message.TransactionId))
                {
                    return;
                }

                var transaction = await _transactionBlobStorage.GetTransaction(message.TransactionId, TransactionBlobType.Initial);

                var tr = new Transaction(transaction);

                await _spentOutputService.RemoveSpentOutputs(tr);

                var queue = _pregeneratedOutputsQueueFactory.CreateFeeQueue();

                await queue.EnqueueOutputs(message.FeeCoins.Select(x => x.ToCoin()).ToArray());
            }
            else
            {
                context.MoveMessageToEnd();
                context.SetCountQueueBasedDelay(5000, 100);
            }
        }
コード例 #5
0
        public async Task Broadcast([FromBody] BroadcastTransactionRequest model)
        {
            var signRequest = await _transactionSignRequestRepository.GetSignRequest(model.TransactionId);

            if (signRequest == null)
            {
                throw new BackendException("Transaction is not found", ErrorCode.BadTransaction);
            }

            if (signRequest.Invalidated == true)
            {
                throw new BackendException("Transaction was invalidated", ErrorCode.BadTransaction);
            }

            var initialTransaction = await _transactionBlobStorage.GetTransaction(model.TransactionId, TransactionBlobType.Initial);

            if (!TransactionComparer.CompareTransactions(initialTransaction, model.Transaction))
            {
                throw new BackendException("Signed transaction is not equals to initial transaction", ErrorCode.BadTransaction);
            }

            var transaction = new Transaction(model.Transaction);

            if (transaction.Inputs.All(o => o.ScriptSig == null || o.ScriptSig.Length == 0))
            {
                throw new BackendException("Transaction is not signed by client", ErrorCode.BadTransaction);
            }

            var fullSignedHex = signRequest.DoNotSign ? model.Transaction : await _signatureApiProvider.SignTransaction(model.Transaction);

            await _transactionBlobStorage.AddOrReplaceTransaction(model.TransactionId, TransactionBlobType.Signed, fullSignedHex);

            var fullSigned = new Transaction(fullSignedHex);

            await _broadcastService.BroadcastTransaction(model.TransactionId, fullSigned, useHandlers : false, savePaidFees : !signRequest.DoNotSign);
        }
コード例 #6
0
        private async Task <BuiltTransactionInfo> GetExistingTransaction(Guid operationId, string hash)
        {
            var alreadyBuildedTransaction = await _transactionBlobStorage.GetTransaction(operationId, hash, TransactionBlobType.Initial);

            return(Serializer.ToObject <BuiltTransactionInfo>(alreadyBuildedTransaction));
        }