diff --git a/Atomex.Client.Core b/Atomex.Client.Core index 5a73643..5ebc632 160000 --- a/Atomex.Client.Core +++ b/Atomex.Client.Core @@ -1 +1 @@ -Subproject commit 5a7364344ead065b98a9e53e4c192b399a0c15c9 +Subproject commit 5ebc632e81c01d9eb50d56a6e566322557d9dc06 diff --git a/Atomex.Client.Wpf.Installer/Product.wxs b/Atomex.Client.Wpf.Installer/Product.wxs index 14a36ab..dd128ed 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/Properties/Resources.Designer.cs b/Atomex.Client.Wpf/Properties/Resources.Designer.cs index adf9fef..c382ba9 100644 --- a/Atomex.Client.Wpf/Properties/Resources.Designer.cs +++ b/Atomex.Client.Wpf/Properties/Resources.Designer.cs @@ -69,6 +69,15 @@ public static string ActiveSwapsWarning { } } + /// + /// Ищет локализованную строку, похожую на Amount is greater than the available. Please use the Max button to get the maximum available value.. + /// + public static string CvBigAmount { + get { + return ResourceManager.GetString("CvBigAmount", resourceCulture); + } + } + /// /// Ищет локализованную строку, похожую на Conversion error. Please contant technical support.. /// @@ -205,11 +214,11 @@ public static string CvWarning { } /// - /// Ищет локализованную строку, похожую на Amount to convert must be greater than zero.. + /// Ищет локализованную строку, похожую на Amount must be greater than zero.. /// - public static string CvWrongAmount { + public static string CvZeroAmount { get { - return ResourceManager.GetString("CvWrongAmount", resourceCulture); + return ResourceManager.GetString("CvZeroAmount", resourceCulture); } } diff --git a/Atomex.Client.Wpf/Properties/Resources.resx b/Atomex.Client.Wpf/Properties/Resources.resx index e1594cd..2fe54c6 100644 --- a/Atomex.Client.Wpf/Properties/Resources.resx +++ b/Atomex.Client.Wpf/Properties/Resources.resx @@ -237,8 +237,8 @@ Warning - - Amount to convert must be greater than zero. + + Amount is greater than the available. Please use the Max button to get the maximum available value. Not enough liquidity to convert a specified amount. @@ -296,4 +296,7 @@ NOTE: Do not sign out or close the application until the swap is completed, othe Too high network fee for this amount ({0} is {1})! + + Amount must be greater than zero. + \ No newline at end of file diff --git a/Atomex.Client.Wpf/Styles/AmountTextBoxStyle.xaml b/Atomex.Client.Wpf/Styles/AmountTextBoxStyle.xaml index 3ed1f43..ff9260d 100644 --- a/Atomex.Client.Wpf/Styles/AmountTextBoxStyle.xaml +++ b/Atomex.Client.Wpf/Styles/AmountTextBoxStyle.xaml @@ -129,4 +129,17 @@ + + \ No newline at end of file diff --git a/Atomex.Client.Wpf/Themes/blue.xaml b/Atomex.Client.Wpf/Themes/blue.xaml index 1e6b152..55e7daa 100644 --- a/Atomex.Client.Wpf/Themes/blue.xaml +++ b/Atomex.Client.Wpf/Themes/blue.xaml @@ -233,6 +233,7 @@ + diff --git a/Atomex.Client.Wpf/ViewModels/ConversionConfirmationViewModel.cs b/Atomex.Client.Wpf/ViewModels/ConversionConfirmationViewModel.cs index 71097f0..2940c6a 100644 --- a/Atomex.Client.Wpf/ViewModels/ConversionConfirmationViewModel.cs +++ b/Atomex.Client.Wpf/ViewModels/ConversionConfirmationViewModel.cs @@ -148,7 +148,7 @@ private async Task ConvertAsync() .ToList(); if (Amount == 0) - return new Error(Errors.SwapError, Resources.CvWrongAmount); + return new Error(Errors.SwapError, Resources.CvZeroAmount); if (Amount > 0 && !fromWallets.Any()) return new Error(Errors.SwapError, Resources.CvInsufficientFunds); diff --git a/Atomex.Client.Wpf/ViewModels/ConversionViewModel.cs b/Atomex.Client.Wpf/ViewModels/ConversionViewModel.cs index fa4dfec..cb8d021 100644 --- a/Atomex.Client.Wpf/ViewModels/ConversionViewModel.cs +++ b/Atomex.Client.Wpf/ViewModels/ConversionViewModel.cs @@ -110,7 +110,8 @@ public virtual Currency FromCurrency FromCurrencyViewModel = _currencyViewModels .First(c => c.Currency.Name == _fromCurrency.Name); - Amount = 0; + _amount = 0; + _ = UpdateAmountAsync(_amount, updateUi: true); } } @@ -233,10 +234,27 @@ public string BaseCurrencyFormat } protected decimal _amount; - public decimal Amount + + public string AmountString { - get => _amount; - set { _ = UpdateAmountAsync(value); } + get => _amount.ToString(CurrencyFormat, CultureInfo.InvariantCulture); + set + { + if (!decimal.TryParse(value, NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out var amount)) + return; + + _amount = amount.TruncateByFormat(CurrencyFormat); + + if (_amount > long.MaxValue) + _amount = long.MaxValue; + + _ = UpdateAmountAsync(_amount, updateUi: false); + } + } + + public string FromAmountString + { + get => _amount.ToString(CurrencyFormat, CultureInfo.InvariantCulture); } private decimal _amountInBase; @@ -253,6 +271,13 @@ public bool IsAmountUpdating set { _isAmountUpdating = value; OnPropertyChanged(nameof(IsAmountUpdating)); } } + private bool _isAmountValid = true; + public bool IsAmountValid + { + get => _isAmountValid; + set { _isAmountValid = value; OnPropertyChanged(nameof(IsAmountValid)); } + } + private decimal _targetAmount; public decimal TargetAmount { @@ -458,9 +483,35 @@ public ConversionViewModel( public ICommand ConvertCommand => _convertCommand ??= new Command(OnConvertClick); private ICommand _maxAmountCommand; - public ICommand MaxAmountCommand => _maxAmountCommand ??= new Command(() => + public ICommand MaxAmountCommand => _maxAmountCommand ??= new Command(async () => + { + try + { + var swapParams = await Atomex.ViewModels.Helpers + .EstimateSwapPaymentParamsAsync( + amount: EstimatedMaxAmount, + fromCurrency: FromCurrency, + toCurrency: ToCurrency, + account: App.Account, + atomexClient: App.Terminal, + symbolsProvider: App.SymbolsProvider); + + _amount = Math.Min(swapParams.Amount, EstimatedMaxAmount); + _ = UpdateAmountAsync(_amount, updateUi: true); + } + catch (Exception e) + { + Log.Error(e, "Max amount command error."); + } + }); + + + private ICommand _swapCurrenciesCommand; + public ICommand SwapCurrenciesCommand => _swapCurrenciesCommand ??= new Command(() => { - Amount = EstimatedMaxAmount; + var temp = _toCurrency; + _toCurrency = _fromCurrency; + FromCurrency = temp; }); private void SubscribeToServices() @@ -471,7 +522,7 @@ private void SubscribeToServices() App.QuotesProvider.QuotesUpdated += OnBaseQuotesUpdatedEventHandler; } - protected virtual async Task UpdateAmountAsync(decimal value) + protected virtual async Task UpdateAmountAsync(decimal value, bool updateUi = false) { Warning = string.Empty; @@ -505,15 +556,19 @@ protected virtual async Task UpdateAmountAsync(decimal value) Warning = string.Empty; } - _amount = swapParams.Amount; _estimatedPaymentFee = swapParams.PaymentFee; _estimatedMakerNetworkFee = swapParams.MakerNetworkFee; OnPropertyChanged(nameof(CurrencyFormat)); OnPropertyChanged(nameof(TargetCurrencyFormat)); - OnPropertyChanged(nameof(Amount)); OnPropertyChanged(nameof(EstimatedPaymentFee)); OnPropertyChanged(nameof(EstimatedMakerNetworkFee)); + OnPropertyChanged(nameof(FromAmountString)); + + IsAmountValid = _amount <= swapParams.Amount.TruncateByFormat(CurrencyFormat); + + if (updateUi) + OnPropertyChanged(nameof(AmountString)); await UpdateRedeemAndRewardFeesAsync(); @@ -681,7 +736,7 @@ protected async void OnQuotesUpdatedEventHandler(object sender, MarketDataEventA try { var swapPriceEstimation = await Atomex.ViewModels.Helpers.EstimateSwapPriceAsync( - amount: Amount, + amount: _amount, fromCurrency: FromCurrency, toCurrency: ToCurrency, account: App.Account, @@ -749,9 +804,15 @@ await Application.Current.Dispatcher.InvokeAsync(() => private void OnConvertClick() { - if (Amount == 0) + if (_amount == 0) + { + DialogViewer.ShowMessage(Resources.CvWarning, Resources.CvZeroAmount); + return; + } + + if (!IsAmountValid) { - DialogViewer.ShowMessage(Resources.CvWarning, Resources.CvWrongAmount); + DialogViewer.ShowMessage(Resources.CvWarning, Resources.CvBigAmount); return; } @@ -777,7 +838,7 @@ private void OnConvertClick() var side = symbol.OrderSideForBuyCurrency(ToCurrency); var price = EstimatedPrice; var baseCurrency = Currencies.GetByName(symbol.Base); - var qty = AmountHelper.AmountToQty(side, Amount, price, baseCurrency.DigitsMultiplier); + var qty = AmountHelper.AmountToQty(side, _amount, price, baseCurrency.DigitsMultiplier); if (qty < symbol.MinimumQty) { @@ -808,7 +869,7 @@ private void OnConvertClick() TargetFeeCurrencyCode = TargetFeeCurrencyCode, TargetFeeCurrencyFormat = TargetFeeCurrencyFormat, - Amount = Amount, + Amount = _amount, AmountInBase = AmountInBase, TargetAmount = TargetAmount, TargetAmountInBase = TargetAmountInBase, @@ -836,7 +897,8 @@ private void OnConvertClick() private void OnSuccessConvertion(object sender, EventArgs e) { - Amount = _amount; // recalculate amount + _amount = Math.Min(_amount, EstimatedMaxAmount); // recalculate amount + _ = UpdateAmountAsync(_amount, updateUi: true); } private void DesignerMode() diff --git a/Atomex.Client.Wpf/Views/ConversionView.xaml b/Atomex.Client.Wpf/Views/ConversionView.xaml index 3ebbf2f..28ebe03 100644 --- a/Atomex.Client.Wpf/Views/ConversionView.xaml +++ b/Atomex.Client.Wpf/Views/ConversionView.xaml @@ -43,6 +43,7 @@ + + + + + + + + + + + - - - - - - @@ -111,42 +130,44 @@ - + Grid.Row="2" + Content="Max" + Style="{DynamicResource ConvertButtonStyle}"/> - - - + - - - + - - - - - - + + + + + - - - + - - - - - -