public IActionResult GetExplorerUrl([Required] string address)
        {
            if (!_balanceService.IsAddressValid(address))
            {
                return(BadRequest(ErrorResponse.Create("Invalid parameter").AddModelError("address", "Address must be valid")));
            }

            var baseAddress = _balanceService.GetBaseAddress(address);
            var urls        = _balanceService.GetExplorerUrls(baseAddress);

            return(Ok(urls));
        }
        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
            }));
        }