partial implementation of coinjoin.
MODIFY
WalletWasabi.Dependencies/AvalonStudio.Shell
WalletWasabi.Dependencies/AvalonStudio.Shell
-Subproject commit a7b3ac6176918de412b5692d4ee7a110bd8584b2
+Subproject commit f04a84415d3eb7a4557af832aab59b7ac834346b

MODIFY
WalletWasabi.Gui/Controls/WalletExplorer/CoinJoinTabView.xaml
WalletWasabi.Gui/Controls/WalletExplorer/CoinJoinTabView.xaml
<controls:GroupBox Title="Coins" TextBlock.FontSize="30" Padding="20" Margin="10">
<Grid Classes="content">
<DockPanel LastChildFill="True">
- <Button DockPanel.Dock="Bottom" Content="Enqueue" Command="{Binding EnqueueCommand}" />
+ <StackPanel Orientation="Horizontal" DockPanel.Dock="Bottom" Gap="4">
+ <Button Content="Enqueue" Command="{Binding EnqueueCommand}" />
+ <TextBox PasswordChar="*" Text="{Binding Password}" Watermark="Password" UseFloatingWatermark="True" />
+ </StackPanel>
<local:CoinListView DataContext="{Binding AvailableCoinsList}" />
</DockPanel>
</Grid>

MODIFY
WalletWasabi.Gui/Controls/WalletExplorer/CoinJoinTabViewModel.cs
WalletWasabi.Gui/Controls/WalletExplorer/CoinJoinTabViewModel.cs
@@ -12,51 +12,71 @@ namespace WalletWasabi.Gui.Controls.WalletExplorer
{
private CoinListViewModel _availableCoinsList;
private CoinListViewModel _queuedCoinsList;
- private ObservableCollection<CoinViewModel> _availableCoins;
- private ObservableCollection<CoinViewModel> _queuedCoins;
+ private IReadOnlyCollection<CoinViewModel> _availableCoins;
+ private IReadOnlyCollection<CoinViewModel> _queuedCoins;
+ private string _password;
public CoinJoinTabViewModel(WalletViewModel walletViewModel)
: base("CoinJoin", walletViewModel)
{
- AvailableCoins = new ObservableCollection<CoinViewModel>(Global.WalletService.Coins.Where(c => !c.SpentOrCoinJoinInProcess)
- .Select(c => new CoinViewModel(c)));
+ Password = "";
- QueuedCoins = new ObservableCollection<CoinViewModel>();
+ AvailableCoins = Global.WalletService.Coins.CreateDerivedCollection(c => new CoinViewModel(c), c => !c.SpentOrCoinJoinInProcess && c.Confirmed, null, RxApp.MainThreadScheduler);
- AvailableCoinsList = new CoinListViewModel(AvailableCoins);
+ QueuedCoins = Global.WalletService.Coins.CreateDerivedCollection(c => new CoinViewModel(c), c => c.CoinJoinInProcess, null, RxApp.MainThreadScheduler);
- QueuedCoinsList = new CoinListViewModel(QueuedCoins);
+ AvailableCoinsList = new CoinListViewModel(AvailableCoins, (first, second) => second.Amount.CompareTo(first.Amount));
- EnqueueCommand = ReactiveCommand.Create(() =>
+ QueuedCoinsList = new CoinListViewModel(QueuedCoins, (first, second) => second.Amount.CompareTo(first.Amount));
+
+ EnqueueCommand = ReactiveCommand.Create(async () =>
{
- var toMove = AvailableCoinsList.Coins.Where(c => c.IsSelected).ToList();
+ var selectedCoins = AvailableCoinsList.Coins.Where(c => c.IsSelected).ToList();
- foreach (var coin in toMove)
+ foreach (var coin in selectedCoins)
{
- AvailableCoins.Remove(coin);
- QueuedCoins.Add(coin);
+ coin.IsSelected = false;
}
+
+ await Global.ChaumianClient.QueueCoinsToMixAsync(Password, selectedCoins.Select(c => c.Model).ToArray());
});
- DequeueCommand = ReactiveCommand.Create(() =>
+ DequeueCommand = ReactiveCommand.Create(async () =>
{
- var toMove = QueuedCoinsList.Coins.Where(c => c.IsSelected).ToList();
+ var selectedCoins = QueuedCoinsList.Coins.Where(c => c.IsSelected).ToList();
- foreach (var coin in toMove)
+ foreach (var coin in selectedCoins)
{
- QueuedCoins.Remove(coin);
- AvailableCoins.Add(coin);
+ coin.IsSelected = false;
}
+
+ await Global.ChaumianClient.DequeueCoinsFromMixAsync(selectedCoins.Select(c => c.Model).ToArray());
});
}
- public ObservableCollection<CoinViewModel> AvailableCoins
+ public override void OnSelected()
+ {
+ Global.ChaumianClient.ActivateFrequentStatusProcessing();
+ }
+
+ public override void OnDeselected()
+ {
+ Global.ChaumianClient.DeactivateFrequentStatusProcessingIfNotMixing();
+ }
+
+ public string Password
+ {
+ get { return _password; }
+ set { this.RaiseAndSetIfChanged(ref _password, value); }
+ }
+
+ public IReadOnlyCollection<CoinViewModel> AvailableCoins
{
get { return _availableCoins; }
set { this.RaiseAndSetIfChanged(ref _availableCoins, value); }
}
- public ObservableCollection<CoinViewModel> QueuedCoins
+ public IReadOnlyCollection<CoinViewModel> QueuedCoins
{
get { return _queuedCoins; }
set { this.RaiseAndSetIfChanged(ref _queuedCoins, value); }

MODIFY
WalletWasabi.Gui/Controls/WalletExplorer/CoinListViewModel.cs
WalletWasabi.Gui/Controls/WalletExplorer/CoinListViewModel.cs
@@ -18,10 +18,9 @@ namespace WalletWasabi.Gui.Controls.WalletExplorer
private bool _clipboardNotificationVisible;
private long _disableClipboard;
- public CoinListViewModel(IEnumerable<CoinViewModel> coins)
+ public CoinListViewModel(IEnumerable<CoinViewModel> coins, Func<CoinViewModel, CoinViewModel, int> orderer = null)
{
- Coins = coins.CreateDerivedCollection(c => c, null, (first, second) =>
- first.Amount.CompareTo(second.Amount), RxApp.MainThreadScheduler);
+ Coins = coins.CreateDerivedCollection(c => c, null, orderer, RxApp.MainThreadScheduler);
this.WhenAnyValue(x => x.SelectedCoin).Subscribe(async coin =>
{

MODIFY
WalletWasabi.Gui/Controls/WalletExplorer/SendTabViewModel.cs
WalletWasabi.Gui/Controls/WalletExplorer/SendTabViewModel.cs
@@ -34,10 +34,9 @@ namespace WalletWasabi.Gui.Controls.WalletExplorer
var onCoinsSetModified = Observable.FromEventPattern(Global.WalletService.Coins, nameof(Global.WalletService.Coins.HashSetChanged))
.ObserveOn(RxApp.MainThreadScheduler);
- // TODO reset on item properties changing?
-
CoinList = new CoinListViewModel(
- Global.WalletService.Coins.CreateDerivedCollection(c => new CoinViewModel(c), c => !c.SpentOrCoinJoinInProcess, signalReset: onCoinsSetModified));
+ Global.WalletService.Coins.CreateDerivedCollection(c => new CoinViewModel(c), c => !c.SpentOrCoinJoinInProcess, signalReset: onCoinsSetModified),
+ (first, second) => second.Amount.CompareTo(first.Amount));
BuildTransactionButtonText = BuildTransactionButtonTextString;

MODIFY
WalletWasabi.Gui/Shell/Commands/HelpCommands.cs
WalletWasabi.Gui/Shell/Commands/HelpCommands.cs
@@ -72,20 +72,20 @@ namespace WalletWasabi.Gui.Shell.Commands
commandIconService.GetCompletionKindImage("DevTools"),
ReactiveCommand.Create(() =>
{
- var devTools = new DevTools(Window.OpenWindows.FirstOrDefault());
-
- var devToolsWindow = new Window
- {
- Width = 1024,
- Height = 512,
- Content = devTools,
- DataTemplates =
- {
- new ViewLocator<Avalonia.Diagnostics.ViewModels.ViewModelBase>(),
- }
- };
-
- devToolsWindow.Show();
+ //var devTools = new DevTools(Window..FirstOrDefault());
+
+ //var devToolsWindow = new Window
+ //{
+ // Width = 1024,
+ // Height = 512,
+ // Content = devTools,
+ // DataTemplates =
+ // {
+ // new ViewLocator<Avalonia.Diagnostics.ViewModels.ViewModelBase>(),
+ // }
+ //};
+
+ //devToolsWindow.Show();
}));
}

MODIFY
WalletWasabi.Gui/Styles/Styles.xaml
WalletWasabi.Gui/Styles/Styles.xaml
<sys:Double x:Key="FontSizeSmall">12</sys:Double>
<sys:Double x:Key="FontSizeNormal">14</sys:Double>
- <sys:Double x:Key="FontSizeLarge">18</sys:Double>
+ <sys:Double x:Key="FontSizeLarge">16</sys:Double>
</Style.Resources>
</Style>
<Style Selector="TextBox.selectableTextBlock">

MODIFY
WalletWasabi.Gui/ViewModels/WasabiDocumentTabViewModel.cs
WalletWasabi.Gui/ViewModels/WasabiDocumentTabViewModel.cs
@@ -27,5 +27,13 @@ namespace WalletWasabi.Gui.ViewModels
{
IoC.Get<IShell>().RemoveDocument(this);
}
+
+ public virtual void OnSelected()
+ {
+ }
+
+ public virtual void OnDeselected()
+ {
+ }
}
}

partial implementation of coinjoin.