public async Task <IActionResult> BuildSingle([Required, FromBody] BuildSingleTransactionRequest request) { if (!ModelState.IsValid) { return(BadRequest()); } string xdrBase64; var build = await _transactionService.GetTxBuildAsync(request.OperationId); if (build != null) { xdrBase64 = build.XdrBase64; } else { if (!_balanceService.IsAddressValid(request.FromAddress)) { return(BadRequest(ErrorResponse.Create($"{nameof(request.FromAddress)} is not a valid"))); } if (!_balanceService.IsAddressValid(request.ToAddress)) { return(BadRequest(ErrorResponse.Create($"{nameof(request.ToAddress)} is not a valid"))); } if (request.AssetId != Asset.Stellar.Id) { return(BadRequest(ErrorResponse.Create($"{nameof(request.AssetId)} was not found"))); } Int64 amount; try { amount = Int64.Parse(request.Amount); } catch (FormatException) { // too small (e.g. 0.1) return(BadRequest(StellarErrorResponse.Create($"Amount is too small. min=1, amount={request.Amount}", BlockchainErrorCode.AmountIsTooSmall))); } var fees = await _transactionService.GetFeesAsync(); var fromAddressBalance = await _balanceService.GetAddressBalanceAsync(request.FromAddress, fees); Int64 requiredBalance; if (request.IncludeFee) { requiredBalance = amount; amount -= fees.BaseFee; } else { requiredBalance = amount + fees.BaseFee; }; var availableBalance = fromAddressBalance?.Balance ?? 0; if (requiredBalance > availableBalance) { return(BadRequest(StellarErrorResponse.Create($"Not enough balance to create transaction. required={requiredBalance}, available={availableBalance}" , BlockchainErrorCode.NotEnoughtBalance))); } xdrBase64 = await _transactionService.BuildTransactionAsync(request.OperationId, fromAddressBalance, request.ToAddress, amount); } return(Ok(new BuildTransactionResponse { TransactionContext = xdrBase64 })); }
public async Task <IActionResult> BuildSingle([Required, FromBody] BuildSingleTransactionRequest request) { if (request == null || request.OperationId.Equals(Guid.Empty)) { return(BadRequest(ErrorResponse.Create("Invalid parameter").AddModelError(nameof(request.OperationId), "Must be valid guid"))); } string xdrBase64; var broadcast = await _transactionService.GetTxBroadcastAsync(request.OperationId); if (broadcast != null) { return(new StatusCodeResult(StatusCodes.Status409Conflict)); } var build = await _transactionService.GetTxBuildAsync(request.OperationId); if (build != null) { xdrBase64 = build.XdrBase64; } else { string memo = null; if (!_balanceService.IsAddressValid(request.FromAddress, out var fromAddressHasExtension)) { return(BadRequest(ErrorResponse.Create($"{nameof(request.FromAddress)} is not a valid"))); } if (!_balanceService.IsAddressValid(request.ToAddress, out var toAddressHasExtension)) { return(BadRequest(ErrorResponse.Create($"{nameof(request.ToAddress)} is not a valid"))); } if (fromAddressHasExtension) { if (!_balanceService.IsDepositBaseAddress(request.FromAddress)) { return(BadRequest(ErrorResponse.Create($"{nameof(request.FromAddress)} is not a valid. Public address extension allowed for deposit base address only!"))); } if (!_balanceService.IsDepositBaseAddress(request.ToAddress) || toAddressHasExtension) { return(BadRequest(ErrorResponse.Create($"{nameof(request.ToAddress)} is not a valid. Only deposit base address allowed as destination, when sending from address with public address extension!"))); } memo = _balanceService.GetPublicAddressExtension(request.FromAddress); } var toBaseAddress = _balanceService.GetBaseAddress(request.ToAddress); if (toAddressHasExtension) { memo = _balanceService.GetPublicAddressExtension(request.ToAddress); } if (request.AssetId != _blockchainAssetsService.GetNativeAsset().Id) { return(BadRequest(ErrorResponse.Create($"{nameof(request.AssetId)} was not found"))); } long amount; try { amount = long.Parse(request.Amount); } catch (FormatException) { // too small (e.g. 0.1) return(BadRequest(StellarErrorResponse.Create($"Amount is too small. min=1, amount={request.Amount}", BlockchainErrorCode.AmountIsTooSmall))); } var fees = new Fees(); if (!fromAddressHasExtension) { fees = await _transactionService.GetFeesAsync(); } var fromAddressBalance = await _balanceService.GetAddressBalanceAsync(request.FromAddress, fees); long requiredBalance; if (request.IncludeFee) { requiredBalance = amount; amount -= fees.BaseFee; } else { requiredBalance = amount + fees.BaseFee; } var availableBalance = fromAddressBalance.Balance; if (requiredBalance > availableBalance) { return(BadRequest(StellarErrorResponse.Create($"Not enough balance to create transaction. required={requiredBalance}, available={availableBalance}", BlockchainErrorCode.NotEnoughBalance))); } xdrBase64 = await _transactionService.BuildTransactionAsync(request.OperationId, fromAddressBalance, toBaseAddress, memo, amount); } return(Ok(new BuildTransactionResponse { TransactionContext = xdrBase64 })); }