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
Rafael Saes committed
May 15, 2023 at 09:39 UTC
0231298381ac6ca739ba773ffd41407e682c8761
3 files changed
+46
-23
lib/core/address_validator.dart
+8
-6
@@ -1,4 +1,4 @@
1
-import 'package:flutter/foundation.dart';
1
+import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin;
2
import 'package:cake_wallet/generated/i18n.dart';
3
import 'package:cake_wallet/core/validator.dart';
4
import 'package:cw_core/crypto_currency.dart';
@@ -7,6 +7,9 @@ class AddressValidator extends TextValidator {
7
AddressValidator({required CryptoCurrency type})
8
: super(
9
errorMessage: S.current.error_text_address,
10
+ useAdditionalValidation: type == CryptoCurrency.btc
11
+ ? bitcoin.Address.validateAddress
12
+ : null,
13
pattern: getPattern(type),
14
length: getLength(type));
15
@@ -18,8 +21,7 @@ class AddressValidator extends TextValidator {
21
return '^[0-9a-zA-Z]{59}\$|^[0-9a-zA-Z]{92}\$|^[0-9a-zA-Z]{104}\$'
22
'|^[0-9a-zA-Z]{105}\$|^addr1[0-9a-zA-Z]{98}\$';
23
case CryptoCurrency.btc:
21
- return '^1[0-9a-zA-Z]{32}\$|^1[0-9a-zA-Z]{33}\$|^3[0-9a-zA-Z]{32}\$'
22
- '|^3[0-9a-zA-Z]{33}\$|^bc1[0-9a-zA-Z]{39}\$|^bc1[0-9a-zA-Z]{59}\$';
24
+ return '^3[0-9a-zA-Z]{32}\$|^3[0-9a-zA-Z]{33}\$|^bc1[0-9a-zA-Z]{59}\$';
25
case CryptoCurrency.nano:
26
return '[0-9a-zA-Z_]';
27
case CryptoCurrency.usdc:
@@ -63,7 +65,7 @@ class AddressValidator extends TextValidator {
65
case CryptoCurrency.bch:
66
case CryptoCurrency.bnb:
67
return '[0-9a-zA-Z]';
66
- case CryptoCurrency.hbar:
68
+ case CryptoCurrency.hbar:
69
return '[0-9a-zA-Z.]';
70
case CryptoCurrency.zaddr:
71
return '^zs[0-9a-zA-Z]{75}';
@@ -165,9 +167,9 @@ class AddressValidator extends TextValidator {
167
return [34];
168
case CryptoCurrency.hbar:
169
return [4, 5, 6, 7, 8, 9, 10, 11];
168
- case CryptoCurrency.xvg:
170
+ case CryptoCurrency.xvg:
171
return [34];
170
- case CryptoCurrency.zen:
172
+ case CryptoCurrency.zen:
173
return [35];
174
case CryptoCurrency.zaddr:
175
return null;
lib/core/validator.dart
+34
-17
@@ -1,24 +1,26 @@
1
-import 'package:flutter/foundation.dart';
2
-
1
abstract class Validator<T> {
4
- Validator({required this.errorMessage});
2
+ Validator({required this.errorMessage, this.useAdditionalValidation});
3
4
final String errorMessage;
5
+ final bool Function(T)? useAdditionalValidation;
6
7
bool isValid(T? value);
8
10
- String? call(T? value) => !isValid(value) ? errorMessage : null;
9
+ String? call(T? value) => !isValid(value) ? errorMessage : null;
10
}
11
12
class TextValidator extends Validator<String> {
14
- TextValidator(
15
- {this.minLength,
16
- this.maxLength,
17
- this.pattern,
18
- String errorMessage = '',
19
- this.length,
20
- this.isAutovalidate = false})
21
- : super(errorMessage: errorMessage);
13
+ TextValidator({
14
+ bool Function(String)? useAdditionalValidation,
15
+ this.minLength,
16
+ this.maxLength,
17
+ this.pattern,
18
+ String errorMessage = '',
19
+ this.length,
20
+ this.isAutovalidate = false,
21
+ }) : super(
22
+ errorMessage: errorMessage,
23
+ useAdditionalValidation: useAdditionalValidation);
24
25
final int? minLength;
26
final int? maxLength;
@@ -32,11 +34,26 @@ class TextValidator extends Validator<String> {
34
return isAutovalidate ? true : false;
35
}
36
35
- return value.length > (minLength ?? 0) &&
36
- (length?.contains(value.length) ?? true) &&
37
- ((maxLength ?? 0) > 0 ? (value.length <= maxLength!) : true) &&
38
- (pattern != null ? match(value) : true);
37
+ final greaterThanMinLength = value.length > (minLength ?? 0);
38
+ if (!greaterThanMinLength) return false;
39
+
40
+ final lengthMatched = length?.contains(value.length) ?? true;
41
+ if (!lengthMatched) return false;
42
+
43
+ final lowerThanMaxLength =
44
+ (maxLength ?? 0) > 0 ? (value.length <= maxLength!) : true;
45
+ if (!lowerThanMaxLength) return false;
46
+
47
+ if (pattern == null) return true;
48
+
49
+ final valueMatched = match(value);
50
+ final valueValidated = useAdditionalValidation != null
51
+ ? useAdditionalValidation!(value) || valueMatched
52
+ : valueMatched;
53
+
54
+ return valueValidated;
55
}
56
41
- bool match(String value) => pattern != null ? RegExp(pattern!).hasMatch(value) : false;
57
+ bool match(String value) =>
58
+ pattern != null ? RegExp(pattern!).hasMatch(value) : false;
59
}
pubspec_base.yaml
+4
@@ -81,6 +81,10 @@ dependencies:
81
path_provider_android: 2.0.24
82
shared_preferences_android: 2.0.17
83
url_launcher_android: 6.0.24
84
+ bitcoin_flutter:
85
+ git:
86
+ url: https://github.com/cake-tech/bitcoin_flutter.git
87
+ ref: cake-update-v2
88
89
dev_dependencies:
90
flutter_test: