diff --git a/src/interfaces/wallet.h b/src/interfaces/wallet.h index a56ed8802d..4213a22749 100644 --- a/src/interfaces/wallet.h +++ b/src/interfaces/wallet.h @@ -322,6 +322,9 @@ public: //! Return default wallet directory. virtual std::string getWalletDir() = 0; + //! Restore backup wallet + virtual std::unique_ptr restoreWallet(const std::string& backup_file, const std::string& wallet_name, bilingual_str& error, std::vector& warnings) = 0; + //! Return available wallets in wallet directory. virtual std::vector listWalletDir() = 0; diff --git a/src/wallet/interfaces.cpp b/src/wallet/interfaces.cpp index 6c9d0ca132..bba909b807 100644 --- a/src/wallet/interfaces.cpp +++ b/src/wallet/interfaces.cpp @@ -552,6 +552,12 @@ public: options.require_existing = true; return MakeWallet(m_context, LoadWallet(m_context, name, true /* load_on_start */, options, status, error, warnings)); } + std::unique_ptr restoreWallet(const std::string& backup_file, const std::string& wallet_name, bilingual_str& error, std::vector& warnings) override + { + DatabaseStatus status; + + return MakeWallet(m_context, RestoreWallet(m_context, backup_file, wallet_name, /*load_on_start=*/true, status, error, warnings)); + } std::string getWalletDir() override { return fs::PathToString(GetWalletDir()); diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index cfe550cb3f..59ed8c2571 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -357,6 +357,31 @@ std::shared_ptr CreateWallet(WalletContext& context, const std::string& return wallet; } +std::shared_ptr RestoreWallet(WalletContext& context, const std::string& backup_file, const std::string& wallet_name, std::optional load_on_start, DatabaseStatus& status, bilingual_str& error, std::vector& warnings) +{ + DatabaseOptions options; + options.require_existing = true; + + if (!fs::exists(fs::u8path(backup_file))) { + error = Untranslated("Backup file does not exist"); + status = DatabaseStatus::FAILED_BAD_PATH; + return nullptr; + } + + const fs::path wallet_path = fsbridge::AbsPathJoin(GetWalletDir(), fs::u8path(wallet_name)); + + if (fs::exists(wallet_path) || !TryCreateDirectories(wallet_path)) { + error = Untranslated(strprintf("Failed to create database path '%s'. Database already exists.", fs::PathToString(wallet_path))); + status = DatabaseStatus::FAILED_ALREADY_EXISTS; + return nullptr; + } + + auto wallet_file = wallet_path / "wallet.dat"; + fs::copy_file(backup_file, wallet_file, fs::copy_option::fail_if_exists); + + return LoadWallet(context, wallet_name, load_on_start, options, status, error, warnings); +} + /** @defgroup mapWallet * * @{ diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index dbf0f6375d..1dc40d228e 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -60,6 +60,7 @@ std::vector> GetWallets(WalletContext& context); std::shared_ptr GetWallet(WalletContext& context, const std::string& name); std::shared_ptr LoadWallet(WalletContext& context, const std::string& name, std::optional load_on_start, const DatabaseOptions& options, DatabaseStatus& status, bilingual_str& error, std::vector& warnings); std::shared_ptr CreateWallet(WalletContext& context, const std::string& name, std::optional load_on_start, DatabaseOptions& options, DatabaseStatus& status, bilingual_str& error, std::vector& warnings); +std::shared_ptr RestoreWallet(WalletContext& context, const std::string& backup_file, const std::string& wallet_name, std::optional load_on_start, DatabaseStatus& status, bilingual_str& error, std::vector& warnings); std::unique_ptr HandleLoadWallet(WalletContext& context, LoadWalletFn load_wallet); std::unique_ptr MakeWalletDatabase(const std::string& name, const DatabaseOptions& options, DatabaseStatus& status, bilingual_str& error);