From 0231298381ac6ca739ba773ffd41407e682c8761 Mon Sep 17 00:00:00 2001 From: Rafael Saes <76502841+saltrafael@users.noreply.github.com> Date: Mon, 15 May 2023 09:39:00 -0300 Subject: [PATCH] CW-254-proper-bitcoin-address-validation-in-exchange-screen (#900) * feat: Proper Bitcoin address validation in exchange screen * fix: use custom validation in addition to RegEx to make sure all address cases are validated - for cases like P2SH addresses starting with a 3, which are not validated by bitcoin_flutter functions * feat: add bitcoin_flutter to root project * refactor: improve conditional isValid return chain --- lib/core/address_validator.dart | 14 +++++---- lib/core/validator.dart | 51 ++++++++++++++++++++++----------- pubspec_base.yaml | 4 +++ 3 files changed, 46 insertions(+), 23 deletions(-) diff --git a/lib/core/address_validator.dart b/lib/core/address_validator.dart index 0bed0611c..57318254a 100644 --- a/lib/core/address_validator.dart +++ b/lib/core/address_validator.dart @@ -1,4 +1,4 @@ -import 'package:flutter/foundation.dart'; +import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/core/validator.dart'; import 'package:cw_core/crypto_currency.dart'; @@ -7,6 +7,9 @@ class AddressValidator extends TextValidator { AddressValidator({required CryptoCurrency type}) : super( errorMessage: S.current.error_text_address, + useAdditionalValidation: type == CryptoCurrency.btc + ? bitcoin.Address.validateAddress + : null, pattern: getPattern(type), length: getLength(type)); @@ -18,8 +21,7 @@ class AddressValidator extends TextValidator { return '^[0-9a-zA-Z]{59}\$|^[0-9a-zA-Z]{92}\$|^[0-9a-zA-Z]{104}\$' '|^[0-9a-zA-Z]{105}\$|^addr1[0-9a-zA-Z]{98}\$'; case CryptoCurrency.btc: - return '^1[0-9a-zA-Z]{32}\$|^1[0-9a-zA-Z]{33}\$|^3[0-9a-zA-Z]{32}\$' - '|^3[0-9a-zA-Z]{33}\$|^bc1[0-9a-zA-Z]{39}\$|^bc1[0-9a-zA-Z]{59}\$'; + return '^3[0-9a-zA-Z]{32}\$|^3[0-9a-zA-Z]{33}\$|^bc1[0-9a-zA-Z]{59}\$'; case CryptoCurrency.nano: return '[0-9a-zA-Z_]'; case CryptoCurrency.usdc: @@ -63,7 +65,7 @@ class AddressValidator extends TextValidator { case CryptoCurrency.bch: case CryptoCurrency.bnb: return '[0-9a-zA-Z]'; - case CryptoCurrency.hbar: + case CryptoCurrency.hbar: return '[0-9a-zA-Z.]'; case CryptoCurrency.zaddr: return '^zs[0-9a-zA-Z]{75}'; @@ -165,9 +167,9 @@ class AddressValidator extends TextValidator { return [34]; case CryptoCurrency.hbar: return [4, 5, 6, 7, 8, 9, 10, 11]; - case CryptoCurrency.xvg: + case CryptoCurrency.xvg: return [34]; - case CryptoCurrency.zen: + case CryptoCurrency.zen: return [35]; case CryptoCurrency.zaddr: return null; diff --git a/lib/core/validator.dart b/lib/core/validator.dart index 96c382b7d..34e985991 100644 --- a/lib/core/validator.dart +++ b/lib/core/validator.dart @@ -1,24 +1,26 @@ -import 'package:flutter/foundation.dart'; - abstract class Validator { - Validator({required this.errorMessage}); + Validator({required this.errorMessage, this.useAdditionalValidation}); final String errorMessage; + final bool Function(T)? useAdditionalValidation; bool isValid(T? value); - String? call(T? value) => !isValid(value) ? errorMessage : null; + String? call(T? value) => !isValid(value) ? errorMessage : null; } class TextValidator extends Validator { - TextValidator( - {this.minLength, - this.maxLength, - this.pattern, - String errorMessage = '', - this.length, - this.isAutovalidate = false}) - : super(errorMessage: errorMessage); + TextValidator({ + bool Function(String)? useAdditionalValidation, + this.minLength, + this.maxLength, + this.pattern, + String errorMessage = '', + this.length, + this.isAutovalidate = false, + }) : super( + errorMessage: errorMessage, + useAdditionalValidation: useAdditionalValidation); final int? minLength; final int? maxLength; @@ -32,11 +34,26 @@ class TextValidator extends Validator { return isAutovalidate ? true : false; } - return value.length > (minLength ?? 0) && - (length?.contains(value.length) ?? true) && - ((maxLength ?? 0) > 0 ? (value.length <= maxLength!) : true) && - (pattern != null ? match(value) : true); + final greaterThanMinLength = value.length > (minLength ?? 0); + if (!greaterThanMinLength) return false; + + final lengthMatched = length?.contains(value.length) ?? true; + if (!lengthMatched) return false; + + final lowerThanMaxLength = + (maxLength ?? 0) > 0 ? (value.length <= maxLength!) : true; + if (!lowerThanMaxLength) return false; + + if (pattern == null) return true; + + final valueMatched = match(value); + final valueValidated = useAdditionalValidation != null + ? useAdditionalValidation!(value) || valueMatched + : valueMatched; + + return valueValidated; } - bool match(String value) => pattern != null ? RegExp(pattern!).hasMatch(value) : false; + bool match(String value) => + pattern != null ? RegExp(pattern!).hasMatch(value) : false; } diff --git a/pubspec_base.yaml b/pubspec_base.yaml index ebe276a54..8c25bd80c 100644 --- a/pubspec_base.yaml +++ b/pubspec_base.yaml @@ -81,6 +81,10 @@ dependencies: path_provider_android: 2.0.24 shared_preferences_android: 2.0.17 url_launcher_android: 6.0.24 + bitcoin_flutter: + git: + url: https://github.com/cake-tech/bitcoin_flutter.git + ref: cake-update-v2 dev_dependencies: flutter_test: