Introduce HardwareWalletViewModel
MODIFY
WalletWasabi.Gui/Models/LoadWalletEntry.cs
WalletWasabi.Gui/Models/LoadWalletEntry.cs
@@ -8,42 +8,10 @@ namespace WalletWasabi.Gui.Models
public class LoadWalletEntry
{
public string WalletName { get; set; } = null;
- public HwiEnumerateEntry HardwareWalletInfo { get; set; } = null;
public LoadWalletEntry(string walletName)
{
WalletName = walletName;
- HardwareWalletInfo = null;
- }
-
- public LoadWalletEntry(HwiEnumerateEntry hwi)
- {
- string typeString = hwi.Model.ToString();
- var walletNameBuilder = new StringBuilder(typeString);
-
- if (hwi.NeedsPinSent is true)
- {
- walletNameBuilder.Append(" - Needs PIN Sent");
- }
- else if (hwi.NeedsPassphraseSent is true)
- {
- walletNameBuilder.Append(" - Needs Passphrase Sent");
- }
- else if (!string.IsNullOrWhiteSpace(hwi.Error))
- {
- walletNameBuilder.Append($" - Error: {hwi.Error}");
- }
- else if (hwi.Code != null)
- {
- walletNameBuilder.Append($" - Error: {hwi.Code}");
- }
- else if (hwi.Fingerprint is null)
- {
- walletNameBuilder.Append(" - Could Not Acquire Fingerprint");
- }
-
- WalletName = walletNameBuilder.ToString();
- HardwareWalletInfo = hwi;
}
public override string ToString()

MODIFY
WalletWasabi.Gui/Tabs/WalletManager/HardwareWallets/ConnectHardwareWalletViewModel.cs
WalletWasabi.Gui/Tabs/WalletManager/HardwareWallets/ConnectHardwareWalletViewModel.cs
@@ -33,8 +33,8 @@ namespace WalletWasabi.Gui.Tabs.WalletManager.HardwareWallets
{
public class ConnectHardwareWalletViewModel : CategoryViewModel
{
- private ObservableCollection<LoadWalletEntry> _wallets;
- private LoadWalletEntry _selectedWallet;
+ private ObservableCollection<HardwareWalletViewModel> _wallets;
+ private HardwareWalletViewModel _selectedWallet;
private bool _isWalletSelected;
private bool _isWalletOpened;
private bool _canLoadWallet;
@@ -47,7 +47,7 @@ namespace WalletWasabi.Gui.Tabs.WalletManager.HardwareWallets
{
Global = Locator.Current.GetService<Global>();
Owner = owner;
- Wallets = new ObservableCollection<LoadWalletEntry>();
+ Wallets = new ObservableCollection<HardwareWalletViewModel>();
IsHwWalletSearchTextVisible = false;
this.WhenAnyValue(x => x.SelectedWallet)
@@ -143,13 +143,13 @@ namespace WalletWasabi.Gui.Tabs.WalletManager.HardwareWallets
set => this.RaiseAndSetIfChanged(ref _isHwWalletSearchTextVisible, value);
}
- public ObservableCollection<LoadWalletEntry> Wallets
+ public ObservableCollection<HardwareWalletViewModel> Wallets
{
get => _wallets;
set => this.RaiseAndSetIfChanged(ref _wallets, value);
}
- public LoadWalletEntry SelectedWallet
+ public HardwareWalletViewModel SelectedWallet
{
get => _selectedWallet;
set => this.RaiseAndSetIfChanged(ref _selectedWallet, value);
@@ -467,7 +467,7 @@ namespace WalletWasabi.Gui.Tabs.WalletManager.HardwareWallets
Wallets.Clear();
foreach (var dev in devices)
{
- var walletEntry = new LoadWalletEntry(dev);
+ var walletEntry = new HardwareWalletViewModel(dev);
Wallets.Add(walletEntry);
}
TrySetWalletStates();

ADD
WalletWasabi.Gui/Tabs/WalletManager/HardwareWallets/HardwareWalletViewModel.cs
+using System.Text;
+using WalletWasabi.Hwi.Models;
+
+namespace WalletWasabi.Gui.Tabs.WalletManager.HardwareWallets
+{
+ public class HardwareWalletViewModel
+ {
+ public string WalletName { get; set; } = null;
+ public HwiEnumerateEntry HardwareWalletInfo { get; set; } = null;
+
+ public HardwareWalletViewModel(HwiEnumerateEntry hwi)
+ {
+ string typeString = hwi.Model.ToString();
+ var walletNameBuilder = new StringBuilder(typeString);
+
+ if (hwi.NeedsPinSent is true)
+ {
+ walletNameBuilder.Append(" - Needs PIN Sent");
+ }
+ else if (hwi.NeedsPassphraseSent is true)
+ {
+ walletNameBuilder.Append(" - Needs Passphrase Sent");
+ }
+ else if (!string.IsNullOrWhiteSpace(hwi.Error))
+ {
+ walletNameBuilder.Append($" - Error: {hwi.Error}");
+ }
+ else if (hwi.Code != null)
+ {
+ walletNameBuilder.Append($" - Error: {hwi.Code}");
+ }
+ else if (hwi.Fingerprint is null)
+ {
+ walletNameBuilder.Append(" - Could Not Acquire Fingerprint");
+ }
+
+ WalletName = walletNameBuilder.ToString();
+ HardwareWalletInfo = hwi;
+ }
+
+ public override string ToString()
+ {
+ return WalletName;
+ }
+ }
+}

MODIFY
WalletWasabi.Gui/Tabs/WalletManager/LoadWallets/LoadWalletViewModel.cs
WalletWasabi.Gui/Tabs/WalletManager/LoadWallets/LoadWalletViewModel.cs
@@ -72,7 +72,7 @@ namespace WalletWasabi.Gui.Tabs.WalletManager.LoadWallets
.Subscribe(_ => TrySetWalletStates());
LoadCommand = ReactiveCommand.CreateFromTask(LoadWalletAsync, this.WhenAnyValue(x => x.CanLoadWallet));
- TestPasswordCommand = ReactiveCommand.CreateFromTask(LoadKeyManagerAsync, this.WhenAnyValue(x => x.CanTestPassword));
+ TestPasswordCommand = ReactiveCommand.Create(LoadKeyManager, this.WhenAnyValue(x => x.CanTestPassword));
OpenFolderCommand = ReactiveCommand.Create(OpenWalletsFolder);
Observable
@@ -193,24 +193,6 @@ namespace WalletWasabi.Gui.Tabs.WalletManager.LoadWallets
{
text = "Loading...";
}
- else
- {
- // If the hardware wallet was not initialized, then make the button say Setup, not Load.
- // If pin is needed, then make the button say Send Pin instead.
-
- if (SelectedWallet?.HardwareWalletInfo != null)
- {
- if (!SelectedWallet.HardwareWalletInfo.IsInitialized())
- {
- text = "Setup Wallet";
- }
-
- if (SelectedWallet.HardwareWalletInfo.NeedsPinSent is true)
- {
- text = "Send PIN";
- }
- }
- }
LoadButtonText = text;
}
@@ -242,7 +224,7 @@ namespace WalletWasabi.Gui.Tabs.WalletManager.LoadWallets
}
}
- public async Task<KeyManager> LoadKeyManagerAsync()
+ public KeyManager LoadKeyManager()
{
try
{
@@ -258,119 +240,6 @@ namespace WalletWasabi.Gui.Tabs.WalletManager.LoadWallets
}
var walletName = selectedWallet.WalletName;
- if (IsHardwareWallet)
- {
- var client = new HwiClient(Global.Network);
-
- if (selectedWallet.HardwareWalletInfo is null)
- {
- NotificationHelpers.Warning("No hardware wallet detected.");
- return null;
- }
-
- if (!selectedWallet.HardwareWalletInfo.IsInitialized())
- {
- try
- {
- IsHardwareBusy = true;
- MainWindowViewModel.Instance.StatusBar.TryAddStatus(StatusType.SettingUpHardwareWallet);
-
- // Setup may take a while for users to write down stuff.
- using (var ctsSetup = new CancellationTokenSource(TimeSpan.FromMinutes(21)))
- {
- // Trezor T doesn't require interactive mode.
- if (selectedWallet.HardwareWalletInfo.Model == HardwareWalletModels.Trezor_T
- || selectedWallet.HardwareWalletInfo.Model == HardwareWalletModels.Trezor_T_Simulator)
- {
- await client.SetupAsync(selectedWallet.HardwareWalletInfo.Model, selectedWallet.HardwareWalletInfo.Path, false, ctsSetup.Token);
- }
- else
- {
- await client.SetupAsync(selectedWallet.HardwareWalletInfo.Model, selectedWallet.HardwareWalletInfo.Path, true, ctsSetup.Token);
- }
- }
-
- MainWindowViewModel.Instance.StatusBar.TryAddStatus(StatusType.ConnectingToHardwareWallet);
- await EnumerateIfHardwareWalletsAsync();
- }
- finally
- {
- IsHardwareBusy = false;
- MainWindowViewModel.Instance.StatusBar.TryRemoveStatus(StatusType.SettingUpHardwareWallet, StatusType.ConnectingToHardwareWallet);
- }
-
- return await LoadKeyManagerAsync();
- }
- else if (selectedWallet.HardwareWalletInfo.NeedsPinSent is true)
- {
- await PinPadViewModel.UnlockAsync(selectedWallet.HardwareWalletInfo);
-
- var p = selectedWallet.HardwareWalletInfo.Path;
- var t = selectedWallet.HardwareWalletInfo.Model;
- await EnumerateIfHardwareWalletsAsync();
- selectedWallet = Wallets.FirstOrDefault(x => x.HardwareWalletInfo.Model == t && x.HardwareWalletInfo.Path == p);
- if (selectedWallet is null)
- {
- NotificationHelpers.Warning("Could not find the hardware wallet. Did you disconnect it?");
- return null;
- }
- else
- {
- SelectedWallet = selectedWallet;
- }
-
- if (!selectedWallet.HardwareWalletInfo.IsInitialized())
- {
- NotificationHelpers.Warning("Hardware wallet is not initialized.");
- return null;
- }
-
- if (selectedWallet.HardwareWalletInfo.NeedsPinSent is true)
- {
- NotificationHelpers.Warning("Hardware wallet needs a PIN to be sent.");
- return null;
- }
- }
-
- ExtPubKey extPubKey;
- var cts = new CancellationTokenSource(TimeSpan.FromMinutes(3));
- try
- {
- MainWindowViewModel.Instance.StatusBar.TryAddStatus(StatusType.AcquiringXpubFromHardwareWallet);
- extPubKey = await client.GetXpubAsync(selectedWallet.HardwareWalletInfo.Model, selectedWallet.HardwareWalletInfo.Path, KeyManager.DefaultAccountKeyPath, cts.Token);
- }
- finally
- {
- cts?.Dispose();
- MainWindowViewModel.Instance.StatusBar.TryRemoveStatus(StatusType.AcquiringXpubFromHardwareWallet);
- }
-
- Logger.LogInfo("Hardware wallet was not used previously on this computer. Creating a new wallet file.");
-
- if (TryFindWalletByExtPubKey(extPubKey, out string wn))
- {
- walletName = wn;
- }
- else
- {
- var prefix = selectedWallet.HardwareWalletInfo is null ? "HardwareWallet" : selectedWallet.HardwareWalletInfo.Model.ToString();
-
- walletName = Global.WalletManager.WalletDirectories.GetNextWalletName(prefix);
- var path = Global.WalletManager.WalletDirectories.GetWalletFilePaths(walletName).walletFilePath;
-
- // Get xpub should had triggered passphrase request, so the fingerprint should be available here.
- if (!selectedWallet.HardwareWalletInfo.Fingerprint.HasValue)
- {
- await EnumerateIfHardwareWalletsAsync();
- selectedWallet = Wallets.FirstOrDefault(x => x.HardwareWalletInfo.Model == selectedWallet.HardwareWalletInfo.Model && x.HardwareWalletInfo.Path == selectedWallet.HardwareWalletInfo.Path);
- }
- if (!selectedWallet.HardwareWalletInfo.Fingerprint.HasValue)
- {
- throw new InvalidOperationException("Hardware wallet did not provide fingerprint.");
- }
- KeyManager.CreateNewHardwareWalletWatchOnly(selectedWallet.HardwareWalletInfo.Fingerprint.Value, extPubKey, path);
- }
- }
KeyManager keyManager = Global.WalletManager.GetWalletByName(walletName).KeyManager;
@@ -406,15 +275,6 @@ namespace WalletWasabi.Gui.Tabs.WalletManager.LoadWallets
}
catch (Exception ex)
{
- try
- {
- await EnumerateIfHardwareWalletsAsync();
- }
- catch (Exception ex2)
- {
- Logger.LogError(ex2);
- }
-
// Initialization failed.
NotificationHelpers.Error(ex.ToUserFriendlyString());
Logger.LogError(ex);
@@ -433,7 +293,7 @@ namespace WalletWasabi.Gui.Tabs.WalletManager.LoadWallets
{
IsBusy = true;
- var keyManager = await LoadKeyManagerAsync();
+ var keyManager = LoadKeyManager();
if (keyManager is null)
{
return;
@@ -507,34 +367,6 @@ namespace WalletWasabi.Gui.Tabs.WalletManager.LoadWallets
return false;
}
- protected async Task EnumerateIfHardwareWalletsAsync()
- {
- if (!IsHardwareWallet)
- {
- return;
- }
- var cts = new CancellationTokenSource(TimeSpan.FromMinutes(3));
- IsHwWalletSearchTextVisible = true;
- try
- {
- var client = new HwiClient(Global.Network);
- var devices = await client.EnumerateAsync(cts.Token);
-
- Wallets.Clear();
- foreach (var dev in devices)
- {
- var walletEntry = new LoadWalletEntry(dev);
- Wallets.Add(walletEntry);
- }
- TrySetWalletStates();
- }
- finally
- {
- IsHwWalletSearchTextVisible = false;
- cts.Dispose();
- }
- }
-
private bool TryFindWalletByExtPubKey(ExtPubKey extPubKey, out string walletName)
{
walletName = Global.WalletManager.WalletDirectories

Introduce HardwareWalletViewModel