public async Task <IActionResult> GetHistoryFrom(
            [FromRoute] string address,
            [FromQuery] string afterHash,
            [FromQuery] int take)
        {
            if (take <= 0)
            {
                return(BadRequest(new ErrorResponse()
                {
                    ErrorMessage = $"{nameof(take)} must be greater than zero"
                }));
            }

            ValidateAddress(address);

            var addr   = _addressValidator.ParseAddress(address);
            var result = await _historyService.GetHistoryFrom(addr, afterHash, take);

            return(Ok(result.Select(ToHistoricalTransaction)));
        }
        public async Task <ActionResult> BuildSingle([FromBody] BuildSingleTransactionRequest request)
        {
            if (request == null)
            {
                throw new BusinessException("Unable deserialize request", ErrorCode.BadInputParameter);
            }

            var amountSatoshi = MoneyConversionHelper.SatoshiFromContract(request.Amount);

            if (amountSatoshi <= 0)
            {
                throw new BusinessException($"Amount can't be less or equal to zero: {amountSatoshi}", ErrorCode.BadInputParameter);
            }

            if (request.AssetId != Constants.Assets.BitcoinGold.AssetId)
            {
                throw new BusinessException("Invalid assetId", ErrorCode.BadInputParameter);
            }

            var toBitcoinAddress = _addressValidator.ParseAddress(request.ToAddress);

            if (toBitcoinAddress == null)
            {
                throw new BusinessException("Invalid ToAddress ", ErrorCode.BadInputParameter);
            }

            var fromBitcoinAddress = _addressValidator.ParseAddress(request.FromAddress);

            if (fromBitcoinAddress == null)
            {
                throw new BusinessException("Invalid FromAddress", ErrorCode.BadInputParameter);
            }

            if (request.OperationId == Guid.Empty)
            {
                throw new BusinessException("Invalid operation id (GUID)", ErrorCode.BadInputParameter);
            }


            PubKey fromAddressPubkey = null;
            var    pubKeyString      = request.FromAddressContext?.DeserializeJson <AddressContextContract>()?.PubKey;

            if (pubKeyString != null)
            {
                if (!_addressValidator.IsPubkeyValid(pubKeyString))
                {
                    throw new BusinessException("Invalid pubkey string", ErrorCode.BadInputParameter);
                }

                fromAddressPubkey = _addressValidator.GetPubkey(pubKeyString);
            }

            if (await _operationEventRepository.Exist(request.OperationId, OperationEventType.Broadcasted))
            {
                return(Conflict());
            }

            BuiltTransactionInfo tx;

            try
            {
                tx = await _operationService.GetOrBuildTransferTransaction(request.OperationId, fromBitcoinAddress, fromAddressPubkey, toBitcoinAddress,
                                                                           request.AssetId, new Money(amountSatoshi), request.IncludeFee);
            }
            catch (NotEnoughFundsException)
            {
                return(BadRequest(BlockchainErrorResponse.FromKnownError(BlockchainErrorCode.NotEnoughBalance)));
            }
            catch (BusinessException e) when(e.Code == ErrorCode.NotEnoughFundsAvailable)
            {
                return(BadRequest(BlockchainErrorResponse.FromKnownError(BlockchainErrorCode.NotEnoughBalance)));
            }


            return(Ok(new BuildTransactionResponse
            {
                TransactionContext = tx.ToJson(_network)
            }));
        }