diff --git a/src/interfaces/node.cpp b/src/interfaces/node.cpp
index 0d18fbeb1f..a871243087 100644
--- a/src/interfaces/node.cpp
+++ b/src/interfaces/node.cpp
@@ -1,301 +1,313 @@
 // 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);
         }
         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,
+                             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 getDustRelayFee() override { return ::dustRelayFee; }
+        CFeeRate getPayTxFee() override { CHECK_WALLET(return ::payTxFee); }
         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);
         }
         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 3fab620409..bb4b3f3c1f 100644
--- a/src/interfaces/node.h
+++ b/src/interfaces/node.h
@@ -1,239 +1,251 @@
 // 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 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;
 
     //! 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,
+                                 const CCoinControl &coin_control) = 0;
+
     //! Get max tx fee.
     virtual Amount getMaxTxFee() = 0;
 
+    //! Get dust relay fee.
+    virtual CFeeRate getDustRelayFee() = 0;
+
+    //! Get pay tx fee.
+    virtual CFeeRate getPayTxFee() = 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;
 
     //! 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/interfaces/wallet.cpp b/src/interfaces/wallet.cpp
index b6525415b1..6c64792173 100644
--- a/src/interfaces/wallet.cpp
+++ b/src/interfaces/wallet.cpp
@@ -1,232 +1,274 @@
 // 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/wallet.h>
 
 #include <amount.h>
 #include <chain.h>
 #include <consensus/validation.h>
 #include <interfaces/handler.h>
 #include <net.h>
 #include <policy/policy.h>
 #include <primitives/transaction.h>
 #include <script/ismine.h>
 #include <script/standard.h>
 #include <support/allocators/secure.h>
 #include <sync.h>
 #include <ui_interface.h>
 #include <validation.h>
 #include <wallet/wallet.h>
 
 #include <memory>
 
 namespace interfaces {
 namespace {
 
     class PendingWalletTxImpl : public PendingWalletTx {
     public:
         PendingWalletTxImpl(CWallet &wallet)
             : m_wallet(wallet), m_key(&wallet) {}
 
         const CTransaction &get() override { return *m_tx; }
 
         bool commit(WalletValueMap value_map, WalletOrderForm order_form,
                     std::string from_account,
                     std::string &reject_reason) override {
             LOCK2(cs_main, m_wallet.cs_wallet);
             CValidationState state;
             if (!m_wallet.CommitTransaction(
                     m_tx, std::move(value_map), std::move(order_form),
                     std::move(from_account), m_key, g_connman.get(), state)) {
                 reject_reason = state.GetRejectReason();
                 return false;
             }
             return true;
         }
 
         CTransactionRef m_tx;
         CWallet &m_wallet;
         CReserveKey m_key;
     };
 
+    //! Construct wallet TxOut struct.
+    WalletTxOut MakeWalletTxOut(CWallet &wallet, const CWalletTx &wtx, int n,
+                                int depth) {
+        WalletTxOut result;
+        result.txout = wtx.tx->vout[n];
+        result.time = wtx.GetTxTime();
+        result.depth_in_main_chain = depth;
+        result.is_spent = wallet.IsSpent(wtx.GetId(), n);
+        return result;
+    }
+
     class WalletImpl : public Wallet {
     public:
         WalletImpl(CWallet &wallet) : m_wallet(wallet) {}
 
         bool encryptWallet(const SecureString &wallet_passphrase) override {
             return m_wallet.EncryptWallet(wallet_passphrase);
         }
         bool isCrypted() override { return m_wallet.IsCrypted(); }
         bool lock() override { return m_wallet.Lock(); }
         bool unlock(const SecureString &wallet_passphrase) override {
             return m_wallet.Unlock(wallet_passphrase);
         }
         bool isLocked() override { return m_wallet.IsLocked(); }
         bool changeWalletPassphrase(
             const SecureString &old_wallet_passphrase,
             const SecureString &new_wallet_passphrase) override {
             return m_wallet.ChangeWalletPassphrase(old_wallet_passphrase,
                                                    new_wallet_passphrase);
         }
         bool backupWallet(const std::string &filename) override {
             return m_wallet.BackupWallet(filename);
         }
         std::string getWalletName() override { return m_wallet.GetName(); }
         const CChainParams &getChainParams() override {
             return m_wallet.chainParams;
         }
         bool getPubKey(const CKeyID &address, CPubKey &pub_key) override {
             return m_wallet.GetPubKey(address, pub_key);
         }
         bool getPrivKey(const CKeyID &address, CKey &key) override {
             return m_wallet.GetKey(address, key);
         }
         bool isSpendable(const CTxDestination &dest) override {
             return IsMine(m_wallet, dest) & ISMINE_SPENDABLE;
         }
         bool haveWatchOnly() override { return m_wallet.HaveWatchOnly(); };
         bool setAddressBook(const CTxDestination &dest, const std::string &name,
                             const std::string &purpose) override {
             return m_wallet.SetAddressBook(dest, name, purpose);
         }
         bool getAddress(const CTxDestination &dest, std::string *name,
                         isminetype *is_mine) override {
             LOCK(m_wallet.cs_wallet);
             auto it = m_wallet.mapAddressBook.find(dest);
             if (it == m_wallet.mapAddressBook.end()) {
                 return false;
             }
             if (name) {
                 *name = it->second.name;
             }
             if (is_mine) {
                 *is_mine = IsMine(m_wallet, dest);
             }
             return true;
         }
         bool addDestData(const CTxDestination &dest, const std::string &key,
                          const std::string &value) override {
             LOCK(m_wallet.cs_wallet);
             return m_wallet.AddDestData(dest, key, value);
         }
         bool eraseDestData(const CTxDestination &dest,
                            const std::string &key) override {
             LOCK(m_wallet.cs_wallet);
             return m_wallet.EraseDestData(dest, key);
         }
         std::vector<std::string>
         getDestValues(const std::string &prefix) override {
             return m_wallet.GetDestValues(prefix);
         }
         void lockCoin(const COutPoint &output) override {
             LOCK2(cs_main, m_wallet.cs_wallet);
             return m_wallet.LockCoin(output);
         }
         void unlockCoin(const COutPoint &output) override {
             LOCK2(cs_main, m_wallet.cs_wallet);
             return m_wallet.UnlockCoin(output);
         }
         bool isLockedCoin(const COutPoint &output) override {
             LOCK2(cs_main, m_wallet.cs_wallet);
             return m_wallet.IsLockedCoin(output.GetTxId(), output.GetN());
         }
         void listLockedCoins(std::vector<COutPoint> &outputs) override {
             LOCK2(cs_main, m_wallet.cs_wallet);
             return m_wallet.ListLockedCoins(outputs);
         }
         std::unique_ptr<PendingWalletTx>
         createTransaction(const std::vector<CRecipient> &recipients,
                           const CCoinControl &coin_control, bool sign,
                           int &change_pos, Amount &fee,
                           std::string &fail_reason) override {
             LOCK2(cs_main, m_wallet.cs_wallet);
             auto pending = std::make_unique<PendingWalletTxImpl>(m_wallet);
             if (!m_wallet.CreateTransaction(recipients, pending->m_tx,
                                             pending->m_key, fee, change_pos,
                                             fail_reason, coin_control, sign)) {
                 return {};
             }
             return std::move(pending);
         }
         bool transactionCanBeAbandoned(const TxId &txid) override {
             return m_wallet.TransactionCanBeAbandoned(txid);
         }
         bool abandonTransaction(const TxId &txid) override {
             LOCK2(cs_main, m_wallet.cs_wallet);
             return m_wallet.AbandonTransaction(txid);
         }
         WalletBalances getBalances() override {
             WalletBalances result;
             result.balance = m_wallet.GetBalance();
             result.unconfirmed_balance = m_wallet.GetUnconfirmedBalance();
             result.immature_balance = m_wallet.GetImmatureBalance();
             result.have_watch_only = m_wallet.HaveWatchOnly();
             if (result.have_watch_only) {
                 result.watch_only_balance = m_wallet.GetWatchOnlyBalance();
                 result.unconfirmed_watch_only_balance =
                     m_wallet.GetUnconfirmedWatchOnlyBalance();
                 result.immature_watch_only_balance =
                     m_wallet.GetImmatureWatchOnlyBalance();
             }
             return result;
         }
         bool tryGetBalances(WalletBalances &balances,
                             int &num_blocks) override {
             TRY_LOCK(cs_main, locked_chain);
             if (!locked_chain) {
                 return false;
             }
             TRY_LOCK(m_wallet.cs_wallet, locked_wallet);
             if (!locked_wallet) {
                 return false;
             }
             balances = getBalances();
             num_blocks = ::chainActive.Height();
             return true;
         }
         Amount getBalance() override { return m_wallet.GetBalance(); }
         Amount getAvailableBalance(const CCoinControl &coin_control) override {
             return m_wallet.GetAvailableBalance(&coin_control);
         }
+        CoinsList listCoins() override {
+            LOCK2(::cs_main, m_wallet.cs_wallet);
+            CoinsList result;
+            for (const auto &entry : m_wallet.ListCoins()) {
+                auto &group = result[entry.first];
+                for (const auto &coin : entry.second) {
+                    group.emplace_back(COutPoint(coin.tx->GetId(), coin.i),
+                                       MakeWalletTxOut(m_wallet, *coin.tx,
+                                                       coin.i, coin.nDepth));
+                }
+            }
+            return result;
+        }
+        std::vector<WalletTxOut>
+        getCoins(const std::vector<COutPoint> &outputs) override {
+            LOCK2(::cs_main, m_wallet.cs_wallet);
+            std::vector<WalletTxOut> result;
+            result.reserve(outputs.size());
+            for (const auto &output : outputs) {
+                result.emplace_back();
+                auto it = m_wallet.mapWallet.find(output.GetTxId());
+                if (it != m_wallet.mapWallet.end()) {
+                    int depth = it->second.GetDepthInMainChain();
+                    if (depth >= 0) {
+                        result.back() = MakeWalletTxOut(m_wallet, it->second,
+                                                        output.GetN(), depth);
+                    }
+                }
+            }
+            return result;
+        }
         bool hdEnabled() override { return m_wallet.IsHDEnabled(); }
         std::unique_ptr<Handler>
         handleShowProgress(ShowProgressFn fn) override {
             return MakeHandler(m_wallet.ShowProgress.connect(fn));
         }
         std::unique_ptr<Handler>
         handleStatusChanged(StatusChangedFn fn) override {
             return MakeHandler(m_wallet.NotifyStatusChanged.connect(
                 [fn](CCryptoKeyStore *) { fn(); }));
         }
         std::unique_ptr<Handler>
         handleAddressBookChanged(AddressBookChangedFn fn) override {
             return MakeHandler(m_wallet.NotifyAddressBookChanged.connect(
                 [fn](CWallet *, const CTxDestination &address,
                      const std::string &label, bool is_mine,
                      const std::string &purpose, ChangeType status) {
                     fn(address, label, is_mine, purpose, status);
                 }));
         }
         std::unique_ptr<Handler>
         handleTransactionChanged(TransactionChangedFn fn) override {
             return MakeHandler(m_wallet.NotifyTransactionChanged.connect(
                 [fn, this](CWallet *, const TxId &txid, ChangeType status) {
                     fn(txid, status);
                 }));
         }
         std::unique_ptr<Handler>
         handleWatchOnlyChanged(WatchOnlyChangedFn fn) override {
             return MakeHandler(m_wallet.NotifyWatchonlyChanged.connect(fn));
         }
 
         CWallet &m_wallet;
     };
 
 } // namespace
 
 std::unique_ptr<Wallet> MakeWallet(CWallet &wallet) {
     return std::make_unique<WalletImpl>(wallet);
 }
 
 } // namespace interfaces
diff --git a/src/interfaces/wallet.h b/src/interfaces/wallet.h
index e7cd542d59..2d3660fedd 100644
--- a/src/interfaces/wallet.h
+++ b/src/interfaces/wallet.h
@@ -1,221 +1,242 @@
 // 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_WALLET_H
 #define BITCOIN_INTERFACES_WALLET_H
 
 #include <amount.h>                    // For Amount
+#include <primitives/transaction.h>    // For CTxOut
 #include <script/ismine.h>             // For isminefilter, isminetype
 #include <script/standard.h>           // For CTxDestination
 #include <support/allocators/secure.h> // For SecureString
 #include <ui_interface.h>              // For ChangeType
 
 #include <cstdint>
 #include <functional>
 #include <map>
 #include <memory>
 #include <string>
+#include <tuple>
 #include <utility>
 #include <vector>
 
 class CChainParams;
 class CCoinControl;
 class CKey;
 class CMutableTransaction;
 class COutPoint;
 class CTransaction;
 class CWallet;
 enum class OutputType;
 struct CRecipient;
 struct TxId;
 
 namespace interfaces {
 
 class Handler;
 class PendingWalletTx;
 struct WalletBalances;
+struct WalletTxOut;
 
 using WalletOrderForm = std::vector<std::pair<std::string, std::string>>;
 using WalletValueMap = std::map<std::string, std::string>;
 
 //! Interface for accessing a wallet.
 class Wallet {
 public:
     virtual ~Wallet() {}
 
     //! Encrypt wallet.
     virtual bool encryptWallet(const SecureString &wallet_passphrase) = 0;
 
     //! Return whether wallet is encrypted.
     virtual bool isCrypted() = 0;
 
     //! Lock wallet.
     virtual bool lock() = 0;
 
     //! Unlock wallet.
     virtual bool unlock(const SecureString &wallet_passphrase) = 0;
 
     //! Return whether wallet is locked.
     virtual bool isLocked() = 0;
 
     //! Change wallet passphrase.
     virtual bool
     changeWalletPassphrase(const SecureString &old_wallet_passphrase,
                            const SecureString &new_wallet_passphrase) = 0;
 
     //! Back up wallet.
     virtual bool backupWallet(const std::string &filename) = 0;
 
     //! Get wallet name.
     virtual std::string getWalletName() = 0;
 
     //! Get chainparams.
     virtual const CChainParams &getChainParams() = 0;
 
     //! Get public key.
     virtual bool getPubKey(const CKeyID &address, CPubKey &pub_key) = 0;
 
     //! Get private key.
     virtual bool getPrivKey(const CKeyID &address, CKey &key) = 0;
 
     //! Return whether wallet has private key.
     virtual bool isSpendable(const CTxDestination &dest) = 0;
 
     //! Return whether wallet has watch only keys.
     virtual bool haveWatchOnly() = 0;
 
     //! Add or update address.
     virtual bool setAddressBook(const CTxDestination &dest,
                                 const std::string &name,
                                 const std::string &purpose) = 0;
 
     //! Look up address in wallet, return whether exists.
     virtual bool getAddress(const CTxDestination &dest,
                             std::string *name = nullptr,
                             isminetype *is_mine = nullptr) = 0;
 
     //! Add dest data.
     virtual bool addDestData(const CTxDestination &dest, const std::string &key,
                              const std::string &value) = 0;
 
     //! Erase dest data.
     virtual bool eraseDestData(const CTxDestination &dest,
                                const std::string &key) = 0;
 
     //! Get dest values with prefix.
     virtual std::vector<std::string>
     getDestValues(const std::string &prefix) = 0;
 
     //! Lock coin.
     virtual void lockCoin(const COutPoint &output) = 0;
 
     //! Unlock coin.
     virtual void unlockCoin(const COutPoint &output) = 0;
 
     //! Return whether coin is locked.
     virtual bool isLockedCoin(const COutPoint &output) = 0;
 
     //! List locked coins.
     virtual void listLockedCoins(std::vector<COutPoint> &outputs) = 0;
 
     //! Create transaction.
     virtual std::unique_ptr<PendingWalletTx>
     createTransaction(const std::vector<CRecipient> &recipients,
                       const CCoinControl &coin_control, bool sign,
                       int &change_pos, Amount &fee,
                       std::string &fail_reason) = 0;
 
     //! Return whether transaction can be abandoned.
     virtual bool transactionCanBeAbandoned(const TxId &txid) = 0;
 
     //! Abandon transaction.
     virtual bool abandonTransaction(const TxId &txid) = 0;
 
     //! Get balances.
     virtual WalletBalances getBalances() = 0;
 
     //! Get balances if possible without blocking.
     virtual bool tryGetBalances(WalletBalances &balances, int &num_blocks) = 0;
 
     //! Get balance.
     virtual Amount getBalance() = 0;
 
     //! Get available balance.
     virtual Amount getAvailableBalance(const CCoinControl &coin_control) = 0;
 
+    //! Return AvailableCoins + LockedCoins grouped by wallet address.
+    //! (put change in one group with wallet address)
+    using CoinsList = std::map<CTxDestination,
+                               std::vector<std::tuple<COutPoint, WalletTxOut>>>;
+    virtual CoinsList listCoins() = 0;
+
+    //! Return wallet transaction output information.
+    virtual std::vector<WalletTxOut>
+    getCoins(const std::vector<COutPoint> &outputs) = 0;
+
     // Return whether HD enabled.
     virtual bool hdEnabled() = 0;
 
     //! Register handler for show progress messages.
     using ShowProgressFn =
         std::function<void(const std::string &title, int progress)>;
     virtual std::unique_ptr<Handler> handleShowProgress(ShowProgressFn fn) = 0;
 
     //! Register handler for status changed messages.
     using StatusChangedFn = std::function<void()>;
     virtual std::unique_ptr<Handler>
     handleStatusChanged(StatusChangedFn fn) = 0;
 
     //! Register handler for address book changed messages.
     using AddressBookChangedFn = std::function<void(
         const CTxDestination &address, const std::string &label, bool is_mine,
         const std::string &purpose, ChangeType status)>;
     virtual std::unique_ptr<Handler>
     handleAddressBookChanged(AddressBookChangedFn fn) = 0;
 
     //! Register handler for transaction changed messages.
     using TransactionChangedFn =
         std::function<void(const TxId &txid, ChangeType status)>;
     virtual std::unique_ptr<Handler>
     handleTransactionChanged(TransactionChangedFn fn) = 0;
 
     //! Register handler for watchonly changed messages.
     using WatchOnlyChangedFn = std::function<void(bool have_watch_only)>;
     virtual std::unique_ptr<Handler>
     handleWatchOnlyChanged(WatchOnlyChangedFn fn) = 0;
 };
 
 //! Tracking object returned by CreateTransaction and passed to
 //! CommitTransaction.
 class PendingWalletTx {
 public:
     virtual ~PendingWalletTx() {}
 
     //! Get transaction data.
     virtual const CTransaction &get() = 0;
 
     //! Send pending transaction and commit to wallet.
     virtual bool commit(WalletValueMap value_map, WalletOrderForm order_form,
                         std::string from_account,
                         std::string &reject_reason) = 0;
 };
 
 //! Collection of wallet balances.
 struct WalletBalances {
     Amount balance = Amount::zero();
     Amount unconfirmed_balance = Amount::zero();
     Amount immature_balance = Amount::zero();
     bool have_watch_only = false;
     Amount watch_only_balance = Amount::zero();
     Amount unconfirmed_watch_only_balance = Amount::zero();
     Amount immature_watch_only_balance = Amount::zero();
 
     bool balanceChanged(const WalletBalances &prev) const {
         return balance != prev.balance ||
                unconfirmed_balance != prev.unconfirmed_balance ||
                immature_balance != prev.immature_balance ||
                watch_only_balance != prev.watch_only_balance ||
                unconfirmed_watch_only_balance !=
                    prev.unconfirmed_watch_only_balance ||
                immature_watch_only_balance != prev.immature_watch_only_balance;
     }
 };
 
+//! Wallet transaction output.
+struct WalletTxOut {
+    CTxOut txout;
+    int64_t time;
+    int depth_in_main_chain = -1;
+    bool is_spent = false;
+};
+
 //! Return implementation of Wallet interface. This function will be undefined
 //! in builds where ENABLE_WALLET is false.
 std::unique_ptr<Wallet> MakeWallet(CWallet &wallet);
 
 } // namespace interfaces
 
 #endif // BITCOIN_INTERFACES_WALLET_H
diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp
index 4deeb972d7..b173178cdb 100644
--- a/src/qt/coincontroldialog.cpp
+++ b/src/qt/coincontroldialog.cpp
@@ -1,836 +1,834 @@
 // 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 "coincontroldialog.h"
-#include "ui_coincontroldialog.h"
-
-#include "addresstablemodel.h"
-#include "bitcoinunits.h"
-#include "guiutil.h"
-#include "optionsmodel.h"
-#include "platformstyle.h"
-#include "txmempool.h"
-#include "walletmodel.h"
-
-#include "dstencode.h"
-#include "init.h"
-#include "policy/policy.h"
-#include "validation.h" // For mempool
-#include "wallet/coincontrol.h"
-#include "wallet/fees.h"
-#include "wallet/wallet.h"
+#include <qt/coincontroldialog.h>
+#include <qt/forms/ui_coincontroldialog.h>
+
+#include <dstencode.h>
+#include <interfaces/node.h>
+#include <policy/policy.h>
+#include <qt/addresstablemodel.h>
+#include <qt/bitcoinunits.h>
+#include <qt/guiutil.h>
+#include <qt/optionsmodel.h>
+#include <qt/platformstyle.h>
+#include <qt/walletmodel.h>
+#include <txmempool.h>
+#include <validation.h> // For mempool
+#include <wallet/coincontrol.h>
+#include <wallet/fees.h>
+#include <wallet/wallet.h>
 
 #include <QApplication>
 #include <QCheckBox>
 #include <QCursor>
 #include <QDialogButtonBox>
 #include <QFlags>
 #include <QIcon>
 #include <QSettings>
 #include <QString>
 #include <QTreeWidget>
 #include <QTreeWidgetItem>
 
 QList<Amount> CoinControlDialog::payAmounts;
 bool CoinControlDialog::fSubtractFeeFromAmount = false;
 
 bool CCoinControlWidgetItem::operator<(const QTreeWidgetItem &other) const {
     int column = treeWidget()->sortColumn();
     if (column == CoinControlDialog::COLUMN_AMOUNT ||
         column == CoinControlDialog::COLUMN_DATE ||
         column == CoinControlDialog::COLUMN_CONFIRMATIONS)
         return data(column, Qt::UserRole).toLongLong() <
                other.data(column, Qt::UserRole).toLongLong();
     return QTreeWidgetItem::operator<(other);
 }
 
 CoinControlDialog::CoinControlDialog(const PlatformStyle *_platformStyle,
                                      QWidget *parent)
     : QDialog(parent), ui(new Ui::CoinControlDialog), model(0),
       platformStyle(_platformStyle) {
     ui->setupUi(this);
 
     // context menu actions
     QAction *copyAddressAction = new QAction(tr("Copy address"), this);
     QAction *copyLabelAction = new QAction(tr("Copy label"), this);
     QAction *copyAmountAction = new QAction(tr("Copy amount"), this);
     // we need to enable/disable this
     copyTransactionHashAction = new QAction(tr("Copy transaction ID"), this);
     // we need to enable/disable this
     lockAction = new QAction(tr("Lock unspent"), this);
     // we need to enable/disable this
     unlockAction = new QAction(tr("Unlock unspent"), this);
 
     // context menu
     contextMenu = new QMenu(this);
     contextMenu->addAction(copyAddressAction);
     contextMenu->addAction(copyLabelAction);
     contextMenu->addAction(copyAmountAction);
     contextMenu->addAction(copyTransactionHashAction);
     contextMenu->addSeparator();
     contextMenu->addAction(lockAction);
     contextMenu->addAction(unlockAction);
 
     // context menu signals
     connect(ui->treeWidget, SIGNAL(customContextMenuRequested(QPoint)), this,
             SLOT(showMenu(QPoint)));
     connect(copyAddressAction, SIGNAL(triggered()), this, SLOT(copyAddress()));
     connect(copyLabelAction, SIGNAL(triggered()), this, SLOT(copyLabel()));
     connect(copyAmountAction, SIGNAL(triggered()), this, SLOT(copyAmount()));
     connect(copyTransactionHashAction, SIGNAL(triggered()), this,
             SLOT(copyTransactionHash()));
     connect(lockAction, SIGNAL(triggered()), this, SLOT(lockCoin()));
     connect(unlockAction, SIGNAL(triggered()), this, SLOT(unlockCoin()));
 
     // 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(clipboardQuantity()));
     connect(clipboardAmountAction, SIGNAL(triggered()), this,
             SLOT(clipboardAmount()));
     connect(clipboardFeeAction, SIGNAL(triggered()), this,
             SLOT(clipboardFee()));
     connect(clipboardAfterFeeAction, SIGNAL(triggered()), this,
             SLOT(clipboardAfterFee()));
     connect(clipboardBytesAction, SIGNAL(triggered()), this,
             SLOT(clipboardBytes()));
     connect(clipboardLowOutputAction, SIGNAL(triggered()), this,
             SLOT(clipboardLowOutput()));
     connect(clipboardChangeAction, SIGNAL(triggered()), this,
             SLOT(clipboardChange()));
 
     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);
 
     // toggle tree/list mode
     connect(ui->radioTreeMode, SIGNAL(toggled(bool)), this,
             SLOT(radioTreeMode(bool)));
     connect(ui->radioListMode, SIGNAL(toggled(bool)), this,
             SLOT(radioListMode(bool)));
 
     // click on checkbox
     connect(ui->treeWidget, SIGNAL(itemChanged(QTreeWidgetItem *, int)), this,
             SLOT(viewItemChanged(QTreeWidgetItem *, int)));
 
     // click on header
     ui->treeWidget->header()->setSectionsClickable(true);
     connect(ui->treeWidget->header(), SIGNAL(sectionClicked(int)), this,
             SLOT(headerSectionClicked(int)));
 
     // ok button
     connect(ui->buttonBox, SIGNAL(clicked(QAbstractButton *)), this,
             SLOT(buttonBoxClicked(QAbstractButton *)));
 
     // (un)select all
     connect(ui->pushButtonSelectAll, SIGNAL(clicked()), this,
             SLOT(buttonSelectAllClicked()));
 
     // change coin control first column label due Qt4 bug.
     // see https://github.com/bitcoin/bitcoin/issues/5716
     ui->treeWidget->headerItem()->setText(COLUMN_CHECKBOX, QString());
 
     ui->treeWidget->setColumnWidth(COLUMN_CHECKBOX, 84);
     ui->treeWidget->setColumnWidth(COLUMN_AMOUNT, 110);
     ui->treeWidget->setColumnWidth(COLUMN_LABEL, 190);
     ui->treeWidget->setColumnWidth(COLUMN_ADDRESS, 320);
     ui->treeWidget->setColumnWidth(COLUMN_DATE, 130);
     ui->treeWidget->setColumnWidth(COLUMN_CONFIRMATIONS, 110);
     // store transaction hash in this column, but don't show it
     ui->treeWidget->setColumnHidden(COLUMN_TXHASH, true);
     // store vout index in this column, but don't show it
     ui->treeWidget->setColumnHidden(COLUMN_VOUT_INDEX, true);
 
     // default view is sorted by amount desc
     sortView(COLUMN_AMOUNT, Qt::DescendingOrder);
 
     // restore list mode and sortorder as a convenience feature
     QSettings settings;
     if (settings.contains("nCoinControlMode") &&
         !settings.value("nCoinControlMode").toBool())
         ui->radioTreeMode->click();
     if (settings.contains("nCoinControlSortColumn") &&
         settings.contains("nCoinControlSortOrder"))
         sortView(settings.value("nCoinControlSortColumn").toInt(),
                  (static_cast<Qt::SortOrder>(
                      settings.value("nCoinControlSortOrder").toInt())));
 }
 
 CoinControlDialog::~CoinControlDialog() {
     QSettings settings;
     settings.setValue("nCoinControlMode", ui->radioListMode->isChecked());
     settings.setValue("nCoinControlSortColumn", sortColumn);
     settings.setValue("nCoinControlSortOrder", (int)sortOrder);
 
     delete ui;
 }
 
 void CoinControlDialog::setModel(WalletModel *_model) {
     this->model = _model;
 
     if (_model && _model->getOptionsModel() && _model->getAddressTableModel()) {
         updateView();
         updateLabelLocked();
         CoinControlDialog::updateLabels(_model, this);
     }
 }
 
 // ok button
 void CoinControlDialog::buttonBoxClicked(QAbstractButton *button) {
     if (ui->buttonBox->buttonRole(button) == QDialogButtonBox::AcceptRole) {
         // closes the dialog
         done(QDialog::Accepted);
     }
 }
 
 // (un)select all
 void CoinControlDialog::buttonSelectAllClicked() {
     Qt::CheckState state = Qt::Checked;
     for (int i = 0; i < ui->treeWidget->topLevelItemCount(); i++) {
         if (ui->treeWidget->topLevelItem(i)->checkState(COLUMN_CHECKBOX) !=
             Qt::Unchecked) {
             state = Qt::Unchecked;
             break;
         }
     }
     ui->treeWidget->setEnabled(false);
     for (int i = 0; i < ui->treeWidget->topLevelItemCount(); i++)
         if (ui->treeWidget->topLevelItem(i)->checkState(COLUMN_CHECKBOX) !=
             state) {
             ui->treeWidget->topLevelItem(i)->setCheckState(COLUMN_CHECKBOX,
                                                            state);
         }
     ui->treeWidget->setEnabled(true);
     if (state == Qt::Unchecked) {
         // just to be sure
         coinControl()->UnSelectAll();
     }
     CoinControlDialog::updateLabels(model, this);
 }
 
 // context menu
 void CoinControlDialog::showMenu(const QPoint &point) {
     QTreeWidgetItem *item = ui->treeWidget->itemAt(point);
     if (item) {
         contextMenuItem = item;
 
         // disable some items (like Copy Transaction ID, lock, unlock) for tree
         // roots in context menu
         if (item->text(COLUMN_TXHASH).length() == 64) {
             TxId txid;
             txid.SetHex(item->text(COLUMN_TXHASH).toStdString());
 
             // transaction hash is 64 characters (this means its a child node,
             // so its not a parent node in tree mode)
             copyTransactionHashAction->setEnabled(true);
             if (model->wallet().isLockedCoin(
                     COutPoint(txid, item->text(COLUMN_VOUT_INDEX).toUInt()))) {
                 lockAction->setEnabled(false);
                 unlockAction->setEnabled(true);
             } else {
                 lockAction->setEnabled(true);
                 unlockAction->setEnabled(false);
             }
         } else {
             // this means click on parent node in tree mode -> disable all
             copyTransactionHashAction->setEnabled(false);
             lockAction->setEnabled(false);
             unlockAction->setEnabled(false);
         }
 
         // show context menu
         contextMenu->exec(QCursor::pos());
     }
 }
 
 // context menu action: copy amount
 void CoinControlDialog::copyAmount() {
     GUIUtil::setClipboard(
         BitcoinUnits::removeSpaces(contextMenuItem->text(COLUMN_AMOUNT)));
 }
 
 // context menu action: copy label
 void CoinControlDialog::copyLabel() {
     if (ui->radioTreeMode->isChecked() &&
         contextMenuItem->text(COLUMN_LABEL).length() == 0 &&
         contextMenuItem->parent()) {
         GUIUtil::setClipboard(contextMenuItem->parent()->text(COLUMN_LABEL));
     } else {
         GUIUtil::setClipboard(contextMenuItem->text(COLUMN_LABEL));
     }
 }
 
 // context menu action: copy address
 void CoinControlDialog::copyAddress() {
     if (ui->radioTreeMode->isChecked() &&
         contextMenuItem->text(COLUMN_ADDRESS).length() == 0 &&
         contextMenuItem->parent()) {
         GUIUtil::setClipboard(contextMenuItem->parent()->text(COLUMN_ADDRESS));
     } else {
         GUIUtil::setClipboard(contextMenuItem->text(COLUMN_ADDRESS));
     }
 }
 
 // context menu action: copy transaction id
 void CoinControlDialog::copyTransactionHash() {
     GUIUtil::setClipboard(contextMenuItem->text(COLUMN_TXHASH));
 }
 
 // context menu action: lock coin
 void CoinControlDialog::lockCoin() {
     if (contextMenuItem->checkState(COLUMN_CHECKBOX) == Qt::Checked) {
         contextMenuItem->setCheckState(COLUMN_CHECKBOX, Qt::Unchecked);
     }
 
     COutPoint outpt(
         uint256S(contextMenuItem->text(COLUMN_TXHASH).toStdString()),
         contextMenuItem->text(COLUMN_VOUT_INDEX).toUInt());
     model->wallet().lockCoin(outpt);
     contextMenuItem->setDisabled(true);
     contextMenuItem->setIcon(
         COLUMN_CHECKBOX, platformStyle->SingleColorIcon(":/icons/lock_closed"));
     updateLabelLocked();
 }
 
 // context menu action: unlock coin
 void CoinControlDialog::unlockCoin() {
     COutPoint outpt(
         uint256S(contextMenuItem->text(COLUMN_TXHASH).toStdString()),
         contextMenuItem->text(COLUMN_VOUT_INDEX).toUInt());
     model->wallet().unlockCoin(outpt);
     contextMenuItem->setDisabled(false);
     contextMenuItem->setIcon(COLUMN_CHECKBOX, QIcon());
     updateLabelLocked();
 }
 
 // copy label "Quantity" to clipboard
 void CoinControlDialog::clipboardQuantity() {
     GUIUtil::setClipboard(ui->labelCoinControlQuantity->text());
 }
 
 // copy label "Amount" to clipboard
 void CoinControlDialog::clipboardAmount() {
     GUIUtil::setClipboard(ui->labelCoinControlAmount->text().left(
         ui->labelCoinControlAmount->text().indexOf(" ")));
 }
 
 // copy label "Fee" to clipboard
 void CoinControlDialog::clipboardFee() {
     GUIUtil::setClipboard(
         ui->labelCoinControlFee->text()
             .left(ui->labelCoinControlFee->text().indexOf(" "))
             .replace(ASYMP_UTF8, ""));
 }
 
 // copy label "After fee" to clipboard
 void CoinControlDialog::clipboardAfterFee() {
     GUIUtil::setClipboard(
         ui->labelCoinControlAfterFee->text()
             .left(ui->labelCoinControlAfterFee->text().indexOf(" "))
             .replace(ASYMP_UTF8, ""));
 }
 
 // copy label "Bytes" to clipboard
 void CoinControlDialog::clipboardBytes() {
     GUIUtil::setClipboard(
         ui->labelCoinControlBytes->text().replace(ASYMP_UTF8, ""));
 }
 
 // copy label "Dust" to clipboard
 void CoinControlDialog::clipboardLowOutput() {
     GUIUtil::setClipboard(ui->labelCoinControlLowOutput->text());
 }
 
 // copy label "Change" to clipboard
 void CoinControlDialog::clipboardChange() {
     GUIUtil::setClipboard(
         ui->labelCoinControlChange->text()
             .left(ui->labelCoinControlChange->text().indexOf(" "))
             .replace(ASYMP_UTF8, ""));
 }
 
 // treeview: sort
 void CoinControlDialog::sortView(int column, Qt::SortOrder order) {
     sortColumn = column;
     sortOrder = order;
     ui->treeWidget->sortItems(column, order);
     ui->treeWidget->header()->setSortIndicator(sortColumn, sortOrder);
 }
 
 // treeview: clicked on header
 void CoinControlDialog::headerSectionClicked(int logicalIndex) {
     // click on most left column -> do nothing
     if (logicalIndex == COLUMN_CHECKBOX) {
         ui->treeWidget->header()->setSortIndicator(sortColumn, sortOrder);
     } else {
         if (sortColumn == logicalIndex) {
             sortOrder =
                 ((sortOrder == Qt::AscendingOrder) ? Qt::DescendingOrder
                                                    : Qt::AscendingOrder);
         } else {
             sortColumn = logicalIndex;
             // if label or address then default => asc, else default => desc
             sortOrder =
                 ((sortColumn == COLUMN_LABEL || sortColumn == COLUMN_ADDRESS)
                      ? Qt::AscendingOrder
                      : Qt::DescendingOrder);
         }
 
         sortView(sortColumn, sortOrder);
     }
 }
 
 // toggle tree mode
 void CoinControlDialog::radioTreeMode(bool checked) {
     if (checked && model) {
         updateView();
     }
 }
 
 // toggle list mode
 void CoinControlDialog::radioListMode(bool checked) {
     if (checked && model) {
         updateView();
     }
 }
 
 // checkbox clicked by user
 void CoinControlDialog::viewItemChanged(QTreeWidgetItem *item, int column) {
     // transaction hash is 64 characters (this means its a child node, so its
     // not a parent node in tree mode)
     if (column == COLUMN_CHECKBOX && item->text(COLUMN_TXHASH).length() == 64) {
         COutPoint outpt(uint256S(item->text(COLUMN_TXHASH).toStdString()),
                         item->text(COLUMN_VOUT_INDEX).toUInt());
 
         if (item->checkState(COLUMN_CHECKBOX) == Qt::Unchecked) {
             coinControl()->UnSelect(outpt);
         } else if (item->isDisabled()) {
             // locked (this happens if "check all" through parent node)
             item->setCheckState(COLUMN_CHECKBOX, Qt::Unchecked);
         } else {
             coinControl()->Select(outpt);
         }
 
         // selection changed -> update labels
         if (ui->treeWidget->isEnabled()) {
             // do not update on every click for (un)select all
             CoinControlDialog::updateLabels(model, this);
         }
     }
 
     // TODO: Remove this temporary qt5 fix after Qt5.3 and Qt5.4 are no longer
     // used.
     // Fixed in Qt5.5 and above: https://bugreports.qt.io/browse/QTBUG-43473
     else if (column == COLUMN_CHECKBOX && item->childCount() > 0) {
         if (item->checkState(COLUMN_CHECKBOX) == Qt::PartiallyChecked &&
             item->child(0)->checkState(COLUMN_CHECKBOX) ==
                 Qt::PartiallyChecked) {
             item->setCheckState(COLUMN_CHECKBOX, Qt::Checked);
         }
     }
 }
 
 // shows count of locked unspent outputs
 void CoinControlDialog::updateLabelLocked() {
     std::vector<COutPoint> vOutpts;
     model->wallet().listLockedCoins(vOutpts);
     if (vOutpts.size() > 0) {
         ui->labelLocked->setText(tr("(%1 locked)").arg(vOutpts.size()));
         ui->labelLocked->setVisible(true);
     } else {
         ui->labelLocked->setVisible(false);
     }
 }
 
 void CoinControlDialog::updateLabels(WalletModel *model, QDialog *dialog) {
     if (!model) {
         return;
     }
 
     // nPayAmount
     Amount nPayAmount = Amount::zero();
     bool fDust = false;
     CMutableTransaction txDummy;
     for (const Amount amount : CoinControlDialog::payAmounts) {
         nPayAmount += amount;
 
         if (amount > Amount::zero()) {
             CTxOut txout(amount,
                          static_cast<CScript>(std::vector<uint8_t>(24, 0)));
             txDummy.vout.push_back(txout);
-            if (txout.IsDust(dustRelayFee)) {
+            if (txout.IsDust(model->node().getDustRelayFee())) {
                 fDust = true;
             }
         }
     }
 
     Amount nAmount = Amount::zero();
     Amount nPayFee = Amount::zero();
     Amount nAfterFee = Amount::zero();
     Amount nChange = Amount::zero();
     unsigned int nBytes = 0;
     unsigned int nBytesInputs = 0;
     unsigned int nQuantity = 0;
     int nQuantityUncompressed = 0;
 
     std::vector<COutPoint> vCoinControl;
-    std::vector<COutput> vOutputs;
     coinControl()->ListSelected(vCoinControl);
-    model->getOutputs(vCoinControl, vOutputs);
 
-    for (const COutput &out : vOutputs) {
+    size_t i = 0;
+    for (const auto &out : model->wallet().getCoins(vCoinControl)) {
+        if (out.depth_in_main_chain < 0) {
+            continue;
+        }
+
         // unselect already spent, very unlikely scenario, this could happen
         // when selected are spent elsewhere, like rpc or another computer
-        uint256 txhash = out.tx->GetId();
-        COutPoint outpt(txhash, out.i);
-        if (model->isSpent(outpt)) {
+        const COutPoint &outpt = vCoinControl[i++];
+        if (out.is_spent) {
             coinControl()->UnSelect(outpt);
             continue;
         }
 
         // Quantity
         nQuantity++;
 
         // Amount
-        nAmount += out.tx->tx->vout[out.i].nValue;
+        nAmount += out.txout.nValue;
 
         // Bytes
         CTxDestination address;
-        if (ExtractDestination(out.tx->tx->vout[out.i].scriptPubKey, address)) {
+        if (ExtractDestination(out.txout.scriptPubKey, address)) {
             CPubKey pubkey;
             CKeyID *keyid = boost::get<CKeyID>(&address);
             if (keyid && model->wallet().getPubKey(*keyid, pubkey)) {
                 nBytesInputs += (pubkey.IsCompressed() ? 148 : 180);
                 if (!pubkey.IsCompressed()) {
                     nQuantityUncompressed++;
                 }
             } else {
                 // in all error cases, simply assume 148 here
                 nBytesInputs += 148;
             }
         } else {
             nBytesInputs += 148;
         }
     }
 
     // calculation
     if (nQuantity > 0) {
         // Bytes
         // always assume +1 output for change here
         nBytes = nBytesInputs +
                  ((CoinControlDialog::payAmounts.size() > 0
                        ? CoinControlDialog::payAmounts.size() + 1
                        : 2) *
                   34) +
                  10;
 
         // in the subtract fee from amount case, we can tell if zero change
         // already and subtract the bytes, so that fee calculation afterwards is
         // accurate
         if (CoinControlDialog::fSubtractFeeFromAmount) {
             if (nAmount - nPayAmount == Amount::zero()) {
                 nBytes -= 34;
             }
         }
 
         // Fee
-        nPayFee = GetMinimumFee(nBytes, g_mempool, *coinControl());
+        nPayFee = model->node().getMinimumFee(nBytes, *coinControl());
 
         if (nPayAmount > Amount::zero()) {
             nChange = nAmount - nPayAmount;
             if (!CoinControlDialog::fSubtractFeeFromAmount) {
                 nChange -= nPayFee;
             }
 
             // Never create dust outputs; if we would, just add the dust to the
             // fee.
             if (nChange > Amount::zero() && nChange < MIN_CHANGE) {
                 CTxOut txout(nChange,
                              static_cast<CScript>(std::vector<uint8_t>(24, 0)));
-                if (txout.IsDust(dustRelayFee)) {
+                if (txout.IsDust(model->node().getDustRelayFee())) {
                     // dust-change will be raised until no dust
                     if (CoinControlDialog::fSubtractFeeFromAmount) {
-                        nChange = txout.GetDustThreshold(dustRelayFee);
+                        nChange = txout.GetDustThreshold(
+                            model->node().getDustRelayFee());
                     } else {
                         nPayFee += nChange;
                         nChange = Amount::zero();
                     }
                 }
             }
 
             if (nChange == Amount::zero() &&
                 !CoinControlDialog::fSubtractFeeFromAmount) {
                 nBytes -= 34;
             }
         }
 
         // after fee
         nAfterFee = std::max(nAmount - nPayFee, Amount::zero());
     }
 
     // actually update labels
     int nDisplayUnit = BitcoinUnits::BCH;
     if (model && model->getOptionsModel()) {
         nDisplayUnit = model->getOptionsModel()->getDisplayUnit();
     }
 
     QLabel *l1 = dialog->findChild<QLabel *>("labelCoinControlQuantity");
     QLabel *l2 = dialog->findChild<QLabel *>("labelCoinControlAmount");
     QLabel *l3 = dialog->findChild<QLabel *>("labelCoinControlFee");
     QLabel *l4 = dialog->findChild<QLabel *>("labelCoinControlAfterFee");
     QLabel *l5 = dialog->findChild<QLabel *>("labelCoinControlBytes");
     QLabel *l7 = dialog->findChild<QLabel *>("labelCoinControlLowOutput");
     QLabel *l8 = dialog->findChild<QLabel *>("labelCoinControlChange");
 
     // enable/disable "dust" and "change"
     dialog->findChild<QLabel *>("labelCoinControlLowOutputText")
         ->setEnabled(nPayAmount > Amount::zero());
     dialog->findChild<QLabel *>("labelCoinControlLowOutput")
         ->setEnabled(nPayAmount > Amount::zero());
     dialog->findChild<QLabel *>("labelCoinControlChangeText")
         ->setEnabled(nPayAmount > Amount::zero());
     dialog->findChild<QLabel *>("labelCoinControlChange")
         ->setEnabled(nPayAmount > Amount::zero());
 
     // stats
     // Quantity
     l1->setText(QString::number(nQuantity));
     // Amount
     l2->setText(BitcoinUnits::formatWithUnit(nDisplayUnit, nAmount));
     // Fee
     l3->setText(BitcoinUnits::formatWithUnit(nDisplayUnit, nPayFee));
     // After Fee
     l4->setText(BitcoinUnits::formatWithUnit(nDisplayUnit, nAfterFee));
     // Bytes
     l5->setText(((nBytes > 0) ? ASYMP_UTF8 : "") + QString::number(nBytes));
     // Dust
     l7->setText(fDust ? tr("yes") : tr("no"));
     // Change
     l8->setText(BitcoinUnits::formatWithUnit(nDisplayUnit, nChange));
     if (nPayFee > Amount::zero()) {
         l3->setText(ASYMP_UTF8 + l3->text());
         l4->setText(ASYMP_UTF8 + l4->text());
         if (nChange > Amount::zero() &&
             !CoinControlDialog::fSubtractFeeFromAmount) {
             l8->setText(ASYMP_UTF8 + l8->text());
         }
     }
 
     // turn label red when dust
     l7->setStyleSheet((fDust) ? "color:red;" : "");
 
     // tool tips
     QString toolTipDust =
         tr("This label turns red if any recipient receives an amount smaller "
            "than the current dust threshold.");
 
     // how many satoshis the estimated fee can vary per byte we guess wrong
     double dFeeVary = GetMinimumFee(1000, g_mempool) / (1000 * SATOSHI);
 
     QString toolTip4 =
         tr("Can vary +/- %1 satoshi(s) per input.").arg(dFeeVary);
 
     l3->setToolTip(toolTip4);
     l4->setToolTip(toolTip4);
     l7->setToolTip(toolTipDust);
     l8->setToolTip(toolTip4);
     dialog->findChild<QLabel *>("labelCoinControlFeeText")
         ->setToolTip(l3->toolTip());
     dialog->findChild<QLabel *>("labelCoinControlAfterFeeText")
         ->setToolTip(l4->toolTip());
     dialog->findChild<QLabel *>("labelCoinControlBytesText")
         ->setToolTip(l5->toolTip());
     dialog->findChild<QLabel *>("labelCoinControlLowOutputText")
         ->setToolTip(l7->toolTip());
     dialog->findChild<QLabel *>("labelCoinControlChangeText")
         ->setToolTip(l8->toolTip());
 
     // Insufficient funds
     QLabel *label = dialog->findChild<QLabel *>("labelCoinControlInsuffFunds");
     if (label) {
         label->setVisible(nChange < Amount::zero());
     }
 }
 
 CCoinControl *CoinControlDialog::coinControl() {
     static CCoinControl coin_control;
     return &coin_control;
 }
 
 void CoinControlDialog::updateView() {
     if (!model || !model->getOptionsModel() || !model->getAddressTableModel()) {
         return;
     }
 
     bool treeMode = ui->radioTreeMode->isChecked();
 
     ui->treeWidget->clear();
     // performance, otherwise updateLabels would be called for every checked
     // checkbox
     ui->treeWidget->setEnabled(false);
     ui->treeWidget->setAlternatingRowColors(!treeMode);
     QFlags<Qt::ItemFlag> flgCheckbox =
         Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsUserCheckable;
     QFlags<Qt::ItemFlag> flgTristate =
         Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsUserCheckable |
         Qt::ItemIsTristate;
 
     int nDisplayUnit = model->getOptionsModel()->getDisplayUnit();
 
-    std::map<QString, std::vector<COutput>> mapCoins;
-    model->listCoins(mapCoins);
-
-    for (const std::pair<QString, std::vector<COutput>> &coins : mapCoins) {
+    for (const auto &coins : model->wallet().listCoins()) {
         CCoinControlWidgetItem *itemWalletAddress =
             new CCoinControlWidgetItem();
         itemWalletAddress->setCheckState(COLUMN_CHECKBOX, Qt::Unchecked);
-        QString sWalletAddress = coins.first;
+        QString sWalletAddress =
+            QString::fromStdString(EncodeDestination(coins.first));
         QString sWalletLabel =
             model->getAddressTableModel()->labelForAddress(sWalletAddress);
         if (sWalletLabel.isEmpty()) {
             sWalletLabel = tr("(no label)");
         }
 
         if (treeMode) {
             // wallet address
             ui->treeWidget->addTopLevelItem(itemWalletAddress);
 
             itemWalletAddress->setFlags(flgTristate);
             itemWalletAddress->setCheckState(COLUMN_CHECKBOX, Qt::Unchecked);
 
             // label
             itemWalletAddress->setText(COLUMN_LABEL, sWalletLabel);
 
             // address
             itemWalletAddress->setText(COLUMN_ADDRESS, sWalletAddress);
         }
 
         Amount nSum = Amount::zero();
         int nChildren = 0;
-        for (const COutput &out : coins.second) {
-            nSum += out.tx->tx->vout[out.i].nValue;
+        for (const auto &outpair : coins.second) {
+            const COutPoint &output = std::get<0>(outpair);
+            const interfaces::WalletTxOut &out = std::get<1>(outpair);
+            nSum += out.txout.nValue;
             nChildren++;
 
             CCoinControlWidgetItem *itemOutput;
             if (treeMode) {
                 itemOutput = new CCoinControlWidgetItem(itemWalletAddress);
             } else {
                 itemOutput = new CCoinControlWidgetItem(ui->treeWidget);
             }
             itemOutput->setFlags(flgCheckbox);
             itemOutput->setCheckState(COLUMN_CHECKBOX, Qt::Unchecked);
 
             // address
             CTxDestination outputAddress;
             QString sAddress = "";
-            if (ExtractDestination(out.tx->tx->vout[out.i].scriptPubKey,
-                                   outputAddress)) {
+            if (ExtractDestination(out.txout.scriptPubKey, outputAddress)) {
                 sAddress =
                     QString::fromStdString(EncodeDestination(outputAddress));
 
                 // if listMode or change => show bitcoin address. In tree mode,
                 // address is not shown again for direct wallet address outputs
                 if (!treeMode || (!(sAddress == sWalletAddress))) {
                     itemOutput->setText(COLUMN_ADDRESS, sAddress);
                 }
             }
 
             // label
             if (!(sAddress == sWalletAddress)) {
                 // change tooltip from where the change comes from
                 itemOutput->setToolTip(COLUMN_LABEL, tr("change from %1 (%2)")
                                                          .arg(sWalletLabel)
                                                          .arg(sWalletAddress));
                 itemOutput->setText(COLUMN_LABEL, tr("(change)"));
             } else if (!treeMode) {
                 QString sLabel =
                     model->getAddressTableModel()->labelForAddress(sAddress);
                 if (sLabel.isEmpty()) {
                     sLabel = tr("(no label)");
                 }
                 itemOutput->setText(COLUMN_LABEL, sLabel);
             }
 
             // amount
             itemOutput->setText(
                 COLUMN_AMOUNT,
-                BitcoinUnits::format(nDisplayUnit,
-                                     out.tx->tx->vout[out.i].nValue));
+                BitcoinUnits::format(nDisplayUnit, out.txout.nValue));
             // padding so that sorting works correctly
             itemOutput->setData(
                 COLUMN_AMOUNT, Qt::UserRole,
-                QVariant(qlonglong(out.tx->tx->vout[out.i].nValue / SATOSHI)));
+                QVariant(qlonglong(out.txout.nValue / SATOSHI)));
 
             // date
-            itemOutput->setText(COLUMN_DATE,
-                                GUIUtil::dateTimeStr(out.tx->GetTxTime()));
+            itemOutput->setText(COLUMN_DATE, GUIUtil::dateTimeStr(out.time));
             itemOutput->setData(COLUMN_DATE, Qt::UserRole,
-                                QVariant((qlonglong)out.tx->GetTxTime()));
+                                QVariant((qlonglong)out.time));
 
             // confirmations
             itemOutput->setText(COLUMN_CONFIRMATIONS,
-                                QString::number(out.nDepth));
+                                QString::number(out.depth_in_main_chain));
             itemOutput->setData(COLUMN_CONFIRMATIONS, Qt::UserRole,
-                                QVariant((qlonglong)out.nDepth));
+                                QVariant((qlonglong)out.depth_in_main_chain));
 
             // transaction id
-            const TxId txid = out.tx->GetId();
-            itemOutput->setText(COLUMN_TXHASH,
-                                QString::fromStdString(txid.GetHex()));
+            itemOutput->setText(COLUMN_TXHASH, QString::fromStdString(
+                                                   output.GetTxId().GetHex()));
 
             // vout index
-            itemOutput->setText(COLUMN_VOUT_INDEX, QString::number(out.i));
+            itemOutput->setText(COLUMN_VOUT_INDEX,
+                                QString::number(output.GetN()));
 
             // disable locked coins
-            if (model->wallet().isLockedCoin(COutPoint(txid, out.i))) {
-                COutPoint outpt(txid, out.i);
+            if (model->wallet().isLockedCoin(output)) {
                 // just to be sure
-                coinControl()->UnSelect(outpt);
+                coinControl()->UnSelect(output);
                 itemOutput->setDisabled(true);
                 itemOutput->setIcon(
                     COLUMN_CHECKBOX,
                     platformStyle->SingleColorIcon(":/icons/lock_closed"));
             }
 
             // set checkbox
-            if (coinControl()->IsSelected(COutPoint(txid, out.i))) {
+            if (coinControl()->IsSelected(output)) {
                 itemOutput->setCheckState(COLUMN_CHECKBOX, Qt::Checked);
             }
         }
 
         // amount
         if (treeMode) {
             itemWalletAddress->setText(COLUMN_CHECKBOX,
                                        "(" + QString::number(nChildren) + ")");
             itemWalletAddress->setText(
                 COLUMN_AMOUNT, BitcoinUnits::format(nDisplayUnit, nSum));
             itemWalletAddress->setData(COLUMN_AMOUNT, Qt::UserRole,
                                        QVariant(qlonglong(nSum / SATOSHI)));
         }
     }
 
     // expand all partially selected
     if (treeMode) {
         for (int i = 0; i < ui->treeWidget->topLevelItemCount(); i++) {
             if (ui->treeWidget->topLevelItem(i)->checkState(COLUMN_CHECKBOX) ==
                 Qt::PartiallyChecked)
                 ui->treeWidget->topLevelItem(i)->setExpanded(true);
         }
     }
 
     // sort view
     sortView(sortColumn, sortOrder);
     ui->treeWidget->setEnabled(true);
 }
diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp
index 57515745da..147c1c0ed2 100644
--- a/src/qt/walletmodel.cpp
+++ b/src/qt/walletmodel.cpp
@@ -1,527 +1,490 @@
 // 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/walletmodel.h>
 
 #include <chain.h>
 #include <config.h>
 #include <consensus/validation.h>
 #include <dstencode.h>
 #include <interfaces/handler.h>
 #include <interfaces/node.h>
 #include <keystore.h>
 #include <net.h> // for g_connman
 #include <qt/addresstablemodel.h>
 #include <qt/guiconstants.h>
 #include <qt/guiutil.h>
 #include <qt/paymentserver.h>
 #include <qt/recentrequeststablemodel.h>
 #include <qt/transactiontablemodel.h>
 #include <sync.h>
 #include <ui_interface.h>
 #include <util.h> // for GetBoolArg
 #include <validation.h>
 #include <wallet/coincontrol.h>
 #include <wallet/wallet.h>
 #include <wallet/walletdb.h> // for BackupWallet
 
 #include <QDebug>
 #include <QSet>
 #include <QTimer>
 
 #include <cstdint>
 
 WalletModel::WalletModel(std::unique_ptr<interfaces::Wallet> wallet,
                          interfaces::Node &node,
                          const PlatformStyle *platformStyle, CWallet *_wallet,
                          OptionsModel *_optionsModel, QObject *parent)
     : QObject(parent), m_wallet(std::move(wallet)), m_node(node),
       cwallet(_wallet), optionsModel(_optionsModel), addressTableModel(0),
       transactionTableModel(0), recentRequestsTableModel(0),
       cachedEncryptionStatus(Unencrypted), cachedNumBlocks(0) {
     fHaveWatchOnly = m_wallet->haveWatchOnly();
     fForceCheckBalanceChanged = false;
 
     addressTableModel = new AddressTableModel(cwallet, this);
     transactionTableModel =
         new TransactionTableModel(platformStyle, cwallet, this);
     recentRequestsTableModel = new RecentRequestsTableModel(cwallet, this);
 
     // This timer will be fired repeatedly to update the balance
     pollTimer = new QTimer(this);
     connect(pollTimer, SIGNAL(timeout()), this, SLOT(pollBalanceChanged()));
     pollTimer->start(MODEL_UPDATE_DELAY);
 
     subscribeToCoreSignals();
 }
 
 WalletModel::~WalletModel() {
     unsubscribeFromCoreSignals();
 }
 
 void WalletModel::updateStatus() {
     EncryptionStatus newEncryptionStatus = getEncryptionStatus();
 
     if (cachedEncryptionStatus != newEncryptionStatus) {
         Q_EMIT encryptionStatusChanged();
     }
 }
 
 void WalletModel::pollBalanceChanged() {
     // Try to get balances and return early if locks can't be acquired. This
     // avoids the GUI from getting stuck on periodical polls if the core is
     // holding the locks for a longer time - for example, during a wallet
     // rescan.
     interfaces::WalletBalances new_balances;
     int numBlocks = -1;
     if (!m_wallet->tryGetBalances(new_balances, numBlocks)) {
         return;
     }
 
     if (fForceCheckBalanceChanged || m_node.getNumBlocks() != cachedNumBlocks) {
         fForceCheckBalanceChanged = false;
 
         // Balance and number of transactions might have changed
         cachedNumBlocks = m_node.getNumBlocks();
 
         checkBalanceChanged(new_balances);
         if (transactionTableModel) {
             transactionTableModel->updateConfirmations();
         }
     }
 }
 
 void WalletModel::checkBalanceChanged(
     const interfaces::WalletBalances &new_balances) {
     if (new_balances.balanceChanged(m_cached_balances)) {
         m_cached_balances = new_balances;
         Q_EMIT balanceChanged(
             new_balances.balance, new_balances.unconfirmed_balance,
             new_balances.immature_balance, new_balances.watch_only_balance,
             new_balances.unconfirmed_watch_only_balance,
             new_balances.immature_watch_only_balance);
     }
 }
 
 void WalletModel::updateTransaction() {
     // Balance and number of transactions might have changed
     fForceCheckBalanceChanged = true;
 }
 
 void WalletModel::updateAddressBook(const QString &address,
                                     const QString &label, bool isMine,
                                     const QString &purpose, int status) {
     if (addressTableModel) {
         addressTableModel->updateEntry(address, label, isMine, purpose, status);
     }
 }
 
 void WalletModel::updateWatchOnlyFlag(bool fHaveWatchonly) {
     fHaveWatchOnly = fHaveWatchonly;
     Q_EMIT notifyWatchonlyChanged(fHaveWatchonly);
 }
 
 bool WalletModel::validateAddress(const QString &address) {
     return IsValidDestinationString(address.toStdString(), getChainParams());
 }
 
 WalletModel::SendCoinsReturn
 WalletModel::prepareTransaction(WalletModelTransaction &transaction,
                                 const CCoinControl &coinControl) {
     Amount total = Amount::zero();
     bool fSubtractFeeFromAmount = false;
     QList<SendCoinsRecipient> recipients = transaction.getRecipients();
     std::vector<CRecipient> vecSend;
 
     if (recipients.empty()) {
         return OK;
     }
 
     // Used to detect duplicates
     QSet<QString> setAddress;
     int nAddresses = 0;
 
     // Pre-check input data for validity
     for (const SendCoinsRecipient &rcp : recipients) {
         if (rcp.fSubtractFeeFromAmount) fSubtractFeeFromAmount = true;
 
         // PaymentRequest...
         if (rcp.paymentRequest.IsInitialized()) {
             Amount subtotal = Amount::zero();
             const payments::PaymentDetails &details =
                 rcp.paymentRequest.getDetails();
             for (int i = 0; i < details.outputs_size(); i++) {
                 const payments::Output &out = details.outputs(i);
                 if (out.amount() <= 0) {
                     continue;
                 }
 
                 subtotal += int64_t(out.amount()) * SATOSHI;
                 const uint8_t *scriptStr = (const uint8_t *)out.script().data();
                 CScript scriptPubKey(scriptStr,
                                      scriptStr + out.script().size());
                 Amount nAmount = int64_t(out.amount()) * SATOSHI;
                 CRecipient recipient = {scriptPubKey, nAmount,
                                         rcp.fSubtractFeeFromAmount};
                 vecSend.push_back(recipient);
             }
 
             if (subtotal <= Amount::zero()) {
                 return InvalidAmount;
             }
             total += subtotal;
         } else {
             // User-entered bitcoin address / amount:
             if (!validateAddress(rcp.address)) {
                 return InvalidAddress;
             }
             if (rcp.amount <= Amount::zero()) {
                 return InvalidAmount;
             }
             setAddress.insert(rcp.address);
             ++nAddresses;
 
             CScript scriptPubKey = GetScriptForDestination(
                 DecodeDestination(rcp.address.toStdString(), getChainParams()));
             CRecipient recipient = {scriptPubKey, Amount(rcp.amount),
                                     rcp.fSubtractFeeFromAmount};
             vecSend.push_back(recipient);
 
             total += rcp.amount;
         }
     }
     if (setAddress.size() != nAddresses) {
         return DuplicateAddress;
     }
 
     Amount nBalance = m_wallet->getAvailableBalance(coinControl);
 
     if (total > nBalance) {
         return AmountExceedsBalance;
     }
 
     Amount nFeeRequired = Amount::zero();
     int nChangePosRet = -1;
     std::string strFailReason;
 
     auto &newTx = transaction.getWtx();
     newTx =
         m_wallet->createTransaction(vecSend, coinControl, true /* sign */,
                                     nChangePosRet, nFeeRequired, strFailReason);
     transaction.setTransactionFee(nFeeRequired);
     if (fSubtractFeeFromAmount && newTx) {
         transaction.reassignAmounts(nChangePosRet);
     }
 
     if (!newTx) {
         if (!fSubtractFeeFromAmount && (total + nFeeRequired) > nBalance) {
             return SendCoinsReturn(AmountWithFeeExceedsBalance);
         }
         Q_EMIT message(tr("Send Coins"), QString::fromStdString(strFailReason),
                        CClientUIInterface::MSG_ERROR);
         return TransactionCreationFailed;
     }
 
     // reject absurdly high fee. (This can never happen because the
     // wallet caps the fee at maxTxFee. This merely serves as a
     // belt-and-suspenders check)
     if (nFeeRequired > m_node.getMaxTxFee()) {
         return AbsurdFee;
     }
 
     return SendCoinsReturn(OK);
 }
 
 WalletModel::SendCoinsReturn
 WalletModel::sendCoins(WalletModelTransaction &transaction) {
     /* store serialized transaction */
     QByteArray transaction_array;
 
     std::vector<std::pair<std::string, std::string>> vOrderForm;
     for (const SendCoinsRecipient &rcp : transaction.getRecipients()) {
         if (rcp.paymentRequest.IsInitialized()) {
             // Make sure any payment requests involved are still valid.
             if (PaymentServer::verifyExpired(rcp.paymentRequest.getDetails())) {
                 return PaymentRequestExpired;
             }
 
             // Store PaymentRequests in wtx.vOrderForm in wallet.
             std::string value;
             rcp.paymentRequest.SerializeToString(&value);
             vOrderForm.emplace_back("PaymentRequest", std::move(value));
         } else if (!rcp.message.isEmpty()) {
             // Message from normal bitcoincash:URI
             // (bitcoincash:123...?message=example)
             vOrderForm.emplace_back("Message", rcp.message.toStdString());
         }
     }
 
     auto &newTx = transaction.getWtx();
     std::string rejectReason;
     if (!newTx->commit({} /* mapValue */, std::move(vOrderForm),
                        {} /* fromAccount */, rejectReason)) {
         return SendCoinsReturn(TransactionCommitFailed,
                                QString::fromStdString(rejectReason));
     }
 
     CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
     ssTx << newTx->get();
     transaction_array.append(&(ssTx[0]), ssTx.size());
 
     // Add addresses / update labels that we've sent to to the address book, and
     // emit coinsSent signal for each recipient
     for (const SendCoinsRecipient &rcp : transaction.getRecipients()) {
         // Don't touch the address book when we have a payment request
         if (!rcp.paymentRequest.IsInitialized()) {
             std::string strAddress = rcp.address.toStdString();
             CTxDestination dest =
                 DecodeDestination(strAddress, getChainParams());
             std::string strLabel = rcp.label.toStdString();
             // Check if we have a new address or an updated label
             std::string name;
             if (!m_wallet->getAddress(dest, &name)) {
                 m_wallet->setAddressBook(dest, strLabel, "send");
             } else if (name != strLabel) {
                 // "" means don't change purpose
                 m_wallet->setAddressBook(dest, strLabel, "");
             }
         }
         Q_EMIT coinsSent(cwallet, rcp, transaction_array);
     }
 
     // update balance immediately, otherwise there could be a short noticeable
     // delay until pollBalanceChanged hits
     checkBalanceChanged(m_wallet->getBalances());
 
     return SendCoinsReturn(OK);
 }
 
 OptionsModel *WalletModel::getOptionsModel() {
     return optionsModel;
 }
 
 AddressTableModel *WalletModel::getAddressTableModel() {
     return addressTableModel;
 }
 
 TransactionTableModel *WalletModel::getTransactionTableModel() {
     return transactionTableModel;
 }
 
 RecentRequestsTableModel *WalletModel::getRecentRequestsTableModel() {
     return recentRequestsTableModel;
 }
 
 WalletModel::EncryptionStatus WalletModel::getEncryptionStatus() const {
     if (!m_wallet->isCrypted()) {
         return Unencrypted;
     } else if (m_wallet->isLocked()) {
         return Locked;
     } else {
         return Unlocked;
     }
 }
 
 bool WalletModel::setWalletEncrypted(bool encrypted,
                                      const SecureString &passphrase) {
     if (encrypted) {
         // Encrypt
         return m_wallet->encryptWallet(passphrase);
     } else {
         // Decrypt -- TODO; not supported yet
         return false;
     }
 }
 
 bool WalletModel::setWalletLocked(bool locked, const SecureString &passPhrase) {
     if (locked) {
         // Lock
         return m_wallet->lock();
     } else {
         // Unlock
         return m_wallet->unlock(passPhrase);
     }
 }
 
 bool WalletModel::changePassphrase(const SecureString &oldPass,
                                    const SecureString &newPass) {
     // Make sure wallet is locked before attempting pass change
     m_wallet->lock();
     return m_wallet->changeWalletPassphrase(oldPass, newPass);
 }
 
 // Handlers for core signals
 static void NotifyKeyStoreStatusChanged(WalletModel *walletmodel) {
     qDebug() << "NotifyKeyStoreStatusChanged";
     QMetaObject::invokeMethod(walletmodel, "updateStatus",
                               Qt::QueuedConnection);
 }
 
 static void NotifyAddressBookChanged(WalletModel *walletmodel,
                                      const CTxDestination &address,
                                      const std::string &label, bool isMine,
                                      const std::string &purpose,
                                      ChangeType status) {
     QString strAddress = QString::fromStdString(EncodeDestination(address));
     QString strLabel = QString::fromStdString(label);
     QString strPurpose = QString::fromStdString(purpose);
 
     qDebug() << "NotifyAddressBookChanged: " + strAddress + " " + strLabel +
                     " isMine=" + QString::number(isMine) +
                     " purpose=" + strPurpose +
                     " status=" + QString::number(status);
     QMetaObject::invokeMethod(walletmodel, "updateAddressBook",
                               Qt::QueuedConnection, Q_ARG(QString, strAddress),
                               Q_ARG(QString, strLabel), Q_ARG(bool, isMine),
                               Q_ARG(QString, strPurpose), Q_ARG(int, status));
 }
 
 static void NotifyTransactionChanged(WalletModel *walletmodel, const TxId &hash,
                                      ChangeType status) {
     Q_UNUSED(hash);
     Q_UNUSED(status);
     QMetaObject::invokeMethod(walletmodel, "updateTransaction",
                               Qt::QueuedConnection);
 }
 
 static void ShowProgress(WalletModel *walletmodel, const std::string &title,
                          int nProgress) {
     // emits signal "showProgress"
     QMetaObject::invokeMethod(walletmodel, "showProgress", Qt::QueuedConnection,
                               Q_ARG(QString, QString::fromStdString(title)),
                               Q_ARG(int, nProgress));
 }
 
 static void NotifyWatchonlyChanged(WalletModel *walletmodel,
                                    bool fHaveWatchonly) {
     QMetaObject::invokeMethod(walletmodel, "updateWatchOnlyFlag",
                               Qt::QueuedConnection,
                               Q_ARG(bool, fHaveWatchonly));
 }
 
 void WalletModel::subscribeToCoreSignals() {
     // Connect signals to wallet
     m_handler_status_changed = m_wallet->handleStatusChanged(
         boost::bind(&NotifyKeyStoreStatusChanged, this));
     m_handler_address_book_changed = m_wallet->handleAddressBookChanged(
         boost::bind(NotifyAddressBookChanged, this, _1, _2, _3, _4, _5));
     m_handler_transaction_changed = m_wallet->handleTransactionChanged(
         boost::bind(NotifyTransactionChanged, this, _1, _2));
     m_handler_show_progress =
         m_wallet->handleShowProgress(boost::bind(ShowProgress, this, _1, _2));
     m_handler_watch_only_changed = m_wallet->handleWatchOnlyChanged(
         boost::bind(NotifyWatchonlyChanged, this, _1));
 }
 
 void WalletModel::unsubscribeFromCoreSignals() {
     // Disconnect signals from wallet
     m_handler_status_changed->disconnect();
     m_handler_address_book_changed->disconnect();
     m_handler_transaction_changed->disconnect();
     m_handler_show_progress->disconnect();
     m_handler_watch_only_changed->disconnect();
 }
 
 // WalletModel::UnlockContext implementation
 WalletModel::UnlockContext WalletModel::requestUnlock() {
     bool was_locked = getEncryptionStatus() == Locked;
     if (was_locked) {
         // Request UI to unlock wallet
         Q_EMIT requireUnlock();
     }
     // If wallet is still locked, unlock was failed or cancelled, mark context
     // as invalid
     bool valid = getEncryptionStatus() != Locked;
 
     return UnlockContext(this, valid, was_locked);
 }
 
 WalletModel::UnlockContext::UnlockContext(WalletModel *_wallet, bool _valid,
                                           bool _relock)
     : wallet(_wallet), valid(_valid), relock(_relock) {}
 
 WalletModel::UnlockContext::~UnlockContext() {
     if (valid && relock) {
         wallet->setWalletLocked(true);
     }
 }
 
 void WalletModel::UnlockContext::CopyFrom(const UnlockContext &rhs) {
     // Transfer context; old object no longer relocks wallet
     *this = rhs;
     rhs.relock = false;
 }
 
-// returns a list of COutputs from COutPoints
-void WalletModel::getOutputs(const std::vector<COutPoint> &vOutpoints,
-                             std::vector<COutput> &vOutputs) {
-    LOCK2(cs_main, cwallet->cs_wallet);
-    for (const COutPoint &outpoint : vOutpoints) {
-        auto it = cwallet->mapWallet.find(outpoint.GetTxId());
-        if (it == cwallet->mapWallet.end()) {
-            continue;
-        }
-        int nDepth = it->second.GetDepthInMainChain();
-        if (nDepth < 0) {
-            continue;
-        }
-        COutput out(&it->second, outpoint.GetN(), nDepth, true /* spendable */,
-                    true /* solvable */, true /* safe */);
-        vOutputs.push_back(out);
-    }
-}
-
-bool WalletModel::isSpent(const COutPoint &outpoint) const {
-    LOCK2(cs_main, cwallet->cs_wallet);
-    return cwallet->IsSpent(outpoint.GetTxId(), outpoint.GetN());
-}
-
-// AvailableCoins + LockedCoins grouped by wallet address (put change in one
-// group with wallet address)
-void WalletModel::listCoins(
-    std::map<QString, std::vector<COutput>> &mapCoins) const {
-    for (auto &group : cwallet->ListCoins()) {
-        auto &resultGroup =
-            mapCoins[QString::fromStdString(EncodeDestination(group.first))];
-        for (auto &coin : group.second) {
-            resultGroup.emplace_back(std::move(coin));
-        }
-    }
-}
-
 void WalletModel::loadReceiveRequests(
     std::vector<std::string> &vReceiveRequests) {
     // receive request
     vReceiveRequests = m_wallet->getDestValues("rr");
 }
 
 bool WalletModel::saveReceiveRequest(const std::string &sAddress,
                                      const int64_t nId,
                                      const std::string &sRequest) {
     CTxDestination dest = DecodeDestination(sAddress, getChainParams());
 
     std::stringstream ss;
     ss << nId;
     // "rr" prefix = "receive request" in destdata
     std::string key = "rr" + ss.str();
 
     return sRequest.empty() ? m_wallet->eraseDestData(dest, key)
                             : m_wallet->addDestData(dest, key, sRequest);
 }
 
 bool WalletModel::isWalletEnabled() {
     return !gArgs.GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET);
 }
 
 QString WalletModel::getWalletName() const {
     return QString::fromStdString(m_wallet->getWalletName());
 }
 
 bool WalletModel::isMultiwallet() {
     return m_node.getWallets().size() > 1;
 }
 
 const CChainParams &WalletModel::getChainParams() const {
     return GetConfig().GetChainParams();
 }
diff --git a/src/qt/walletmodel.h b/src/qt/walletmodel.h
index 77ed02a3e9..0717267f1e 100644
--- a/src/qt/walletmodel.h
+++ b/src/qt/walletmodel.h
@@ -1,305 +1,300 @@
 // 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.
 
 #ifndef BITCOIN_QT_WALLETMODEL_H
 #define BITCOIN_QT_WALLETMODEL_H
 
 #include <chainparams.h>
 #include <interfaces/wallet.h>
 #include <qt/paymentrequestplus.h>
 #include <qt/walletmodeltransaction.h>
 #include <support/allocators/secure.h>
 
 #include <QObject>
 
 #include <map>
 #include <vector>
 
 class AddressTableModel;
 class OptionsModel;
 class PlatformStyle;
 class RecentRequestsTableModel;
 class TransactionTableModel;
 class WalletModelTransaction;
 
 class CCoinControl;
 class CKeyID;
 class COutPoint;
 class COutput;
 class CPubKey;
 
 namespace interfaces {
 class Node;
 } // namespace interface
 
 QT_BEGIN_NAMESPACE
 class QTimer;
 QT_END_NAMESPACE
 
 class SendCoinsRecipient {
 public:
     explicit SendCoinsRecipient()
         : amount(), fSubtractFeeFromAmount(false),
           nVersion(SendCoinsRecipient::CURRENT_VERSION) {}
     explicit SendCoinsRecipient(const QString &addr, const QString &_label,
                                 const Amount _amount, const QString &_message)
         : address(addr), label(_label), amount(_amount), message(_message),
           fSubtractFeeFromAmount(false),
           nVersion(SendCoinsRecipient::CURRENT_VERSION) {}
 
     // If from an unauthenticated payment request, this is used for storing the
     // addresses, e.g. address-A<br />address-B<br />address-C.
     // Info: As we don't need to process addresses in here when using payment
     // requests, we can abuse it for displaying an address list.
     // TOFO: This is a hack, should be replaced with a cleaner solution!
     QString address;
     QString label;
     Amount amount;
     // If from a payment request, this is used for storing the memo
     QString message;
 
     // If from a payment request, paymentRequest.IsInitialized() will be true
     PaymentRequestPlus paymentRequest;
     // Empty if no authentication or invalid signature/cert/etc.
     QString authenticatedMerchant;
 
     // memory only
     bool fSubtractFeeFromAmount;
 
     static const int CURRENT_VERSION = 1;
     int nVersion;
 
     ADD_SERIALIZE_METHODS;
 
     template <typename Stream, typename Operation>
     inline void SerializationOp(Stream &s, Operation ser_action) {
         std::string sAddress = address.toStdString();
         std::string sLabel = label.toStdString();
         std::string sMessage = message.toStdString();
         std::string sPaymentRequest;
         if (!ser_action.ForRead() && paymentRequest.IsInitialized()) {
             paymentRequest.SerializeToString(&sPaymentRequest);
         }
 
         std::string sAuthenticatedMerchant =
             authenticatedMerchant.toStdString();
 
         READWRITE(this->nVersion);
         READWRITE(sAddress);
         READWRITE(sLabel);
         READWRITE(amount);
         READWRITE(sMessage);
         READWRITE(sPaymentRequest);
         READWRITE(sAuthenticatedMerchant);
 
         if (ser_action.ForRead()) {
             address = QString::fromStdString(sAddress);
             label = QString::fromStdString(sLabel);
             message = QString::fromStdString(sMessage);
             if (!sPaymentRequest.empty()) {
                 paymentRequest.parse(QByteArray::fromRawData(
                     sPaymentRequest.data(), sPaymentRequest.size()));
             }
 
             authenticatedMerchant =
                 QString::fromStdString(sAuthenticatedMerchant);
         }
     }
 };
 
 /** Interface to Bitcoin wallet from Qt view code. */
 class WalletModel : public QObject {
     Q_OBJECT
 
 public:
     explicit WalletModel(std::unique_ptr<interfaces::Wallet> wallet,
                          interfaces::Node &node,
                          const PlatformStyle *platformStyle, CWallet *cwallet,
                          OptionsModel *optionsModel, QObject *parent = nullptr);
     ~WalletModel();
 
     // Returned by sendCoins
     enum StatusCode {
         OK,
         InvalidAmount,
         InvalidAddress,
         AmountExceedsBalance,
         AmountWithFeeExceedsBalance,
         DuplicateAddress,
         // Error returned when wallet is still locked
         TransactionCreationFailed,
         TransactionCommitFailed,
         AbsurdFee,
         PaymentRequestExpired
     };
 
     enum EncryptionStatus {
         // !wallet->IsCrypted()
         Unencrypted,
         // wallet->IsCrypted() && wallet->IsLocked()
         Locked,
         // wallet->IsCrypted() && !wallet->IsLocked()
         Unlocked
     };
 
     OptionsModel *getOptionsModel();
     AddressTableModel *getAddressTableModel();
     TransactionTableModel *getTransactionTableModel();
     RecentRequestsTableModel *getRecentRequestsTableModel();
 
     EncryptionStatus getEncryptionStatus() const;
 
     // Check address for validity
     bool validateAddress(const QString &address);
 
     // Return status record for SendCoins, contains error id + information
     struct SendCoinsReturn {
         SendCoinsReturn(StatusCode _status = OK,
                         QString _reasonCommitFailed = "")
             : status(_status), reasonCommitFailed(_reasonCommitFailed) {}
         StatusCode status;
         QString reasonCommitFailed;
     };
 
     // prepare transaction for getting txfee before sending coins
     SendCoinsReturn prepareTransaction(WalletModelTransaction &transaction,
                                        const CCoinControl &coinControl);
 
     // Send coins to a list of recipients
     SendCoinsReturn sendCoins(WalletModelTransaction &transaction);
 
     // Wallet encryption
     bool setWalletEncrypted(bool encrypted, const SecureString &passphrase);
     // Passphrase only needed when unlocking
     bool setWalletLocked(bool locked,
                          const SecureString &passPhrase = SecureString());
     bool changePassphrase(const SecureString &oldPass,
                           const SecureString &newPass);
 
     // RAI object for unlocking wallet, returned by requestUnlock()
     class UnlockContext {
     public:
         UnlockContext(WalletModel *wallet, bool valid, bool relock);
         ~UnlockContext();
 
         bool isValid() const { return valid; }
 
         // Copy operator and constructor transfer the context
         UnlockContext(const UnlockContext &obj) { CopyFrom(obj); }
         UnlockContext &operator=(const UnlockContext &rhs) {
             CopyFrom(rhs);
             return *this;
         }
 
     private:
         WalletModel *wallet;
         bool valid;
         // mutable, as it can be set to false by copying
         mutable bool relock;
 
         void CopyFrom(const UnlockContext &rhs);
     };
 
     UnlockContext requestUnlock();
 
-    void getOutputs(const std::vector<COutPoint> &vOutpoints,
-                    std::vector<COutput> &vOutputs);
-    bool isSpent(const COutPoint &outpoint) const;
-    void listCoins(std::map<QString, std::vector<COutput>> &mapCoins) const;
-
     void loadReceiveRequests(std::vector<std::string> &vReceiveRequests);
     bool saveReceiveRequest(const std::string &sAddress, const int64_t nId,
                             const std::string &sRequest);
 
     static bool isWalletEnabled();
 
     interfaces::Node &node() const { return m_node; }
     interfaces::Wallet &wallet() const { return *m_wallet; }
 
     const CChainParams &getChainParams() const;
 
     QString getWalletName() const;
 
     bool isMultiwallet();
 
 private:
     std::unique_ptr<interfaces::Wallet> m_wallet;
     std::unique_ptr<interfaces::Handler> m_handler_status_changed;
     std::unique_ptr<interfaces::Handler> m_handler_address_book_changed;
     std::unique_ptr<interfaces::Handler> m_handler_transaction_changed;
     std::unique_ptr<interfaces::Handler> m_handler_show_progress;
     std::unique_ptr<interfaces::Handler> m_handler_watch_only_changed;
     interfaces::Node &m_node;
 
     CWallet *cwallet;
     bool fHaveWatchOnly;
     bool fForceCheckBalanceChanged;
 
     // Wallet has an options model for wallet-specific options (transaction fee,
     // for example)
     OptionsModel *optionsModel;
 
     AddressTableModel *addressTableModel;
     TransactionTableModel *transactionTableModel;
     RecentRequestsTableModel *recentRequestsTableModel;
 
     // Cache some values to be able to detect changes
     interfaces::WalletBalances m_cached_balances;
     EncryptionStatus cachedEncryptionStatus;
     int cachedNumBlocks;
 
     QTimer *pollTimer;
 
     void subscribeToCoreSignals();
     void unsubscribeFromCoreSignals();
     void checkBalanceChanged(const interfaces::WalletBalances &new_balances);
 
 Q_SIGNALS:
     // Signal that balance in wallet changed
     void balanceChanged(const Amount balance, const Amount unconfirmedBalance,
                         const Amount immatureBalance,
                         const Amount watchOnlyBalance,
                         const Amount watchUnconfBalance,
                         const Amount watchImmatureBalance);
 
     // Encryption status of wallet changed
     void encryptionStatusChanged();
 
     // Signal emitted when wallet needs to be unlocked
     // It is valid behaviour for listeners to keep the wallet locked after this
     // signal; this means that the unlocking failed or was cancelled.
     void requireUnlock();
 
     // Fired when a message should be reported to the user
     void message(const QString &title, const QString &message,
                  unsigned int style);
 
     // Coins sent: from wallet, to recipient, in (serialized) transaction:
     void coinsSent(CWallet *wallet, SendCoinsRecipient recipient,
                    QByteArray transaction);
 
     // Show progress dialog e.g. for rescan
     void showProgress(const QString &title, int nProgress);
 
     // Watch-only address added
     void notifyWatchonlyChanged(bool fHaveWatchonly);
 
 public Q_SLOTS:
     /** Wallet status might have changed. */
     void updateStatus();
     /** New transaction, or transaction changed status. */
     void updateTransaction();
     /** New, updated or removed address book entry. */
     void updateAddressBook(const QString &address, const QString &label,
                            bool isMine, const QString &purpose, int status);
     /** Watch-only added. */
     void updateWatchOnlyFlag(bool fHaveWatchonly);
     /**
      * Current, immature or unconfirmed balance might have changed - emit
      * 'balanceChanged' if so.
      */
     void pollBalanceChanged();
 };
 
 #endif // BITCOIN_QT_WALLETMODEL_H