diff --git a/src/interfaces/node.cpp b/src/interfaces/node.cpp
index 72d531ed6d..152923535d 100644
--- a/src/interfaces/node.cpp
+++ b/src/interfaces/node.cpp
@@ -1,318 +1,330 @@
 // Copyright (c) 2018 The Bitcoin Core developers
 // Distributed under the MIT software license, see the accompanying
 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 
 #include <interfaces/node.h>
 
 #include <addrdb.h>
 #include <amount.h>
 #include <chain.h>
 #include <chainparams.h>
 #include <config.h>
 #include <init.h>
 #include <interfaces/handler.h>
 #include <interfaces/wallet.h>
 #include <net.h>
 #include <net_processing.h>
 #include <netaddress.h>
 #include <netbase.h>
 #include <policy/fees.h>
 #include <policy/policy.h>
 #include <primitives/block.h>
 #include <rpc/server.h>
 #include <scheduler.h>
 #include <sync.h>
 #include <txmempool.h>
 #include <ui_interface.h>
 #include <util.h>
 #include <validation.h>
 #include <warnings.h>
 
 #if defined(HAVE_CONFIG_H)
 #include <config/bitcoin-config.h>
 #endif
 #ifdef ENABLE_WALLET
 #include <wallet/fees.h>
 #include <wallet/wallet.h>
 #define CHECK_WALLET(x) x
 #else
 #define CHECK_WALLET(x)                                                        \
     throw std::logic_error("Wallet function called in non-wallet build.")
 #endif
 
 #include <boost/thread/thread.hpp>
 #include <univalue.h>
 
 #include <atomic>
 
 class HTTPRPCRequestProcessor;
 
 namespace interfaces {
 namespace {
 
     class NodeImpl : public Node {
         void parseParameters(int argc, const char *const argv[]) override {
             gArgs.ParseParameters(argc, argv);
         }
         void readConfigFile(const std::string &conf_path) override {
             gArgs.ReadConfigFile(conf_path);
         }
         bool softSetArg(const std::string &arg,
                         const std::string &value) override {
             return gArgs.SoftSetArg(arg, value);
         }
         bool softSetBoolArg(const std::string &arg, bool value) override {
             return gArgs.SoftSetBoolArg(arg, value);
         }
         void selectParams(const std::string &network) override {
             SelectParams(network);
         }
         std::string getNetwork() override { return Params().NetworkIDString(); }
         void initLogging() override { InitLogging(); }
         void initParameterInteraction() override { InitParameterInteraction(); }
         std::string getWarnings(const std::string &type) override {
             return GetWarnings(type);
         }
         bool baseInitialize(Config &config, RPCServer &rpcServer) override {
             return AppInitBasicSetup() &&
                    AppInitParameterInteraction(config, rpcServer) &&
                    AppInitSanityChecks() && AppInitLockDataDirectory();
         }
         bool
         appInitMain(Config &config,
                     HTTPRPCRequestProcessor &httpRPCRequestProcessor) override {
             return AppInitMain(config, httpRPCRequestProcessor);
         }
         void appShutdown() override {
             Interrupt();
             Shutdown();
         }
         void startShutdown() override { StartShutdown(); }
         bool shutdownRequested() override { return ShutdownRequested(); }
         void mapPort(bool use_upnp) override {
             if (use_upnp) {
                 StartMapPort();
             } else {
                 InterruptMapPort();
                 StopMapPort();
             }
         }
         std::string helpMessage(HelpMessageMode mode) override {
             return HelpMessage(mode);
         }
         bool getProxy(Network net, proxyType &proxy_info) override {
             return GetProxy(net, proxy_info);
         }
         size_t getNodeCount(CConnman::NumConnections flags) override {
             return g_connman ? g_connman->GetNodeCount(flags) : 0;
         }
         bool getNodesStats(NodesStats &stats) override {
             stats.clear();
 
             if (g_connman) {
                 std::vector<CNodeStats> stats_temp;
                 g_connman->GetNodeStats(stats_temp);
 
                 stats.reserve(stats_temp.size());
                 for (auto &node_stats_temp : stats_temp) {
                     stats.emplace_back(std::move(node_stats_temp), false,
                                        CNodeStateStats());
                 }
 
                 // Try to retrieve the CNodeStateStats for each node.
                 TRY_LOCK(::cs_main, lockMain);
                 if (lockMain) {
                     for (auto &node_stats : stats) {
                         std::get<1>(node_stats) =
                             GetNodeStateStats(std::get<0>(node_stats).nodeid,
                                               std::get<2>(node_stats));
                     }
                 }
                 return true;
             }
             return false;
         }
         bool getBanned(banmap_t &banmap) override {
             if (g_connman) {
                 g_connman->GetBanned(banmap);
                 return true;
             }
             return false;
         }
         bool ban(const CNetAddr &net_addr, BanReason reason,
                  int64_t ban_time_offset) override {
             if (g_connman) {
                 g_connman->Ban(net_addr, reason, ban_time_offset);
                 return true;
             }
             return false;
         }
         bool unban(const CSubNet &ip) override {
             if (g_connman) {
                 g_connman->Unban(ip);
                 return true;
             }
             return false;
         }
         bool disconnect(NodeId id) override {
             if (g_connman) {
                 return g_connman->DisconnectNode(id);
             }
             return false;
         }
         int64_t getTotalBytesRecv() override {
             return g_connman ? g_connman->GetTotalBytesRecv() : 0;
         }
         int64_t getTotalBytesSent() override {
             return g_connman ? g_connman->GetTotalBytesSent() : 0;
         }
         size_t getMempoolSize() override { return g_mempool.size(); }
         size_t getMempoolDynamicUsage() override {
             return g_mempool.DynamicMemoryUsage();
         }
         bool getHeaderTip(int &height, int64_t &block_time) override {
             LOCK(::cs_main);
             if (::pindexBestHeader) {
                 height = ::pindexBestHeader->nHeight;
                 block_time = ::pindexBestHeader->GetBlockTime();
                 return true;
             }
             return false;
         }
         int getNumBlocks() override {
             LOCK(::cs_main);
             return ::chainActive.Height();
         }
         int64_t getLastBlockTime() override {
             LOCK(::cs_main);
             if (::chainActive.Tip()) {
                 return ::chainActive.Tip()->GetBlockTime();
             }
             // Genesis block's time of current network
             return Params().GenesisBlock().GetBlockTime();
         }
         double getVerificationProgress() override {
             const CBlockIndex *tip;
             {
                 LOCK(::cs_main);
                 tip = ::chainActive.Tip();
             }
             return GuessVerificationProgress(Params().TxData(), tip);
         }
         bool isInitialBlockDownload() override {
             return IsInitialBlockDownload();
         }
         bool getReindex() override { return ::fReindex; }
         bool getImporting() override { return ::fImporting; }
         void setNetworkActive(bool active) override {
             if (g_connman) {
                 g_connman->SetNetworkActive(active);
             }
         }
         bool getNetworkActive() override {
             return g_connman && g_connman->GetNetworkActive();
         }
+        Amount getMinimumFee(unsigned int tx_bytes) override {
+            Amount result;
+            CHECK_WALLET(result = GetMinimumFee(tx_bytes, g_mempool));
+            return result;
+        }
         Amount getMinimumFee(unsigned int tx_bytes,
                              const CCoinControl &coin_control) override {
             Amount result;
             CHECK_WALLET(result =
                              GetMinimumFee(tx_bytes, g_mempool, coin_control));
             return result;
         }
         Amount getMaxTxFee() override { return ::maxTxFee; }
+        CFeeRate estimateSmartFee() override { return g_mempool.estimateFee(); }
         CFeeRate getDustRelayFee() override { return ::dustRelayFee; }
+        CFeeRate getFallbackFee() override {
+            CHECK_WALLET(return CWallet::fallbackFee);
+        }
         CFeeRate getPayTxFee() override { CHECK_WALLET(return ::payTxFee); }
+        void setPayTxFee(CFeeRate rate) override {
+            CHECK_WALLET(::payTxFee = rate);
+        }
         UniValue executeRpc(Config &config, const std::string &command,
                             const UniValue &params,
                             const std::string &uri) override {
             JSONRPCRequest req;
             req.params = params;
             req.strMethod = command;
             req.URI = uri;
             return ::tableRPC.execute(config, req);
         }
         std::vector<std::string> listRpcCommands() override {
             return ::tableRPC.listCommands();
         }
         void rpcSetTimerInterfaceIfUnset(RPCTimerInterface *iface) override {
             RPCSetTimerInterfaceIfUnset(iface);
         }
         void rpcUnsetTimerInterface(RPCTimerInterface *iface) override {
             RPCUnsetTimerInterface(iface);
         }
         bool getUnspentOutput(const COutPoint &output, Coin &coin) override {
             LOCK(::cs_main);
             return ::pcoinsTip->GetCoin(output, coin);
         }
         std::vector<std::unique_ptr<Wallet>> getWallets() override {
 #ifdef ENABLE_WALLET
             std::vector<std::unique_ptr<Wallet>> wallets;
             for (CWalletRef wallet : ::vpwallets) {
                 wallets.emplace_back(MakeWallet(*wallet));
             }
             return wallets;
 #else
             throw std::logic_error(
                 "Node::getWallets() called in non-wallet build.");
 #endif
         }
         std::unique_ptr<Handler> handleInitMessage(InitMessageFn fn) override {
             return MakeHandler(::uiInterface.InitMessage.connect(fn));
         }
         std::unique_ptr<Handler> handleMessageBox(MessageBoxFn fn) override {
             return MakeHandler(::uiInterface.ThreadSafeMessageBox.connect(fn));
         }
         std::unique_ptr<Handler> handleQuestion(QuestionFn fn) override {
             return MakeHandler(::uiInterface.ThreadSafeQuestion.connect(fn));
         }
         std::unique_ptr<Handler>
         handleShowProgress(ShowProgressFn fn) override {
             return MakeHandler(::uiInterface.ShowProgress.connect(fn));
         }
         std::unique_ptr<Handler> handleLoadWallet(LoadWalletFn fn) override {
             CHECK_WALLET(return MakeHandler(::uiInterface.LoadWallet.connect(
                 [fn](CWallet *wallet) { fn(MakeWallet(*wallet)); })));
         }
         std::unique_ptr<Handler> handleNotifyNumConnectionsChanged(
             NotifyNumConnectionsChangedFn fn) override {
             return MakeHandler(
                 ::uiInterface.NotifyNumConnectionsChanged.connect(fn));
         }
         std::unique_ptr<Handler> handleNotifyNetworkActiveChanged(
             NotifyNetworkActiveChangedFn fn) override {
             return MakeHandler(
                 ::uiInterface.NotifyNetworkActiveChanged.connect(fn));
         }
         std::unique_ptr<Handler>
         handleNotifyAlertChanged(NotifyAlertChangedFn fn) override {
             return MakeHandler(::uiInterface.NotifyAlertChanged.connect(fn));
         }
         std::unique_ptr<Handler>
         handleBannedListChanged(BannedListChangedFn fn) override {
             return MakeHandler(::uiInterface.BannedListChanged.connect(fn));
         }
         std::unique_ptr<Handler>
         handleNotifyBlockTip(NotifyBlockTipFn fn) override {
             return MakeHandler(::uiInterface.NotifyBlockTip.connect(
                 [fn](bool initial_download, const CBlockIndex *block) {
                     fn(initial_download, block->nHeight, block->GetBlockTime(),
                        GuessVerificationProgress(Params().TxData(), block));
                 }));
         }
         std::unique_ptr<Handler>
         handleNotifyHeaderTip(NotifyHeaderTipFn fn) override {
             return MakeHandler(::uiInterface.NotifyHeaderTip.connect(
                 [fn](bool initial_download, const CBlockIndex *block) {
                     fn(initial_download, block->nHeight, block->GetBlockTime(),
                        GuessVerificationProgress(Params().TxData(), block));
                 }));
         }
     };
 
 } // namespace
 
 std::unique_ptr<Node> MakeNode() {
     return std::make_unique<NodeImpl>();
 }
 
 } // namespace interfaces
diff --git a/src/interfaces/node.h b/src/interfaces/node.h
index 23cd55fab6..1e4b41ab66 100644
--- a/src/interfaces/node.h
+++ b/src/interfaces/node.h
@@ -1,258 +1,270 @@
 // Copyright (c) 2018 The Bitcoin Core developers
 // Distributed under the MIT software license, see the accompanying
 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 
 #ifndef BITCOIN_INTERFACES_NODE_H
 #define BITCOIN_INTERFACES_NODE_H
 
 #include <addrdb.h>     // For banmap_t
 #include <amount.h>     // For Amount
 #include <init.h>       // For HelpMessageMode
 #include <net.h>        // For CConnman::NumConnections
 #include <netaddress.h> // For Network
 
 #include <cstddef>
 #include <cstdint>
 #include <functional>
 #include <memory>
 #include <string>
 #include <tuple>
 #include <vector>
 
 class CCoinControl;
 class CFeeRate;
 struct CNodeStateStats;
 struct CNodeStats;
 class Coin;
 class Config;
 class HTTPRPCRequestProcessor;
 class proxyType;
 class RPCServer;
 class RPCTimerInterface;
 class UniValue;
 
 namespace interfaces {
 
 class Handler;
 class Wallet;
 
 //! Top-level interface for a bitcoin node (bitcoind process).
 class Node {
 public:
     virtual ~Node() {}
 
     //! Set command line arguments.
     virtual void parseParameters(int argc, const char *const argv[]) = 0;
 
     //! Set a command line argument if it doesn't already have a value
     virtual bool softSetArg(const std::string &arg,
                             const std::string &value) = 0;
 
     //! Set a command line boolean argument if it doesn't already have a value
     virtual bool softSetBoolArg(const std::string &arg, bool value) = 0;
 
     //! Load settings from configuration file.
     virtual void readConfigFile(const std::string &conf_path) = 0;
 
     //! Choose network parameters.
     virtual void selectParams(const std::string &network) = 0;
 
     //! Get network name.
     virtual std::string getNetwork() = 0;
 
     //! Init logging.
     virtual void initLogging() = 0;
 
     //! Init parameter interaction.
     virtual void initParameterInteraction() = 0;
 
     //! Get warnings.
     virtual std::string getWarnings(const std::string &type) = 0;
 
     //! Initialize app dependencies.
     virtual bool baseInitialize(Config &config, RPCServer &rpcServer) = 0;
 
     //! Start node.
     virtual bool
     appInitMain(Config &config,
                 HTTPRPCRequestProcessor &httpRPCRequestProcessor) = 0;
 
     //! Stop node.
     virtual void appShutdown() = 0;
 
     //! Start shutdown.
     virtual void startShutdown() = 0;
 
     //! Return whether shutdown was requested.
     virtual bool shutdownRequested() = 0;
 
     //! Get help message string.
     virtual std::string helpMessage(HelpMessageMode mode) = 0;
 
     //! Map port.
     virtual void mapPort(bool use_upnp) = 0;
 
     //! Get proxy.
     virtual bool getProxy(Network net, proxyType &proxy_info) = 0;
 
     //! Get number of connections.
     virtual size_t getNodeCount(CConnman::NumConnections flags) = 0;
 
     //! Get stats for connected nodes.
     using NodesStats =
         std::vector<std::tuple<CNodeStats, bool, CNodeStateStats>>;
     virtual bool getNodesStats(NodesStats &stats) = 0;
 
     //! Get ban map entries.
     virtual bool getBanned(banmap_t &banmap) = 0;
 
     //! Ban node.
     virtual bool ban(const CNetAddr &net_addr, BanReason reason,
                      int64_t ban_time_offset) = 0;
 
     //! Unban node.
     virtual bool unban(const CSubNet &ip) = 0;
 
     //! Disconnect node.
     virtual bool disconnect(NodeId id) = 0;
 
     //! Get total bytes recv.
     virtual int64_t getTotalBytesRecv() = 0;
 
     //! Get total bytes sent.
     virtual int64_t getTotalBytesSent() = 0;
 
     //! Get mempool size.
     virtual size_t getMempoolSize() = 0;
 
     //! Get mempool dynamic usage.
     virtual size_t getMempoolDynamicUsage() = 0;
 
     //! Get header tip height and time.
     virtual bool getHeaderTip(int &height, int64_t &block_time) = 0;
 
     //! Get num blocks.
     virtual int getNumBlocks() = 0;
 
     //! Get last block time.
     virtual int64_t getLastBlockTime() = 0;
 
     //! Get verification progress.
     virtual double getVerificationProgress() = 0;
 
     //! Is initial block download.
     virtual bool isInitialBlockDownload() = 0;
 
     //! Get reindex.
     virtual bool getReindex() = 0;
 
     //! Get importing.
     virtual bool getImporting() = 0;
 
     //! Set network active.
     virtual void setNetworkActive(bool active) = 0;
 
     //! Get network active.
     virtual bool getNetworkActive() = 0;
 
     //! Get minimum fee.
+    virtual Amount getMinimumFee(unsigned int tx_bytes) = 0;
+
+    //! Get minimum fee with coin control.
     virtual Amount getMinimumFee(unsigned int tx_bytes,
                                  const CCoinControl &coin_control) = 0;
 
     //! Get max tx fee.
     virtual Amount getMaxTxFee() = 0;
 
+    //! Estimate smart fee.
+    virtual CFeeRate estimateSmartFee() = 0;
+
     //! Get dust relay fee.
     virtual CFeeRate getDustRelayFee() = 0;
 
+    //! Get fallback fee.
+    virtual CFeeRate getFallbackFee() = 0;
+
     //! Get pay tx fee.
     virtual CFeeRate getPayTxFee() = 0;
 
+    //! Set pay tx fee.
+    virtual void setPayTxFee(CFeeRate rate) = 0;
+
     //! Execute rpc command.
     virtual UniValue executeRpc(Config &config, const std::string &command,
                                 const UniValue &params,
                                 const std::string &uri) = 0;
 
     //! List rpc commands.
     virtual std::vector<std::string> listRpcCommands() = 0;
 
     //! Set RPC timer interface if unset.
     virtual void rpcSetTimerInterfaceIfUnset(RPCTimerInterface *iface) = 0;
 
     //! Unset RPC timer interface.
     virtual void rpcUnsetTimerInterface(RPCTimerInterface *iface) = 0;
 
     //! Get unspent outputs associated with a transaction.
     virtual bool getUnspentOutput(const COutPoint &output, Coin &coin) = 0;
 
     //! Return interfaces for accessing wallets (if any).
     virtual std::vector<std::unique_ptr<Wallet>> getWallets() = 0;
 
     //! Register handler for init messages.
     using InitMessageFn = std::function<void(const std::string &message)>;
     virtual std::unique_ptr<Handler> handleInitMessage(InitMessageFn fn) = 0;
 
     //! Register handler for message box messages.
     using MessageBoxFn =
         std::function<bool(const std::string &message,
                            const std::string &caption, unsigned int style)>;
     virtual std::unique_ptr<Handler> handleMessageBox(MessageBoxFn fn) = 0;
 
     //! Register handler for question messages.
     using QuestionFn = std::function<bool(
         const std::string &message, const std::string &non_interactive_message,
         const std::string &caption, unsigned int style)>;
     virtual std::unique_ptr<Handler> handleQuestion(QuestionFn fn) = 0;
 
     //! Register handler for progress messages.
     using ShowProgressFn = std::function<void(
         const std::string &title, int progress, bool resume_possible)>;
     virtual std::unique_ptr<Handler> handleShowProgress(ShowProgressFn fn) = 0;
 
     //! Register handler for load wallet messages.
     using LoadWalletFn = std::function<void(std::unique_ptr<Wallet> wallet)>;
     virtual std::unique_ptr<Handler> handleLoadWallet(LoadWalletFn fn) = 0;
 
     //! Register handler for number of connections changed messages.
     using NotifyNumConnectionsChangedFn =
         std::function<void(int new_num_connections)>;
     virtual std::unique_ptr<Handler>
     handleNotifyNumConnectionsChanged(NotifyNumConnectionsChangedFn fn) = 0;
 
     //! Register handler for network active messages.
     using NotifyNetworkActiveChangedFn =
         std::function<void(bool network_active)>;
     virtual std::unique_ptr<Handler>
     handleNotifyNetworkActiveChanged(NotifyNetworkActiveChangedFn fn) = 0;
 
     //! Register handler for notify alert messages.
     using NotifyAlertChangedFn = std::function<void()>;
     virtual std::unique_ptr<Handler>
     handleNotifyAlertChanged(NotifyAlertChangedFn fn) = 0;
 
     //! Register handler for ban list messages.
     using BannedListChangedFn = std::function<void()>;
     virtual std::unique_ptr<Handler>
     handleBannedListChanged(BannedListChangedFn fn) = 0;
 
     //! Register handler for block tip messages.
     using NotifyBlockTipFn =
         std::function<void(bool initial_download, int height,
                            int64_t block_time, double verification_progress)>;
     virtual std::unique_ptr<Handler>
     handleNotifyBlockTip(NotifyBlockTipFn fn) = 0;
 
     //! Register handler for header tip messages.
     using NotifyHeaderTipFn =
         std::function<void(bool initial_download, int height,
                            int64_t block_time, double verification_progress)>;
     virtual std::unique_ptr<Handler>
     handleNotifyHeaderTip(NotifyHeaderTipFn fn) = 0;
 };
 
 //! Return implementation of Node interface.
 std::unique_ptr<Node> MakeNode();
 
 } // namespace interfaces
 
 #endif // BITCOIN_INTERFACES_NODE_H
diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp
index 39aa59d847..561357de74 100644
--- a/src/qt/sendcoinsdialog.cpp
+++ b/src/qt/sendcoinsdialog.cpp
@@ -1,955 +1,955 @@
 // Copyright (c) 2011-2016 The Bitcoin Core developers
 // Distributed under the MIT software license, see the accompanying
 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 
 #include <qt/forms/ui_sendcoinsdialog.h>
 #include <qt/sendcoinsdialog.h>
 
 #include <chainparams.h>
 #include <dstencode.h>
 #include <interfaces/node.h>
 #include <qt/addresstablemodel.h>
 #include <qt/bitcoinunits.h>
 #include <qt/clientmodel.h>
 #include <qt/coincontroldialog.h>
 #include <qt/guiutil.h>
 #include <qt/optionsmodel.h>
 #include <qt/platformstyle.h>
 #include <qt/sendcoinsentry.h>
 #include <qt/walletmodel.h>
 #include <txmempool.h>
 #include <ui_interface.h>
-#include <validation.h> // mempool and minRelayTxFee
 #include <wallet/coincontrol.h>
 #include <wallet/fees.h>
 #include <wallet/wallet.h>
 
 #include <QMessageBox>
 #include <QScrollBar>
 #include <QSettings>
 #include <QTextDocument>
 #include <QTimer>
 
 SendCoinsDialog::SendCoinsDialog(const PlatformStyle *_platformStyle,
                                  QWidget *parent)
     : QDialog(parent), ui(new Ui::SendCoinsDialog), clientModel(0), model(0),
       fNewRecipientAllowed(true), fFeeMinimized(true),
       platformStyle(_platformStyle) {
     ui->setupUi(this);
 
     if (!_platformStyle->getImagesOnButtons()) {
         ui->addButton->setIcon(QIcon());
         ui->clearButton->setIcon(QIcon());
         ui->sendButton->setIcon(QIcon());
     } else {
         ui->addButton->setIcon(_platformStyle->SingleColorIcon(":/icons/add"));
         ui->clearButton->setIcon(
             _platformStyle->SingleColorIcon(":/icons/remove"));
         ui->sendButton->setIcon(
             _platformStyle->SingleColorIcon(":/icons/send"));
     }
 
     GUIUtil::setupAddressWidget(ui->lineEditCoinControlChange, this);
 
     addEntry();
 
     connect(ui->addButton, SIGNAL(clicked()), this, SLOT(addEntry()));
     connect(ui->clearButton, SIGNAL(clicked()), this, SLOT(clear()));
 
     // Coin Control
     connect(ui->pushButtonCoinControl, SIGNAL(clicked()), this,
             SLOT(coinControlButtonClicked()));
     connect(ui->checkBoxCoinControlChange, SIGNAL(stateChanged(int)), this,
             SLOT(coinControlChangeChecked(int)));
     connect(ui->lineEditCoinControlChange, SIGNAL(textEdited(const QString &)),
             this, SLOT(coinControlChangeEdited(const QString &)));
 
     // Coin Control: clipboard actions
     QAction *clipboardQuantityAction = new QAction(tr("Copy quantity"), this);
     QAction *clipboardAmountAction = new QAction(tr("Copy amount"), this);
     QAction *clipboardFeeAction = new QAction(tr("Copy fee"), this);
     QAction *clipboardAfterFeeAction = new QAction(tr("Copy after fee"), this);
     QAction *clipboardBytesAction = new QAction(tr("Copy bytes"), this);
     QAction *clipboardLowOutputAction = new QAction(tr("Copy dust"), this);
     QAction *clipboardChangeAction = new QAction(tr("Copy change"), this);
     connect(clipboardQuantityAction, SIGNAL(triggered()), this,
             SLOT(coinControlClipboardQuantity()));
     connect(clipboardAmountAction, SIGNAL(triggered()), this,
             SLOT(coinControlClipboardAmount()));
     connect(clipboardFeeAction, SIGNAL(triggered()), this,
             SLOT(coinControlClipboardFee()));
     connect(clipboardAfterFeeAction, SIGNAL(triggered()), this,
             SLOT(coinControlClipboardAfterFee()));
     connect(clipboardBytesAction, SIGNAL(triggered()), this,
             SLOT(coinControlClipboardBytes()));
     connect(clipboardLowOutputAction, SIGNAL(triggered()), this,
             SLOT(coinControlClipboardLowOutput()));
     connect(clipboardChangeAction, SIGNAL(triggered()), this,
             SLOT(coinControlClipboardChange()));
     ui->labelCoinControlQuantity->addAction(clipboardQuantityAction);
     ui->labelCoinControlAmount->addAction(clipboardAmountAction);
     ui->labelCoinControlFee->addAction(clipboardFeeAction);
     ui->labelCoinControlAfterFee->addAction(clipboardAfterFeeAction);
     ui->labelCoinControlBytes->addAction(clipboardBytesAction);
     ui->labelCoinControlLowOutput->addAction(clipboardLowOutputAction);
     ui->labelCoinControlChange->addAction(clipboardChangeAction);
 
     // init transaction fee section
     QSettings settings;
     if (!settings.contains("fFeeSectionMinimized")) {
         settings.setValue("fFeeSectionMinimized", true);
     }
     // compatibility
     if (!settings.contains("nFeeRadio") &&
         settings.contains("nTransactionFee") &&
         settings.value("nTransactionFee").toLongLong() > 0) {
         // custom
         settings.setValue("nFeeRadio", 1);
     }
     if (!settings.contains("nFeeRadio")) {
         // recommended
         settings.setValue("nFeeRadio", 0);
     }
     // compatibility
     if (!settings.contains("nCustomFeeRadio") &&
         settings.contains("nTransactionFee") &&
         settings.value("nTransactionFee").toLongLong() > 0) {
         // total at least
         settings.setValue("nCustomFeeRadio", 1);
     }
     if (!settings.contains("nCustomFeeRadio")) {
         // per kilobyte
         settings.setValue("nCustomFeeRadio", 0);
     }
     if (!settings.contains("nTransactionFee")) {
         settings.setValue("nTransactionFee",
                           qint64(DEFAULT_TRANSACTION_FEE / SATOSHI));
     }
     if (!settings.contains("fPayOnlyMinFee")) {
         settings.setValue("fPayOnlyMinFee", false);
     }
     ui->groupFee->setId(ui->radioSmartFee, 0);
     ui->groupFee->setId(ui->radioCustomFee, 1);
     ui->groupFee
         ->button(
             std::max<int>(0, std::min(1, settings.value("nFeeRadio").toInt())))
         ->setChecked(true);
     ui->groupCustomFee->setId(ui->radioCustomPerKilobyte, 0);
     ui->groupCustomFee->button(0)->setChecked(true);
     ui->customFee->setValue(
         int64_t(settings.value("nTransactionFee").toLongLong()) * SATOSHI);
     ui->checkBoxMinimumFee->setChecked(
         settings.value("fPayOnlyMinFee").toBool());
     minimizeFeeSection(settings.value("fFeeSectionMinimized").toBool());
 }
 
 void SendCoinsDialog::setClientModel(ClientModel *_clientModel) {
     this->clientModel = _clientModel;
 
     if (_clientModel) {
         connect(_clientModel,
                 SIGNAL(numBlocksChanged(int, QDateTime, double, bool)), this,
                 SLOT(updateSmartFeeLabel()));
     }
 }
 
 void SendCoinsDialog::setModel(WalletModel *_model) {
     this->model = _model;
 
     if (_model && _model->getOptionsModel()) {
         for (int i = 0; i < ui->entries->count(); ++i) {
             SendCoinsEntry *entry = qobject_cast<SendCoinsEntry *>(
                 ui->entries->itemAt(i)->widget());
             if (entry) {
                 entry->setModel(_model);
             }
         }
 
         interfaces::WalletBalances balances = _model->wallet().getBalances();
         setBalance(balances.balance, balances.unconfirmed_balance,
                    balances.immature_balance, balances.watch_only_balance,
                    balances.unconfirmed_watch_only_balance,
                    balances.immature_watch_only_balance);
         connect(
             _model,
             SIGNAL(
                 balanceChanged(Amount, Amount, Amount, Amount, Amount, Amount)),
             this,
             SLOT(setBalance(Amount, Amount, Amount, Amount, Amount, Amount)));
         connect(_model->getOptionsModel(), SIGNAL(displayUnitChanged(int)),
                 this, SLOT(updateDisplayUnit()));
         updateDisplayUnit();
 
         // Coin Control
         connect(_model->getOptionsModel(), SIGNAL(displayUnitChanged(int)),
                 this, SLOT(coinControlUpdateLabels()));
         connect(_model->getOptionsModel(),
                 SIGNAL(coinControlFeaturesChanged(bool)), this,
                 SLOT(coinControlFeatureChanged(bool)));
         ui->frameCoinControl->setVisible(
             _model->getOptionsModel()->getCoinControlFeatures());
         coinControlUpdateLabels();
 
         // fee section
         connect(ui->groupFee, SIGNAL(buttonClicked(int)), this,
                 SLOT(updateFeeSectionControls()));
         connect(ui->groupFee, SIGNAL(buttonClicked(int)), this,
                 SLOT(coinControlUpdateLabels()));
         connect(ui->groupCustomFee, SIGNAL(buttonClicked(int)), this,
                 SLOT(coinControlUpdateLabels()));
         connect(ui->customFee, SIGNAL(valueChanged()), this,
                 SLOT(coinControlUpdateLabels()));
         connect(ui->checkBoxMinimumFee, SIGNAL(stateChanged(int)), this,
                 SLOT(setMinimumFee()));
         connect(ui->checkBoxMinimumFee, SIGNAL(stateChanged(int)), this,
                 SLOT(updateFeeSectionControls()));
         connect(ui->checkBoxMinimumFee, SIGNAL(stateChanged(int)), this,
                 SLOT(coinControlUpdateLabels()));
 
-        ui->customFee->setSingleStep(GetMinimumFee(1000, g_mempool));
+        ui->customFee->setSingleStep(model->node().getMinimumFee(1000));
         updateFeeSectionControls();
         updateMinFeeLabel();
         updateSmartFeeLabel();
 
         // Cleanup old confirmation target related settings
         // TODO: Remove these in 0.20
         QSettings settings;
         if (settings.value("nSmartFeeSliderPosition").toInt() != 0) {
             settings.remove("nSmartFeeSliderPosition");
         }
         if (settings.value("nConfTarget").toInt() != 0) {
             settings.remove("nConfTarget");
         }
     }
 }
 
 SendCoinsDialog::~SendCoinsDialog() {
     QSettings settings;
     settings.setValue("fFeeSectionMinimized", fFeeMinimized);
     settings.setValue("nFeeRadio", ui->groupFee->checkedId());
     settings.setValue("nCustomFeeRadio", ui->groupCustomFee->checkedId());
     settings.setValue("nTransactionFee",
                       qint64(ui->customFee->value() / SATOSHI));
     settings.setValue("fPayOnlyMinFee", ui->checkBoxMinimumFee->isChecked());
 
     delete ui;
 }
 
 void SendCoinsDialog::on_sendButton_clicked() {
     if (!model || !model->getOptionsModel()) {
         return;
     }
 
     QList<SendCoinsRecipient> recipients;
     bool valid = true;
 
     for (int i = 0; i < ui->entries->count(); ++i) {
         SendCoinsEntry *entry =
             qobject_cast<SendCoinsEntry *>(ui->entries->itemAt(i)->widget());
         if (entry) {
             if (entry->validate(model->node())) {
                 recipients.append(entry->getValue());
             } else {
                 valid = false;
             }
         }
     }
 
     if (!valid || recipients.isEmpty()) {
         return;
     }
 
     fNewRecipientAllowed = false;
     WalletModel::UnlockContext ctx(model->requestUnlock());
     if (!ctx.isValid()) {
         // Unlock wallet was cancelled
         fNewRecipientAllowed = true;
         return;
     }
 
     // prepare transaction for getting txFee earlier
     WalletModelTransaction currentTransaction(recipients);
     WalletModel::SendCoinsReturn prepareStatus;
 
     // Always use a CCoinControl instance, use the CoinControlDialog instance if
     // CoinControl has been enabled
     CCoinControl ctrl;
     if (model->getOptionsModel()->getCoinControlFeatures()) {
         ctrl = *CoinControlDialog::coinControl();
     }
 
     updateCoinControlState(ctrl);
 
     prepareStatus = model->prepareTransaction(currentTransaction, ctrl);
 
     // process prepareStatus and on error generate message shown to user
     processSendCoinsReturn(
         prepareStatus,
         BitcoinUnits::formatWithUnit(model->getOptionsModel()->getDisplayUnit(),
                                      currentTransaction.getTransactionFee()));
 
     if (prepareStatus.status != WalletModel::OK) {
         fNewRecipientAllowed = true;
         return;
     }
 
     Amount txFee = currentTransaction.getTransactionFee();
 
     // Format confirmation message
     QStringList formatted;
     for (const SendCoinsRecipient &rcp : currentTransaction.getRecipients()) {
         // generate bold amount string with wallet name in case of multiwallet
         QString amount =
             "<b>" + BitcoinUnits::formatHtmlWithUnit(
                         model->getOptionsModel()->getDisplayUnit(), rcp.amount);
         if (model->isMultiwallet()) {
             amount.append(
                 " <u>" +
                 tr("from wallet %1")
                     .arg(GUIUtil::HtmlEscape(model->getWalletName())) +
                 "</u> ");
         }
         amount.append("</b>");
         // generate monospace address string
         QString address =
             "<span style='font-family: monospace;'>" + rcp.address;
         address.append("</span>");
 
         QString recipientElement;
 
         // normal payment
         if (!rcp.paymentRequest.IsInitialized()) {
             if (rcp.label.length() > 0) {
                 // label with address
                 recipientElement =
                     tr("%1 to %2").arg(amount, GUIUtil::HtmlEscape(rcp.label));
                 recipientElement.append(QString(" (%1)").arg(address));
             } else {
                 // just address
                 recipientElement = tr("%1 to %2").arg(amount, address);
             }
         } else if (!rcp.authenticatedMerchant.isEmpty()) {
             // authenticated payment request
             recipientElement =
                 tr("%1 to %2")
                     .arg(amount,
                          GUIUtil::HtmlEscape(rcp.authenticatedMerchant));
         } else {
             // unauthenticated payment request
             recipientElement = tr("%1 to %2").arg(amount, address);
         }
 
         formatted.append(recipientElement);
     }
 
     QString questionString = tr("Are you sure you want to send?");
     questionString.append("<br /><br />%1");
 
     if (txFee > Amount::zero()) {
         // append fee string if a fee is required
         questionString.append("<hr /><span style='color:#aa0000;'>");
         questionString.append(BitcoinUnits::formatHtmlWithUnit(
             model->getOptionsModel()->getDisplayUnit(), txFee));
         questionString.append("</span> ");
         questionString.append(tr("added as transaction fee"));
 
         // append transaction size
         questionString.append(
             " (" +
             QString::number((double)currentTransaction.getTransactionSize() /
                             1000) +
             " kB)");
     }
 
     // add total amount in all subdivision units
     questionString.append("<hr />");
     Amount totalAmount = currentTransaction.getTotalTransactionAmount() + txFee;
     QStringList alternativeUnits;
     for (BitcoinUnits::Unit u : BitcoinUnits::availableUnits()) {
         if (u != model->getOptionsModel()->getDisplayUnit()) {
             alternativeUnits.append(
                 BitcoinUnits::formatHtmlWithUnit(u, totalAmount));
         }
     }
     questionString.append(
         tr("Total Amount %1")
             .arg(BitcoinUnits::formatHtmlWithUnit(
                 model->getOptionsModel()->getDisplayUnit(), totalAmount)));
     questionString.append(
         QString("<span style='font-size:10pt;font-weight:normal;'><br "
                 "/>(=%2)</span>")
             .arg(alternativeUnits.join(" " + tr("or") + "<br />")));
 
     SendConfirmationDialog confirmationDialog(
         tr("Confirm send coins"), questionString.arg(formatted.join("<br />")),
         SEND_CONFIRM_DELAY, this);
     confirmationDialog.exec();
     QMessageBox::StandardButton retval =
         static_cast<QMessageBox::StandardButton>(confirmationDialog.result());
 
     if (retval != QMessageBox::Yes) {
         fNewRecipientAllowed = true;
         return;
     }
 
     // now send the prepared transaction
     WalletModel::SendCoinsReturn sendStatus =
         model->sendCoins(currentTransaction);
     // process sendStatus and on error generate message shown to user
     processSendCoinsReturn(sendStatus);
 
     if (sendStatus.status == WalletModel::OK) {
         accept();
         CoinControlDialog::coinControl()->UnSelectAll();
         coinControlUpdateLabels();
         Q_EMIT coinsSent(currentTransaction.getWtx()->get().GetId());
     }
     fNewRecipientAllowed = true;
 }
 
 void SendCoinsDialog::clear() {
     // Remove entries until only one left
     while (ui->entries->count()) {
         ui->entries->takeAt(0)->widget()->deleteLater();
     }
     addEntry();
 
     updateTabsAndLabels();
 }
 
 void SendCoinsDialog::reject() {
     clear();
 }
 
 void SendCoinsDialog::accept() {
     clear();
 }
 
 SendCoinsEntry *SendCoinsDialog::addEntry() {
     SendCoinsEntry *entry = new SendCoinsEntry(platformStyle, this);
     entry->setModel(model);
     ui->entries->addWidget(entry);
     connect(entry, SIGNAL(removeEntry(SendCoinsEntry *)), this,
             SLOT(removeEntry(SendCoinsEntry *)));
     connect(entry, SIGNAL(useAvailableBalance(SendCoinsEntry *)), this,
             SLOT(useAvailableBalance(SendCoinsEntry *)));
     connect(entry, SIGNAL(payAmountChanged()), this,
             SLOT(coinControlUpdateLabels()));
     connect(entry, SIGNAL(subtractFeeFromAmountChanged()), this,
             SLOT(coinControlUpdateLabels()));
 
     // Focus the field, so that entry can start immediately
     entry->clear();
     entry->setFocus();
     ui->scrollAreaWidgetContents->resize(
         ui->scrollAreaWidgetContents->sizeHint());
     qApp->processEvents();
     QScrollBar *bar = ui->scrollArea->verticalScrollBar();
     if (bar) {
         bar->setSliderPosition(bar->maximum());
     }
 
     updateTabsAndLabels();
     return entry;
 }
 
 void SendCoinsDialog::updateTabsAndLabels() {
     setupTabChain(0);
     coinControlUpdateLabels();
 }
 
 void SendCoinsDialog::removeEntry(SendCoinsEntry *entry) {
     entry->hide();
 
     // If the last entry is about to be removed add an empty one
     if (ui->entries->count() == 1) {
         addEntry();
     }
 
     entry->deleteLater();
 
     updateTabsAndLabels();
 }
 
 QWidget *SendCoinsDialog::setupTabChain(QWidget *prev) {
     for (int i = 0; i < ui->entries->count(); ++i) {
         SendCoinsEntry *entry =
             qobject_cast<SendCoinsEntry *>(ui->entries->itemAt(i)->widget());
         if (entry) {
             prev = entry->setupTabChain(prev);
         }
     }
     QWidget::setTabOrder(prev, ui->sendButton);
     QWidget::setTabOrder(ui->sendButton, ui->clearButton);
     QWidget::setTabOrder(ui->clearButton, ui->addButton);
     return ui->addButton;
 }
 
 void SendCoinsDialog::setAddress(const QString &address) {
     SendCoinsEntry *entry = 0;
     // Replace the first entry if it is still unused
     if (ui->entries->count() == 1) {
         SendCoinsEntry *first =
             qobject_cast<SendCoinsEntry *>(ui->entries->itemAt(0)->widget());
         if (first->isClear()) {
             entry = first;
         }
     }
     if (!entry) {
         entry = addEntry();
     }
 
     entry->setAddress(address);
 }
 
 void SendCoinsDialog::pasteEntry(const SendCoinsRecipient &rv) {
     if (!fNewRecipientAllowed) {
         return;
     }
 
     SendCoinsEntry *entry = 0;
     // Replace the first entry if it is still unused
     if (ui->entries->count() == 1) {
         SendCoinsEntry *first =
             qobject_cast<SendCoinsEntry *>(ui->entries->itemAt(0)->widget());
         if (first->isClear()) {
             entry = first;
         }
     }
     if (!entry) {
         entry = addEntry();
     }
 
     entry->setValue(rv);
     updateTabsAndLabels();
 }
 
 bool SendCoinsDialog::handlePaymentRequest(const SendCoinsRecipient &rv) {
     // Just paste the entry, all pre-checks are done in paymentserver.cpp.
     pasteEntry(rv);
     return true;
 }
 
 void SendCoinsDialog::setBalance(const Amount balance,
                                  const Amount unconfirmedBalance,
                                  const Amount immatureBalance,
                                  const Amount watchBalance,
                                  const Amount watchUnconfirmedBalance,
                                  const Amount watchImmatureBalance) {
     Q_UNUSED(unconfirmedBalance);
     Q_UNUSED(immatureBalance);
     Q_UNUSED(watchBalance);
     Q_UNUSED(watchUnconfirmedBalance);
     Q_UNUSED(watchImmatureBalance);
 
     if (model && model->getOptionsModel()) {
         ui->labelBalance->setText(BitcoinUnits::formatWithUnit(
             model->getOptionsModel()->getDisplayUnit(), balance));
     }
 }
 
 void SendCoinsDialog::updateDisplayUnit() {
     setBalance(model->wallet().getBalance(), Amount::zero(), Amount::zero(),
                Amount::zero(), Amount::zero(), Amount::zero());
     ui->customFee->setDisplayUnit(model->getOptionsModel()->getDisplayUnit());
     updateMinFeeLabel();
     updateSmartFeeLabel();
 }
 
 void SendCoinsDialog::processSendCoinsReturn(
     const WalletModel::SendCoinsReturn &sendCoinsReturn,
     const QString &msgArg) {
     QPair<QString, CClientUIInterface::MessageBoxFlags> msgParams;
     // Default to a warning message, override if error message is needed
     msgParams.second = CClientUIInterface::MSG_WARNING;
 
     // This comment is specific to SendCoinsDialog usage of
     // WalletModel::SendCoinsReturn.
     // WalletModel::TransactionCommitFailed is used only in
     // WalletModel::sendCoins() all others are used only in
     // WalletModel::prepareTransaction()
     switch (sendCoinsReturn.status) {
         case WalletModel::InvalidAddress:
             msgParams.first =
                 tr("The recipient address is not valid. Please recheck.");
             break;
         case WalletModel::InvalidAmount:
             msgParams.first = tr("The amount to pay must be larger than 0.");
             break;
         case WalletModel::AmountExceedsBalance:
             msgParams.first = tr("The amount exceeds your balance.");
             break;
         case WalletModel::AmountWithFeeExceedsBalance:
             msgParams.first = tr("The total exceeds your balance when the %1 "
                                  "transaction fee is included.")
                                   .arg(msgArg);
             break;
         case WalletModel::DuplicateAddress:
             msgParams.first = tr("Duplicate address found: addresses should "
                                  "only be used once each.");
             break;
         case WalletModel::TransactionCreationFailed:
             msgParams.first = tr("Transaction creation failed!");
             msgParams.second = CClientUIInterface::MSG_ERROR;
             break;
         case WalletModel::TransactionCommitFailed:
             msgParams.first =
                 tr("The transaction was rejected with the following reason: %1")
                     .arg(sendCoinsReturn.reasonCommitFailed);
             msgParams.second = CClientUIInterface::MSG_ERROR;
             break;
         case WalletModel::AbsurdFee:
             msgParams.first =
                 tr("A fee higher than %1 is considered an absurdly high fee.")
                     .arg(BitcoinUnits::formatWithUnit(
-                        model->getOptionsModel()->getDisplayUnit(), maxTxFee));
+                        model->getOptionsModel()->getDisplayUnit(),
+                        model->node().getMaxTxFee()));
             break;
         case WalletModel::PaymentRequestExpired:
             msgParams.first = tr("Payment request expired.");
             msgParams.second = CClientUIInterface::MSG_ERROR;
             break;
         // included to prevent a compiler warning.
         case WalletModel::OK:
         default:
             return;
     }
 
     Q_EMIT message(tr("Send Coins"), msgParams.first, msgParams.second);
 }
 
 void SendCoinsDialog::minimizeFeeSection(bool fMinimize) {
     ui->labelFeeMinimized->setVisible(fMinimize);
     ui->buttonChooseFee->setVisible(fMinimize);
     ui->buttonMinimizeFee->setVisible(!fMinimize);
     ui->frameFeeSelection->setVisible(!fMinimize);
     ui->horizontalLayoutSmartFee->setContentsMargins(0, (fMinimize ? 0 : 6), 0,
                                                      0);
     fFeeMinimized = fMinimize;
 }
 
 void SendCoinsDialog::on_buttonChooseFee_clicked() {
     minimizeFeeSection(false);
 }
 
 void SendCoinsDialog::on_buttonMinimizeFee_clicked() {
     updateFeeMinimizedLabel();
     minimizeFeeSection(true);
 }
 
 void SendCoinsDialog::useAvailableBalance(SendCoinsEntry *entry) {
     // Get CCoinControl instance if CoinControl is enabled or create a new one.
     CCoinControl coin_control;
     if (model->getOptionsModel()->getCoinControlFeatures()) {
         coin_control = *CoinControlDialog::coinControl();
     }
 
     // Calculate available amount to send.
     Amount amount = model->wallet().getAvailableBalance(coin_control);
     for (int i = 0; i < ui->entries->count(); ++i) {
         SendCoinsEntry *e =
             qobject_cast<SendCoinsEntry *>(ui->entries->itemAt(i)->widget());
         if (e && !e->isHidden() && e != entry) {
             amount -= e->getValue().amount;
         }
     }
 
     if (amount > Amount::zero()) {
         entry->checkSubtractFeeFromAmount();
         entry->setAmount(amount);
     } else {
         entry->setAmount(Amount::zero());
     }
 }
 
 void SendCoinsDialog::setMinimumFee() {
     ui->radioCustomPerKilobyte->setChecked(true);
-    ui->customFee->setValue(GetMinimumFee(1000, g_mempool));
+    ui->customFee->setValue(model->node().getMinimumFee(1000));
 }
 
 void SendCoinsDialog::updateFeeSectionControls() {
     ui->labelSmartFee->setEnabled(ui->radioSmartFee->isChecked());
     ui->labelSmartFee2->setEnabled(ui->radioSmartFee->isChecked());
     ui->labelFeeEstimation->setEnabled(ui->radioSmartFee->isChecked());
     ui->checkBoxMinimumFee->setEnabled(ui->radioCustomFee->isChecked());
     ui->labelMinFeeWarning->setEnabled(ui->radioCustomFee->isChecked());
     ui->radioCustomPerKilobyte->setEnabled(
         ui->radioCustomFee->isChecked() &&
         !ui->checkBoxMinimumFee->isChecked());
     ui->customFee->setEnabled(ui->radioCustomFee->isChecked() &&
                               !ui->checkBoxMinimumFee->isChecked());
 }
 
 void SendCoinsDialog::updateFeeMinimizedLabel() {
     if (!model || !model->getOptionsModel()) {
         return;
     }
 
     if (ui->radioSmartFee->isChecked()) {
         ui->labelFeeMinimized->setText(ui->labelSmartFee->text());
     } else {
         ui->labelFeeMinimized->setText(
             BitcoinUnits::formatWithUnit(
                 model->getOptionsModel()->getDisplayUnit(),
                 ui->customFee->value()) +
             ((ui->radioCustomPerKilobyte->isChecked()) ? "/kB" : ""));
     }
 }
 
 void SendCoinsDialog::updateMinFeeLabel() {
     if (model && model->getOptionsModel()) {
         ui->checkBoxMinimumFee->setText(
             tr("Pay only the required fee of %1")
                 .arg(BitcoinUnits::formatWithUnit(
                          model->getOptionsModel()->getDisplayUnit(),
-                         GetMinimumFee(1000, g_mempool)) +
+                         model->node().getMinimumFee(1000)) +
                      "/kB"));
     }
 }
 
 void SendCoinsDialog::updateCoinControlState(CCoinControl &ctrl) {
     if (ui->radioCustomFee->isChecked()) {
         ctrl.m_feerate = CFeeRate(ui->customFee->value());
     } else {
         ctrl.m_feerate.reset();
     }
 }
 
 void SendCoinsDialog::updateSmartFeeLabel() {
     if (!model || !model->getOptionsModel()) {
         return;
     }
 
-    CFeeRate feeRate = g_mempool.estimateFee();
+    CFeeRate feeRate = model->node().estimateSmartFee();
 
     ui->labelSmartFee->setText(
         BitcoinUnits::formatWithUnit(
             model->getOptionsModel()->getDisplayUnit(),
-            std::max(feeRate.GetFeePerK(), GetMinimumFee(1000, g_mempool))) +
+            std::max(feeRate.GetFeePerK(), model->node().getMinimumFee(1000))) +
         "/kB");
     // not enough data => minfee
     if (feeRate <= CFeeRate(Amount::zero())) {
         // (Smart fee not initialized yet. This usually takes a few blocks...)
         ui->labelSmartFee2->show();
         ui->labelFeeEstimation->setText("");
     } else {
         ui->labelSmartFee2->hide();
         ui->labelFeeEstimation->setText(
             tr("Estimated to begin confirmation by next block."));
     }
 
     updateFeeMinimizedLabel();
 }
 
 // Coin Control: copy label "Quantity" to clipboard
 void SendCoinsDialog::coinControlClipboardQuantity() {
     GUIUtil::setClipboard(ui->labelCoinControlQuantity->text());
 }
 
 // Coin Control: copy label "Amount" to clipboard
 void SendCoinsDialog::coinControlClipboardAmount() {
     GUIUtil::setClipboard(ui->labelCoinControlAmount->text().left(
         ui->labelCoinControlAmount->text().indexOf(" ")));
 }
 
 // Coin Control: copy label "Fee" to clipboard
 void SendCoinsDialog::coinControlClipboardFee() {
     GUIUtil::setClipboard(
         ui->labelCoinControlFee->text()
             .left(ui->labelCoinControlFee->text().indexOf(" "))
             .replace(ASYMP_UTF8, ""));
 }
 
 // Coin Control: copy label "After fee" to clipboard
 void SendCoinsDialog::coinControlClipboardAfterFee() {
     GUIUtil::setClipboard(
         ui->labelCoinControlAfterFee->text()
             .left(ui->labelCoinControlAfterFee->text().indexOf(" "))
             .replace(ASYMP_UTF8, ""));
 }
 
 // Coin Control: copy label "Bytes" to clipboard
 void SendCoinsDialog::coinControlClipboardBytes() {
     GUIUtil::setClipboard(
         ui->labelCoinControlBytes->text().replace(ASYMP_UTF8, ""));
 }
 
 // Coin Control: copy label "Dust" to clipboard
 void SendCoinsDialog::coinControlClipboardLowOutput() {
     GUIUtil::setClipboard(ui->labelCoinControlLowOutput->text());
 }
 
 // Coin Control: copy label "Change" to clipboard
 void SendCoinsDialog::coinControlClipboardChange() {
     GUIUtil::setClipboard(
         ui->labelCoinControlChange->text()
             .left(ui->labelCoinControlChange->text().indexOf(" "))
             .replace(ASYMP_UTF8, ""));
 }
 
 // Coin Control: settings menu - coin control enabled/disabled by user
 void SendCoinsDialog::coinControlFeatureChanged(bool checked) {
     ui->frameCoinControl->setVisible(checked);
 
     // coin control features disabled
     if (!checked && model) {
         CoinControlDialog::coinControl()->SetNull();
     }
 
     coinControlUpdateLabels();
 }
 
 // Coin Control: button inputs -> show actual coin control dialog
 void SendCoinsDialog::coinControlButtonClicked() {
     CoinControlDialog dlg(platformStyle);
     dlg.setModel(model);
     dlg.exec();
     coinControlUpdateLabels();
 }
 
 // Coin Control: checkbox custom change address
 void SendCoinsDialog::coinControlChangeChecked(int state) {
     if (state == Qt::Unchecked) {
         CoinControlDialog::coinControl()->destChange = CNoDestination();
         ui->labelCoinControlChangeLabel->clear();
     } else {
         // use this to re-validate an already entered address
         coinControlChangeEdited(ui->lineEditCoinControlChange->text());
     }
 
     ui->lineEditCoinControlChange->setEnabled((state == Qt::Checked));
 }
 
 // Coin Control: custom change address changed
 void SendCoinsDialog::coinControlChangeEdited(const QString &text) {
     if (model && model->getAddressTableModel()) {
         // Default to no change address until verified
         CoinControlDialog::coinControl()->destChange = CNoDestination();
         ui->labelCoinControlChangeLabel->setStyleSheet("QLabel{color:red;}");
 
         const CTxDestination dest =
             DecodeDestination(text.toStdString(), model->getChainParams());
 
         if (text.isEmpty()) {
             // Nothing entered
             ui->labelCoinControlChangeLabel->setText("");
         } else if (!IsValidDestination(dest)) {
             // Invalid address
             ui->labelCoinControlChangeLabel->setText(
                 tr("Warning: Invalid Bitcoin address"));
         } else {
             // Valid address
             if (!model->wallet().isSpendable(dest)) {
                 ui->labelCoinControlChangeLabel->setText(
                     tr("Warning: Unknown change address"));
 
                 // confirmation dialog
                 QMessageBox::StandardButton btnRetVal = QMessageBox::question(
                     this, tr("Confirm custom change address"),
                     tr("The address you selected for change is not part of "
                        "this wallet. Any or all funds in your wallet may be "
                        "sent to this address. Are you sure?"),
                     QMessageBox::Yes | QMessageBox::Cancel,
                     QMessageBox::Cancel);
 
                 if (btnRetVal == QMessageBox::Yes) {
                     CoinControlDialog::coinControl()->destChange = dest;
                 } else {
                     ui->lineEditCoinControlChange->setText("");
                     ui->labelCoinControlChangeLabel->setStyleSheet(
                         "QLabel{color:black;}");
                     ui->labelCoinControlChangeLabel->setText("");
                 }
             } else {
                 // Known change address
                 ui->labelCoinControlChangeLabel->setStyleSheet(
                     "QLabel{color:black;}");
 
                 // Query label
                 QString associatedLabel =
                     model->getAddressTableModel()->labelForAddress(text);
                 if (!associatedLabel.isEmpty()) {
                     ui->labelCoinControlChangeLabel->setText(associatedLabel);
                 } else {
                     ui->labelCoinControlChangeLabel->setText(tr("(no label)"));
                 }
 
                 CoinControlDialog::coinControl()->destChange = dest;
             }
         }
     }
 }
 
 // Coin Control: update labels
 void SendCoinsDialog::coinControlUpdateLabels() {
     if (!model || !model->getOptionsModel()) {
         return;
     }
 
     updateCoinControlState(*CoinControlDialog::coinControl());
 
     // set pay amounts
     CoinControlDialog::payAmounts.clear();
     CoinControlDialog::fSubtractFeeFromAmount = false;
     for (int i = 0; i < ui->entries->count(); ++i) {
         SendCoinsEntry *entry =
             qobject_cast<SendCoinsEntry *>(ui->entries->itemAt(i)->widget());
         if (entry && !entry->isHidden()) {
             SendCoinsRecipient rcp = entry->getValue();
             CoinControlDialog::payAmounts.append(rcp.amount);
             if (rcp.fSubtractFeeFromAmount) {
                 CoinControlDialog::fSubtractFeeFromAmount = true;
             }
         }
     }
 
     if (CoinControlDialog::coinControl()->HasSelected()) {
         // actual coin control calculation
         CoinControlDialog::updateLabels(model, this);
 
         // show coin control stats
         ui->labelCoinControlAutomaticallySelected->hide();
         ui->widgetCoinControl->show();
     } else {
         // hide coin control stats
         ui->labelCoinControlAutomaticallySelected->show();
         ui->widgetCoinControl->hide();
         ui->labelCoinControlInsuffFunds->hide();
     }
 }
 
 SendConfirmationDialog::SendConfirmationDialog(const QString &title,
                                                const QString &text,
                                                int _secDelay, QWidget *parent)
     : QMessageBox(QMessageBox::Question, title, text,
                   QMessageBox::Yes | QMessageBox::Cancel, parent),
       secDelay(_secDelay) {
     setDefaultButton(QMessageBox::Cancel);
     yesButton = button(QMessageBox::Yes);
     updateYesButton();
     connect(&countDownTimer, SIGNAL(timeout()), this, SLOT(countDown()));
 }
 
 int SendConfirmationDialog::exec() {
     updateYesButton();
     countDownTimer.start(1000);
     return QMessageBox::exec();
 }
 
 void SendConfirmationDialog::countDown() {
     secDelay--;
     updateYesButton();
 
     if (secDelay <= 0) {
         countDownTimer.stop();
     }
 }
 
 void SendConfirmationDialog::updateYesButton() {
     if (secDelay > 0) {
         yesButton->setEnabled(false);
         yesButton->setText(tr("Yes") + " (" + QString::number(secDelay) + ")");
     } else {
         yesButton->setEnabled(true);
         yesButton->setText(tr("Yes"));
     }
 }