#pragma once #include "wallet_state.h" #include #include #include #include #include #include struct sqlite3; namespace dragonx { namespace data { class TransactionHistoryCache { public: struct LoadResult { bool loaded = false; bool invalidated = false; int tipHeight = 0; std::string tipHash; std::time_t updatedAt = 0; std::vector transactions; std::unordered_map shieldedScanHeights; }; TransactionHistoryCache(); explicit TransactionHistoryCache(std::string databasePath); ~TransactionHistoryCache(); TransactionHistoryCache(const TransactionHistoryCache&) = delete; TransactionHistoryCache& operator=(const TransactionHistoryCache&) = delete; static std::string defaultDatabasePath(); static std::string walletIdentityFromAddresses(const std::vector& shieldedAddresses, const std::vector& transparentAddresses); static std::string walletIdentityHash(const std::string& walletIdentity); bool ensureOpen(); bool unlockWithPassphrase(const std::string& walletIdentity, const std::string& passphrase); void lockKey(); bool hasKey() const { return key_ready_; } bool isUnlockedFor(const std::string& walletIdentity) const; LoadResult load(const std::string& walletIdentity, int currentTipHeight, const std::string& currentTipHash); bool replace(const std::string& walletIdentity, int tipHeight, const std::string& tipHash, const std::vector& transactions, std::time_t updatedAt, const std::unordered_map& shieldedScanHeights = {}); void clearWallet(const std::string& walletIdentity); int snapshotCount(); private: bool exec(const char* sql); bool createSchema(); std::vector getOrCreateSalt(const std::string& walletHash); bool deriveKey(const std::string& passphrase, const std::vector& salt); bool encryptPayload(const std::string& walletHash, const std::string& plainText, std::vector& nonce, std::vector& cipherText) const; bool decryptPayload(const std::string& walletHash, const std::vector& nonce, const std::vector& cipherText, std::string& plainText) const; bool readSnapshot(const std::string& walletHash, int& tipHeight, std::string& tipHash, std::time_t& updatedAt, std::vector& nonce, std::vector& cipherText); void clearWalletByHash(const std::string& walletHash); void close(); sqlite3* db_ = nullptr; std::string database_path_; std::array key_{}; bool key_ready_ = false; std::string unlocked_wallet_hash_; }; } // namespace data } // namespace dragonx