Start building out chaumian coinjoin status
MODIFY
WalletWasabi.Gui/Controls/WalletExplorer/CoinJoinTabView.xaml
WalletWasabi.Gui/Controls/WalletExplorer/CoinJoinTabView.xaml
</Grid>
</controls:GroupBox>
- <controls:GroupBox Title="Status" TextBlock.FontSize="16" Padding="20" Margin="10 5 10 5" Grid.Row="1">
+ <controls:GroupBox Title="Status" TextBlock.FontSize="16" Padding="10" Margin="10 5 10 5" Grid.Row="1">
<Grid Classes="content">
+ <StackPanel Orientation="Vertical">
+ <StackPanel Orientation="Horizontal" Gap="4">
+ <TextBlock Text="Round ID:"> </TextBlock>
+ <TextBlock Text="{Binding RoundId}"> </TextBlock>
+ </StackPanel>
+
+ <StackPanel Orientation="Horizontal" Gap="4">
+ <TextBlock Text="Phase:"> </TextBlock>
+ <TextBlock Text="{Binding Phase}"> </TextBlock>
+ </StackPanel>
+
+ <StackPanel Orientation="Horizontal" Gap="4">
+ <TextBlock Text="Number Of Registered Peers:"> </TextBlock>
+ <TextBlock Text="{Binding PeersRegistered}"> </TextBlock>
+ <TextBlock Text="/"> </TextBlock>
+ <TextBlock Text="{Binding PeersNeeded}"> </TextBlock>
+ </StackPanel>
+ </StackPanel>
</Grid>
</controls:GroupBox>

MODIFY
WalletWasabi.Gui/Controls/WalletExplorer/CoinJoinTabViewModel.cs
WalletWasabi.Gui/Controls/WalletExplorer/CoinJoinTabViewModel.cs
@@ -6,6 +6,7 @@ using System.Reactive.Linq;
using System.Text;
using Avalonia.Controls;
using ReactiveUI;
+using WalletWasabi.Models.ChaumianCoinJoin;
namespace WalletWasabi.Gui.Controls.WalletExplorer
{
@@ -13,6 +14,10 @@ namespace WalletWasabi.Gui.Controls.WalletExplorer
{
private CoinListViewModel _availableCoinsList;
private CoinListViewModel _queuedCoinsList;
+ private long _roundId;
+ private string _phase;
+ private int _peersRegistered;
+ private int _peersNeeded;
private string _password;
public CoinJoinTabViewModel(WalletViewModel walletViewModel)
@@ -34,6 +39,23 @@ namespace WalletWasabi.Gui.Controls.WalletExplorer
QueuedCoinsList = new CoinListViewModel(queued);
+ var mostAdvancedRound = Global.ChaumianClient.State.GetMostAdvancedRoundOrDefault();
+ if (mostAdvancedRound != default)
+ {
+ RoundId = mostAdvancedRound.State.RoundId;
+ Phase = mostAdvancedRound.State.Phase.ToString();
+ PeersRegistered = mostAdvancedRound.State.RegisteredPeerCount;
+ PeersNeeded = mostAdvancedRound.State.RequiredPeerCount;
+ }
+ else
+ {
+ RoundId = -1;
+ Phase = CcjRoundPhase.InputRegistration.ToString();
+ PeersRegistered = 0;
+ PeersNeeded = 100;
+ }
+ Global.ChaumianClient.StateUpdated += ChaumianClient_StateUpdated;
+
EnqueueCommand = ReactiveCommand.Create(async () =>
{
var selectedCoins = AvailableCoinsList.Coins.Where(c => c.IsSelected).ToList();
@@ -59,6 +81,18 @@ namespace WalletWasabi.Gui.Controls.WalletExplorer
});
}
+ private void ChaumianClient_StateUpdated(object sender, EventArgs e)
+ {
+ var mostAdvancedRound = Global.ChaumianClient.State.GetMostAdvancedRoundOrDefault();
+ if (mostAdvancedRound != default)
+ {
+ RoundId = mostAdvancedRound.State.RoundId;
+ Phase = mostAdvancedRound.State.Phase.ToString();
+ PeersRegistered = mostAdvancedRound.State.RegisteredPeerCount;
+ PeersNeeded = mostAdvancedRound.State.RequiredPeerCount;
+ }
+ }
+
public override void OnSelected()
{
Global.ChaumianClient.ActivateFrequentStatusProcessing();
@@ -87,6 +121,30 @@ namespace WalletWasabi.Gui.Controls.WalletExplorer
set { this.RaiseAndSetIfChanged(ref _queuedCoinsList, value); }
}
+ public long RoundId
+ {
+ get { return _roundId; }
+ set { this.RaiseAndSetIfChanged(ref _roundId, value); }
+ }
+
+ public string Phase
+ {
+ get { return _phase; }
+ set { this.RaiseAndSetIfChanged(ref _phase, value); }
+ }
+
+ public int PeersRegistered
+ {
+ get { return _peersRegistered; }
+ set { this.RaiseAndSetIfChanged(ref _peersRegistered, value); }
+ }
+
+ public int PeersNeeded
+ {
+ get { return _peersNeeded; }
+ set { this.RaiseAndSetIfChanged(ref _peersNeeded, value); }
+ }
+
public ReactiveCommand EnqueueCommand { get; }
public ReactiveCommand DequeueCommand { get; }

MODIFY
WalletWasabi/Models/ChaumianCoinJoin/CcjClientState.cs
WalletWasabi/Models/ChaumianCoinJoin/CcjClientState.cs
@@ -150,6 +150,30 @@ namespace WalletWasabi.Models.ChaumianCoinJoin
}
}
+ public CcjClientRound GetRegistrableRoundOrDefault()
+ {
+ lock (StateLock)
+ {
+ return Rounds.FirstOrDefault(x => x.State.Phase == CcjRoundPhase.InputRegistration);
+ }
+ }
+
+ public CcjClientRound GetMostAdvancedRoundOrDefault()
+ {
+ lock (StateLock)
+ {
+ var foundAdvanced = Rounds.FirstOrDefault(x => x.State.Phase != CcjRoundPhase.InputRegistration);
+ if (foundAdvanced != default)
+ {
+ return foundAdvanced;
+ }
+ else
+ {
+ return Rounds.FirstOrDefault();
+ }
+ }
+ }
+
public int GetSmallestRegistrationTimeout()
{
lock (StateLock)
@@ -215,14 +239,6 @@ namespace WalletWasabi.Models.ChaumianCoinJoin
}
}
- public CcjClientRound GetRegistrableRoundOrDefault()
- {
- lock (StateLock)
- {
- return Rounds.FirstOrDefault(x => x.State.Phase == CcjRoundPhase.InputRegistration);
- }
- }
-
public void AddOrReplaceRound(CcjClientRound round)
{
lock (StateLock)

MODIFY
WalletWasabi/Services/CcjClient.cs
WalletWasabi/Services/CcjClient.cs
@@ -37,6 +37,8 @@ namespace WalletWasabi.Services
public CcjClientState State { get; }
+ public event EventHandler StateUpdated;
+
private long _frequentStatusProcessingIfNotMixing;
/// <summary>
@@ -157,6 +159,7 @@ namespace WalletWasabi.Services
states = await SatoshiClient.GetAllRoundStatesAsync();
State.UpdateRoundsByStates(states.ToArray());
+ StateUpdated?.Invoke(this, null);
delay = new Random().Next(0, 7); // delay the response to defend timing attack privacy
}

Start building out chaumian coinjoin status