dev
dart 105 lines 3.4 KB
Raw
1 import 'package:cake_wallet/core/address_resolver/unstoppable/unstoppable_address_provider.dart';
2 import 'package:cake_wallet/core/address_validator.dart';
3 import 'package:cw_core/crypto_currency.dart';
4 import 'package:cw_core/utils/print_verbose.dart';
5
6 class AddressResolverUtils {
7 static Future<Map<CryptoCurrency, String>> resolveUnstoppableDomainFromText({
8 required String raw,
9 required List<CryptoCurrency> currencies,
10 }) async {
11 final domain = extractUnstoppableDomain(raw);
12 if (domain.isEmpty) return {};
13
14 final result = <CryptoCurrency, String>{};
15
16 for (final currency in currencies) {
17 final address =
18 await UnstoppableAddressProvider.fetchUnstoppableDomainAddress(domain, currency.title);
19 if (address.isNotEmpty) {
20 result[currency] = address;
21 }
22 }
23
24 return result;
25 }
26
27 static String extractUnstoppableDomain(String raw) {
28 // sort by length to avoid matching shorter tld instead of longer
29 final domains = List<String>.from(UnstoppableAddressProvider.unstoppableDomains)
30 ..sort((a, b) => b.length.compareTo(a.length));
31 for (final tld in domains) {
32 final pattern = RegExp(r'([A-Za-z0-9-]+)\.' + RegExp.escape(tld), caseSensitive: false);
33 final match = pattern.firstMatch(raw);
34 if (match != null) return match.group(0)!;
35 }
36 return '';
37 }
38
39 static Map<CryptoCurrency, String> extractAddressesFromText({
40 required String raw,
41 required List<CryptoCurrency> currencies,
42 bool requireSurroundingWhitespaces = true,
43 }) {
44 final result = <CryptoCurrency, String>{};
45 var text = raw;
46
47 for (final currency in currencies) {
48 final address = extractAddressByType(
49 raw: text,
50 type: currency,
51 requireSurroundingWhitespaces: requireSurroundingWhitespaces,
52 );
53
54 if (address != null && address.isNotEmpty) {
55 result[currency] = address;
56 text = text.replaceFirst(address, '');
57 }
58 }
59
60 return result;
61 }
62
63 static String? extractAddressByType({
64 required String raw,
65 required CryptoCurrency type,
66 bool requireSurroundingWhitespaces = true,
67 }) {
68 var addressPattern = AddressValidator.getAddressFromStringPattern(type);
69 if (addressPattern == null) {
70 printV('Unknown pattern for $type');
71 return null;
72 }
73 if (requireSurroundingWhitespaces) addressPattern = "$BEFORE_REGEX$addressPattern$AFTER_REGEX";
74 final text = stripHtmlTags(raw);
75 final match = RegExp(addressPattern, multiLine: true, caseSensitive: false).firstMatch(text);
76 if (match == null) return null;
77 return match.group(0)?.replaceAllMapped(RegExp('[^0-9a-zA-Z]|bitcoincash:|nano_|ban_'),
78 (Match match) {
79 String group = match.group(0)!;
80 if (group.startsWith('bitcoincash:') ||
81 group.startsWith('nano_') ||
82 group.startsWith('ban_')) {
83 return group;
84 }
85 return '';
86 });
87 }
88
89 static bool isEmailFormat(String address) {
90 final RegExp emailRegex = RegExp(
91 r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$',
92 caseSensitive: false,
93 );
94 return emailRegex.hasMatch(address);
95 }
96
97 static String stripHtmlTags(String value) {
98 return value
99 .replaceAll(RegExp(r'[\u2028\u2029]'), '\n')
100 .replaceAll(RegExp(r'<br\s*/?>', caseSensitive: false), '\n')
101 .replaceAll(RegExp(r'</p\s*>', caseSensitive: false), '\n')
102 .replaceAll(RegExp(r'<[^>]*>'), ' ')
103 .trim();
104 }
105 }