Use friendly wallet names.
MODIFY
WalletWasabi.Gui/Tabs/WalletManager/HardwareWallets/ConnectHardwareWalletViewModel.cs
WalletWasabi.Gui/Tabs/WalletManager/HardwareWallets/ConnectHardwareWalletViewModel.cs
@@ -324,10 +324,7 @@ namespace WalletWasabi.Gui.Tabs.WalletManager.HardwareWallets
else
{
Logger.LogInfo("Hardware wallet was not used previously on this computer. Creating a new wallet file.");
-
- var prefix = selectedWallet.HardwareWalletInfo is null ? "HardwareWallet" : selectedWallet.HardwareWalletInfo.Model.ToString();
-
- walletName = WalletManager.WalletDirectories.GetNextWalletName(prefix);
+ walletName = WalletManager.WalletDirectories.GetNextHardwareWalletName(selectedWallet.HardwareWalletInfo?.Model ?? HardwareWalletModels.Unknown);
var path = WalletManager.WalletDirectories.GetWalletFilePaths(walletName).walletFilePath;
// Get xpub should had triggered passphrase request, so the fingerprint should be available here.

MODIFY
WalletWasabi.Tests/UnitTests/WalletDirTests.cs
WalletWasabi.Tests/UnitTests/WalletDirTests.cs
@@ -5,6 +5,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WalletWasabi.Helpers;
+using WalletWasabi.Hwi.Models;
using WalletWasabi.Wallets;
using Xunit;
@@ -157,21 +158,84 @@ namespace WalletWasabi.Tests.UnitTests
{
var baseDir = Path.Combine(Global.Instance.DataDir, EnvironmentHelpers.GetCallerFileName(), EnvironmentHelpers.GetMethodName());
await CleanupWalletDirectoriesAsync(baseDir);
-
var walletDirectories = new WalletDirectories(baseDir);
+ IoHelpers.CreateEmptyFile(Path.Combine(walletDirectories.WalletsDir, "Random Wallet 3.json"));
+
+ Assert.Equal("Random Wallet", walletDirectories.GetNextWalletName());
+ IoHelpers.CreateEmptyFile(Path.Combine(walletDirectories.WalletsDir, "Random Wallet.json"));
+ Assert.Equal("Random Wallet 2", walletDirectories.GetNextWalletName());
+ IoHelpers.CreateEmptyFile(Path.Combine(walletDirectories.WalletsDir, "Random Wallet 2.json"));
+ Assert.Equal("Random Wallet 4", walletDirectories.GetNextWalletName());
+
+ IoHelpers.CreateEmptyFile(Path.Combine(walletDirectories.WalletsDir, "Random Wallet 4.dat"));
+ IoHelpers.CreateEmptyFile(Path.Combine(walletDirectories.WalletsDir, "Random Wallet 4"));
+ Assert.Equal("Random Wallet 4", walletDirectories.GetNextWalletName());
+
+ File.Delete(Path.Combine(walletDirectories.WalletsDir, "Random Wallet.json"));
+ File.Delete(Path.Combine(walletDirectories.WalletsDir, "Random Wallet 3.json"));
+ Assert.Equal("Random Wallet", walletDirectories.GetNextWalletName());
+ IoHelpers.CreateEmptyFile(Path.Combine(walletDirectories.WalletsDir, "Random Wallet.json"));
+ Assert.Equal("Random Wallet 3", walletDirectories.GetNextWalletName());
+ IoHelpers.CreateEmptyFile(Path.Combine(walletDirectories.WalletsDir, "Random Wallet 3.json"));
+ File.Delete(Path.Combine(walletDirectories.WalletsDir, "Random Wallet 3.json"));
+
+ Assert.Equal("Foo", walletDirectories.GetNextWalletName("Foo"));
+ IoHelpers.CreateEmptyFile(Path.Combine(walletDirectories.WalletsDir, "Foo.json"));
+ Assert.Equal("Foo 2", walletDirectories.GetNextWalletName("Foo"));
+ IoHelpers.CreateEmptyFile(Path.Combine(walletDirectories.WalletsDir, "Foo 2.json"));
+ }
- Assert.Equal("Wallet0", walletDirectories.GetNextWalletName());
-
- await File.Create(Path.Combine(walletDirectories.WalletsDir, $"Wallet0.json")).DisposeAsync();
- await File.Create(Path.Combine(walletDirectories.WalletsDir, $"Wallet1.json")).DisposeAsync();
- await File.Create(Path.Combine(walletDirectories.WalletsDir, $"Wallet3.json")).DisposeAsync();
-
- // This should not matter.
- await File.Create(Path.Combine(walletDirectories.WalletsBackupDir, $"Wallet2.json")).DisposeAsync();
-
- Assert.Equal("Wallet2", walletDirectories.GetNextWalletName());
+ [Fact]
+ public async Task GetNextHardwareWalletNameAsync()
+ {
+ var baseDir = Path.Combine(Global.Instance.DataDir, EnvironmentHelpers.GetCallerFileName(), EnvironmentHelpers.GetMethodName());
+ await CleanupWalletDirectoriesAsync(baseDir);
+ var walletDirectories = new WalletDirectories(baseDir);
- Assert.Equal("Foo0", walletDirectories.GetNextWalletName("Foo"));
+ Assert.Equal("Hardware Wallet", walletDirectories.GetNextHardwareWalletName(HardwareWalletModels.Unknown));
+ IoHelpers.CreateEmptyFile(Path.Combine(walletDirectories.WalletsDir, "Hardware Wallet.json"));
+ Assert.Equal("Hardware Wallet 2", walletDirectories.GetNextHardwareWalletName(HardwareWalletModels.Unknown));
+ IoHelpers.CreateEmptyFile(Path.Combine(walletDirectories.WalletsDir, "Hardware Wallet 2.json"));
+
+ Assert.Equal("Coldcard", walletDirectories.GetNextHardwareWalletName(HardwareWalletModels.Coldcard));
+ IoHelpers.CreateEmptyFile(Path.Combine(walletDirectories.WalletsDir, "Coldcard.json"));
+ Assert.Equal("Coldcard 2", walletDirectories.GetNextHardwareWalletName(HardwareWalletModels.Coldcard));
+ IoHelpers.CreateEmptyFile(Path.Combine(walletDirectories.WalletsDir, "Coldcard 2.json"));
+
+ Assert.Equal("Coldcard Simulator", walletDirectories.GetNextHardwareWalletName(HardwareWalletModels.Coldcard_Simulator));
+ IoHelpers.CreateEmptyFile(Path.Combine(walletDirectories.WalletsDir, "Coldcard Simulator.json"));
+ Assert.Equal("Coldcard Simulator 2", walletDirectories.GetNextHardwareWalletName(HardwareWalletModels.Coldcard_Simulator));
+ IoHelpers.CreateEmptyFile(Path.Combine(walletDirectories.WalletsDir, "Coldcard Simulator 2.json"));
+
+ IoHelpers.CreateEmptyFile(Path.Combine(walletDirectories.WalletsDir, "Trezor T.json"));
+ Assert.Equal("Trezor T 2", walletDirectories.GetNextHardwareWalletName(HardwareWalletModels.Trezor_T));
+ IoHelpers.CreateEmptyFile(Path.Combine(walletDirectories.WalletsDir, "Trezor T 2.json"));
+ Assert.Equal("Trezor T 3", walletDirectories.GetNextHardwareWalletName(HardwareWalletModels.Trezor_T));
+ IoHelpers.CreateEmptyFile(Path.Combine(walletDirectories.WalletsDir, "Trezor T 3.json"));
+
+ Assert.Equal("BitBox", walletDirectories.GetNextHardwareWalletName(HardwareWalletModels.BitBox02_BTCOnly));
+ IoHelpers.CreateEmptyFile(Path.Combine(walletDirectories.WalletsDir, "BitBox.json"));
+ Assert.Equal("BitBox 2", walletDirectories.GetNextHardwareWalletName(HardwareWalletModels.BitBox02_Multi));
+ IoHelpers.CreateEmptyFile(Path.Combine(walletDirectories.WalletsDir, "BitBox 2.json"));
+ Assert.Equal("BitBox 3", walletDirectories.GetNextHardwareWalletName(HardwareWalletModels.BitBox02_BTCOnly));
+ IoHelpers.CreateEmptyFile(Path.Combine(walletDirectories.WalletsDir, "BitBox 3.json"));
+ Assert.Equal("BitBox 4", walletDirectories.GetNextHardwareWalletName(HardwareWalletModels.DigitalBitBox_01));
+ IoHelpers.CreateEmptyFile(Path.Combine(walletDirectories.WalletsDir, "BitBox 4.json"));
+
+ Assert.Equal("BitBox Simulator", walletDirectories.GetNextHardwareWalletName(HardwareWalletModels.DigitalBitBox_01_Simulator));
+ IoHelpers.CreateEmptyFile(Path.Combine(walletDirectories.WalletsDir, "BitBox Simulator.json"));
+ Assert.Equal("BitBox Simulator 2", walletDirectories.GetNextHardwareWalletName(HardwareWalletModels.DigitalBitBox_01_Simulator));
+ IoHelpers.CreateEmptyFile(Path.Combine(walletDirectories.WalletsDir, "BitBox Simulator 2.json"));
+
+ Assert.Equal("Ledger Nano S", walletDirectories.GetNextHardwareWalletName(HardwareWalletModels.Ledger_Nano_S));
+ IoHelpers.CreateEmptyFile(Path.Combine(walletDirectories.WalletsDir, "Ledger Nano S.json"));
+ Assert.Equal("Ledger Nano S 2", walletDirectories.GetNextHardwareWalletName(HardwareWalletModels.Ledger_Nano_S));
+ IoHelpers.CreateEmptyFile(Path.Combine(walletDirectories.WalletsDir, "Ledger Nano S 2.json"));
+
+ Assert.Equal("Trezor One", walletDirectories.GetNextHardwareWalletName(HardwareWalletModels.Trezor_1));
+ IoHelpers.CreateEmptyFile(Path.Combine(walletDirectories.WalletsDir, "Trezor One.json"));
+ Assert.Equal("Trezor One 2", walletDirectories.GetNextHardwareWalletName(HardwareWalletModels.Trezor_1));
+ IoHelpers.CreateEmptyFile(Path.Combine(walletDirectories.WalletsDir, "Trezor One 2.json"));
}
}
}

MODIFY
WalletWasabi/Helpers/IoHelpers.cs
WalletWasabi/Helpers/IoHelpers.cs
@@ -174,5 +174,10 @@ namespace System.IO
file.CopyTo(Path.Combine(target.FullName, file.Name));
}
}
+
+ public static void CreateEmptyFile(string path)
+ {
+ using var _ = File.Create(path);
+ }
}
}

MODIFY
WalletWasabi/Wallets/WalletDirectories.cs
WalletWasabi/Wallets/WalletDirectories.cs
@@ -68,13 +68,15 @@ namespace WalletWasabi.Wallets
return result.OrderByDescending(t => t.LastAccessTimeUtc);
}
- public string GetNextWalletName(string prefix = "Wallet")
+ public string GetNextWalletName(string prefix = "Random Wallet")
{
- int i = 0;
+ int i = 1;
+ var walletNames = EnumerateWalletFiles(true).Select(x => Path.GetFileNameWithoutExtension(x.Name));
while (true)
{
- var walletName = $"{prefix}{i}";
- if (!File.Exists(GetWalletFilePaths(walletName).walletFilePath))
+ var walletName = i == 1 ? prefix : $"{prefix} {i}";
+
+ if (!walletNames.Contains(walletName))
{
return walletName;
}
@@ -82,5 +84,38 @@ namespace WalletWasabi.Wallets
i++;
}
}
+
+ public string GetNextHardwareWalletName(HardwareWalletModels model)
+ {
+ string prefix;
+ if (model == HardwareWalletModels.Unknown)
+ {
+ prefix = "Hardware Wallet";
+ }
+ else if (model == HardwareWalletModels.BitBox02_BTCOnly
+ || model == HardwareWalletModels.BitBox02_Multi
+ || model == HardwareWalletModels.DigitalBitBox_01)
+ {
+ prefix = "BitBox";
+ }
+ else if (model == HardwareWalletModels.DigitalBitBox_01_Simulator)
+ {
+ prefix = "BitBox Simulator";
+ }
+ else if (model == HardwareWalletModels.Trezor_1)
+ {
+ prefix = "Trezor One";
+ }
+ else if (model == HardwareWalletModels.Trezor_1_Simulator)
+ {
+ prefix = "Trezor One Simulator";
+ }
+ else
+ {
+ prefix = GetNextWalletName(model.ToString().Replace('_', ' '));
+ }
+
+ return GetNextWalletName(prefix);
+ }
}
}

Use friendly wallet names.