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
This commit is contained in:
Rafael Saes 2023-05-15 09:39:00 -03:00 committed by GitHub
parent 7fa7c45c0c
commit 0231298381
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 46 additions and 23 deletions

View file

@ -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;

View file

@ -1,24 +1,26 @@
import 'package:flutter/foundation.dart';
abstract class Validator<T> {
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<String> {
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<String> {
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;
}

View file

@ -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: