Skip to content

(minotari) Restore from keys/rename wallet#44

Merged
brianp merged 3 commits intominotari_integrationfrom
minotari_integration_improve
Feb 20, 2026
Merged

(minotari) Restore from keys/rename wallet#44
brianp merged 3 commits intominotari_integrationfrom
minotari_integration_improve

Conversation

@igordanilcenko
Copy link

  • Implemented wallet restoration from keys (read-only)
  • Implemented wallet renaming
  • Improved wallet database handling

@igordanilcenko igordanilcenko self-assigned this Feb 18, 2026
@gemini-code-assist
Copy link

Summary of Changes

Hello @igordanilcenko, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances Minotari wallet management by introducing key-based restoration for read-only access and the ability to rename wallets. It also includes a fundamental improvement to how wallet databases are handled, centralizing them for better performance and maintainability. These changes provide users with more flexible options for wallet recovery and organization, while streamlining the underlying architecture.

Highlights

  • Wallet Restoration from Keys: Implemented the ability to restore Minotari wallets using private view keys and public spend keys, enabling read-only wallet functionality.
  • Wallet Renaming: Added functionality to rename existing Minotari wallets, including updating internal database states and associated files.
  • Improved Wallet Database Handling: Refactored the Minotari wallet database initialization to use a single, shared database file per wallet type, improving efficiency and consistency across multiple wallets.
  • Random Passphrase Generation: Introduced automatic generation of random passphrases for new or restored wallets if no passphrase is explicitly provided, enhancing security.
Changelog
  • cw_minotari/lib/minotari_ffi.dart
    • Imported new FFI functions: importViewOnlyWallet and renameWallet.
    • Added a static _dbInitialized flag and _ensureDbInitialized method to manage shared database initialization.
    • Refactored wallet creation and restoration methods to use the new shared database initialization logic.
    • Introduced importViewOnly method for restoring wallets from view and spend keys.
    • Added rename method to facilitate wallet renaming within the FFI layer.
    • Reduced the default batchSize for transaction scanning from 1000 to 25.
  • cw_minotari/lib/minotari_wallet.dart
    • Imported dart:io for file system operations.
    • Added viewPrivateKeyHex and spendPublicKeyHex properties to MinotariWalletBase.
    • Updated walletKeysData getter to include scanSecret and spendPubkey.
    • Modified init method to use a shared database path for Minotari FFI initialization.
    • Implemented renameWalletFiles to handle renaming wallet directories and associated key files, and calling the FFI rename function.
  • cw_minotari/lib/minotari_wallet_service.dart
    • Imported dart:math for random number generation.
    • Added _PassphraseExtension to generate random passphrases if none are provided.
    • Updated create method to use the shared database path and the new random passphrase generation.
    • Implemented restoreFromKeys method for Minotari wallets, utilizing the new importViewOnly FFI function.
    • Updated restoreFromSeed method to use the shared database path and random passphrase generation.
    • Modified rename method to update the wallet's ID after renaming.
    • Adjusted isWalletExit logic to check for the existence of the .keys file within the wallet's type directory.
    • Refactored MinotariRestoreWalletFromKeysCredentials to include viewPrivateKeyHex, spendPublicKeyHex, and birthday.
  • lib/minotari/cw_minotari.dart
    • Overrode createMinotariRestoreWalletFromKeysCredentials to provide Minotari-specific credentials.
    • Updated getWalletKeys to include viewPrivateKey and spendPublicKey if available.
  • lib/minotari/minotari.dart
    • Added an abstract method createMinotariRestoreWalletFromKeysCredentials to the Minotari interface.
  • lib/src/screens/restore/wallet_restore_from_keys_form.dart
    • Added conditional UI fields for Minotari wallet restoration from keys, including view and spend key input fields and a blockchain height widget.
  • lib/src/screens/restore/wallet_restore_page.dart
    • Updated the onViewKeyEntered callback to enable the button for Minotari wallet type when view keys are entered.
  • lib/view_model/wallet_restore_view_model.dart
    • Updated availableModes for WalletType.minotari to include WalletRestoreMode.keys.
    • Added logic to createWalletCredentials to handle Minotari wallet restoration from keys.
  • res/values/strings_en.arb
    • Added a new string resource for restore_spend_key_public.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@igordanilcenko igordanilcenko force-pushed the minotari_integration_improve branch from e5e32f0 to 868e67d Compare February 18, 2026 17:08
Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces wallet restoration from keys and wallet renaming for Minotari. It also refactors the wallet database handling to use a shared database per wallet type, which is a good improvement for managing multiple wallets. The implementation of the new features seems solid and well-integrated. I've found one potential issue with the atomicity of the wallet renaming process which could lead to an inconsistent state. My specific feedback is in the review comment.

Comment on lines 439 to 461
Future<void> renameWalletFiles(String newWalletName) async {
// TODO: Implement wallet file renaming
final currentWalletPath = await pathForWallet(name: walletInfo.name, type: walletInfo.type);
final currentDirPath = await pathForWalletDir(name: walletInfo.name, type: walletInfo.type);

final newWalletPath = await pathForWallet(name: newWalletName, type: walletInfo.type);

printV('renameWalletFiles from \"${walletInfo.name}\" (in ${currentWalletPath} ) to \"$newWalletName\"');
final typeDir = await pathForWalletTypeDir(type: walletInfo.type);
final ffi = MinotariFfi(dataPath: '$typeDir/wallet.db', walletName: walletInfo.name);
await ffi.rename(newWalletName: newWalletName);

final currentKeysFile = File('$currentWalletPath.keys');
if (currentKeysFile.existsSync()) {
await currentKeysFile.copy('$newWalletPath.keys');
}

final currentKeysBackupFile = File('$currentWalletPath.keys.backup');
if (currentKeysBackupFile.existsSync()) {
await currentKeysBackupFile.copy('$newWalletPath.keys.backup');
}

await Directory(currentDirPath).delete(recursive: true);
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The current implementation of renameWalletFiles is not atomic. It renames the wallet in the database before copying the key files. If the file copy operation fails, the wallet could be left in an inconsistent state, potentially making it inaccessible. The database would have the new name, but the key files would still be at the old location.

To make this operation safer, the file operations should be performed before the database update. If the database update fails, the file changes can be reverted. Also, it's better to use the asynchronous exists() instead of the synchronous existsSync() in an async function.

  Future<void> renameWalletFiles(String newWalletName) async {
    final currentWalletPath = await pathForWallet(name: walletInfo.name, type: walletInfo.type);
    final currentDirPath = await pathForWalletDir(name: walletInfo.name, type: walletInfo.type);
    final newWalletPath = await pathForWallet(name: newWalletName, type: walletInfo.type);
    final newDirPath = await pathForWalletDir(name: newWalletName, type: walletInfo.type);

    printV('renameWalletFiles from "${walletInfo.name}" (in ${currentWalletPath} ) to "$newWalletName"');

    // Create new directory and copy files first to make the operation more robust.
    await Directory(newDirPath).create(recursive: true);

    final currentKeysFile = File('$currentWalletPath.keys');
    if (await currentKeysFile.exists()) {
      await currentKeysFile.copy('$newWalletPath.keys');
    }

    final currentKeysBackupFile = File('$currentWalletPath.keys.backup');
    if (await currentKeysBackupFile.exists()) {
      await currentKeysBackupFile.copy('$newWalletPath.keys.backup');
    }

    try {
      final typeDir = await pathForWalletTypeDir(type: walletInfo.type);
      final ffi = MinotariFfi(dataPath: '$typeDir/wallet.db', walletName: walletInfo.name);
      await ffi.rename(newWalletName: newWalletName);
    } catch (e) {
      // If DB rename fails, clean up the copied files to revert.
      await Directory(newDirPath).delete(recursive: true);
      rethrow;
    }

    // On success, remove the old wallet directory.
    await Directory(currentDirPath).delete(recursive: true);
  }

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It shouldn't fail

@brianp brianp merged commit 56a9f3e into minotari_integration Feb 20, 2026
5 of 6 checks passed
@brianp brianp deleted the minotari_integration_improve branch February 20, 2026 13:04
igordanilcenko added a commit that referenced this pull request Feb 24, 2026
* feat(minotari): Implement random passphrase generation for wallet creation and restoration

* feat(minotari): Add support for restoring wallets from view and spend keys

* feat(minotari): Improve database initialization and wallet renaming logic
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants