diff --git a/Atomex.Client.Wpf.Installer/Product.wxs b/Atomex.Client.Wpf.Installer/Product.wxs
index 1748b7a..62e9b09 100644
--- a/Atomex.Client.Wpf.Installer/Product.wxs
+++ b/Atomex.Client.Wpf.Installer/Product.wxs
@@ -3,7 +3,7 @@
-
+
diff --git a/Atomex.Client.Wpf/Atomex.Client.Wpf.csproj b/Atomex.Client.Wpf/Atomex.Client.Wpf.csproj
index 2309894..dc49e94 100644
--- a/Atomex.Client.Wpf/Atomex.Client.Wpf.csproj
+++ b/Atomex.Client.Wpf/Atomex.Client.Wpf.csproj
@@ -369,6 +369,7 @@
+
diff --git a/Atomex.Client.Wpf/ViewModels/MessageViewModel.cs b/Atomex.Client.Wpf/ViewModels/MessageViewModel.cs
index 43b9838..5d466d1 100644
--- a/Atomex.Client.Wpf/ViewModels/MessageViewModel.cs
+++ b/Atomex.Client.Wpf/ViewModels/MessageViewModel.cs
@@ -80,14 +80,11 @@ public MessageViewModel(
_nextAction = nextAction;
}
- public static MessageViewModel Error(string text)
- {
- return Error(text, goBackPages: 1);
- }
+ public static MessageViewModel Error(string text) =>
+ Error(text, goBackPages: 1);
- public static MessageViewModel Error(string text, int goBackPages)
- {
- return new MessageViewModel(
+ public static MessageViewModel Error(string text, int goBackPages) =>
+ new MessageViewModel(
title: Resources.SvError,
text: text,
backTitle: Resources.SvBack,
@@ -98,22 +95,18 @@ public static MessageViewModel Error(string text, int goBackPages)
Navigation.Back();
},
nextAction: null);
- }
- public static MessageViewModel Success(string text, Action nextAction)
- {
- return new MessageViewModel(
+ public static MessageViewModel Success(string text, Action nextAction) =>
+ new MessageViewModel(
title: Resources.SvSuccess,
text: text,
backTitle: null,
nextTitle: Resources.SvOk,
backAction: null,
nextAction: nextAction);
- }
- public static MessageViewModel Message(string title, string text, int goBackPages)
- {
- return new MessageViewModel(
+ public static MessageViewModel Message(string title, string text, int goBackPages) =>
+ new MessageViewModel(
title: title,
text: text,
backTitle: Resources.SvBack,
@@ -124,11 +117,9 @@ public static MessageViewModel Message(string title, string text, int goBackPage
Navigation.Back();
},
nextAction: null);
- }
- public static MessageViewModel Success(string text, string baseUrl, string id, Action nextAction)
- {
- return new MessageViewModel(
+ public static MessageViewModel Success(string text, string baseUrl, string id, Action nextAction) =>
+ new MessageViewModel(
title: Resources.SvSuccess,
text: text,
baseUrl: baseUrl,
@@ -137,7 +128,6 @@ public static MessageViewModel Success(string text, string baseUrl, string id, A
nextTitle: Resources.SvOk,
backAction: null,
nextAction: nextAction);
- }
private ICommand _openTxInExplorerCommand;
public ICommand OpenTxInExplorerCommand => _openTxInExplorerCommand ?? (_openTxInExplorerCommand = new RelayCommand((id) =>
diff --git a/Atomex.Client.Wpf/ViewModels/ReceiveViewModel.cs b/Atomex.Client.Wpf/ViewModels/ReceiveViewModel.cs
index da28be6..f624721 100644
--- a/Atomex.Client.Wpf/ViewModels/ReceiveViewModel.cs
+++ b/Atomex.Client.Wpf/ViewModels/ReceiveViewModel.cs
@@ -7,8 +7,12 @@
using Atomex.Core.Entities;
using Atomex.Client.Wpf.Common;
using Atomex.Client.Wpf.ViewModels.Abstract;
+using Atomex.Client.Wpf.ViewModels.SendViewModels;
using Atomex.Common;
using QRCoder;
+using System;
+using System.Windows.Input;
+using Serilog;
namespace Atomex.Client.Wpf.ViewModels
{
@@ -16,6 +20,8 @@ public class ReceiveViewModel : BaseViewModel
{
private const int PixelsPerModule = 20;
+ private IAtomexApp App { get; }
+
private List _fromCurrencies;
public List FromCurrencies
{
@@ -31,30 +37,64 @@ public Currency Currency
{
_currency = value;
OnPropertyChanged(nameof(Currency));
-
#if DEBUG
if (!Env.IsInDesignerMode())
+ {
#endif
- Address = App.AtomexApp.Account
+ var activeAddresses = App.Account
+ .GetUnspentAddressesAsync(_currency)
+ .WaitForResult();
+
+ var freeAddress = App.Account
.GetFreeExternalAddressAsync(_currency)
- .WaitForResult()
- .Address;
+ .WaitForResult();
+
+ FromAddressList = activeAddresses
+ .Select(wa => new WalletAddressViewModel(wa))
+ .ToList()
+ .AddEx(new WalletAddressViewModel(freeAddress, isFreeAddress: true));
+#if DEBUG
+ }
+#endif
+ }
+ }
+
+ private List _fromAddressList;
+ public List FromAddressList
+ {
+ get => _fromAddressList;
+ private set
+ {
+ _fromAddressList = value;
+ OnPropertyChanged(nameof(FromAddressList));
+
+ SelectedAddress = GetDefaultAddress();
}
}
- private string _address;
- public string Address
+ private WalletAddress _selectedAddress;
+ public WalletAddress SelectedAddress
{
- get => _address;
+ get => _selectedAddress;
set
{
- _address = value;
- OnPropertyChanged(nameof(Address));
+ _selectedAddress = value;
+ OnPropertyChanged(nameof(SelectedAddress));
+
+ if (_selectedAddress != null)
+ CreateQrCodeAsync().FireAndForget();
- CreateQrCodeAsync().FireAndForget();
+ Warning = string.Empty;
}
}
+ private string _warning;
+ public string Warning
+ {
+ get => _warning;
+ set { _warning = value; OnPropertyChanged(nameof(Warning)); }
+ }
+
public BitmapSource QrCode { get; private set; }
public ReceiveViewModel()
@@ -72,6 +112,8 @@ public ReceiveViewModel(IAtomexApp app)
public ReceiveViewModel(IAtomexApp app, Currency currency)
{
+ App = app ?? throw new ArgumentNullException(nameof(app));
+
FromCurrencies = app.Account.Currencies
.Where(c => c.IsTransactionsAvailable)
.Select(CurrencyViewModelCreator.CreateViewModel)
@@ -87,7 +129,7 @@ private async Task CreateQrCodeAsync()
await Task.Factory.StartNew(() =>
{
using (var qrGenerator = new QRCodeGenerator())
- using (var qrData = qrGenerator.CreateQrCode(Address, QRCodeGenerator.ECCLevel.Q))
+ using (var qrData = qrGenerator.CreateQrCode(_selectedAddress.Address, QRCodeGenerator.ECCLevel.Q))
using (var qrCode = new QRCode(qrData))
qrCodeBitmap = qrCode.GetGraphic(PixelsPerModule);
});
@@ -104,6 +146,35 @@ await Application.Current.Dispatcher.InvokeAsync(() =>
}
}
+ private WalletAddress GetDefaultAddress()
+ {
+ if (Currency is Tezos || Currency is Ethereum)
+ {
+ var activeAddressViewModel = FromAddressList
+ .FirstOrDefault(vm => vm.WalletAddress.HasActivity && vm.WalletAddress.AvailableBalance() > 0);
+
+ if (activeAddressViewModel != null)
+ return activeAddressViewModel.WalletAddress;
+ }
+
+ return FromAddressList.First(vm => vm.IsFreeAddress).WalletAddress;
+ }
+
+ private ICommand _copyCommand;
+ public ICommand CopyCommand => _copyCommand ?? (_copyCommand = new RelayCommand((s) =>
+ {
+ try
+ {
+ Clipboard.SetText(SelectedAddress.Address);
+
+ Warning = "Address successfully copied to clipboard.";
+ }
+ catch (Exception e)
+ {
+ Log.Error(e, "Copy to clipboard error");
+ }
+ }));
+
private void DesignerMode()
{
FromCurrencies = DesignTime.Currencies
@@ -111,7 +182,7 @@ private void DesignerMode()
.ToList();
Currency = FromCurrencies.First().Currency;
- Address = "mzztP8VVJYxV93EUiiYrJUbL55MLx7KLoM";
+ // Address = "mzztP8VVJYxV93EUiiYrJUbL55MLx7KLoM";
}
}
}
\ No newline at end of file
diff --git a/Atomex.Client.Wpf/ViewModels/SendViewModels/DelegateViewModel.cs b/Atomex.Client.Wpf/ViewModels/SendViewModels/DelegateViewModel.cs
index 882cb78..d507aa2 100644
--- a/Atomex.Client.Wpf/ViewModels/SendViewModels/DelegateViewModel.cs
+++ b/Atomex.Client.Wpf/ViewModels/SendViewModels/DelegateViewModel.cs
@@ -22,17 +22,6 @@
namespace Atomex.Client.Wpf.ViewModels.SendViewModels
{
- public class WalletAddressViewModel
- {
- public WalletAddress WalletAddress { get; set; }
-
- public string Address => WalletAddress.Address;
- public decimal AvailableBalance => WalletAddress.AvailableBalance();
-
- public WalletAddressViewModel(WalletAddress walletAddress) =>
- WalletAddress = walletAddress;
- }
-
public class DelegateViewModel : BaseViewModel
{
private IAtomexApp App { get; }
diff --git a/Atomex.Client.Wpf/ViewModels/SendViewModels/WalletAddressViewModel.cs b/Atomex.Client.Wpf/ViewModels/SendViewModels/WalletAddressViewModel.cs
new file mode 100644
index 0000000..b8b19e7
--- /dev/null
+++ b/Atomex.Client.Wpf/ViewModels/SendViewModels/WalletAddressViewModel.cs
@@ -0,0 +1,19 @@
+using Atomex.Core.Entities;
+
+namespace Atomex.Client.Wpf.ViewModels.SendViewModels
+{
+ public class WalletAddressViewModel
+ {
+ public WalletAddress WalletAddress { get; }
+ public string Address => WalletAddress.Address;
+ public decimal AvailableBalance => WalletAddress.AvailableBalance();
+ public string CurrencyFormat => WalletAddress.Currency.Format;
+ public bool IsFreeAddress { get; }
+
+ public WalletAddressViewModel(WalletAddress walletAddress, bool isFreeAddress = false)
+ {
+ WalletAddress = walletAddress;
+ IsFreeAddress = isFreeAddress;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Atomex.Client.Wpf/Views/ReceiveView.xaml b/Atomex.Client.Wpf/Views/ReceiveView.xaml
index d491cc2..ff5d05d 100644
--- a/Atomex.Client.Wpf/Views/ReceiveView.xaml
+++ b/Atomex.Client.Wpf/Views/ReceiveView.xaml
@@ -7,7 +7,9 @@
xmlns:helpers="clr-namespace:Atomex.Client.Wpf.Helpers"
xmlns:viewModels="clr-namespace:Atomex.Client.Wpf.ViewModels"
xmlns:common="clr-namespace:Atomex.Client.Wpf.Common"
- mc:Ignorable="d"
+ xmlns:iconPacks="http://metro.mahapps.com/winfx/xaml/iconpacks"
+ xmlns:converters="clr-namespace:Atomex.Client.Wpf.Converters"
+ mc:Ignorable="d"
ShowTitleBar="False"
Background="Transparent"
@@ -17,12 +19,22 @@
UseLayoutRounding="True"
common:ChildWindowHelper.IsOpen="True"
- d:DesignWidth="600"
+ d:DesignWidth="630"
d:DesignHeight="400"
d:DataContext="{d:DesignInstance Type=viewModels:ReceiveViewModel, IsDesignTimeCreatable=True}">
+
+
+
+
+
+
+
+
+
+
+ Width="630">
-
+ HorizontalAlignment="Center"
+ Margin="37 0 0 0">
-
+ helpers:ComboBoxHelper.CornerRadius="0 20 20 0"
+ Style="{StaticResource CustomComboBox}">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+