public IActionResult EstimateOfflineColdStakingSetupFee([FromBody] SetupOfflineColdStakingRequest request)
        {
            Guard.NotNull(request, nameof(request));

            // Checks the request is valid.
            if (!this.ModelState.IsValid)
            {
                this.logger.LogTrace("(-)[MODEL_STATE_INVALID]");
                return(ModelStateErrors.BuildErrorResponse(this.ModelState));
            }

            try
            {
                Money amount = Money.Parse(request.Amount);

                Money estimatedFee = this.ColdStakingManager.EstimateSetupTransactionFee(
                    this.walletTransactionHandler,
                    request.ColdWalletAddress,
                    request.HotWalletAddress,
                    request.WalletName,
                    request.WalletAccount,
                    null,
                    amount,
                    request.SubtractFeeFromAmount,
                    true,
                    request.SegwitChangeAddress,
                    request.SplitCount);

                this.logger.LogTrace("(-):'{0}'", estimatedFee);
                return(this.Json(estimatedFee));
            }
            catch (Exception e)
            {
                this.logger.LogError("Exception occurred: {0}", e.ToString());
                this.logger.LogTrace("(-)[ERROR]");
                return(ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, e.Message, e.ToString()));
            }
        }
        public IActionResult SetupOfflineColdStaking([FromBody] SetupOfflineColdStakingRequest request)
        {
            Guard.NotNull(request, nameof(request));

            // Checks the request is valid.
            if (!this.ModelState.IsValid)
            {
                this.logger.LogTrace("(-)[MODEL_STATE_INVALID]");
                return(ModelStateErrors.BuildErrorResponse(this.ModelState));
            }

            try
            {
                Money amount    = Money.Parse(request.Amount);
                Money feeAmount = Money.Parse(request.Fees);

                (Transaction transaction, TransactionBuildContext context) = this.ColdStakingManager.GetColdStakingSetupTransaction(
                    this.walletTransactionHandler,
                    request.ColdWalletAddress,
                    request.HotWalletAddress,
                    request.WalletName,
                    request.WalletAccount,
                    null,
                    amount,
                    feeAmount,
                    request.SubtractFeeFromAmount,
                    true,
                    request.SplitCount,
                    request.SegwitChangeAddress);

                // TODO: We use the same code in the regular wallet for offline signing request construction, perhaps it should be moved to a common method
                // Need to be able to look up the keypath for the UTXOs that were used.
                IEnumerable <UnspentOutputReference> spendableTransactions = this.ColdStakingManager.GetSpendableTransactionsInAccount(
                    new WalletAccountReference(request.WalletName, request.WalletAccount)).ToList();

                var utxos     = new List <UtxoDescriptor>();
                var addresses = new List <AddressDescriptor>();
                foreach (ICoin coin in context.TransactionBuilder.FindSpentCoins(transaction))
                {
                    utxos.Add(new UtxoDescriptor()
                    {
                        Amount        = coin.TxOut.Value.ToUnit(MoneyUnit.BTC).ToString(),
                        TransactionId = coin.Outpoint.Hash.ToString(),
                        Index         = coin.Outpoint.N.ToString(),
                        ScriptPubKey  = coin.TxOut.ScriptPubKey.ToHex()
                    });

                    UnspentOutputReference outputReference = spendableTransactions.FirstOrDefault(u => u.Transaction.Id == coin.Outpoint.Hash && u.Transaction.Index == coin.Outpoint.N);

                    if (outputReference != null)
                    {
                        bool segwit = outputReference.Transaction.ScriptPubKey.IsScriptType(ScriptType.P2WPKH);
                        addresses.Add(new AddressDescriptor()
                        {
                            Address = segwit ? outputReference.Address.Bech32Address : outputReference.Address.Address, AddressType = segwit ? "p2wpkh" : "p2pkh", KeyPath = outputReference.Address.HdPath
                        });
                    }
                }

                // Return transaction hex, UTXO list, address list. The offline signer will infer from the transaction structure that a cold staking setup is being made.
                var model = new BuildOfflineSignResponse()
                {
                    WalletName          = request.WalletName,
                    WalletAccount       = request.WalletAccount,
                    Fee                 = context.TransactionFee.ToUnit(MoneyUnit.BTC).ToString(),
                    UnsignedTransaction = transaction.ToHex(),
                    Utxos               = utxos,
                    Addresses           = addresses
                };

                this.logger.LogTrace("(-):'{0}'", model);
                return(this.Json(model));
            }
            catch (Exception e)
            {
                this.logger.LogError("Exception occurred: {0}", e.ToString());
                this.logger.LogTrace("(-)[ERROR]");
                return(ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, e.Message, e.ToString()));
            }
        }