// DragonX Wallet - ImGui Edition // Copyright 2024-2026 The Hush Developers // Released under the GPLv3 #pragma once #include #include namespace dragonx { namespace util { /** * @brief Platform-specific utilities */ class Platform { public: /** * @brief Open a URL in the default browser * @param url The URL to open * @return true if successful */ static bool openUrl(const std::string& url); /** * @brief Open a folder in the system file manager * @param path Path to the folder * @param createIfMissing Create the folder if it doesn't exist * @return true if successful */ static bool openFolder(const std::string& path, bool createIfMissing = true); /** * @brief Get the size of a file in bytes * @param path Path to the file * @return File size in bytes, or 0 if file doesn't exist */ static uint64_t getFileSize(const std::string& path); /** * @brief Format a file size as human-readable string * @param bytes Size in bytes * @return Formatted string (e.g., "5.23 MB") */ static std::string formatFileSize(uint64_t bytes); /** * @brief Get the user's home directory * @return Home directory path */ static std::string getHomeDir(); /** * @brief Get the DragonX data directory * @return Path like ~/.hush/DRAGONX/ or %APPDATA%\Hush\DRAGONX\ */ static std::string getDragonXDataDir(); /** * @brief Get the wallet data directory (alias for getDragonXDataDir) * @return Path like ~/.hush/DRAGONX/ or %APPDATA%\Hush\DRAGONX\ */ static std::string getDataDir(); /** * @brief Get the LITE wallet data directory (where the SilentDragonXLite backend stores * silentdragonxlite-wallet.dat). Mirrors the backend's get_zcash_data_path() for the * "main" chain: dirs::data_dir()/silentdragonxlite on Windows/macOS, ~/.silentdragonxlite * on Linux. Distinct from getDragonXDataDir() (the full-node blocks/wallet dir). * @return Path like ~/.silentdragonxlite/ or %APPDATA%\silentdragonxlite\ */ static std::string getLiteWalletDataDir(); /** * @brief Get the config directory for storing wallet exports/backups * @return Path like ~/.config/ObsidianDragon/ or %APPDATA%\ObsidianDragon\ */ static std::string getConfigDir(); /** * @brief Delete a file * @param path Path to the file * @return true if successful or file didn't exist */ static bool deleteFile(const std::string& path); /** * @brief Write a file atomically and durably. * * Writes @p content to `.tmp`, flushes it to stable storage * (fsync / FlushFileBuffers), then atomically renames it over @p path * (POSIX rename / Win32 MoveFileEx with REPLACE_EXISTING). A crash or power * loss at any point leaves either the old file intact or the fully-written * new one — never a truncated/corrupt file. The parent directory is created * if missing, and on POSIX it is fsync'd so the rename itself is durable. * * @param path Destination file path. * @param content Bytes to write. * @param restrictPermissions When true, create the file owner-only (0600 on * POSIX) before the rename so it is never briefly world-readable. * @return true on success; on failure any pre-existing file is left untouched. */ static bool writeFileAtomically(const std::string& path, const std::string& content, bool restrictPermissions = false); /** * @brief Get the directory containing the executable * @return Path to executable's directory */ static std::string getExecutableDirectory(); /** * @brief Get the ObsidianDragon config directory * @return Path like ~/.config/ObsidianDragon/ or %APPDATA%\ObsidianDragon\ */ static std::string getObsidianDragonDir(); /** * @brief Create ObsidianDragon folder structure and template files on first run * * Creates: * ObsidianDragon/ * ObsidianDragon/themes/ * ObsidianDragon/themes/my_theme.toml (template) * * Only writes template files if they don't already exist. */ static void ensureObsidianDragonSetup(); /** * @brief Create a directory (and parents) if missing, with a clear error on failure. * * Uses the non-throwing std::error_code overload internally. On failure sets *outError * (when non-null) to one consistent, user-facing message: * "Cannot create : . Check permissions / free space." * * @return true if the directory exists (already did, or was just created). */ static bool ensureDirectory(const std::string& dir, std::string* outError = nullptr); /** * @brief Get total system RAM in megabytes * @return Total physical RAM in MB, or 0 on failure */ static double getTotalSystemRAM_MB(); /** * @brief Get currently used system RAM in megabytes * @return Used physical RAM in MB (total - available), or 0 on failure */ static double getUsedSystemRAM_MB(); /** * @brief Get this process's own RSS (resident set size) in megabytes * @return Self process RSS in MB, or 0 on failure */ static double getSelfMemoryUsageMB(); /** * @brief Get total RSS of all dragonxd daemon processes in megabytes * Scans for any running dragonxd process by name, regardless of how it was launched. * @return Combined daemon RSS in MB, or 0 if no daemon found */ static double getDaemonMemoryUsageMB(); /** * @brief Get system-wide idle time in seconds * Uses platform-specific APIs: GetLastInputInfo (Windows), * XScreenSaverQueryInfo via dlopen (Linux), IOKit (macOS). * @return Seconds since last user input, or 0 on failure */ static int getSystemIdleSeconds(); /** * @brief Get GPU utilization percentage (0–100). * Linux: reads sysfs for AMD, /proc for NVIDIA. * Windows: queries PDH GPU engine counters. * @return GPU busy percent, or -1 if unavailable. */ static int getGpuUtilization(); }; /** * @brief Get the directory containing the executable (free function) * @return Path to executable's directory */ std::string getExecutableDirectory(); } // namespace util } // namespace dragonx