uiservices class, so less passing stuff around,
MODIFY
WalletWasabi.Fluent/ViewModels/AddWallet/AddWalletPageViewModel.cs
WalletWasabi.Fluent/ViewModels/AddWallet/AddWalletPageViewModel.cs
@@ -32,7 +32,7 @@ namespace WalletWasabi.Fluent.ViewModels.AddWallet
[AutoNotify] private string _walletName = "";
[AutoNotify] private bool _optionsEnabled;
- public AddWalletPageViewModel(WalletManagerViewModel walletManagerViewModel)
+ public AddWalletPageViewModel()
{
SelectionMode = NavBarItemSelectionMode.Button;
@@ -52,11 +52,11 @@ namespace WalletWasabi.Fluent.ViewModels.AddWallet
.Select(x => !string.IsNullOrWhiteSpace(x))
.Subscribe(x => OptionsEnabled = x && !Validations.Any);
- RecoverWalletCommand = ReactiveCommand.Create(() => OnRecoverWallet(walletManagerViewModel));
+ RecoverWalletCommand = ReactiveCommand.Create(() => OnRecoverWallet());
ImportWalletCommand = ReactiveCommand.CreateFromTask(async () => await OnImportWalletAsync());
- ConnectHardwareWalletCommand = ReactiveCommand.Create(() => OnConnectHardwareWallet(walletManagerViewModel));
+ ConnectHardwareWalletCommand = ReactiveCommand.Create(() => OnConnectHardwareWallet());
CreateWalletCommand = ReactiveCommand.CreateFromTask(async () => await OnCreateWalletAsync());
@@ -102,14 +102,14 @@ namespace WalletWasabi.Fluent.ViewModels.AddWallet
public ICommand ConnectHardwareWalletCommand { get; }
- private void OnRecoverWallet(WalletManagerViewModel walletManagerViewModel)
+ private void OnRecoverWallet()
{
Navigate().To(new RecoverWalletViewModel(WalletName));
}
- private void OnConnectHardwareWallet(WalletManagerViewModel walletManagerViewModel)
+ private void OnConnectHardwareWallet()
{
- Navigate().To(new ConnectHardwareWalletViewModel(WalletName, walletManagerViewModel));
+ Navigate().To(new ConnectHardwareWalletViewModel(WalletName));
}
private async Task OnImportWalletAsync()

MODIFY
WalletWasabi.Fluent/ViewModels/AddWallet/HardwareWallet/ConnectHardwareWalletViewModel.cs
WalletWasabi.Fluent/ViewModels/AddWallet/HardwareWallet/ConnectHardwareWalletViewModel.cs
@@ -27,11 +27,11 @@ namespace WalletWasabi.Fluent.ViewModels.AddWallet.HardwareWallet
[AutoNotify] private bool _existingWalletFound;
[AutoNotify] private bool _confirmationRequired;
- public ConnectHardwareWalletViewModel(string walletName, WalletManagerViewModel walletManagerViewModel)
+ public ConnectHardwareWalletViewModel(string walletName)
{
_message = "";
WalletName = walletName;
- Wallets = walletManagerViewModel.Wallets;
+ Wallets = UiServices.WalletManager.Wallets;
AbandonedTasks = new AbandonedTasks();
CancelCts = new CancellationTokenSource();

MODIFY
WalletWasabi.Fluent/ViewModels/MainViewModel.cs
WalletWasabi.Fluent/ViewModels/MainViewModel.cs
@@ -25,7 +25,6 @@ namespace WalletWasabi.Fluent.ViewModels
private readonly SearchPageViewModel _searchPage;
private readonly PrivacyModeViewModel _privacyMode;
private readonly AddWalletPageViewModel _addWalletPage;
- private readonly WalletManagerViewModel _walletManagerViewModel;
[AutoNotify] private bool _isMainContentEnabled;
[AutoNotify] private bool _isDialogScreenEnabled;
[AutoNotify] private bool _isFullScreenEnabled;
@@ -62,12 +61,13 @@ namespace WalletWasabi.Fluent.ViewModels
Services.BitcoinStore.SmartHeaderChain,
Services.Synchronizer);
- _walletManagerViewModel = new WalletManagerViewModel();
- _addWalletPage = new AddWalletPageViewModel(_walletManagerViewModel);
+ UiServices.Initialize();
+
+ _addWalletPage = new AddWalletPageViewModel();
_settingsPage = new SettingsPageViewModel();
_privacyMode = new PrivacyModeViewModel();
_searchPage = new SearchPageViewModel();
- _navBar = new NavBarViewModel(MainScreen, _walletManagerViewModel);
+ _navBar = new NavBarViewModel(MainScreen);
NavigationManager.RegisterType(_navBar);

MODIFY
WalletWasabi.Fluent/ViewModels/NavBar/NavBarViewModel.cs
WalletWasabi.Fluent/ViewModels/NavBar/NavBarViewModel.cs
@@ -18,7 +18,6 @@ namespace WalletWasabi.Fluent.ViewModels.NavBar
private const double NormalOpenPaneLength = 280;
private NavBarItemViewModel? _selectedItem;
- private readonly WalletManagerViewModel _walletManager;
private bool _isNavigating;
[AutoNotify] private ObservableCollection<NavBarItemViewModel> _topItems;
[AutoNotify] private ObservableCollection<NavBarItemViewModel> _bottomItems;
@@ -30,16 +29,15 @@ namespace WalletWasabi.Fluent.ViewModels.NavBar
[AutoNotify] private double _currentCompactPaneLength;
[AutoNotify] private bool _isHidden;
- public NavBarViewModel(TargettedNavigationStack mainScreen, WalletManagerViewModel walletManager)
+ public NavBarViewModel(TargettedNavigationStack mainScreen)
{
- _walletManager = walletManager;
_topItems = new ObservableCollection<NavBarItemViewModel>();
_bottomItems = new ObservableCollection<NavBarItemViewModel>();
mainScreen.WhenAnyValue(x => x.CurrentPage)
.OfType<NavBarItemViewModel>()
.DistinctUntilChanged()
- .Subscribe(x => CurrentPageChanged(x, walletManager));
+ .Subscribe(x => CurrentPageChanged(x));
this.WhenAnyValue(x => x.SelectedItem)
.Subscribe(selectedItem =>
@@ -60,7 +58,7 @@ namespace WalletWasabi.Fluent.ViewModels.NavBar
{
if (x > 0 && SelectedItem is null)
{
- if (!_walletManager.IsLoadingWallet)
+ if (!UiServices.WalletManager.IsLoadingWallet)
{
var lastSelectedItem = Items.FirstOrDefault(x => x is WalletViewModelBase wallet && wallet.WalletName == Services.UiConfig.LastSelectedWallet);
@@ -86,7 +84,7 @@ namespace WalletWasabi.Fluent.ViewModels.NavBar
CurrentOpenPaneLength = x ? 0 : NormalOpenPaneLength;
});
- _walletManager.WhenAnyValue(x => x.SelectedWallet)
+ UiServices.WalletManager.WhenAnyValue(x => x.SelectedWallet)
.OfType<NavBarItemViewModel>()
.Subscribe(x =>
{
@@ -97,9 +95,9 @@ namespace WalletWasabi.Fluent.ViewModels.NavBar
});
}
- public ReadOnlyObservableCollection<NavBarItemViewModel> Items => _walletManager.Items;
+ public ReadOnlyObservableCollection<NavBarItemViewModel> Items => UiServices.WalletManager.Items;
- public ObservableCollection<WalletViewModelBase> Wallets => _walletManager.Wallets;
+ public ObservableCollection<WalletViewModelBase> Wallets => UiServices.WalletManager.Wallets;
public NavBarItemViewModel? SelectedItem
{
@@ -206,8 +204,10 @@ namespace WalletWasabi.Fluent.ViewModels.NavBar
}
}
- private void CurrentPageChanged(NavBarItemViewModel x, WalletManagerViewModel walletManager)
+ private void CurrentPageChanged(NavBarItemViewModel x)
{
+ var walletManager = UiServices.WalletManager;
+
if (walletManager.Items.Contains(x) || _topItems.Contains(x) || _bottomItems.Contains(x))
{
if (!_isNavigating)
@@ -236,7 +236,7 @@ namespace WalletWasabi.Fluent.ViewModels.NavBar
{
_isNavigating = true;
- var result = _walletManager.SelectionChanged(x);
+ var result = UiServices.WalletManager.SelectionChanged(x);
if (result is not null)
{
SelectedItem = result;

ADD
WalletWasabi.Fluent/ViewModels/UiServices.cs
+using WalletWasabi.Helpers;
+
+namespace WalletWasabi.Fluent.ViewModels
+{
+ public static class UiServices
+ {
+ public static WalletManagerViewModel WalletManager { get; private set; } = null!;
+
+ public static void Initialize()
+ {
+ WalletManager = new WalletManagerViewModel();
+ }
+ }
+}
\ No newline at end of file

MODIFY
WalletWasabi.Fluent/ViewModels/WalletManagerViewModel.cs
WalletWasabi.Fluent/ViewModels/WalletManagerViewModel.cs
@@ -110,6 +110,23 @@ namespace WalletWasabi.Fluent.ViewModels
public ReadOnlyObservableCollection<NavBarItemViewModel> Items => _items;
+ public WalletViewModel GetWalletViewModel(Wallet wallet)
+ {
+ WalletViewModel? result = null;
+
+ if (_walletDictionary.ContainsKey(wallet))
+ {
+ result = _walletDictionary[wallet] as WalletViewModel;
+ }
+
+ if (result is { })
+ {
+ return result;
+ }
+
+ throw new Exception("Wallet not found, invalid api usage");
+ }
+
public async Task LoadWalletAsync(ClosedWalletViewModel closedWalletViewModel)
{
var wallet = closedWalletViewModel.Wallet;

MODIFY
WalletWasabi.Fluent/ViewModels/Wallets/Receive/AddressViewModel.cs
WalletWasabi.Fluent/ViewModels/Wallets/Receive/AddressViewModel.cs
@@ -5,6 +5,7 @@ using NBitcoin;
using ReactiveUI;
using WalletWasabi.Blockchain.Analysis.Clustering;
using WalletWasabi.Blockchain.Keys;
+using WalletWasabi.Wallets;
namespace WalletWasabi.Fluent.ViewModels.Wallets.Receive
{
@@ -13,7 +14,7 @@ namespace WalletWasabi.Fluent.ViewModels.Wallets.Receive
[AutoNotify] private SmartLabel _label;
[AutoNotify] private string _address;
- public AddressViewModel(ReceiveAddressesViewModel parent, HdPubKey model, Network network)
+ public AddressViewModel(ReceiveAddressesViewModel parent, Wallet wallet, HdPubKey model, Network network)
{
_address = model.GetP2wpkhAddress(network).ToString();
_label = model.Label;
@@ -27,12 +28,7 @@ namespace WalletWasabi.Fluent.ViewModels.Wallets.Receive
NavigateCommand = ReactiveCommand.Create(() =>
{
- parent.Navigate().To(
- new ReceiveAddressViewModel(
- model,
- network,
- parent.Wallet.KeyManager.MasterFingerprint,
- parent.Wallet.KeyManager.IsHardwareWallet));
+ parent.Navigate().To(new ReceiveAddressViewModel(wallet, model));
});
}

MODIFY
WalletWasabi.Fluent/ViewModels/Wallets/Receive/ReceiveAddressViewModel.cs
WalletWasabi.Fluent/ViewModels/Wallets/Receive/ReceiveAddressViewModel.cs
@@ -13,17 +13,18 @@ using WalletWasabi.Blockchain.Keys;
using WalletWasabi.Fluent.ViewModels.Navigation;
using WalletWasabi.Hwi;
using WalletWasabi.Logging;
+using WalletWasabi.Wallets;
namespace WalletWasabi.Fluent.ViewModels.Wallets.Receive
{
[NavigationMetaData(Title = "Receive Address")]
public partial class ReceiveAddressViewModel : RoutableViewModel
{
- public ReceiveAddressViewModel(HdPubKey model, Network network, HDFingerprint? masterFingerprint, bool isHardwareWallet)
+ public ReceiveAddressViewModel(Wallet wallet, HdPubKey model)
{
- Address = model.GetP2wpkhAddress(network).ToString();
+ Address = model.GetP2wpkhAddress(wallet.Network).ToString();
Labels = model.Label;
- IsHardwareWallet = isHardwareWallet;
+ IsHardwareWallet = wallet.KeyManager.IsHardwareWallet;
IsAutoCopyEnabled = Services.UiConfig.Autocopy;
GenerateQrCode();
@@ -34,7 +35,7 @@ namespace WalletWasabi.Fluent.ViewModels.Wallets.Receive
CopyAddressCommand = ReactiveCommand.CreateFromTask(async () => await Application.Current.Clipboard.SetTextAsync(Address));
- ShowOnHwWalletCommand = ReactiveCommand.CreateFromTask(async () => await OnShowOnHwWalletAsync(model, network, masterFingerprint));
+ ShowOnHwWalletCommand = ReactiveCommand.CreateFromTask(async () => await OnShowOnHwWalletAsync(model, wallet.Network, wallet.KeyManager.MasterFingerprint));
SaveQrCodeCommand = ReactiveCommand.CreateFromTask(async () => await OnSaveQrCodeAsync());

MODIFY
WalletWasabi.Fluent/ViewModels/Wallets/Receive/ReceiveAddressesViewModel.cs
WalletWasabi.Fluent/ViewModels/Wallets/Receive/ReceiveAddressesViewModel.cs
@@ -63,7 +63,7 @@ namespace WalletWasabi.Fluent.ViewModels.Wallets.Receive
foreach (HdPubKey key in keys)
{
- Addresses.Add(new AddressViewModel(this, key, Network));
+ Addresses.Add(new AddressViewModel(this, Wallet, key, Network));
}
}
catch (Exception ex)

MODIFY
WalletWasabi.Fluent/ViewModels/Wallets/Receive/ReceiveViewModel.cs
WalletWasabi.Fluent/ViewModels/Wallets/Receive/ReceiveViewModel.cs
@@ -23,13 +23,14 @@ namespace WalletWasabi.Fluent.ViewModels.Wallets.Receive
NavigationTarget = NavigationTarget.DialogScreen)]
public partial class ReceiveViewModel : NavBarItemViewModel
{
+ private readonly Wallet _wallet;
[AutoNotify] private ObservableCollection<string> _labels;
[AutoNotify] private HashSet<string> _suggestions;
[AutoNotify] private bool _isExistingAddressesButtonVisible;
- public ReceiveViewModel(WalletViewModelBase wallet) : base(NavigationMode.Normal)
+ public ReceiveViewModel(Wallet wallet) : base(NavigationMode.Normal)
{
- WasabiWallet = wallet.Wallet;
+ _wallet = wallet;
_labels = new ObservableCollection<string>();
_suggestions = GetLabels();
@@ -47,11 +48,11 @@ namespace WalletWasabi.Fluent.ViewModels.Wallets.Receive
private void OnNext()
{
- var newKey = WasabiWallet.KeyManager.GetNextReceiveKey(new SmartLabel(Labels), out bool minGapLimitIncreased);
+ var newKey = _wallet.KeyManager.GetNextReceiveKey(new SmartLabel(Labels), out bool minGapLimitIncreased);
if (minGapLimitIncreased)
{
- int minGapLimit = WasabiWallet.KeyManager.MinGapLimit.Value;
+ int minGapLimit = _wallet.KeyManager.MinGapLimit.Value;
int prevMinGapLimit = minGapLimit - 1;
var minGapLimitMessage = $"Minimum gap limit increased from {prevMinGapLimit} to {minGapLimit}.";
// TODO: notification
@@ -59,24 +60,21 @@ namespace WalletWasabi.Fluent.ViewModels.Wallets.Receive
Labels.Clear();
- Navigate().To(new ReceiveAddressViewModel(newKey, WasabiWallet.Network, WasabiWallet.KeyManager.MasterFingerprint,
- WasabiWallet.KeyManager.IsHardwareWallet));
+ Navigate().To(new ReceiveAddressViewModel(_wallet, newKey));
}
private void OnShowExistingAddresses()
{
- Navigate().To(new ReceiveAddressesViewModel(WasabiWallet, Suggestions));
+ Navigate().To(new ReceiveAddressesViewModel(_wallet, Suggestions));
}
- public Wallet WasabiWallet { get; }
-
public ICommand ShowExistingAddressesCommand { get; }
protected override void OnNavigatedTo(bool isInHistory, CompositeDisposable disposable)
{
base.OnNavigatedTo(isInHistory, disposable);
- IsExistingAddressesButtonVisible = WasabiWallet.KeyManager.GetKeys(x => !x.Label.IsEmpty && !x.IsInternal && x.KeyState == KeyState.Clean).Any();
+ IsExistingAddressesButtonVisible = _wallet.KeyManager.GetKeys(x => !x.Label.IsEmpty && !x.IsInternal && x.KeyState == KeyState.Clean).Any();
}
private HashSet<string> GetLabels()

MODIFY
WalletWasabi.Fluent/ViewModels/Wallets/Send/OptimisePrivacyViewModel.cs
WalletWasabi.Fluent/ViewModels/Wallets/Send/OptimisePrivacyViewModel.cs
@@ -8,7 +8,6 @@ using System.Reactive.Disposables;
using System.Reactive.Linq;
using System.Threading.Tasks;
using ReactiveUI;
-using WalletWasabi.Blockchain.TransactionBroadcasting;
using WalletWasabi.Blockchain.TransactionBuilding;
using WalletWasabi.Fluent.Helpers;
using WalletWasabi.Fluent.ViewModels.Navigation;
@@ -28,10 +27,10 @@ namespace WalletWasabi.Fluent.ViewModels.Wallets.Send
[AutoNotify] private bool _exactAmountWarningVisible;
private PrivacySuggestionControlViewModel? _defaultSelection;
- public OptimisePrivacyViewModel(WalletViewModel owner,
+ public OptimisePrivacyViewModel(Wallet wallet,
TransactionInfo transactionInfo, BuildTransactionResult requestedTransaction)
{
- _wallet = owner.Wallet;
+ _wallet = wallet;
_requestedTransaction = requestedTransaction;
_transactionInfo = transactionInfo;
@@ -45,13 +44,13 @@ namespace WalletWasabi.Fluent.ViewModels.Wallets.Send
EnableBack = true;
NextCommand = ReactiveCommand.Create(
- () => OnNext(owner, transactionInfo),
+ () => OnNext(transactionInfo),
this.WhenAnyValue(x => x.SelectedPrivacySuggestion).Select(x => x is { }));
}
- private void OnNext(WalletViewModel owner, TransactionInfo transactionInfo)
+ private void OnNext(TransactionInfo transactionInfo)
{
- Navigate().To(new TransactionPreviewViewModel(owner, transactionInfo,
+ Navigate().To(new TransactionPreviewViewModel(_wallet, transactionInfo,
SelectedPrivacySuggestion!.TransactionResult));
}

MODIFY
WalletWasabi.Fluent/ViewModels/Wallets/Send/PrivacyControlViewModel.cs
WalletWasabi.Fluent/ViewModels/Wallets/Send/PrivacyControlViewModel.cs
@@ -2,14 +2,11 @@ using System;
using System.Collections.ObjectModel;
using System.Linq;
using System.Reactive.Disposables;
-using System.Reactive.Linq;
using System.Threading.Tasks;
using DynamicData;
using DynamicData.Aggregation;
using NBitcoin;
using ReactiveUI;
-using WalletWasabi.Blockchain.Analysis.Clustering;
-using WalletWasabi.Blockchain.TransactionBroadcasting;
using WalletWasabi.Exceptions;
using WalletWasabi.Fluent.Helpers;
using WalletWasabi.Fluent.Model;
@@ -23,20 +20,17 @@ namespace WalletWasabi.Fluent.ViewModels.Wallets.Send
[NavigationMetaData(Title = "Privacy Control")]
public partial class PrivacyControlViewModel : RoutableViewModel
{
- private readonly WalletViewModel _owner;
private readonly Wallet _wallet;
private readonly SourceList<PocketViewModel> _pocketSource;
private readonly ReadOnlyObservableCollection<PocketViewModel> _pockets;
private PocketViewModel? _privatePocket;
- private readonly IObservableList<PocketViewModel> _selectedList;
[AutoNotify] private decimal _stillNeeded;
[AutoNotify] private bool _enoughSelected;
- public PrivacyControlViewModel(WalletViewModel owner, TransactionInfo transactionInfo)
+ public PrivacyControlViewModel(Wallet wallet, TransactionInfo transactionInfo)
{
- _owner = owner;
- _wallet = owner.Wallet;
+ _wallet = wallet;
_pocketSource = new SourceList<PocketViewModel>();
@@ -48,14 +42,14 @@ namespace WalletWasabi.Fluent.ViewModels.Wallets.Send
.AutoRefresh()
.Filter(x => x.IsSelected);
- _selectedList = selected.AsObservableList();
+ var selectedList = selected.AsObservableList();
selected.Sum(x => x.TotalBtc)
.Subscribe(x =>
{
if (_privatePocket is { })
{
- _privatePocket.IsWarningOpen = _privatePocket.IsSelected && _selectedList.Count > 1;
+ _privatePocket.IsWarningOpen = _privatePocket.IsSelected && selectedList.Count > 1;
}
StillNeeded = transactionInfo.Amount.ToDecimal(MoneyUnit.BTC) - x;
@@ -68,7 +62,7 @@ namespace WalletWasabi.Fluent.ViewModels.Wallets.Send
EnableBack = true;
NextCommand = ReactiveCommand.CreateFromTask(
- async () => await OnNextAsync(_owner, transactionInfo, _selectedList),
+ async () => await OnNextAsync(transactionInfo, selectedList),
this.WhenAnyValue(x => x.EnoughSelected));
EnableAutoBusyOn(NextCommand);
@@ -76,7 +70,7 @@ namespace WalletWasabi.Fluent.ViewModels.Wallets.Send
public ReadOnlyObservableCollection<PocketViewModel> Pockets => _pockets;
- private async Task OnNextAsync(WalletViewModel owner, TransactionInfo transactionInfo,
+ private async Task OnNextAsync(TransactionInfo transactionInfo,
IObservableList<PocketViewModel> selectedList)
{
transactionInfo.Coins = selectedList.Items.SelectMany(x => x.Coins).ToArray();
@@ -90,11 +84,11 @@ namespace WalletWasabi.Fluent.ViewModels.Wallets.Send
{
if (transactionInfo.PayJoinClient is { })
{
- await BuildTransactionAsPayJoinAsync(owner, transactionInfo);
+ await BuildTransactionAsPayJoinAsync(transactionInfo);
}
else
{
- await BuildTransactionAsNormalAsync(owner, transactionInfo);
+ await BuildTransactionAsNormalAsync(transactionInfo);
}
}
catch (Exception ex)
@@ -105,22 +99,22 @@ namespace WalletWasabi.Fluent.ViewModels.Wallets.Send
}
}
- private async Task BuildTransactionAsNormalAsync(WalletViewModel owner, TransactionInfo transactionInfo)
+ private async Task BuildTransactionAsNormalAsync(TransactionInfo transactionInfo)
{
try
{
var transactionResult = await Task.Run(() => TransactionHelpers.BuildTransaction(_wallet, transactionInfo));
- Navigate().To(new OptimisePrivacyViewModel(owner, transactionInfo, transactionResult));
+ Navigate().To(new OptimisePrivacyViewModel(_wallet, transactionInfo, transactionResult));
}
catch (InsufficientBalanceException)
{
var transactionResult = await Task.Run(() => TransactionHelpers.BuildTransaction(_wallet, transactionInfo, subtractFee: true));
- var dialog = new InsufficientBalanceDialogViewModel(BalanceType.Pocket, transactionResult, owner.Wallet.Synchronizer.UsdExchangeRate);
+ var dialog = new InsufficientBalanceDialogViewModel(BalanceType.Pocket, transactionResult, _wallet.Synchronizer.UsdExchangeRate);
var result = await NavigateDialogAsync(dialog, NavigationTarget.DialogScreen);
if (result.Result)
{
- Navigate().To(new OptimisePrivacyViewModel(owner, transactionInfo, transactionResult));
+ Navigate().To(new OptimisePrivacyViewModel(_wallet, transactionInfo, transactionResult));
}
else
{
@@ -129,13 +123,13 @@ namespace WalletWasabi.Fluent.ViewModels.Wallets.Send
}
}
- private async Task BuildTransactionAsPayJoinAsync(WalletViewModel owner, TransactionInfo transactionInfo)
+ private async Task BuildTransactionAsPayJoinAsync(TransactionInfo transactionInfo)
{
try
{
// Do not add the PayJoin client yet, it will be added before broadcasting.
var transactionResult = await Task.Run(() => TransactionHelpers.BuildTransaction(_wallet, transactionInfo));
- Navigate().To(new TransactionPreviewViewModel(owner, transactionInfo, transactionResult));
+ Navigate().To(new TransactionPreviewViewModel(_wallet, transactionInfo, transactionResult));
}
catch (InsufficientBalanceException)
{

MODIFY
WalletWasabi.Fluent/ViewModels/Wallets/Send/SendSuccessViewModel.cs
WalletWasabi.Fluent/ViewModels/Wallets/Send/SendSuccessViewModel.cs
using ReactiveUI;
using WalletWasabi.Blockchain.Transactions;
using WalletWasabi.Fluent.ViewModels.Navigation;
+using WalletWasabi.Wallets;
namespace WalletWasabi.Fluent.ViewModels.Wallets.Send
{
[NavigationMetaData(Title = "Payment successful")]
public partial class SendSuccessViewModel : RoutableViewModel
{
- private readonly WalletViewModel _owner;
+ private readonly Wallet _wallet;
private readonly SmartTransaction _finalTransaction;
- public SendSuccessViewModel(WalletViewModel owner, SmartTransaction finalTransaction)
+ public SendSuccessViewModel(Wallet wallet, SmartTransaction finalTransaction)
{
- _owner = owner;
+ _wallet = wallet;
_finalTransaction = finalTransaction;
NextCommand = ReactiveCommand.Create(OnNext);
@@ -24,7 +25,9 @@ namespace WalletWasabi.Fluent.ViewModels.Wallets.Send
{
Navigate().Clear();
- _owner.History.SelectTransaction(_finalTransaction.GetHash());
+ var walletViewModel = UiServices.WalletManager.GetWalletViewModel(_wallet);
+
+ walletViewModel.History.SelectTransaction(_finalTransaction.GetHash());
}
}
}

MODIFY
WalletWasabi.Fluent/ViewModels/Wallets/Send/SendViewModel.cs
WalletWasabi.Fluent/ViewModels/Wallets/Send/SendViewModel.cs
@@ -44,7 +44,7 @@ namespace WalletWasabi.Fluent.ViewModels.Wallets.Send
NavigationTarget = NavigationTarget.DialogScreen)]
public partial class SendViewModel : NavBarItemViewModel
{
- private readonly WalletViewModel _owner;
+ private readonly Wallet _wallet;
private readonly TransactionInfo _transactionInfo;
[AutoNotify] private string _to;
@@ -68,17 +68,17 @@ namespace WalletWasabi.Fluent.ViewModels.Wallets.Send
private double _lastXAxisCurrentValue;
private FeeRate _feeRate;
- public SendViewModel(WalletViewModel walletVm) : base(NavigationMode.Normal)
+ public SendViewModel(Wallet wallet) : base(NavigationMode.Normal)
{
_to = "";
- _owner = walletVm;
+ _wallet = wallet;
_transactionInfo = new TransactionInfo();
_labels = new ObservableCollection<string>();
_lastXAxisCurrentValue = _xAxisCurrentValue;
SelectionMode = NavBarItemSelectionMode.Button;
- ExchangeRate = walletVm.Wallet.Synchronizer.UsdExchangeRate;
+ ExchangeRate = _wallet.Synchronizer.UsdExchangeRate;
PriorLabels = new();
this.ValidateProperty(x => x.To, ValidateToField);
@@ -172,16 +172,15 @@ namespace WalletWasabi.Fluent.ViewModels.Wallets.Send
private async Task OnNextAsync()
{
var transactionInfo = _transactionInfo;
- var wallet = _owner.Wallet;
- var targetAnonymitySet = wallet.ServiceConfiguration.GetMixUntilAnonymitySetValue();
- var mixedCoins = wallet.Coins.Where(x => x.HdPubKey.AnonymitySet >= targetAnonymitySet).ToList();
+ var targetAnonymitySet = _wallet.ServiceConfiguration.GetMixUntilAnonymitySetValue();
+ var mixedCoins = _wallet.Coins.Where(x => x.HdPubKey.AnonymitySet >= targetAnonymitySet).ToList();
var totalMixedCoinsAmount = Money.FromUnit(mixedCoins.Sum(coin => coin.Amount), MoneyUnit.Satoshi);
transactionInfo.Coins = mixedCoins;
transactionInfo.FeeRate = _feeRate;
if (transactionInfo.Amount > totalMixedCoinsAmount)
{
- Navigate().To(new PrivacyControlViewModel(_owner, transactionInfo));
+ Navigate().To(new PrivacyControlViewModel(_wallet, transactionInfo));
return;
}
@@ -189,11 +188,11 @@ namespace WalletWasabi.Fluent.ViewModels.Wallets.Send
{
if (IsPayJoin)
{
- await BuildTransactionAsPayJoinAsync(wallet, transactionInfo);
+ await BuildTransactionAsPayJoinAsync(transactionInfo);
}
else
{
- await BuildTransactionAsNormalAsync(wallet, transactionInfo, totalMixedCoinsAmount);
+ await BuildTransactionAsNormalAsync(transactionInfo, totalMixedCoinsAmount);
}
}
catch (Exception ex)
@@ -203,42 +202,42 @@ namespace WalletWasabi.Fluent.ViewModels.Wallets.Send
}
}
- private async Task BuildTransactionAsNormalAsync(Wallet wallet, TransactionInfo transactionInfo, Money totalMixedCoinsAmount)
+ private async Task BuildTransactionAsNormalAsync(TransactionInfo transactionInfo, Money totalMixedCoinsAmount)
{
try
{
- var txRes = await Task.Run(() => TransactionHelpers.BuildTransaction(wallet, transactionInfo));
- Navigate().To(new OptimisePrivacyViewModel(_owner, transactionInfo, txRes));
+ var txRes = await Task.Run(() => TransactionHelpers.BuildTransaction(_wallet, transactionInfo));
+ Navigate().To(new OptimisePrivacyViewModel(_wallet, transactionInfo, txRes));
}
catch (InsufficientBalanceException)
{
- var txRes = await Task.Run(() => TransactionHelpers.BuildTransaction(wallet, transactionInfo.Address, totalMixedCoinsAmount, transactionInfo.Labels, transactionInfo.FeeRate, transactionInfo.Coins, subtractFee: true));
- var dialog = new InsufficientBalanceDialogViewModel(BalanceType.Private, txRes, wallet.Synchronizer.UsdExchangeRate);
+ var txRes = await Task.Run(() => TransactionHelpers.BuildTransaction(_wallet, transactionInfo.Address, totalMixedCoinsAmount, transactionInfo.Labels, transactionInfo.FeeRate, transactionInfo.Coins, subtractFee: true));
+ var dialog = new InsufficientBalanceDialogViewModel(BalanceType.Private, txRes, _wallet.Synchronizer.UsdExchangeRate);
var result = await NavigateDialogAsync(dialog, NavigationTarget.DialogScreen);
if (result.Result)
{
- Navigate().To(new OptimisePrivacyViewModel(_owner, transactionInfo, txRes));
+ Navigate().To(new OptimisePrivacyViewModel(_wallet, transactionInfo, txRes));
}
else
{
- Navigate().To(new PrivacyControlViewModel(_owner, transactionInfo));
+ Navigate().To(new PrivacyControlViewModel(_wallet, transactionInfo));
}
}
}
- private async Task BuildTransactionAsPayJoinAsync(Wallet wallet, TransactionInfo transactionInfo)
+ private async Task BuildTransactionAsPayJoinAsync(TransactionInfo transactionInfo)
{
try
{
// Do not add the PayJoin client yet, it will be added before broadcasting.
- var txRes = await Task.Run(() => TransactionHelpers.BuildTransaction(wallet, transactionInfo));
- Navigate().To(new TransactionPreviewViewModel(_owner, transactionInfo, txRes));
+ var txRes = await Task.Run(() => TransactionHelpers.BuildTransaction(_wallet, transactionInfo));
+ Navigate().To(new TransactionPreviewViewModel(_wallet, transactionInfo, txRes));
}
catch (InsufficientBalanceException)
{
await ShowErrorAsync("Transaction Building", "There are not enough private funds to cover the transaction fee", "Wasabi was unable to create your transaction.");
- Navigate().To(new PrivacyControlViewModel(_owner, transactionInfo));
+ Navigate().To(new PrivacyControlViewModel(_wallet, transactionInfo));
}
}
@@ -310,7 +309,7 @@ namespace WalletWasabi.Fluent.ViewModels.Wallets.Send
{
errors.Add(ErrorSeverity.Error, "Amount must be less than the total supply of BTC.");
}
- else if (AmountBtc > _owner.Wallet.Coins.TotalAmount().ToDecimal(MoneyUnit.BTC))
+ else if (AmountBtc > _wallet.Coins.TotalAmount().ToDecimal(MoneyUnit.BTC))
{
errors.Add(ErrorSeverity.Error, "Insufficient funds to cover the amount requested.");
}
@@ -323,11 +322,11 @@ namespace WalletWasabi.Fluent.ViewModels.Wallets.Send
private void ValidateToField(IValidationErrors errors)
{
if (!string.IsNullOrWhiteSpace(To) &&
- !AddressStringParser.TryParse(To, _owner.Wallet.Network, out _))
+ !AddressStringParser.TryParse(To, _wallet.Network, out _))
{
errors.Add(ErrorSeverity.Error, "Input a valid BTC address or URL.");
}
- else if (IsPayJoin && _owner.Wallet.KeyManager.IsHardwareWallet)
+ else if (IsPayJoin && _wallet.KeyManager.IsHardwareWallet)
{
errors.Add(ErrorSeverity.Error, "PayJoin is not possible with hardware wallets.");
}
@@ -354,9 +353,7 @@ namespace WalletWasabi.Fluent.ViewModels.Wallets.Send
{
bool result = false;
- var wallet = _owner.Wallet;
-
- if (AddressStringParser.TryParse(text, wallet.Network, out BitcoinUrlBuilder? url))
+ if (AddressStringParser.TryParse(text, _wallet.Network, out BitcoinUrlBuilder? url))
{
result = true;
SmartLabel label = url.Label;
@@ -426,12 +423,12 @@ namespace WalletWasabi.Fluent.ViewModels.Wallets.Send
XAxisCurrentValue = _lastXAxisCurrentValue;
}
- _owner.Wallet.Synchronizer.WhenAnyValue(x => x.UsdExchangeRate)
+ _wallet.Synchronizer.WhenAnyValue(x => x.UsdExchangeRate)
.ObserveOn(RxApp.MainThreadScheduler)
.Subscribe(x => ExchangeRate = x)
.DisposeWith(disposables);
- _owner.Wallet.TransactionProcessor.WhenAnyValue(x => x.Coins)
+ _wallet.TransactionProcessor.WhenAnyValue(x => x.Coins)
.ObserveOn(RxApp.MainThreadScheduler)
.Subscribe(x =>
{
@@ -441,7 +438,7 @@ namespace WalletWasabi.Fluent.ViewModels.Wallets.Send
})
.DisposeWith(disposables);
- PriorLabels.AddRange(_owner.Wallet
+ PriorLabels.AddRange(_wallet
.KeyManager
.GetLabels()
.Select(x => x.ToString()
@@ -450,7 +447,7 @@ namespace WalletWasabi.Fluent.ViewModels.Wallets.Send
PriorLabels = new ObservableCollection<string>(PriorLabels.Distinct());
- var feeProvider = _owner.Wallet.FeeProvider;
+ var feeProvider = _wallet.FeeProvider;
Observable
.FromEventPattern(feeProvider, nameof(feeProvider.AllFeeEstimateChanged))
.Select(x => (x.EventArgs as AllFeeEstimate)!.Estimations)
@@ -514,7 +511,7 @@ namespace WalletWasabi.Fluent.ViewModels.Wallets.Send
double[] xAxisValues;
double[] yAxisValues;
- if (_owner.Wallet.Network != Network.TestNet)
+ if (_wallet.Network != Network.TestNet)
{
var labels = feeEstimates.Select(x => x.Key)
.Select(x => FeeTargetTimeConverter.Convert(x, "m", "h", "h", "d", "d"))

MODIFY
WalletWasabi.Fluent/ViewModels/Wallets/Send/TransactionPreviewViewModel.cs
WalletWasabi.Fluent/ViewModels/Wallets/Send/TransactionPreviewViewModel.cs
using System;
-using System.Linq;
using System.Reactive.Disposables;
using System.Threading.Tasks;
using NBitcoin;
using ReactiveUI;
using WalletWasabi.Blockchain.Analysis.Clustering;
-using WalletWasabi.Blockchain.TransactionBroadcasting;
using WalletWasabi.Blockchain.TransactionBuilding;
using WalletWasabi.Blockchain.Transactions;
using WalletWasabi.CoinJoin.Client.Clients.Queuing;
@@ -21,17 +19,16 @@ namespace WalletWasabi.Fluent.ViewModels.Wallets.Send
[NavigationMetaData(Title = "Transaction Preview")]
public partial class TransactionPreviewViewModel : RoutableViewModel
{
- private readonly WalletViewModel _owner;
private readonly Wallet _wallet;
private readonly TransactionInfo _info;
[AutoNotify] private string _confirmationTimeText;
[AutoNotify] private SmartLabel _labels;
- public TransactionPreviewViewModel(WalletViewModel owner, TransactionInfo info, BuildTransactionResult transaction)
+ public TransactionPreviewViewModel(Wallet wallet, TransactionInfo info, BuildTransactionResult transaction)
{
- _owner = owner;
- _wallet = owner.Wallet;
+ _wallet = wallet;
+ _labels = SmartLabel.Empty;
_info = info;
SetupCancel(enableCancel: true, enableCancelOnEscape: true, enableCancelOnPressed: false);
EnableBack = true;
@@ -52,7 +49,7 @@ namespace WalletWasabi.Fluent.ViewModels.Wallets.Send
PayJoinUrl = info.PayJoinClient?.PaymentUrl.AbsoluteUri;
IsPayJoin = PayJoinUrl is not null;
- NextCommand = ReactiveCommand.CreateFromTask(async () => await OnNextAsync(_wallet, transaction));
+ NextCommand = ReactiveCommand.CreateFromTask(async () => await OnNextAsync(transaction));
}
public string AmountText { get; }
@@ -73,11 +70,11 @@ namespace WalletWasabi.Fluent.ViewModels.Wallets.Send
Labels = _info.Labels;
}
- private async Task OnNextAsync(Wallet wallet, BuildTransactionResult transaction)
+ private async Task OnNextAsync(BuildTransactionResult transaction)
{
var transactionAuthorizationInfo = new TransactionAuthorizationInfo(transaction);
- var authResult = await AuthorizeAsync(wallet, transactionAuthorizationInfo);
+ var authResult = await AuthorizeAsync(transactionAuthorizationInfo);
if (authResult)
{
@@ -86,8 +83,8 @@ namespace WalletWasabi.Fluent.ViewModels.Wallets.Send
try
{
var finalTransaction = await GetFinalTransactionAsync(transactionAuthorizationInfo.Transaction, _info);
- await SendTransactionAsync(wallet, finalTransaction);
- Navigate().To(new SendSuccessViewModel(_owner, finalTransaction));
+ await SendTransactionAsync(finalTransaction);
+ Navigate().To(new SendSuccessViewModel(_wallet, finalTransaction));
}
catch (Exception ex)
{
@@ -98,14 +95,14 @@ namespace WalletWasabi.Fluent.ViewModels.Wallets.Send
}
}
- private async Task<bool> AuthorizeAsync(Wallet wallet, TransactionAuthorizationInfo transactionAuthorizationInfo)
+ private async Task<bool> AuthorizeAsync(TransactionAuthorizationInfo transactionAuthorizationInfo)
{
- if (!wallet.KeyManager.IsHardwareWallet && string.IsNullOrEmpty(wallet.Kitchen.SaltSoup())) // Do not show auth dialog when password is empty
+ if (!_wallet.KeyManager.IsHardwareWallet && string.IsNullOrEmpty(_wallet.Kitchen.SaltSoup())) // Do not show auth dialog when password is empty
{
return true;
}
- var authDialog = AuthorizationHelpers.GetAuthorizationDialog(wallet, transactionAuthorizationInfo);
+ var authDialog = AuthorizationHelpers.GetAuthorizationDialog(_wallet, transactionAuthorizationInfo);
var authDialogResult = await NavigateDialogAsync(authDialog, authDialog.DefaultTarget);
if (!authDialogResult.Result && authDialogResult.Kind == DialogResultKind.Normal)
@@ -116,10 +113,10 @@ namespace WalletWasabi.Fluent.ViewModels.Wallets.Send
return authDialogResult.Result;
}
- private async Task SendTransactionAsync(Wallet wallet, SmartTransaction transaction)
+ private async Task SendTransactionAsync( SmartTransaction transaction)
{
// Dequeue any coin-joining coins.
- await wallet.ChaumianClient.DequeueAllCoinsFromMixAsync(DequeueReason.TransactionBuilding);
+ await _wallet.ChaumianClient.DequeueAllCoinsFromMixAsync(DequeueReason.TransactionBuilding);
await Services.TransactionBroadcaster.SendTransactionAsync(transaction);
}

MODIFY
WalletWasabi.Fluent/ViewModels/Wallets/WalletViewModel.cs
WalletWasabi.Fluent/ViewModels/Wallets/WalletViewModel.cs
@@ -79,13 +79,13 @@ namespace WalletWasabi.Fluent.ViewModels.Wallets
SendCommand = ReactiveCommand.Create(() =>
{
Navigate(NavigationTarget.DialogScreen)
- .To(new SendViewModel(this));
+ .To(new SendViewModel(wallet));
});
ReceiveCommand = ReactiveCommand.Create(() =>
{
Navigate(NavigationTarget.DialogScreen)
- .To(new ReceiveViewModel(this));
+ .To(new ReceiveViewModel(wallet));
});
}

uiservices class, so less passing stuff around,