walletmodel.h raw

   1  // Copyright (c) 2011-2022 The Limenka developers
   2  // Distributed under the MIT software license, see the accompanying
   3  // file COPYING or http://www.opensource.org/licenses/mit-license.php.
   4  
   5  #ifndef LIMENKA_QT_WALLETMODEL_H
   6  #define LIMENKA_QT_WALLETMODEL_H
   7  
   8  #include <key.h>
   9  #include <primitives/transaction.h>
  10  
  11  #include <qt/walletmodeltransaction.h>
  12  
  13  #include <interfaces/wallet.h>
  14  #include <support/allocators/secure.h>
  15  
  16  #include <string>
  17  #include <vector>
  18  
  19  #include <QObject>
  20  #include <QValidator>
  21  
  22  enum class OutputType;
  23  
  24  class AddressTableModel;
  25  class ClientModel;
  26  class OptionsModel;
  27  class PlatformStyle;
  28  class RecentRequestsTableModel;
  29  class SendCoinsRecipient;
  30  class TransactionTableModel;
  31  class WalletModelTransaction;
  32  
  33  class CKeyID;
  34  class COutPoint;
  35  class CPubKey;
  36  class uint256;
  37  
  38  namespace interfaces {
  39  class Node;
  40  } // namespace interfaces
  41  namespace wallet {
  42  class CCoinControl;
  43  } // namespace wallet
  44  
  45  QT_BEGIN_NAMESPACE
  46  class QTimer;
  47  QT_END_NAMESPACE
  48  
  49  /** Interface to Limenka wallet from Qt view code. */
  50  class WalletModel : public QObject
  51  {
  52      Q_OBJECT
  53  
  54  public:
  55      explicit WalletModel(std::unique_ptr<interfaces::Wallet> wallet, ClientModel& client_model, const PlatformStyle *platformStyle, QObject *parent = nullptr);
  56      ~WalletModel();
  57  
  58      enum StatusCode // Returned by sendCoins
  59      {
  60          OK,
  61          InvalidAmount,
  62          InvalidAddress,
  63          AmountExceedsBalance,
  64          AmountWithFeeExceedsBalance,
  65          DuplicateAddress,
  66          TransactionCreationFailed, // Error returned when wallet is still locked
  67          AbsurdFee
  68      };
  69  
  70      enum EncryptionStatus
  71      {
  72          NoKeys,       // wallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)
  73          Unencrypted,  // !wallet->IsCrypted()
  74          Locked,       // wallet->IsCrypted() && wallet->IsLocked()
  75          Unlocked      // wallet->IsCrypted() && !wallet->IsLocked()
  76      };
  77  
  78      OptionsModel* getOptionsModel() const;
  79      AddressTableModel* getAddressTableModel() const;
  80      TransactionTableModel* getTransactionTableModel() const;
  81      RecentRequestsTableModel* getRecentRequestsTableModel() const;
  82  
  83      EncryptionStatus getEncryptionStatus() const;
  84  
  85      // Check address for validity
  86      bool validateAddress(const QString& address) const;
  87      bool checkAddressForUsage(const std::vector<std::string>& addresses) const;
  88      bool findAddressUsage(const QStringList& addresses, std::function<void(const QString&, const interfaces::WalletTx&, uint32_t)> callback) const;
  89  
  90      // Return status record for SendCoins, contains error id + information
  91      struct SendCoinsReturn
  92      {
  93          SendCoinsReturn(StatusCode _status = OK, QString _reasonCommitFailed = "")
  94              : status(_status),
  95                reasonCommitFailed(_reasonCommitFailed)
  96          {
  97          }
  98          StatusCode status;
  99          QString reasonCommitFailed;
 100      };
 101  
 102      // prepare transaction for getting txfee before sending coins
 103      SendCoinsReturn prepareTransaction(WalletModelTransaction &transaction, const wallet::CCoinControl& coinControl);
 104  
 105      // Send coins to a list of recipients
 106      void sendCoins(WalletModelTransaction& transaction);
 107  
 108      // Wallet encryption
 109      bool setWalletEncrypted(const SecureString& passphrase);
 110      // Passphrase only needed when unlocking
 111      bool setWalletLocked(bool locked, const SecureString &passPhrase=SecureString());
 112      bool changePassphrase(const SecureString &oldPass, const SecureString &newPass);
 113  
 114      // RAII object for unlocking wallet, returned by requestUnlock()
 115      class UnlockContext
 116      {
 117      public:
 118          UnlockContext(WalletModel *wallet, bool valid, bool relock);
 119          ~UnlockContext();
 120  
 121          bool isValid() const { return valid; }
 122  
 123          // Disable unused copy/move constructors/assignments explicitly.
 124          UnlockContext(const UnlockContext&) = delete;
 125          UnlockContext(UnlockContext&&) = delete;
 126          UnlockContext& operator=(const UnlockContext&) = delete;
 127          UnlockContext& operator=(UnlockContext&&) = delete;
 128  
 129      private:
 130          WalletModel *wallet;
 131          const bool valid;
 132          const bool relock;
 133      };
 134  
 135      UnlockContext requestUnlock();
 136  
 137      bool bumpFee(uint256 hash, uint256& new_hash);
 138      void displayAddress(std::string sAddress) const;
 139  
 140      static bool isWalletEnabled();
 141  
 142      interfaces::Node& node() const { return m_node; }
 143      interfaces::Wallet& wallet() const { return *m_wallet; }
 144      ClientModel& clientModel() const { return *m_client_model; }
 145      void setClientModel(ClientModel* client_model);
 146  
 147      QString getWalletName() const;
 148      QString getDisplayName() const;
 149  
 150      bool isMultiwallet() const;
 151  
 152      void refresh(bool pk_hash_only = false);
 153  
 154      uint256 getLastBlockProcessed() const;
 155  
 156      // Retrieve the cached wallet balance
 157      interfaces::WalletBalances getCachedBalance() const;
 158  
 159      //! Full-precision balance (sub-satoshi + confidential outputs) as a
 160      //! lambda string with up to 26 decimals.
 161      QString getPreciseBalance();
 162  
 163      // If coin control has selected outputs, searches the total amount inside the wallet.
 164      // Otherwise, uses the wallet's cached available balance.
 165      CAmount getAvailableBalance(const wallet::CCoinControl* control);
 166  
 167  private:
 168      std::unique_ptr<interfaces::Wallet> m_wallet;
 169      std::unique_ptr<interfaces::Handler> m_handler_unload;
 170      std::unique_ptr<interfaces::Handler> m_handler_status_changed;
 171      std::unique_ptr<interfaces::Handler> m_handler_address_book_changed;
 172      std::unique_ptr<interfaces::Handler> m_handler_transaction_changed;
 173      std::unique_ptr<interfaces::Handler> m_handler_show_progress;
 174      std::unique_ptr<interfaces::Handler> m_handler_watch_only_changed;
 175      std::unique_ptr<interfaces::Handler> m_handler_can_get_addrs_changed;
 176      ClientModel* m_client_model;
 177      interfaces::Node& m_node;
 178  
 179      bool fHaveWatchOnly;
 180      bool fForceCheckBalanceChanged{false};
 181  
 182      // Wallet has an options model for wallet-specific options
 183      // (transaction fee, for example)
 184      OptionsModel *optionsModel;
 185  
 186      AddressTableModel* addressTableModel{nullptr};
 187      TransactionTableModel* transactionTableModel{nullptr};
 188      RecentRequestsTableModel* recentRequestsTableModel{nullptr};
 189  
 190      // Cache some values to be able to detect changes
 191      interfaces::WalletBalances m_cached_balances;
 192      EncryptionStatus cachedEncryptionStatus{Unencrypted};
 193      QTimer* timer;
 194  
 195      // Block hash denoting when the last balance update was done.
 196      uint256 m_cached_last_update_tip{};
 197  
 198      void subscribeToCoreSignals();
 199      void unsubscribeFromCoreSignals();
 200      void checkBalanceChanged(const interfaces::WalletBalances& new_balances);
 201  
 202  Q_SIGNALS:
 203      // Signal that balance in wallet changed
 204      void balanceChanged(const interfaces::WalletBalances& balances);
 205  
 206      // Encryption status of wallet changed
 207      void encryptionStatusChanged();
 208  
 209      // Signal emitted when wallet needs to be unlocked
 210      // It is valid behaviour for listeners to keep the wallet locked after this signal;
 211      // this means that the unlocking failed or was cancelled.
 212      void requireUnlock();
 213  
 214      // Fired when a message should be reported to the user
 215      void message(const QString &title, const QString &message, unsigned int style);
 216  
 217      // Coins sent: from wallet, to recipient, in (serialized) transaction:
 218      void coinsSent(WalletModel* wallet, SendCoinsRecipient recipient, QByteArray transaction);
 219  
 220      // Show progress dialog e.g. for rescan
 221      void showProgress(const QString &title, int nProgress);
 222  
 223      // Watch-only address added
 224      void notifyWatchonlyChanged(bool fHaveWatchonly);
 225  
 226      // Signal that wallet is about to be removed
 227      void unload();
 228  
 229      // Notify that there are now keys in the keypool
 230      void canGetAddressesChanged();
 231  
 232      void timerTimeout();
 233  
 234  public Q_SLOTS:
 235      /* Starts a timer to periodically update the balance */
 236      void startPollBalance();
 237  
 238      /* Wallet status might have changed */
 239      void updateStatus();
 240      /* New transaction, or transaction changed status */
 241      void updateTransaction();
 242      /* New, updated or removed address book entry */
 243      void updateAddressBook(const QString &address, const QString &label, bool isMine, wallet::AddressPurpose purpose, int status);
 244      /* Watch-only added */
 245      void updateWatchOnlyFlag(bool fHaveWatchonly);
 246      /* Current, immature or unconfirmed balance might have changed - emit 'balanceChanged' if so */
 247      void pollBalanceChanged();
 248  };
 249  
 250  class LimenkaAddressUnusedInWalletValidator : public QValidator
 251  {
 252      Q_OBJECT
 253  
 254      const WalletModel& m_wallet_model;
 255  
 256  public:
 257      explicit LimenkaAddressUnusedInWalletValidator(const WalletModel&, QObject *parent=nullptr);
 258  
 259      State validate(QString &input, int &pos) const override;
 260  };
 261  
 262  #endif // LIMENKA_QT_WALLETMODEL_H
 263