コード例 #1
0
        public IActionResult GetTransactionFeeEstimate([FromQuery] TxFeeEstimateRequest request)
        {
            Guard.NotNull(request, nameof(request));

            // checks the request is valid
            if (!this.ModelState.IsValid)
            {
                return(BuildErrorResponse(this.ModelState));
            }

            try
            {
                var destination = BitcoinAddress.Create(request.DestinationAddress, this.network).ScriptPubKey;
                var context     = new TransactionBuildContext(
                    new WalletAccountReference(request.WalletName, request.AccountName),
                    new[] { new Recipient {
                                Amount = request.Amount, ScriptPubKey = destination
                            } }.ToList())
                {
                    FeeType          = FeeParser.Parse(request.FeeType),
                    MinConfirmations = request.AllowUnconfirmed ? 0 : 1,
                };

                return(this.Json(this.walletTransactionHandler.EstimateFee(context)));
            }
            catch (Exception e)
            {
                this.logger.LogError("Exception occurred: {0}", e.ToString());
                return(ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, e.Message, e.ToString()));
            }
        }
コード例 #2
0
        public IActionResult BuildTransaction([FromBody] BuildTransactionRequest request)
        {
            Guard.NotNull(request, nameof(request));

            // checks the request is valid
            if (!this.ModelState.IsValid)
            {
                return(ModelStateErrors.BuildErrorResponse(this.ModelState));
            }

            try
            {
                Script destination = BitcoinAddress.Create(request.DestinationAddress, this.network).ScriptPubKey;
                var    context     = new TransactionBuildContext(this.network)
                {
                    AccountReference = new WalletAccountReference(request.WalletName, request.AccountName),
                    TransactionFee   = string.IsNullOrEmpty(request.FeeAmount) ? null : Money.Parse(request.FeeAmount),
                    MinConfirmations = request.AllowUnconfirmed ? 0 : 1,
                    Shuffle          = request.ShuffleOutputs ?? true, // We shuffle transaction outputs by default as it's better for anonymity.
                    OpReturnData     = request.OpReturnData,
                    WalletPassword   = request.Password,
                    Recipients       = new[] { new Recipient {
                                                   Amount = request.Amount, ScriptPubKey = destination
                                               } }.ToList()
                };

                context.SingleChangeAddress = request.SingleChangeAddress;

                if (!string.IsNullOrEmpty(request.FeeType))
                {
                    context.FeeType = FeeParser.Parse(request.FeeType);
                }

                Transaction transactionResult = this.walletTransactionHandler.BuildTransaction(context);

                var model = new WalletBuildTransactionModel
                {
                    Hex           = transactionResult.ToHex(),
                    Fee           = context.TransactionFee,
                    TransactionId = transactionResult.GetHash()
                };

                return(this.Json(model));
            }
            catch (Exception e)
            {
                this.logger.LogError("Exception occurred: {0}", e.ToString());
                return(ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, e.Message, e.ToString()));
            }
        }
コード例 #3
0
        public IActionResult BuildTransaction([FromBody] BuildTransactionRequest request)
        {
            Guard.NotNull(request, nameof(request));

            // checks the request is valid
            if (!this.ModelState.IsValid)
            {
                var errors = this.ModelState.Values.SelectMany(e => e.Errors.Select(m => m.ErrorMessage));
                return(ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, "Formatting error", string.Join(Environment.NewLine, errors)));
            }
            var destination = BitcoinAddress.Create(request.DestinationAddress, this.network).ScriptPubKey;

            try
            {
                var context = new TransactionBuildContext(
                    new WalletAccountReference(request.WalletName, request.AccountName),
                    new[] { new Recipient {
                                Amount = request.Amount, ScriptPubKey = destination
                            } }.ToList(),
                    request.Password)
                {
                    FeeType          = FeeParser.Parse(request.FeeType),
                    MinConfirmations = request.AllowUnconfirmed ? 0 : 1,
                    Shuffle          = true
                };

                var transactionResult = this.walletTransactionHandler.BuildTransaction(context);

                var model = new WalletBuildTransactionModel
                {
                    Hex           = transactionResult.ToHex(),
                    Fee           = context.TransactionFee,
                    TransactionId = transactionResult.GetHash()
                };

                return(this.Json(model));
            }
            catch (Exception e)
            {
                this.logger.LogError("Exception occurred: {0}", e.ToString());
                return(ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, e.Message, e.ToString()));
            }
        }
コード例 #4
0
        public IActionResult GetMaximumSpendableBalance([FromQuery] WalletMaximumBalanceRequest request)
        {
            Guard.NotNull(request, nameof(request));

            // Checks the request is valid.
            if (!this.ModelState.IsValid)
            {
                return(BuildErrorResponse(this.ModelState));
            }

            try
            {
                var transactionResult = this.walletTransactionHandler.GetMaximumSpendableAmount(new WalletAccountReference(request.WalletName, request.AccountName), FeeParser.Parse(request.FeeType), request.AllowUnconfirmed);
                return(this.Json(new MaxSpendableAmountModel
                {
                    MaxSpendableAmount = transactionResult.maximumSpendableAmount,
                    Fee = transactionResult.Fee
                }));
            }
            catch (Exception e)
            {
                this.logger.LogError("Exception occurred: {0}", e.ToString());
                return(ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, e.Message, e.ToString()));
            }
        }
コード例 #5
0
        public EstimateFeeResult EstimateFee(ScTxFeeEstimateRequest request)
        {
            Features.Wallet.Wallet wallet = this.walletManager.GetWallet(request.WalletName);

            HdAccount account = wallet.GetAccount(request.AccountName);

            if (account == null)
            {
                return(EstimateFeeResult.Failure(AccountNotInWalletError, $"No account with the name '{request.AccountName}' could be found."));
            }

            HdAddress senderAddress = account.GetCombinedAddresses().FirstOrDefault(x => x.Address == request.Sender);

            if (senderAddress == null)
            {
                return(EstimateFeeResult.Failure(SenderNotInWalletError, $"The given address {request.Sender} was not found in the wallet."));
            }

            if (!this.CheckBalance(senderAddress.Address))
            {
                return(EstimateFeeResult.Failure(InsufficientBalanceError, SenderNoBalanceError));
            }

            List <OutPoint> selectedInputs = this.SelectInputs(request.WalletName, request.Sender, request.Outpoints);

            if (!selectedInputs.Any())
            {
                return(EstimateFeeResult.Failure(InvalidOutpointsError, "Invalid list of request outpoints have been passed to the method. Please ensure that the outpoints are spendable by the sender address."));
            }

            var recipients = new List <Recipient>();

            foreach (RecipientModel recipientModel in request.Recipients)
            {
                BitcoinAddress bitcoinAddress = BitcoinAddress.Create(recipientModel.DestinationAddress, this.network);

                // If it's a potential SC address, check if it's a contract.
                if (bitcoinAddress is BitcoinPubKeyAddress bitcoinPubKeyAddress)
                {
                    var address = new uint160(bitcoinPubKeyAddress.Hash.ToBytes());

                    if (this.stateRoot.IsExist(address))
                    {
                        return(EstimateFeeResult.Failure(TransferFundsToContractError,
                                                         $"The recipient address {recipientModel.DestinationAddress} is a contract. Transferring funds directly to a contract is not supported."));
                    }
                }

                recipients.Add(new Recipient
                {
                    ScriptPubKey = bitcoinAddress.ScriptPubKey,
                    Amount       = recipientModel.Amount
                });
            }

            // Build context
            var context = new TransactionBuildContext(this.network)
            {
                AccountReference = new WalletAccountReference(request.WalletName, request.AccountName),
                MinConfirmations = MinConfirmationsAllChecks,
                Shuffle          = false,
                OpReturnData     = request.OpReturnData,
                OpReturnAmount   = string.IsNullOrEmpty(request.OpReturnAmount) ? null : Money.Parse(request.OpReturnAmount),
                SelectedInputs   = selectedInputs,
                AllowOtherInputs = false,
                Recipients       = recipients,
                ChangeAddress    = senderAddress,

                // Unique for fee estimation
                TransactionFee = null,
                FeeType        = FeeParser.Parse(request.FeeType),
                Sign           = false,
            };

            Money fee = this.walletTransactionHandler.EstimateFee(context);

            return(EstimateFeeResult.Success(fee));
        }
コード例 #6
0
        public IActionResult BuildTransaction([FromBody] BuildTransactionRequest request)
        {
            Guard.NotNull(request, nameof(request));

            // checks the request is valid
            if (!this.ModelState.IsValid)
            {
                var errors = this.ModelState.Values.SelectMany(e => e.Errors.Select(m => m.ErrorMessage));
                return(ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, "Formatting error", string.Join(Environment.NewLine, errors)));
            }
            var destination = BitcoinAddress.Create(request.DestinationAddress, this.network).ScriptPubKey;

            try
            {
                var transactionResult = this.walletManager.BuildTransaction(new WalletAccountReference(request.WalletName, request.AccountName), request.Password, destination, request.Amount, FeeParser.Parse(request.FeeType), request.AllowUnconfirmed ? 0 : 1);
                var model             = new WalletBuildTransactionModel
                {
                    Hex           = transactionResult.hex,
                    Fee           = transactionResult.fee,
                    TransactionId = transactionResult.transactionId
                };
                return(this.Json(model));
            }
            catch (Exception e)
            {
                return(ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, e.Message, e.ToString()));
            }
        }
コード例 #7
0
        public IActionResult GetMaximumSpendableBalance([FromQuery] WalletMaximumBalanceRequest request)
        {
            Guard.NotNull(request, nameof(request));

            // Checks the request is valid.
            if (!this.ModelState.IsValid)
            {
                var errors = this.ModelState.Values.SelectMany(e => e.Errors.Select(m => m.ErrorMessage));
                return(ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, "Formatting error", string.Join(Environment.NewLine, errors)));
            }

            try
            {
                var transactionResult = this.walletTransactionHandler.GetMaximumSpendableAmount(new WalletAccountReference(request.WalletName, request.AccountName), FeeParser.Parse(request.FeeType), request.AllowUnconfirmed);
                return(this.Json(new MaxSpendableAmountModel
                {
                    MaxSpendableAmount = transactionResult.maximumSpendableAmount,
                    Fee = transactionResult.Fee
                }));
            }
            catch (Exception e)
            {
                return(ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, e.Message, e.ToString()));
            }
        }