public async Task <ActionResult> Broadcast(
            [FromBody] BroadcastTransactionRequest request)
        {
            var broadcastResult = await _transactionService.BroadcastTransactionAsync
                                  (
                transactionId : request.OperationId,
                signedTxData : request.SignedTransaction
                                  );

            if (broadcastResult is BroadcastTransactionResult.TransactionHash)
            {
                return(Ok());
            }
            else if (broadcastResult is BroadcastTransactionResult.Error error)
            {
                switch (error.Type)
                {
                case BroadcastTransactionError.AmountIsTooSmall:
                    return(BadRequest(
                               BlockchainErrorResponse.FromKnownError(
                                   BlockchainErrorCode.AmountIsTooSmall)));

                case BroadcastTransactionError.BalanceIsNotEnough:
                    return(BadRequest(
                               BlockchainErrorResponse.FromKnownError(
                                   BlockchainErrorCode.NotEnoughBalance)));

                case BroadcastTransactionError.TransactionHasBeenBroadcasted:
                    return(Conflict(
                               BlockchainErrorResponse.FromUnknownError
                                   ($"Transaction with specified id [{request.OperationId}] has already been broadcasted.")));

                case BroadcastTransactionError.TransactionHasBeenDeleted:
                    return(Conflict(
                               BlockchainErrorResponse.FromUnknownError
                                   ($"Transaction with specified id [{request.OperationId}] has already been deleted.")));

                case BroadcastTransactionError.TransactionShouldBeRebuilt:
                    return(BadRequest(
                               BlockchainErrorResponse.FromKnownError(
                                   BlockchainErrorCode.BuildingShouldBeRepeated)));

                case BroadcastTransactionError.OperationHasNotBeenFound:
                    return(NoContent());

                default:
                    throw new ArgumentOutOfRangeException();
                }
            }
            else
            {
                throw new NotSupportedException(
                          $"{nameof(_transactionService.BroadcastTransactionAsync)} returned unsupported result.");
            }
        }
        public async Task <IActionResult> Broadcast([FromBody] BroadcastTransactionRequest request)
        {
            try
            {
                await _transactionBroadcaster.BroadcastAsync(request);
            }
            catch (TransactionBroadcastingException ex)
            {
                var errorResponse = BlockchainErrorResponse.CreateFromCode(ex.Error, ex.Message);

                return(BadRequest(errorResponse));
            }

            return(Ok());
        }
Exemplo n.º 3
0
        private bool SetBalanceWIthManyOutputs(List <WalletCreationResponse> wallets)
        {
            var run = blockchainApi.Capabilities.GetCapabilities().GetResponseObject().AreManyOutputsSupported;

            if (run == null || !run.Value)
            {
                return(false);
            }

            List <TransactionOutputContract> transactions = new List <TransactionOutputContract>();

            wallets.ForEach(w => transactions.Add(new TransactionOutputContract()
            {
                Amount = AMOUT_WITH_FEE, ToAddress = w.PublicAddress
            }));
            var request = new BuildTransactionWithManyOutputsRequest()
            {
                AssetId     = ASSET_ID,
                OperationId = Guid.NewGuid(),
                FromAddress = EXTERNAL_WALLET,
                Outputs     = transactions
            };

            wallets.ForEach(w =>
                            blockchainApi.Balances.PostBalances(w.PublicAddress));

            var response = blockchainApi.Operations.PostTransactionsManyOutputs(request);

            response.Validate.StatusCode(HttpStatusCode.OK);

            var signResponse = blockchainSign.PostSign(new SignRequest()
            {
                TransactionContext = response.GetResponseObject().TransactionContext, PrivateKeys = new List <string>()
                {
                    EXTERNAL_WALLET_KEY
                }
            });

            var broadcastRequset = new BroadcastTransactionRequest()
            {
                OperationId = request.OperationId, SignedTransaction = signResponse.GetResponseObject().SignedTransaction
            };
            var broadcatedResponse = blockchainApi.Operations.PostTransactionsBroadcast(broadcastRequset);

            WaitForBalance(wallets[0].PublicAddress);

            return(true);
        }
Exemplo n.º 4
0
        public async Task BroadcastAsync(BroadcastTransactionRequest request)
        {
            // TODO: broadcast transaction
            //
            // Throw:
            // - Lykke.Bil2.Contract.Common.Exceptions.RequestValidationException:
            //     if a transaction can’t be broadcasted with the given parameters.
            //     It should be guaranteed that the transaction is not included and will not be
            //     included to the any blockchain block.
            //
            // - Lykke.Bil2.Sdk.TransactionsExecutor.Exceptions.TransactionBroadcastingException:
            //     if a transaction cannot be broadcasted and the reason can be
            //     mapped to the Lykke.Bil2.Contract.TransactionsExecutor.TransactionBroadcastingError.
            //     It should be guaranteed that the transaction is not included and will not be
            //     included to the any blockchain block.
            //
            // - System.Exception:
            //     if there are any other errors.
            //     It can be thrown without guarantee that transaction was broadcasted to the
            //     blockchain or not. Request will be not retried automatically.
            //
            // For example
            //
            // SignedTransaction signed;
            //
            // try
            // {
            //     signed = JsonConvert.DeserializeObject<SignedTransaction>(request.SignedTransaction.DecodeToString());
            // }
            // catch (JsonException ex)
            // {
            //     throw new RequestValidationException("Failed to deserialize signed transaction", request.SignedTransaction, ex, nameof(request.SignedTransaction));
            // }
            //
            // var result = await BcnApi.Send(signed);
            //
            // switch (result)
            // {
            //     case 100:
            //         throw new TransactionBroadcastingException(TransactionBroadcastingError.RebuildRequired, "Transaction expired");
            //
            //     case 200:
            //         throw new TransactionBroadcastingException(TransactionBroadcastingError.RetryLater, "Node is busy");
            // }


            throw new System.NotImplementedException();
        }
        public async Task <IActionResult> Broadcast([FromBody] BroadcastTransactionRequest request)
        {
            try
            {
                // Broadcast the signed transaction
                await _txBroadcastService.Broadcast(request.OperationId, request.SignedTransaction);

                Response.StatusCode = (int)HttpStatusCode.OK;
                return(Json(new { errorMessage = "" }));
            }
            catch (BusinessException ex) when(ex.Reason == ErrorReason.DuplicateRecord)
            {
                // If this operationid was already broadcast, return 409 conflict.
                return(await GenericErrorResponse(ex, request.OperationId, HttpStatusCode.Conflict));
            }
        }
Exemplo n.º 6
0
        public async Task <IActionResult> BroadcastTransaction([FromBody] BroadcastTransactionRequest request)
        {
            if (request == null)
            {
                return(BadRequest(ErrorResponse.Create("Unable to deserialize request")));
            }

            var aggregate = await _operationRepository.GetOrDefault(request.OperationId);

            if (aggregate == null)
            {
                return(BadRequest(ErrorResponse.Create($"Operation {request.OperationId} not found")));
            }

            Transaction tx;

            try
            {
                tx = TransactionSerializer.Deserialize(request.SignedTransaction).transaction;
            }
            catch (InvalidTransactionException)
            {
                return(BadRequest(ErrorResponse.Create($"{nameof(request.SignedTransaction)} is invalid")));
            }

            if (aggregate.IsBroadcasted)
            {
                return(Conflict());
            }

            try
            {
                await _transactionBroadcaster.BroadcastTransaction(tx, aggregate);
            }
            catch (TransactionAlreadyBroadcastedException)
            {
                return(Conflict());
            }

            aggregate.OnBroadcasted(DateTime.UtcNow);
            await _operationRepository.Save(aggregate);

            return(Ok());
        }
        public Task BroadcastAsync(BroadcastTransactionRequest request)
        {
            var     entropy = _random.Next(0, 100);
            dynamic signed;

            try
            {
                signed = JsonConvert.DeserializeObject <dynamic>(request.SignedTransaction.DecodeToString());
            }
            catch (JsonException ex)
            {
                throw new RequestValidationException("Failed to deserialize signed transaction", request.SignedTransaction, ex, nameof(request.SignedTransaction));
            }

            var serializedContext = new Base64String((string)signed.Context).DecodeToString();

            if (string.IsNullOrWhiteSpace(serializedContext))
            {
                throw new RequestValidationException("Context is empty in the signed transaction");
            }

            BuildTransferAmountTransactionRequest context;

            try
            {
                context = JsonConvert.DeserializeObject <BuildTransferAmountTransactionRequest>(serializedContext);
            }
            catch (JsonException ex)
            {
                throw new RequestValidationException("Failed to deserialize signed transaction context", serializedContext, ex, nameof(serializedContext));
            }

            if (context.Expiration?.AfterMoment < DateTime.UtcNow)
            {
                throw new TransactionBroadcastingException(TransactionBroadcastingError.RebuildRequired, "Transaction is expired");
            }

            if (entropy < 10)
            {
                throw new TransactionBroadcastingException(TransactionBroadcastingError.TransientFailure, "Nod is not available");
            }

            return(Task.CompletedTask);
        }
Exemplo n.º 8
0
        public async Task Broadcast_transaction()
        {
            //ARRANGE
            string signedTransaction = "signedTransaction";

            var client = PrepareClient <AppSettings>((options) =>
            {
                var aggregator = CreateMocksAndSetupFactories(options);

                options.IntegrationName = $"{nameof(TransactionExecutorClientTests)}+{nameof(Broadcast_transaction)}";
                aggregator.HealthProvider.Setup(x => x.GetDiseaseAsync()).ReturnsAsync(Disease);
                aggregator.TransactionBroadcaster.Setup(x => x.BroadcastAsync(It.IsAny <BroadcastTransactionRequest>()))
                .Returns(Task.CompletedTask);
            });

            //ACT && ASSERT
            var request = new BroadcastTransactionRequest(Base64String.Encode(signedTransaction));
            await client.BroadcastTransactionAsync(request);

            //Assume everything is ok if no exceptions here
        }
        public async Task <IActionResult> BroadcastTransaction([FromBody] BroadcastTransactionRequest request)
        {
            if (request == null)
            {
                throw new BusinessException("Unable deserialize request", ErrorCode.BadInputParameter);
            }

            try
            {
                await _broadcastService.BroadCastTransaction(request.OperationId, request.SignedTransaction);
            }
            catch (BusinessException e) when(e.Code == ErrorCode.TransactionAlreadyBroadcasted)
            {
                return(new StatusCodeResult(409));
            }
            catch (BusinessException e) when(e.Code == ErrorCode.OperationNotFound)
            {
                return(new StatusCodeResult((int)HttpStatusCode.NoContent));
            }

            return(Ok());
        }
Exemplo n.º 10
0
        public void Internal_server_error_broadcast_transaction()
        {
            //ARRANGE
            string signedTransaction = "signedTransaction";

            var client = PrepareClient <AppSettings>(options =>
            {
                var aggregator = CreateMocksAndSetupFactories(options);

                options.IntegrationName = $"{nameof(TransactionExecutorClientTests)}+{nameof(Internal_server_error_broadcast_transaction)}";
                aggregator.HealthProvider.Setup(x => x.GetDiseaseAsync()).ReturnsAsync(Disease);
                aggregator.TransactionBroadcaster.Setup(x => x.BroadcastAsync(It.IsAny <BroadcastTransactionRequest>()))
                .ThrowsAsync(new Exception("Error"));
            });

            //ACT && ASSERT
            Assert.ThrowsAsync <InternalServerErrorWebApiException>(async() =>
            {
                var request = new BroadcastTransactionRequest(Base64String.Encode(signedTransaction));
                await client.BroadcastTransactionAsync(request);
            });
        }
        public async Task <IActionResult> Broadcast([Required, FromBody] BroadcastTransactionRequest request)
        {
            if (request == null || request.OperationId.Equals(Guid.Empty))
            {
                return(BadRequest(ErrorResponse.Create("Invalid parameter").AddModelError(nameof(request.OperationId), "Must be valid guid")));
            }

            var broadcast = await _transactionService.GetTxBroadcastAsync(request.OperationId);

            if (!_transactionService.CheckSignature(request.SignedTransaction))
            {
                var errorResponse = StellarErrorResponse.Create("Wrong signature", BlockchainErrorCode.BuildingShouldBeRepeated);
                return(BadRequest(errorResponse));
            }

            if (broadcast != null)
            {
                return(new StatusCodeResult(StatusCodes.Status409Conflict));
            }
            try
            {
                await _transactionService.BroadcastTxAsync(request.OperationId, request.SignedTransaction);
            }
            catch (BusinessException ex)
            {
                // technical / unknown problem
                if (string.IsNullOrWhiteSpace(ex.ErrorCode))
                {
                    throw;
                }

                var errorResponse = StellarErrorResponse.Create(ex.Message, (BlockchainErrorCode)Enum.Parse(typeof(BlockchainErrorCode), ex.ErrorCode));
                return(BadRequest(errorResponse));
            }

            return(Ok());
        }
Exemplo n.º 12
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);
        }
Exemplo n.º 13
0
 public IResponse PostTransactionsBroadcast(BroadcastTransactionRequest model)
 {
     return(Request.Post("/transactions/broadcast").AddJsonBody(model).Build().Execute());
 }
 /// <summary>
 /// Broadcast fully signed bitcoin transaction to network
 /// </summary>
 /// <param name='operations'>
 /// The operations group for this extension method.
 /// </param>
 /// <param name='model'>
 /// </param>
 public static ApiException ApiTransactionBroadcastPost(this IBitcoinApi operations, BroadcastTransactionRequest model = default(BroadcastTransactionRequest))
 {
     return(operations.ApiTransactionBroadcastPostAsync(model).GetAwaiter().GetResult());
 }
 /// <summary>
 /// Broadcast fully signed bitcoin transaction to network
 /// </summary>
 /// <param name='operations'>
 /// The operations group for this extension method.
 /// </param>
 /// <param name='model'>
 /// </param>
 /// <param name='cancellationToken'>
 /// The cancellation token.
 /// </param>
 public static async System.Threading.Tasks.Task <ApiException> ApiTransactionBroadcastPostAsync(this IBitcoinApi operations, BroadcastTransactionRequest model = default(BroadcastTransactionRequest), System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken))
 {
     using (var _result = await operations.ApiTransactionBroadcastPostWithHttpMessagesAsync(model, null, cancellationToken).ConfigureAwait(false))
     {
         return(_result.Body);
     }
 }
 /// <summary>
 /// Broadcast fully signed bitcoin transaction to network
 /// </summary>
 /// <param name='operations'>
 /// The operations group for this extension method.
 /// </param>
 /// <param name='model'>
 /// </param>
 public static ApiException ApiTransactionBroadcastPost(this IBitcoinApi operations, BroadcastTransactionRequest model = default(BroadcastTransactionRequest))
 {
     return(System.Threading.Tasks.Task.Factory.StartNew(s => ((IBitcoinApi)s).ApiTransactionBroadcastPostAsync(model), operations, System.Threading.CancellationToken.None, System.Threading.Tasks.TaskCreationOptions.None, System.Threading.Tasks.TaskScheduler.Default).Unwrap().GetAwaiter().GetResult());
 }
        public override async Task <BroadcastTransactionResponse> BroadcastTransaction(BroadcastTransactionRequest request, ServerCallContext context)
        {
            var operation = Guid.Parse(request.OperationId);
            var res       = await _transferService.SendTransactionAsync(operation, request.BlockchainId, request.SignedTransaction);

            var response = new BroadcastTransactionResponse()
            {
                TransactionBroadcastResult = res switch
                {
                    TransactionBroadcastResult.AlreadyBroadcasted => BroadcastTransactionResponse.Types.TransactionBroadcastResult.AlreadyBroadcasted,
                    TransactionBroadcastResult.AmountIsTooSmall => BroadcastTransactionResponse.Types.TransactionBroadcastResult.AmountIsTooSmall,
                    TransactionBroadcastResult.BuildingShouldBeRepeated => BroadcastTransactionResponse.Types.TransactionBroadcastResult.BuildingShouldBeRepeated,
                    TransactionBroadcastResult.NotEnoughBalance => BroadcastTransactionResponse.Types.TransactionBroadcastResult.NotEnoughBalance,
                    TransactionBroadcastResult.Success => BroadcastTransactionResponse.Types.TransactionBroadcastResult.Success,
                }
            };

            return(response);
        }