Implement load hardware wallet screen
MODIFY
WalletWasabi.Gui/Controls/WalletExplorer/PinPadViewModel.cs
WalletWasabi.Gui/Controls/WalletExplorer/PinPadViewModel.cs
@@ -36,6 +36,7 @@ namespace WalletWasabi.Gui.Controls.WalletExplorer
{
SendPinCommand = ReactiveCommand.Create(() =>
{
+ DialogResult = true;
Close();
},
this.WhenAny(x => x.MaskedPin, (maskedPin) => (!string.IsNullOrWhiteSpace(maskedPin.Value))));

MODIFY
WalletWasabi.Gui/Tabs/WalletManager/LoadWalletViewModel.cs
WalletWasabi.Gui/Tabs/WalletManager/LoadWalletViewModel.cs
@@ -366,6 +366,7 @@ namespace WalletWasabi.Gui.Tabs.WalletManager
{
try
{
+ SetValidationMessage("");
CanTestPassword = false;
var password = Guard.Correct(Password); // Don't let whitespaces to the beginning and to the end.
Password = ""; // Clear password field.
@@ -416,17 +417,56 @@ namespace WalletWasabi.Gui.Tabs.WalletManager
{
throw new IOException("promptpin request failed.");
}
- var pinpad = IoC.Get<IShell>().Documents.OfType<PinPadViewModel>().FirstOrDefault();
+
+ PinPadViewModel pinpad = IoC.Get<IShell>().Documents.OfType<PinPadViewModel>().FirstOrDefault();
if (pinpad is null)
{
pinpad = new PinPadViewModel(null);
IoC.Get<IShell>().AddOrSelectDocument(pinpad);
}
var result = await pinpad.ShowDialogAsync();
+ if (!(result is true))
+ {
+ SetValidationMessage("PIN wasn't provided.");
+ return null;
+ }
var maskedPin = pinpad.MaskedPin;
- await HwiProcessManager.SendPinAsync(selectedWallet.HardwareWalletInfo, int.Parse(maskedPin));
- selectedWallet.HardwareWalletInfo.SetNeedPinFalse();
+ if (!await HwiProcessManager.SendPinAsync(selectedWallet.HardwareWalletInfo, maskedPin))
+ {
+ SetValidationMessage("Wrong PIN.");
+ return null;
+ }
+ var p = selectedWallet.HardwareWalletInfo.Path;
+ var t = selectedWallet.HardwareWalletInfo.Type;
+ var enumRes = await HwiProcessManager.EnumerateAsync();
+ TryRefreshHardwareWallets(enumRes);
+ selectedWallet = Wallets.FirstOrDefault(x => x.HardwareWalletInfo.Type == t && x.HardwareWalletInfo.Path == p);
+ if (selectedWallet is null)
+ {
+ SetValidationMessage("Couldn't find the hardware wallet you are working with. Did you disconnect it?");
+ return null;
+ }
+ else
+ {
+ SelectedWallet = selectedWallet;
+ }
+
+ if (!selectedWallet.HardwareWalletInfo.Initialized)
+ {
+ SetValidationMessage("Hardware wallet is not initialized.");
+ return null;
+ }
+ if (!selectedWallet.HardwareWalletInfo.Ready)
+ {
+ SetValidationMessage("Hardware wallet is not ready.");
+ return null;
+ }
+ if (selectedWallet.HardwareWalletInfo.NeedPin)
+ {
+ SetValidationMessage("Hardware wallet still needs a PIN.");
+ return null;
+ }
}
if (selectedWallet.HardwareWalletInfo.MasterFingerprint is null)
@@ -492,6 +532,14 @@ namespace WalletWasabi.Gui.Tabs.WalletManager
}
catch (Exception ex)
{
+ if (ex is IOException && ex.Message.Contains("promptpin", StringComparison.Ordinal))
+ {
+ // This happens for example when the PIN is cleared (timeout, disconnect) after the enumeration and the xpub wasn't yet acquired at all, so we reenumerate.
+ // This will still show up the error, but at least this'll make sure that the new hardware wallet state is shown in the GUI, so they can click Load again.
+ var enumRes = await HwiProcessManager.EnumerateAsync();
+ TryRefreshHardwareWallets(enumRes);
+ }
+
// Initialization failed.
SetValidationMessage(ex.ToTypeMessageString());
Logger.LogError<LoadWalletViewModel>(ex);
@@ -547,6 +595,7 @@ namespace WalletWasabi.Gui.Tabs.WalletManager
try
{
IsBusy = true;
+ SetValidationMessage("");
MainWindowViewModel.Instance.StatusBar.TryAddStatus(StatusBarStatus.Loading);
var keyManager = await LoadKeyManagerAsync(IsPasswordRequired, IsHardwareWallet);

MODIFY
WalletWasabi/Hwi/HwiProcessManager.cs
WalletWasabi/Hwi/HwiProcessManager.cs
@@ -39,7 +39,7 @@ namespace WalletWasabi.Hwi
return success;
}
- public static async Task<bool> SendPinAsync(HardwareWalletInfo hardwareWalletInfo, int pin)
+ public static async Task<bool> SendPinAsync(HardwareWalletInfo hardwareWalletInfo, string pin)
{
var networkString = Network == Network.Main ? "" : "--testnet";
JToken jtok = null;

MODIFY
WalletWasabi/Hwi/Models/HardwareWalletInfo.cs
WalletWasabi/Hwi/Models/HardwareWalletInfo.cs
@@ -52,17 +52,11 @@ namespace WalletWasabi.Hwi.Models
public HDFingerprint? MasterFingerprint { get; }
public bool Initialized { get; }
- public bool NeedPin { get; private set; }
+ public bool NeedPin { get; }
public bool Ready { get; }
public string SerialNumber { get; }
public HardwareWalletType Type { get; }
public string Path { get; }
- public string Error { get; private set; }
-
- public void SetNeedPinFalse()
- {
- NeedPin = false;
- Error = "";
- }
+ public string Error { get; }
}
}

Implement load hardware wallet screen