Add date to History panel
MODIFY
WalletWasabi.Gui/Controls/WalletExplorer/HistoryTabView.xaml
WalletWasabi.Gui/Controls/WalletExplorer/HistoryTabView.xaml
<controls:GroupBox Title="{Binding Title}" TextBlock.FontSize="30" Padding="20" Margin="10">
<Grid Classes="content">
<DockPanel LastChildFill="True">
- <Grid ColumnDefinitions="100, 100, 480, *" Margin="5 0" DockPanel.Dock="Top">
- <TextBlock Text="Confirmed" />
- <TextBlock Text="Amount" Grid.Column="1" />
- <TextBlock Text="Transaction Id" Grid.Column="2" />
- <TextBlock Text="Label" Grid.Column="3" Margin="20 0 0 0" />
- <Grid IsVisible="{Binding ClipboardNotificationVisible}" Grid.ColumnSpan="4">
+ <Grid IsVisible="{Binding ClipboardNotificationVisible}" Grid.ColumnSpan="4" DockPanel.Dock="Top">
<Grid Opacity="{Binding ClipboardNotificationOpacity}">
<Grid.Transitions>
<Transitions>
Duration="0:0:0.5" />
</Transitions>
</Grid.Transitions>
- <TextBlock Text="TransactionId Copied to Clipboard!" Foreground="#22B14C" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="0 0 200 0" />
+ <TextBlock Text="TransactionId Is Copied to Clipboard!" Foreground="#22B14C" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="4" />
</Grid>
</Grid>
+ <DockPanel LastChildFill="True" DockPanel.Dock="Bottom">
+ <Grid ColumnDefinitions="120, 80, 100, *" Margin="5 0" DockPanel.Dock="Top">
+ <TextBlock Text="Date" />
+ <TextBlock Text="Confirmed" Grid.Column="1" />
+ <TextBlock Text="Amount" Grid.Column="2" />
+ <TextBlock Text="Labels" Grid.Column="3" Margin="20 0 0 0" />
</Grid>
<ListBox Items="{Binding Transactions}" SelectedItem="{Binding SelectedTransaction, Mode=TwoWay}">
<ListBox.ItemTemplate>
<DataTemplate>
- <Grid ColumnDefinitions="100, 100, 480, *">
+ <Grid ColumnDefinitions="120, 80, 100, *">
<Grid.Styles>
<Style Selector="TextBlock">
<Setter Property="VerticalAlignment" Value="Center" />
</Style>
</Grid.Styles>
- <Path HorizontalAlignment="Center" Data="F1 M 23.7501,33.25L 34.8334,44.3333L 52.2499,22.1668L 56.9999,26.9168L 34.8334,53.8333L 19.0001,38L 23.7501,33.25 Z" Fill="#22B14C" Height="16" Width="16" IsVisible="{Binding Confirmed}" Stretch="Fill" />
- <TextBlock Text="{Binding AmountBtc}" Grid.Column="1" Foreground="{Binding AmountBtc, Converter={StaticResource MoneyBrushConverter}}" />
- <TextBlock Text="{Binding TransactionId}" Grid.Column="2" />
+ <TextBlock Text="{Binding DateTime}" Grid.Column="0" />
+ <Path Grid.Column="1" HorizontalAlignment="Center" Data="F1 M 23.7501,33.25L 34.8334,44.3333L 52.2499,22.1668L 56.9999,26.9168L 34.8334,53.8333L 19.0001,38L 23.7501,33.25 Z" Fill="#22B14C" Height="16" Width="16" IsVisible="{Binding Confirmed}" Stretch="Fill" />
+ <TextBlock Text="{Binding AmountBtc}" Grid.Column="2" Foreground="{Binding AmountBtc, Converter={StaticResource MoneyBrushConverter}}" />
<TextBlock Text="{Binding Label}" Grid.Column="3" Margin="20 0 0 0" />
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</DockPanel>
+ </DockPanel>
</Grid>
</controls:GroupBox>
</UserControl>

MODIFY
WalletWasabi.Gui/Controls/WalletExplorer/HistoryTabViewModel.cs
WalletWasabi.Gui/Controls/WalletExplorer/HistoryTabViewModel.cs
@@ -71,41 +71,59 @@ namespace WalletWasabi.Gui.Controls.WalletExplorer
private void RewriteTable()
{
- var txRecordList = new List<(Height height, Money amount, string label, uint256 transactionId)>();
+ var txRecordList = new List<(DateTimeOffset dateTime, Height height, Money amount, string label, uint256 transactionId)>();
foreach (SmartCoin coin in Global.WalletService.Coins)
{
var found = txRecordList.FirstOrDefault(x => x.transactionId == coin.TransactionId);
+ SmartTransaction foundTransaction = Global.WalletService.TransactionCache.First(x => x.GetHash() == coin.TransactionId);
+ DateTimeOffset dateTime;
+ if (foundTransaction.Height.Type == HeightType.Chain)
+ {
+ dateTime = Global.WalletService.ProcessedBlocks.First(x => x.Value.height == foundTransaction.Height).Value.dateTime;
+ }
+ else
+ {
+ dateTime = foundTransaction.FirstSeenIfMemPoolTime ?? DateTimeOffset.UtcNow;
+ }
if (found != default) // if found
{
txRecordList.Remove(found);
var foundLabel = found.label != string.Empty ? found.label + ", " : "";
- var newRecord = (found.height, found.amount + coin.Amount, $"{foundLabel}{coin.Label}", coin.TransactionId);
+ var newRecord = (dateTime, found.height, found.amount + coin.Amount, $"{foundLabel}{coin.Label}", coin.TransactionId);
txRecordList.Add(newRecord);
}
else
{
- txRecordList.Add((coin.Height, coin.Amount, coin.Label, coin.TransactionId));
+ txRecordList.Add((dateTime, coin.Height, coin.Amount, coin.Label, coin.TransactionId));
}
if (coin.SpenderTransactionId != null)
{
SmartTransaction foundSpenderTransaction = Global.WalletService.TransactionCache.First(x => x.GetHash() == coin.SpenderTransactionId);
+ if (foundSpenderTransaction.Height.Type == HeightType.Chain)
+ {
+ dateTime = Global.WalletService.ProcessedBlocks.First(x => x.Value.height == foundSpenderTransaction.Height).Value.dateTime;
+ }
+ else
+ {
+ dateTime = foundSpenderTransaction.FirstSeenIfMemPoolTime ?? DateTimeOffset.UtcNow;
+ }
var foundSpenderCoin = txRecordList.FirstOrDefault(x => x.transactionId == coin.SpenderTransactionId);
if (foundSpenderCoin != default) // if found
{
txRecordList.Remove(foundSpenderCoin);
- var newRecord = (foundSpenderTransaction.Height, foundSpenderCoin.amount - coin.Amount, foundSpenderCoin.label, coin.SpenderTransactionId);
+ var newRecord = (dateTime, foundSpenderTransaction.Height, foundSpenderCoin.amount - coin.Amount, foundSpenderCoin.label, coin.SpenderTransactionId);
txRecordList.Add(newRecord);
}
else
{
- txRecordList.Add((foundSpenderTransaction.Height, (Money.Zero - coin.Amount), "", coin.SpenderTransactionId));
+ txRecordList.Add((dateTime, foundSpenderTransaction.Height, (Money.Zero - coin.Amount), "", coin.SpenderTransactionId));
}
}
}
- txRecordList = txRecordList.OrderByDescending(x => x.height).ThenBy(x => x.amount).ToList();
+ txRecordList = txRecordList.OrderByDescending(x => x.dateTime).ThenBy(x => x.amount).ToList();
var rememberSelectedTransactionId = SelectedTransaction?.TransactionId;
Transactions?.Clear();
@@ -113,6 +131,7 @@ namespace WalletWasabi.Gui.Controls.WalletExplorer
{
var txinfo = new TransactionInfo
{
+ DateTime = txr.dateTime.ToLocalTime(),
Confirmed = txr.height != Models.Height.MemPool && txr.height != Models.Height.Unknown,
AmountBtc = $"{txr.amount.ToString(fplus: true, trimExcessZero: true)}",
Label = txr.label,

MODIFY
WalletWasabi.Gui/Controls/WalletExplorer/TransactionInfo.cs
WalletWasabi.Gui/Controls/WalletExplorer/TransactionInfo.cs
@@ -8,10 +8,17 @@ namespace WalletWasabi.Gui.Controls.WalletExplorer
public class TransactionInfo : ReactiveObject
{
private bool _confirmed;
+ private DateTimeOffset _dateTime;
private string _amountBtc;
private string _label;
private string _transactionId;
+ public DateTimeOffset DateTime
+ {
+ get { return _dateTime; }
+ set { this.RaiseAndSetIfChanged(ref _dateTime, value); }
+ }
+
public bool Confirmed
{
get { return _confirmed; }

MODIFY
WalletWasabi/Models/SmartTransaction.cs
WalletWasabi/Models/SmartTransaction.cs
@@ -29,7 +29,7 @@ namespace WalletWasabi.Models
/// only exists in memory,
/// doesn't affect equality
/// </summary>
- public DateTimeOffset? FirstSeenIfMemPoolHeight { get; private set; }
+ public DateTimeOffset? FirstSeenIfMemPoolTime { get; private set; }
#endregion Members
@@ -52,11 +52,11 @@ namespace WalletWasabi.Models
Height = height;
if (height == Height.MemPool)
{
- FirstSeenIfMemPoolHeight = DateTimeOffset.UtcNow;
+ FirstSeenIfMemPoolTime = DateTimeOffset.UtcNow;
}
else
{
- FirstSeenIfMemPoolHeight = null;
+ FirstSeenIfMemPoolTime = null;
}
}

MODIFY
WalletWasabi/Services/WalletService.cs
WalletWasabi/Services/WalletService.cs
@@ -22,6 +22,7 @@ using Nito.AsyncEx;
using System.Collections.ObjectModel;
using WalletWasabi.WebClients.Wasabi;
using Newtonsoft.Json;
+using System.Collections.Concurrent;
namespace WalletWasabi.Services
{
@@ -41,7 +42,7 @@ namespace WalletWasabi.Services
private AsyncLock BlockFolderLock { get; }
public SortedDictionary<Height, uint256> WalletBlocks { get; }
- private HashSet<uint256> ProcessedBlocks { get; }
+ public ConcurrentDictionary<uint256, (Height height, DateTimeOffset dateTime)> ProcessedBlocks { get; }
private AsyncLock WalletBlocksLock { get; }
public NotifyingConcurrentHashSet<SmartCoin> Coins { get; }
@@ -73,7 +74,7 @@ namespace WalletWasabi.Services
MemPool = Guard.NotNull(nameof(memPool), memPool);
WalletBlocks = new SortedDictionary<Height, uint256>();
- ProcessedBlocks = new HashSet<uint256>();
+ ProcessedBlocks = new ConcurrentDictionary<uint256, (Height height, DateTimeOffset dateTime)>();
WalletBlocksLock = new AsyncLock();
HandleFiltersLock = new AsyncLock();
@@ -121,7 +122,7 @@ namespace WalletWasabi.Services
var elem = WalletBlocks.FirstOrDefault(x => x.Value == invalidBlockHash);
await DeleteBlockAsync(invalidBlockHash);
WalletBlocks.RemoveByValue(invalidBlockHash);
- ProcessedBlocks.Remove(invalidBlockHash);
+ ProcessedBlocks.TryRemove(invalidBlockHash, out _);
if (elem.Key != default(Height))
{
foreach (var toRemove in Coins.Where(x => x.Height == elem.Key).ToHashSet())
@@ -210,7 +211,7 @@ namespace WalletWasabi.Services
private async Task ProcessFilterModelAsync(FilterModel filterModel, CancellationToken cancel)
{
- if (ProcessedBlocks.Contains(filterModel.BlockHash))
+ if (ProcessedBlocks.ContainsKey(filterModel.BlockHash))
{
return;
}
@@ -303,7 +304,7 @@ namespace WalletWasabi.Services
ProcessTransaction(new SmartTransaction(tx, height), keys);
}
- ProcessedBlocks.Add(block.GetHash());
+ ProcessedBlocks.TryAdd(block.GetHash(), (height, block.Header.BlockTime));
NewBlockProcessed?.Invoke(this, block);
}

Add date to History panel