update existing DetectionPage.
MODIFY
WalletWasabi.Fluent/Converters/HardwareWalletIconConverter.cs
WalletWasabi.Fluent/Converters/HardwareWalletIconConverter.cs
@@ -25,8 +25,7 @@ namespace WalletWasabi.Fluent.Converters
{
case Hwi.Models.HardwareWalletModels.Coldcard:
case Hwi.Models.HardwareWalletModels.Coldcard_Simulator:
- //uri = new ("avares://WalletWasabi.Fluent/Assets/HardwareIcons/coldcard.png");
- uri = new("avares://WalletWasabi.Fluent/Assets/HardwareIcons/ledger.png");
+ uri = new ("avares://WalletWasabi.Fluent/Assets/HardwareIcons/coldcard.png");
break;
case Hwi.Models.HardwareWalletModels.Trezor_1:

MODIFY
WalletWasabi.Fluent/ViewModels/AddWallet/ConnectHardwareWalletViewModel.cs
WalletWasabi.Fluent/ViewModels/AddWallet/ConnectHardwareWalletViewModel.cs
using NBitcoin;
using ReactiveUI;
-using System;
-using System.Collections.Generic;
using System.Linq;
using System.Reactive;
using System.Reactive.Concurrency;
using System.Reactive.Disposables;
using System.Reactive.Linq;
using System.Threading;
-using System.Threading.Tasks;
-using WalletWasabi.Blockchain.Keys;
using WalletWasabi.Fluent.ViewModels.Navigation;
-using WalletWasabi.Hwi;
using WalletWasabi.Wallets;
namespace WalletWasabi.Fluent.ViewModels.AddWallet
{
- public class HardwareDetectionState
- {
- private HwiClient _client;
-
- public HardwareDetectionState(string walletName, WalletManager walletManager, Network network)
- {
- WalletName = walletName;
- WalletManager = walletManager;
- Network = network;
- _client = new HwiClient(network);
-
- Devices = Enumerable.Empty<Hwi.Models.HwiEnumerateEntry>();
- }
-
- public IEnumerable<Hwi.Models.HwiEnumerateEntry> Devices { get; private set; }
-
- public Hwi.Models.HwiEnumerateEntry? SelectedDevice { get; set; }
-
- public WalletManager WalletManager { get; }
-
- public Network Network { get; }
-
- public string WalletName { get; }
-
- public async Task<KeyManager> GenerateWalletAsync()
- {
- var selectedDevice = SelectedDevice;
-
- if(selectedDevice is null)
- {
- throw new Exception("Cannot be null.");
- }
-
- var fingerPrint = (HDFingerprint)selectedDevice.Fingerprint;
- using var cts = new CancellationTokenSource(TimeSpan.FromMinutes(3));
- var extPubKey = await _client.GetXpubAsync(selectedDevice.Model, selectedDevice.Path, KeyManager.DefaultAccountKeyPath, cts.Token).ConfigureAwait(false);
- var path = WalletManager.WalletDirectories.GetWalletFilePaths(WalletName).walletFilePath;
-
- return KeyManager.CreateNewHardwareWalletWatchOnly(fingerPrint, extPubKey, path);
- }
-
- public async Task EnumerateHardwareWalletsAsync(CancellationToken token)
- {
- Devices = (await _client.EnumerateAsync(token).ConfigureAwait(false))
- .Where(wallet => WalletManager.GetWallets()
- .Any(x=>x.KeyManager.MasterFingerprint == wallet.Fingerprint) == false);
- }
- }
-
public class ConnectHardwareWalletViewModel : RoutableViewModel
{
public ConnectHardwareWalletViewModel(NavigationStateViewModel navigationState, string walletName, Network network, WalletManager walletManager, bool trySkipPage = true)
: base(navigationState, NavigationTarget.DialogScreen)
{
+ var detectionState = new HardwareDetectionState(walletName, walletManager, network);
+
if (trySkipPage)
{
IsBusy = true;
@@ -78,8 +26,6 @@ namespace WalletWasabi.Fluent.ViewModels.AddWallet
{
RxApp.MainThreadScheduler.Schedule(async () =>
{
- var detectionState = new HardwareDetectionState(walletName, walletManager, network);
-
await detectionState.EnumerateHardwareWalletsAsync(CancellationToken.None);
var deviceCount = detectionState.Devices.Count();
@@ -87,6 +33,7 @@ namespace WalletWasabi.Fluent.ViewModels.AddWallet
if (deviceCount == 0)
{
// navigate to detecting page.
+ NavigateTo(new DetectHardwareWalletViewModel(navigationState, detectionState), NavigationTarget.DialogScreen);
}
else if (deviceCount == 1)
{
@@ -109,7 +56,7 @@ namespace WalletWasabi.Fluent.ViewModels.AddWallet
NextCommand = ReactiveCommand.Create(() =>
{
- NavigateTo(new DetectHardwareWalletViewModel(navigationState, walletName, network, walletManager), NavigationTarget.DialogScreen);
+ NavigateTo(new DetectHardwareWalletViewModel(navigationState, detectionState), NavigationTarget.DialogScreen);
});
}

MODIFY
WalletWasabi.Fluent/ViewModels/AddWallet/DetectHardwareWalletViewModel.cs
WalletWasabi.Fluent/ViewModels/AddWallet/DetectHardwareWalletViewModel.cs
@@ -24,22 +24,24 @@ namespace WalletWasabi.Fluent.ViewModels.AddWallet
public class DetectHardwareWalletViewModel : RoutableViewModel
{
private HardwareWalletViewModel? _selectedHardwareWallet;
+ private HardwareDetectionState _detectionState;
- public DetectHardwareWalletViewModel(NavigationStateViewModel navigationState, string walletName, Network network, WalletManager walletManager)
+ public DetectHardwareWalletViewModel(NavigationStateViewModel navigationState, HardwareDetectionState detectionState)
: base(navigationState, NavigationTarget.DialogScreen)
{
- WalletName = walletName;
- WalletManager = walletManager;
- HwiClient = new HwiClient(network);
HardwareWallets = new ObservableCollection<HardwareWalletViewModel>();
+ _detectionState = detectionState;
+
OpenBrowserCommand = ReactiveCommand.CreateFromTask<string>(IoHelpers.OpenBrowserAsync);
- var nextCommandIsExecute =
this.WhenAnyValue(x => x.SelectedHardwareWallet)
.ObserveOn(RxApp.MainThreadScheduler)
- .Select(x => x?.HardwareWalletInfo.Fingerprint is { } && x.HardwareWalletInfo.IsInitialized());
- NextCommand = ReactiveCommand.CreateFromTask(ConnectSelectedHardwareWallet,nextCommandIsExecute);
+ .Select(x => x?.HardwareWalletInfo.Fingerprint is { } && x.HardwareWalletInfo.IsInitialized())
+ .Subscribe(async x=>
+ {
+ await ConnectSelectedHardwareWalletAsync();
+ });
this.WhenAnyValue(x => x.SelectedHardwareWallet)
.ObserveOn(RxApp.MainThreadScheduler)
@@ -60,7 +62,11 @@ namespace WalletWasabi.Fluent.ViewModels.AddWallet
try
{
// TODO: Notify the user to check the device
- await HwiClient.SetupAsync(x.HardwareWalletInfo.Model, x.HardwareWalletInfo.Path, interactiveMode, initCts.Token);
+
+ await _detectionState.Client.SetupAsync(x.HardwareWalletInfo.Model, x.HardwareWalletInfo.Path, interactiveMode, initCts.Token);
+
+ // todo... check this doesnt trigger the other navigage to.
+ await ConnectSelectedHardwareWalletAsync();
}
catch (Exception ex)
{
@@ -82,12 +88,6 @@ namespace WalletWasabi.Fluent.ViewModels.AddWallet
});
}
- private string WalletName { get; }
-
- private WalletManager WalletManager { get; }
-
- private HwiClient HwiClient { get; }
-
private Task? DetectionTask { get; set; }
private CancellationTokenSource? DetectionCts { get; set; }
@@ -104,7 +104,7 @@ namespace WalletWasabi.Fluent.ViewModels.AddWallet
public ReactiveCommand<string, Unit> OpenBrowserCommand { get; }
- private async Task ConnectSelectedHardwareWallet()
+ private async Task ConnectSelectedHardwareWalletAsync()
{
if (SelectedHardwareWallet?.HardwareWalletInfo.Fingerprint is null)
{
@@ -116,20 +116,9 @@ namespace WalletWasabi.Fluent.ViewModels.AddWallet
IsBusy = true;
await StopDetectionAsync();
- var newWallet = await Task.Run(async () =>
- {
- var fingerPrint = (HDFingerprint)SelectedHardwareWallet.HardwareWalletInfo.Fingerprint;
- using var cts = new CancellationTokenSource(TimeSpan.FromMinutes(3));
- var extPubKey = await HwiClient.GetXpubAsync(SelectedHardwareWallet.HardwareWalletInfo.Model, SelectedHardwareWallet.HardwareWalletInfo.Path, KeyManager.DefaultAccountKeyPath, cts.Token);
- var path = WalletManager.WalletDirectories.GetWalletFilePaths(WalletName).walletFilePath;
-
- return KeyManager.CreateNewHardwareWalletWatchOnly(fingerPrint, extPubKey, path);
- });
-
- WalletManager.AddWallet(newWallet);
+ _detectionState.SelectedDevice = SelectedHardwareWallet.HardwareWalletInfo;
- // Close dialog
- ClearNavigation();
+ NavigateTo(new DetectedHardwareWalletViewModel(NavigationState, _detectionState), NavigationTarget.DialogScreen);
}
catch (Exception ex)
{
@@ -173,11 +162,11 @@ namespace WalletWasabi.Fluent.ViewModels.AddWallet
{
using var timeoutCts = new CancellationTokenSource(TimeSpan.FromMinutes(3));
- var detectedHardwareWallets = (await HwiClient.EnumerateAsync(timeoutCts.Token).ConfigureAwait(false)).Select(x => new HardwareWalletViewModel(x)).ToArray();
+ var detectedHardwareWallets = (await _detectionState.Client.EnumerateAsync(timeoutCts.Token).ConfigureAwait(false)).Select(x => new HardwareWalletViewModel(x)).ToArray();
detectionCts.Token.ThrowIfCancellationRequested();
// The wallets that already exist in the software.
- var alreadyExistingWalletsToRemove = detectedHardwareWallets.Where(wallet => WalletManager.GetWallets().Any(x => x.KeyManager.MasterFingerprint == wallet.HardwareWalletInfo.Fingerprint));
+ var alreadyExistingWalletsToRemove = detectedHardwareWallets.Where(wallet => _detectionState.WalletManager.GetWallets().Any(x => x.KeyManager.MasterFingerprint == wallet.HardwareWalletInfo.Fingerprint));
// The wallets that are not detectable since the last enumeration.
var disconnectedWalletsToRemove = HardwareWallets.Except(detectedHardwareWallets);

ADD
WalletWasabi.Fluent/ViewModels/AddWallet/HardwareDetectionState.cs
+using NBitcoin;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reactive.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using WalletWasabi.Blockchain.Keys;
+using WalletWasabi.Hwi;
+using WalletWasabi.Wallets;
+
+namespace WalletWasabi.Fluent.ViewModels.AddWallet
+{
+ public class HardwareDetectionState
+ {
+ public HardwareDetectionState(string walletName, WalletManager walletManager, Network network)
+ {
+ WalletName = walletName;
+ WalletManager = walletManager;
+ Network = network;
+ Client = new HwiClient(network);
+
+ Devices = Enumerable.Empty<Hwi.Models.HwiEnumerateEntry>();
+ }
+
+ public IEnumerable<Hwi.Models.HwiEnumerateEntry> Devices { get; private set; }
+
+ public Hwi.Models.HwiEnumerateEntry? SelectedDevice { get; set; }
+
+ public WalletManager WalletManager { get; }
+
+ public Network Network { get; }
+
+ public HwiClient Client { get; }
+
+ public string WalletName { get; }
+
+ public async Task<KeyManager> GenerateWalletAsync()
+ {
+ var selectedDevice = SelectedDevice;
+
+ if(selectedDevice is null)
+ {
+ throw new Exception("Cannot be null.");
+ }
+
+ var fingerPrint = (HDFingerprint)selectedDevice.Fingerprint;
+ using var cts = new CancellationTokenSource(TimeSpan.FromMinutes(3));
+ var extPubKey = await Client.GetXpubAsync(selectedDevice.Model, selectedDevice.Path, KeyManager.DefaultAccountKeyPath, cts.Token).ConfigureAwait(false);
+ var path = WalletManager.WalletDirectories.GetWalletFilePaths(WalletName).walletFilePath;
+
+ return KeyManager.CreateNewHardwareWalletWatchOnly(fingerPrint, extPubKey, path);
+ }
+
+ public async Task EnumerateHardwareWalletsAsync(CancellationToken token)
+ {
+ Devices = (await Client.EnumerateAsync(token).ConfigureAwait(false))
+ .Where(wallet => WalletManager.GetWallets()
+ .Any(x=>x.KeyManager.MasterFingerprint == wallet.Fingerprint) == false);
+ }
+ }
+}

MODIFY
WalletWasabi.Fluent/Views/AddWallet/DetectHardwareWalletView.axaml
WalletWasabi.Fluent/Views/AddWallet/DetectHardwareWalletView.axaml
<DockPanel>
<Button DockPanel.Dock="Bottom" HorizontalAlignment="Center" Classes="h8 plain activeHyperLink" Foreground="{DynamicResource SystemAccentColor}" Content="More information and help with Hardware Wallets" />
- <Panel>
- <ListBox IsVisible="{Binding WalletListVisible}" Background="Transparent" Items="{Binding HardwareWallets}" SelectedItem="{Binding SelectedHardwareWallet}">
- <ListBox.ItemsPanel>
- <ItemsPanelTemplate>
- <WrapPanel Orientation="Horizontal" HorizontalAlignment="Center" />
- </ItemsPanelTemplate>
- </ListBox.ItemsPanel>
- <ItemsControl.ItemTemplate>
- <DataTemplate>
- <Button Classes="plain" Command="{Binding OpenCommand}" Height="200" Width="150" Margin="8">
- <StackPanel>
- <Image Source="{Binding Path='.' Converter={x:Static conv:HardwareWalletIconConverter.Instance}}" />
- <TextBlock Text="{Binding WalletName}" HorizontalAlignment="Center" />
- </StackPanel>
- </Button>
- </DataTemplate>
- </ItemsControl.ItemTemplate>
- </ListBox>
<DockPanel IsVisible="{Binding !WalletListVisible}">
<StackPanel VerticalAlignment="Top" Spacing="40" DockPanel.Dock="Top" Margin="0 20 0 0">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Spacing="40">
</StackPanel>
<c:ProgressRing IsIndeterminate="True" VerticalAlignment="Center" Height="100" Width="100" />
</DockPanel>
- </Panel>
</DockPanel>
</c:ContentArea>
</UserControl>

update existing DetectionPage.