Cw 262 better handle user exchange amount below minimum or maximum trade size (#868)

* CW-262-Better-handle-user-exchange-amount-below-minimum-or-maximum-trade-size

* fix: App should compute conversion even if it's not within the limits
This commit is contained in:
Adegoke David 2023-04-20 02:13:37 +01:00 committed by GitHub
parent efef30f8eb
commit 7b91b0e938
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
26 changed files with 185 additions and 12 deletions

View file

@ -3,17 +3,45 @@ import 'package:cake_wallet/generated/i18n.dart';
import 'package:cw_core/crypto_currency.dart';
class AmountValidator extends TextValidator {
AmountValidator({required CryptoCurrency currency, bool isAutovalidate = false}) {
AmountValidator({
required CryptoCurrency currency,
bool isAutovalidate = false,
String? minValue,
String? maxValue,
}) {
symbolsAmountValidator =
SymbolsAmountValidator(isAutovalidate: isAutovalidate);
decimalAmountValidator = DecimalAmountValidator(currency: currency,isAutovalidate: isAutovalidate);
amountMinValidator = AmountMinValidator(
minValue: minValue,
isAutovalidate: isAutovalidate,
);
amountMaxValidator = AmountMaxValidator(
maxValue: maxValue,
isAutovalidate: isAutovalidate,
);
}
late final AmountMinValidator amountMinValidator;
late final AmountMaxValidator amountMaxValidator;
late final SymbolsAmountValidator symbolsAmountValidator;
late final DecimalAmountValidator decimalAmountValidator;
String? call(String? value) => symbolsAmountValidator(value) ?? decimalAmountValidator(value);
String? call(String? value) {
//* Validate for Text(length, symbols, decimals etc)
final textValidation = symbolsAmountValidator(value) ?? decimalAmountValidator(value);
//* Validate for Comparison(Value greater than min and less than )
final comparisonValidation = amountMinValidator(value) ?? amountMaxValidator(value);
return textValidation ?? comparisonValidation;
}
}
class SymbolsAmountValidator extends TextValidator {
@ -57,3 +85,71 @@ class AllAmountValidator extends TextValidator {
minLength: 0,
maxLength: 0);
}
class AmountMinValidator extends Validator<String> {
final String? minValue;
final bool isAutovalidate;
AmountMinValidator({
this.minValue,
required this.isAutovalidate,
}) : super(errorMessage: S.current.error_text_input_below_minimum_limit);
@override
bool isValid(String? value) {
if (value == null || value.isEmpty) {
return isAutovalidate ? true : false;
}
if (minValue == null || minValue == "null") {
return true;
}
final valueInDouble = parseToDouble(value);
final minInDouble = parseToDouble(minValue ?? '');
if (valueInDouble == null || minInDouble == null) {
return false;
}
return valueInDouble > minInDouble;
}
double? parseToDouble(String value) {
final data = double.tryParse(value.replaceAll(',', '.'));
return data;
}
}
class AmountMaxValidator extends Validator<String> {
final String? maxValue;
final bool isAutovalidate;
AmountMaxValidator({
this.maxValue,
required this.isAutovalidate,
}) : super(errorMessage: S.current.error_text_input_above_maximum_limit);
@override
bool isValid(String? value) {
if (value == null || value.isEmpty) {
return isAutovalidate ? true : false;
}
if (maxValue == null || maxValue == "null") {
return true;
}
final valueInDouble = parseToDouble(value);
final maxInDouble = parseToDouble(maxValue ?? '');
if (valueInDouble == null || maxInDouble == null) {
return false;
}
return valueInDouble < maxInDouble;
}
double? parseToDouble(String value) {
return double.tryParse(value.replaceAll(',', '.'));
}
}

View file

@ -456,8 +456,7 @@ class ExchangePage extends BasePage {
depositAmountController.addListener(() {
if (depositAmountController.text != exchangeViewModel.depositAmount) {
_depositAmountDebounce.run(() {
exchangeViewModel.changeDepositAmount(
amount: depositAmountController.text);
exchangeViewModel.changeDepositAmount(amount: depositAmountController.text);
exchangeViewModel.isReceiveAmountEntered = false;
});
}
@ -469,8 +468,7 @@ class ExchangePage extends BasePage {
receiveAmountController.addListener(() {
if (receiveAmountController.text != exchangeViewModel.receiveAmount) {
_receiveAmountDebounce.run(() {
exchangeViewModel.changeReceiveAmount(
amount: receiveAmountController.text);
exchangeViewModel.changeReceiveAmount(amount: receiveAmountController.text);
exchangeViewModel.isReceiveAmountEntered = true;
});
}
@ -626,8 +624,16 @@ class ExchangePage extends BasePage {
currencyButtonColor: Colors.transparent,
addressButtonsColor: Theme.of(context).focusColor!,
borderColor: Theme.of(context).primaryTextTheme!.bodyText1!.color!,
currencyValueValidator:
AmountValidator(currency: exchangeViewModel.depositCurrency),
currencyValueValidator: (value) {
return !exchangeViewModel.isFixedRateMode
? AmountValidator(
isAutovalidate: true,
currency: exchangeViewModel.depositCurrency,
minValue: exchangeViewModel.limits.min.toString(),
maxValue: exchangeViewModel.limits.max.toString(),
).call(value)
: null;
},
addressTextFieldValidator:
AddressValidator(type: exchangeViewModel.depositCurrency),
onPushPasteButton: (context) async {
@ -668,8 +674,16 @@ class ExchangePage extends BasePage {
addressButtonsColor: Theme.of(context).focusColor!,
borderColor:
Theme.of(context).primaryTextTheme!.bodyText1!.decorationColor!,
currencyValueValidator:
AmountValidator(currency: exchangeViewModel.receiveCurrency),
currencyValueValidator: (value) {
return exchangeViewModel.isFixedRateMode
? AmountValidator(
isAutovalidate: true,
currency: exchangeViewModel.receiveCurrency,
minValue: exchangeViewModel.limits.min.toString(),
maxValue: exchangeViewModel.limits.max.toString(),
).call(value)
: null;
},
addressTextFieldValidator:
AddressValidator(type: exchangeViewModel.receiveCurrency),
onPushPasteButton: (context) async {

View file

@ -198,6 +198,9 @@ abstract class ExchangeViewModelBase with Store {
@observable
bool isFixedRateMode;
@observable
Limits limits;
@computed
SyncStatus get status => wallet.syncStatus;
@ -241,8 +244,6 @@ abstract class ExchangeViewModelBase with Store {
List<CryptoCurrency> depositCurrencies;
Limits limits;
NumberFormat _cryptoNumberFormat;
final SettingsStore _settingsStore;
@ -320,6 +321,22 @@ abstract class ExchangeViewModelBase with Store {
.replaceAll(RegExp('\\,'), '');
}
bool checkIfInputMeetsMinOrMaxCondition(String input) {
final _enteredAmount = double.tryParse(input.replaceAll(',', '.')) ?? 0;
double minLimit = limits.min ?? 0;
double? maxLimit = limits.max;
if (_enteredAmount < minLimit) {
return false;
}
if (maxLimit != null && _enteredAmount > maxLimit) {
return false;
}
return true;
}
Future<void> _calculateBestRate() async {
final amount = double.tryParse(isFixedRateMode ? receiveAmount : depositAmount) ?? 1;

View file

@ -697,5 +697,7 @@
"onion_link": "رابط البصل",
"settings": "إعدادات",
"sell_monero_com_alert_content": "بيع Monero غير مدعوم حتى الآن",
"error_text_input_below_minimum_limit":" المبلغ أقل من الحد الأدنى",
"error_text_input_above_maximum_limit":"المبلغ أكبر من الحد الأقصى",
"show_market_place": "إظهار السوق"
}

View file

@ -698,5 +698,7 @@
"clearnet_link": "Clearnet връзка",
"onion_link": "Лукова връзка",
"sell_monero_com_alert_content": "Продажбата на Monero все още не се поддържа",
"error_text_input_below_minimum_limit" : "Сумата е по-малко от минималната",
"error_text_input_above_maximum_limit" : "Сумата надвишава максималната",
"show_market_place":"Покажи пазар"
}

View file

@ -698,5 +698,7 @@
"clearnet_link": "Odkaz na Clearnet",
"onion_link": "Cibulový odkaz",
"sell_monero_com_alert_content": "Prodej Monero zatím není podporován",
"error_text_input_below_minimum_limit" : "Částka je menší než minimální hodnota",
"error_text_input_above_maximum_limit" : "Částka je větší než maximální hodnota",
"show_market_place": "Zobrazit trh"
}

View file

@ -699,5 +699,7 @@
"onion_link": "Zwiebel-Link",
"settings": "Einstellungen",
"sell_monero_com_alert_content": "Der Verkauf von Monero wird noch nicht unterstützt",
"error_text_input_below_minimum_limit" : "Menge ist unter dem Minimum",
"error_text_input_above_maximum_limit" : "Menge ist über dem Maximum",
"show_market_place": "Marktplatz anzeigen"
}

View file

@ -699,5 +699,7 @@
"edit_node": "Edit Node",
"settings": "Settings",
"sell_monero_com_alert_content": "Selling Monero is not supported yet",
"error_text_input_below_minimum_limit" : "Amount is less than the minimum",
"error_text_input_above_maximum_limit" : "Amount is more than the maximum",
"show_market_place" :"Show Marketplace"
}

View file

@ -699,5 +699,7 @@
"onion_link": "Enlace de cebolla",
"settings": "Configuraciones",
"sell_monero_com_alert_content": "Aún no se admite la venta de Monero",
"error_text_input_below_minimum_limit" : "La cantidad es menos que mínima",
"error_text_input_above_maximum_limit" : "La cantidad es más que el máximo",
"show_market_place": "Mostrar mercado"
}

View file

@ -699,5 +699,7 @@
"settings": "Paramètres",
"onion_link": "Lien .onion",
"sell_monero_com_alert_content": "La vente de Monero n'est pas encore prise en charge",
"error_text_input_below_minimum_limit" : "Le montant est inférieur au minimum",
"error_text_input_above_maximum_limit" : "Le montant est supérieur au maximum",
"show_market_place" :"Afficher la place de marché"
}

View file

@ -699,5 +699,7 @@
"onion_link": "प्याज का लिंक",
"settings": "समायोजन",
"sell_monero_com_alert_content": "मोनेरो बेचना अभी तक समर्थित नहीं है",
"error_text_input_below_minimum_limit" : "राशि न्यूनतम से कम है",
"error_text_input_above_maximum_limit" : "राशि अधिकतम से अधिक है",
"show_market_place":"बाज़ार दिखाएँ"
}

View file

@ -699,5 +699,7 @@
"onion_link": "Poveznica luka",
"settings": "Postavke",
"sell_monero_com_alert_content": "Prodaja Monera još nije podržana",
"error_text_input_below_minimum_limit" : "Iznos je manji od minimalnog",
"error_text_input_above_maximum_limit" : "Iznos je veći od maskimalnog",
"show_market_place" : "Prikaži tržište"
}

View file

@ -680,5 +680,7 @@
"clearnet_link": "Tautan clearnet",
"onion_link": "Tautan bawang",
"sell_monero_com_alert_content": "Menjual Monero belum didukung",
"error_text_input_below_minimum_limit" : "Jumlah kurang dari minimal",
"error_text_input_above_maximum_limit" : "Jumlah lebih dari maksimal",
"show_market_place": "Tampilkan Pasar"
}

View file

@ -699,5 +699,7 @@
"onion_link": "Collegamento a cipolla",
"settings": "Impostazioni",
"sell_monero_com_alert_content": "La vendita di Monero non è ancora supportata",
"error_text_input_below_minimum_limit" : "L'ammontare è inferiore al minimo",
"error_text_input_above_maximum_limit" : "L'ammontare è superiore al massimo",
"show_market_place":"Mostra mercato"
}

View file

@ -699,5 +699,7 @@
"onion_link": "オニオンリンク",
"settings": "設定",
"sell_monero_com_alert_content": "モネロの販売はまだサポートされていません",
"error_text_input_below_minimum_limit" : "金額は最小額より少ない",
"error_text_input_above_maximum_limit" : "金額は最大値を超えています",
"show_market_place":"マーケットプレイスを表示"
}

View file

@ -699,5 +699,7 @@
"onion_link": "양파 링크",
"settings": "설정",
"sell_monero_com_alert_content": "지원되지 않습니다.",
"error_text_input_below_minimum_limit" : "금액이 최소보다 적습니다.",
"error_text_input_above_maximum_limit" : "금액이 최대 값보다 많습니다.",
"show_market_place":"마켓플레이스 표시"
}

View file

@ -699,5 +699,7 @@
"onion_link": "ကြက်သွန်လင့်",
"settings": "ဆက်တင်များ",
"sell_monero_com_alert_content": "Monero ရောင်းချခြင်းကို မပံ့ပိုးရသေးပါ။",
"error_text_input_below_minimum_limit" : "ပမာဏသည် အနိမ့်ဆုံးထက်နည်းသည်။",
"error_text_input_above_maximum_limit" : "ပမာဏသည် အများဆုံးထက် ပိုများသည်။",
"show_market_place":"စျေးကွက်ကိုပြသပါ။"
}

View file

@ -699,5 +699,7 @@
"onion_link": "Ui koppeling",
"settings": "Instellingen",
"sell_monero_com_alert_content": "Het verkopen van Monero wordt nog niet ondersteund",
"error_text_input_below_minimum_limit" : "Bedrag is minder dan minimaal",
"error_text_input_above_maximum_limit" : "Bedrag is meer dan maximaal",
"show_market_place":"Toon Marktplaats"
}

View file

@ -699,5 +699,7 @@
"onion_link": "Łącznik cebulowy",
"settings": "Ustawienia",
"sell_monero_com_alert_content": "Sprzedaż Monero nie jest jeszcze obsługiwana",
"error_text_input_below_minimum_limit" : "Kwota jest mniejsza niż minimalna",
"error_text_input_above_maximum_limit" : "Kwota jest większa niż maksymalna",
"show_market_place" : "Pokaż rynek"
}

View file

@ -698,5 +698,7 @@
"onion_link": "ligação de cebola",
"settings": "Configurações",
"sell_monero_com_alert_content": "A venda de Monero ainda não é suportada",
"error_text_input_below_minimum_limit" : "O valor é menor que o mínimo",
"error_text_input_above_maximum_limit" : "O valor é superior ao máximo",
"show_market_place":"Mostrar mercado"
}

View file

@ -699,5 +699,7 @@
"onion_link": "Луковая ссылка",
"settings": "Настройки",
"sell_monero_com_alert_content": "Продажа Monero пока не поддерживается",
"error_text_input_below_minimum_limit" : "Сумма меньше минимальной",
"error_text_input_above_maximum_limit" : "Сумма больше максимальной",
"show_market_place":"Показать торговую площадку"
}

View file

@ -697,5 +697,7 @@
"onion_link": "ลิงค์หัวหอม",
"settings": "การตั้งค่า",
"sell_monero_com_alert_content": "ยังไม่รองรับการขาย Monero",
"error_text_input_below_minimum_limit" : "จำนวนเงินน้อยกว่าขั้นต่ำ",
"error_text_input_above_maximum_limit" : "จำนวนเงินสูงกว่าค่าสูงสุด",
"show_market_place":"แสดงตลาดกลาง"
}

View file

@ -699,5 +699,7 @@
"onion_link": "soğan bağlantısı",
"settings": "ayarlar",
"sell_monero_com_alert_content": "Monero satışı henüz desteklenmiyor",
"error_text_input_below_minimum_limit" : "Miktar minimumdan daha azdır",
"error_text_input_above_maximum_limit" : "Miktar maksimumdan daha fazla",
"show_market_place":"Pazar Yerini Göster"
}

View file

@ -698,5 +698,7 @@
"onion_link": "Посилання на цибулю",
"settings": "Налаштування",
"sell_monero_com_alert_content": "Продаж Monero ще не підтримується",
"error_text_input_below_minimum_limit" : "Сума менша мінімальної",
"error_text_input_above_maximum_limit" : "Сума більше максимальної",
"show_market_place":"Шоу Ринок"
}

View file

@ -699,5 +699,7 @@
"clearnet_link": "کلیرنیٹ لنک",
"onion_link": "پیاز کا لنک",
"sell_monero_com_alert_content": "Monero فروخت کرنا ابھی تک تعاون یافتہ نہیں ہے۔",
"error_text_input_below_minimum_limit" : "رقم کم از کم سے کم ہے۔",
"error_text_input_above_maximum_limit" : "رقم زیادہ سے زیادہ سے زیادہ ہے۔",
"show_market_place":"بازار دکھائیں۔"
}

View file

@ -698,5 +698,7 @@
"onion_link": "洋葱链接",
"settings": "设置",
"sell_monero_com_alert_content": "尚不支持出售门罗币",
"error_text_input_below_minimum_limit" : "金额小于最小值",
"error_text_input_above_maximum_limit" : "金额大于最大值",
"show_market_place" :"显示市场"
}