suggest configuring a custom wallets directory when opening a wallet from a non-default location
What changed, and why it matters
This commit adds a user-facing convenience feature: when you open a wallet file from a folder that is not Sparrow's default wallets folder, Sparrow now asks if you want to make that folder your new default wallets directory. It also lets you save a custom wallets directory in settings. There is no security bug being fixed here—this is purely a usability improvement.
No security action required. Review as a normal feature change.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The patch introduces a new configureWalletsDir() helper in AppController that, after a file chooser returns wallet files, checks whether all selected files share a single parent directory different from the current default wallets directory. If so, it shows a confirmation dialog asking the user to set that directory as the default. It adds suggestChangeWalletsDir and walletsDir fields to Config with getters/setters, and updates Storage.getWalletsDir() to prefer the configured directory if it is reachable, otherwise fall back to the default. The change includes a ‘don’t ask again’ toggle and reverts to the default if the configured directory becomes unreachable.
Changed components
src/main/java/com/sparrowwallet/sparrow/AppController.javasrc/main/java/com/sparrowwallet/sparrow/io/Config.javasrc/main/java/com/sparrowwallet/sparrow/io/Storage.javaInspect captured patch +55 / −1
diff --git a/src/main/java/com/sparrowwallet/sparrow/AppController.java b/src/main/java/com/sparrowwallet/sparrow/AppController.java
index 64168bc..7822764 100644
--- a/src/main/java/com/sparrowwallet/sparrow/AppController.java
+++ b/src/main/java/com/sparrowwallet/sparrow/AppController.java
@@ -1140,12 +1140,37 @@ public class AppController implements Initializable {
AppServices.moveToActiveWindowScreen(window, 800, 450);
List<File> files = fileChooser.showOpenMultipleDialog(window);
if(files != null) {
+ configureWalletsDir(files);
for(File file : files) {
openWalletFile(file, forceSameWindow);
}
}
}
+ private static void configureWalletsDir(List<File> files) {
+ List<File> parentDirs = files.stream().map(File::getParentFile).distinct().collect(Collectors.toList());
+ if(parentDirs.size() == 1 && !Boolean.FALSE.equals(Config.get().getSuggestChangeWalletsDir())) {
+ File selectedDir = parentDirs.getFirst();
+ boolean sameDir;
+ try {
+ sameDir = Files.isSameFile(selectedDir.toPath(), Storage.getWalletsDir().toPath());
+ } catch(IOException e) {
+ sameDir = selectedDir.toPath().normalize().equals(Storage.getWalletsDir().toPath().normalize());
+ }
+ if(!sameDir) {
+ ConfirmationAlert alert = new ConfirmationAlert("Change wallets directory?",
+ "Do you want to configure Sparrow to use " + selectedDir + " as the default wallets directory?", ButtonType.NO, ButtonType.YES);
+ Optional<ButtonType> optType = alert.showAndWait();
+ if(optType.isPresent() && optType.get() == ButtonType.YES) {
+ Config.get().setWalletsDir(selectedDir);
+ Config.get().setSuggestChangeWalletsDir(null);
+ } else if(alert.isDontAskAgain()) {
+ Config.get().setSuggestChangeWalletsDir(Boolean.FALSE);
+ }
+ }
+ }
+ }
+
public void openWalletFile(File file, boolean forceSameWindow) {
try {
Storage storage = new Storage(file);
diff --git a/src/main/java/com/sparrowwallet/sparrow/io/Config.java b/src/main/java/com/sparrowwallet/sparrow/io/Config.java
index 2f9e2ad..51793fd 100644
--- a/src/main/java/com/sparrowwallet/sparrow/io/Config.java
+++ b/src/main/java/com/sparrowwallet/sparrow/io/Config.java
@@ -59,6 +59,8 @@ public class Config {
private Boolean connectToBroadcast;
private Boolean connectToResolve;
private Boolean suggestSendToMany;
+ private Boolean suggestChangeWalletsDir;
+ private File walletsDir;
private List<File> recentWalletFiles;
private Integer keyDerivationPeriod;
private long dustAttackThreshold = DUST_ATTACK_THRESHOLD_SATS;
@@ -406,6 +408,24 @@ public class Config {
flush();
}
+ public Boolean getSuggestChangeWalletsDir() {
+ return suggestChangeWalletsDir;
+ }
+
+ public void setSuggestChangeWalletsDir(Boolean suggestChangeWalletsDir) {
+ this.suggestChangeWalletsDir = suggestChangeWalletsDir;
+ flush();
+ }
+
+ public File getWalletsDir() {
+ return walletsDir;
+ }
+
+ public void setWalletsDir(File walletsDir) {
+ this.walletsDir = walletsDir;
+ flush();
+ }
+
public List<File> getRecentWalletFiles() {
return recentWalletFiles;
}
diff --git a/src/main/java/com/sparrowwallet/sparrow/io/Storage.java b/src/main/java/com/sparrowwallet/sparrow/io/Storage.java
index dd7d737..51147fa 100644
--- a/src/main/java/com/sparrowwallet/sparrow/io/Storage.java
+++ b/src/main/java/com/sparrowwallet/sparrow/io/Storage.java
@@ -485,7 +485,16 @@ public class Storage {
}
public static File getWalletsDir() {
- File walletsDir = new File(getSparrowDir(), WALLETS_DIR);
+ File walletsDir = Config.get().getWalletsDir();
+ if(walletsDir != null) {
+ if(!walletsDir.exists() && (walletsDir.getParentFile() == null || !walletsDir.getParentFile().exists() || !walletsDir.getParentFile().canWrite())) {
+ log.info("Configured wallets directory " + walletsDir.getAbsolutePath() + " is not reachable, reverting to default");
+ walletsDir = null;
+ }
+ }
+ if(walletsDir == null) {
+ walletsDir = new File(getSparrowDir(), WALLETS_DIR);
+ }
if(!walletsDir.exists()) {
createOwnerOnlyDirectory(walletsDir);
}
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.