diff --git a/lib/generated/i18n.dart b/lib/generated/i18n.dart index 751fb13af..d99174a72 100644 --- a/lib/generated/i18n.dart +++ b/lib/generated/i18n.dart @@ -102,6 +102,7 @@ class S implements WidgetsLocalizations { String get nodes_list_reset_to_default_message => "Are you sure that you want to reset settings to default?"; String get offer_expires_in => "Offer expires in: "; String get ok => "OK"; + String get openalias_alert_title => "XMR Recipient Detected"; String get outgoing => "Outgoing"; String get password => "Password"; String get paste => "Paste"; @@ -280,6 +281,7 @@ class S implements WidgetsLocalizations { String failed_authentication(String state_error) => "Failed authentication. ${state_error}"; String max_value(String value, String currency) => "Max: ${value} ${currency}"; String min_value(String value, String currency) => "Min: ${value} ${currency}"; + String openalias_alert_content(String recipient_name) => "You will be sending funds to\n${recipient_name}"; String powered_by(String title) => "Powered by ${title}"; String router_no_route(String name) => "No route defined for ${name}"; String send_priority(String transactionPriority) => "Currently the fee is set at ${transactionPriority} priority.\nTransaction priority can be adjusted in the settings"; @@ -436,6 +438,8 @@ class $de extends S { @override String get contact => "Kontakt"; @override + String get openalias_alert_title => "XMR-Empfänger erkannt"; + @override String get auth_store_incorrect_password => "Falsches PIN"; @override String get transaction_priority_slow => "Schleppend"; @@ -844,6 +848,8 @@ class $de extends S { @override String commit_transaction_amount_fee(String amount, String fee) => "Transaktion festschreiben\nMenge: ${amount}\nGebühr: ${fee}"; @override + String openalias_alert_content(String recipient_name) => "Sie senden Geld an\n${recipient_name}"; + @override String wallet_list_failed_to_remove(String wallet_name, String error) => "Fehler beim Entfernen ${wallet_name} Wallet. ${error}"; @override String copied_key_to_clipboard(String key) => "Kopiert ${key} Zur Zwischenablage"; @@ -992,6 +998,8 @@ class $hi extends S { @override String get contact => "संपर्क करें"; @override + String get openalias_alert_title => "XMR प्राप्तकर्ता का पता लगाया"; + @override String get auth_store_incorrect_password => "गलत पिन"; @override String get transaction_priority_slow => "धीरे"; @@ -1400,6 +1408,8 @@ class $hi extends S { @override String commit_transaction_amount_fee(String amount, String fee) => "लेन-देन करें\nरकम: ${amount}\nशुल्क: ${fee}"; @override + String openalias_alert_content(String recipient_name) => "आपको धनराशि भेजी जाएगी\n${recipient_name}"; + @override String wallet_list_failed_to_remove(String wallet_name, String error) => "निकालने में विफल ${wallet_name} बटुआ. ${error}"; @override String copied_key_to_clipboard(String key) => "की नकल की ${key} क्लिपबोर्ड पर"; @@ -1548,6 +1558,8 @@ class $ru extends S { @override String get contact => "Контакт"; @override + String get openalias_alert_title => "Получатель XMR обнаружен"; + @override String get auth_store_incorrect_password => "Некорректный пин"; @override String get transaction_priority_slow => "Медленный"; @@ -1956,6 +1968,8 @@ class $ru extends S { @override String commit_transaction_amount_fee(String amount, String fee) => "Подтвердить транзакцию \nСумма: ${amount}\nСбор: ${fee}"; @override + String openalias_alert_content(String recipient_name) => "Вы будете отправлять средства\n${recipient_name}"; + @override String wallet_list_failed_to_remove(String wallet_name, String error) => "Ошибка при удалении ${wallet_name} кошелька. ${error}"; @override String copied_key_to_clipboard(String key) => "Скопировано ${key} в буфер обмена"; @@ -2104,6 +2118,8 @@ class $ko extends S { @override String get contact => "접촉"; @override + String get openalias_alert_title => "XMR 수신자 감지"; + @override String get auth_store_incorrect_password => "잘못된 PIN"; @override String get transaction_priority_slow => "느린"; @@ -2512,6 +2528,8 @@ class $ko extends S { @override String commit_transaction_amount_fee(String amount, String fee) => "커밋 거래\n양: ${amount}\n보수: ${fee}"; @override + String openalias_alert_content(String recipient_name) => "당신은에 자금을 보낼 것입니다\n${recipient_name}"; + @override String wallet_list_failed_to_remove(String wallet_name, String error) => "제거하지 못했습니다 ${wallet_name} 지갑. ${error}"; @override String copied_key_to_clipboard(String key) => "복사 ${key} 클립 보드로"; @@ -2660,6 +2678,8 @@ class $pt extends S { @override String get contact => "Contato"; @override + String get openalias_alert_title => "Destinatário XMR detectado"; + @override String get auth_store_incorrect_password => "PIN incorreto"; @override String get transaction_priority_slow => "Lenta"; @@ -3068,6 +3088,8 @@ class $pt extends S { @override String commit_transaction_amount_fee(String amount, String fee) => "Confirmar transação\nQuantia: ${amount}\nTaxa: ${fee}"; @override + String openalias_alert_content(String recipient_name) => "Você enviará fundos para\n${recipient_name}"; + @override String wallet_list_failed_to_remove(String wallet_name, String error) => "Falha ao remover a carteira ${wallet_name}. ${error}"; @override String copied_key_to_clipboard(String key) => "${key} copiada para a área de transferência"; @@ -3216,6 +3238,8 @@ class $ja extends S { @override String get contact => "接触"; @override + String get openalias_alert_title => "XMR受信者が検出されました"; + @override String get auth_store_incorrect_password => "間違ったPIN"; @override String get transaction_priority_slow => "スロー"; @@ -3624,6 +3648,8 @@ class $ja extends S { @override String commit_transaction_amount_fee(String amount, String fee) => "トランザクションをコミット\n量: ${amount}\n費用: ${fee}"; @override + String openalias_alert_content(String recipient_name) => "に送金します\n${recipient_name}"; + @override String wallet_list_failed_to_remove(String wallet_name, String error) => "削除できませんでした ${wallet_name} 財布. ${error}"; @override String copied_key_to_clipboard(String key) => "コピー済み ${key} クリップボードへ"; @@ -3776,6 +3802,8 @@ class $pl extends S { @override String get contact => "Kontakt"; @override + String get openalias_alert_title => "Wykryto odbiorcę XMR"; + @override String get auth_store_incorrect_password => "Niepoprawny PIN"; @override String get transaction_priority_slow => "Powolny"; @@ -4184,6 +4212,8 @@ class $pl extends S { @override String commit_transaction_amount_fee(String amount, String fee) => "Zatwierdź transakcję\nIlość: ${amount}\nOpłata: ${fee}"; @override + String openalias_alert_content(String recipient_name) => "Będziesz wysyłać środki na\n${recipient_name}"; + @override String wallet_list_failed_to_remove(String wallet_name, String error) => "Nie udało się usunąć ${wallet_name} portfel. ${error}"; @override String copied_key_to_clipboard(String key) => "Skopiowane ${key} do schowka"; @@ -4332,6 +4362,8 @@ class $es extends S { @override String get contact => "Contacto"; @override + String get openalias_alert_title => "Destinatario XMR detectado"; + @override String get auth_store_incorrect_password => "Contraseña PIN"; @override String get transaction_priority_slow => "Lento"; @@ -4740,6 +4772,8 @@ class $es extends S { @override String commit_transaction_amount_fee(String amount, String fee) => "Confirmar transacción\nCantidad: ${amount}\nCuota: ${fee}"; @override + String openalias_alert_content(String recipient_name) => "Enviará fondos a\n${recipient_name}"; + @override String wallet_list_failed_to_remove(String wallet_name, String error) => "Error al elimina ${wallet_name} billetera. ${error}"; @override String copied_key_to_clipboard(String key) => "Copiado ${key} al portapapeles"; @@ -4888,6 +4922,8 @@ class $nl extends S { @override String get contact => "Contact"; @override + String get openalias_alert_title => "XMR-ontvanger gedetecteerd"; + @override String get auth_store_incorrect_password => "Incorrect PIN"; @override String get transaction_priority_slow => "Langzaam"; @@ -5296,6 +5332,8 @@ class $nl extends S { @override String commit_transaction_amount_fee(String amount, String fee) => "Verricht transactie\nBedrag: ${amount}\nhonorarium: ${fee}"; @override + String openalias_alert_content(String recipient_name) => "U stuurt geld naar\n${recipient_name}"; + @override String wallet_list_failed_to_remove(String wallet_name, String error) => "Verwijderen mislukt ${wallet_name} portemonnee. ${error}"; @override String copied_key_to_clipboard(String key) => "Gekopieerd ${key} naar het klembord"; @@ -5444,6 +5482,8 @@ class $zh extends S { @override String get contact => "联系"; @override + String get openalias_alert_title => "檢測到XMR收件人"; + @override String get auth_store_incorrect_password => "PIN码错误"; @override String get transaction_priority_slow => "慢"; @@ -5852,6 +5892,8 @@ class $zh extends S { @override String commit_transaction_amount_fee(String amount, String fee) => "提交交易\n量: ${amount}\nFee: ${fee}"; @override + String openalias_alert_content(String recipient_name) => "您將匯款至\n${recipient_name}"; + @override String wallet_list_failed_to_remove(String wallet_name, String error) => "删除失败 ${wallet_name} 钱包. ${error}"; @override String copied_key_to_clipboard(String key) => "复制 ${key} 到剪贴板"; diff --git a/lib/src/domain/common/openalias_record.dart b/lib/src/domain/common/openalias_record.dart new file mode 100644 index 000000000..cb659d533 --- /dev/null +++ b/lib/src/domain/common/openalias_record.dart @@ -0,0 +1,62 @@ +import 'package:basic_utils/basic_utils.dart'; + +class OpenaliasRecord { + + OpenaliasRecord({this.address, this.name}); + + final String name; + final String address; + + static String formatDomainName(String name) { + String formattedName = name; + + if (name.contains("@")) { + formattedName = name.replaceAll("@", "."); + } + + return formattedName; + } + + static Future fetchAddressAndName(String formattedName) async { + String address = formattedName; + String name = formattedName; + + if (formattedName.contains(".")) { + try { + final txtRecord = await DnsUtils.lookupRecord(formattedName, RRecordType.TXT, dnssec: true); + + if (txtRecord != null) { + + for (RRecord element in txtRecord) { + String record = element.data; + + if (record.contains("oa1:xmr") && record.contains("recipient_address")) { + record = record.replaceAll('\"', ""); + + final dataList = record.split(";"); + + address = dataList.where((item) => (item.contains("recipient_address"))) + .toString().replaceAll("oa1:xmr recipient_address=", "") + .replaceAll("(", "").replaceAll(")", "").trim(); + + final recipientName = dataList.where((item) => (item.contains("recipient_name"))).toString() + .replaceAll("(", "").replaceAll(")", "").trim(); + + if (recipientName.isNotEmpty) { + name = recipientName.replaceAll("recipient_name=", ""); + } + + break; + } + } + } + } catch (e) { + print("${e.toString()}"); + } + } + + return OpenaliasRecord(address: address, name: name); + } + +} + diff --git a/lib/src/screens/send/send_page.dart b/lib/src/screens/send/send_page.dart index f8fe0bbda..07394e97d 100644 --- a/lib/src/screens/send/send_page.dart +++ b/lib/src/screens/send/send_page.dart @@ -48,10 +48,46 @@ class SendFormState extends State { final _cryptoAmountController = TextEditingController(); final _fiatAmountController = TextEditingController(); + final _focusNode = FocusNode(); + bool _effectsInstalled = false; final _formKey = GlobalKey(); + @override + void initState() { + _focusNode.addListener(() { + if (!_focusNode.hasFocus &&_addressController.text.isNotEmpty) { + getOpenaliasRecord(context); + } + }); + + super.initState(); + } + + Future getOpenaliasRecord(BuildContext context) async { + final sendStore = Provider.of(context); + final isOpenalias = await sendStore.isOpenaliasRecord(_addressController.text); + + if (isOpenalias) { + _addressController.text = sendStore.recordAddress; + + await showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + title: Text(S.of(context).openalias_alert_title), + content: Text(S.of(context).openalias_alert_content(sendStore.recordName)), + actions: [ + FlatButton( + child: Text(S.of(context).ok), + onPressed: () => Navigator.of(context).pop()) + ], + ); + }); + } + } + @override Widget build(BuildContext context) { final settingsStore = Provider.of(context); @@ -150,6 +186,7 @@ class SendFormState extends State { AddressTextField( controller: _addressController, placeholder: S.of(context).send_monero_address, + focusNode: _focusNode, onURIScanned: (uri) { var address = ''; var amount = ''; diff --git a/lib/src/stores/send/send_store.dart b/lib/src/stores/send/send_store.dart index dbad353c4..5f0df3541 100644 --- a/lib/src/stores/send/send_store.dart +++ b/lib/src/stores/send/send_store.dart @@ -11,6 +11,7 @@ import 'package:cake_wallet/src/stores/price/price_store.dart'; import 'package:cake_wallet/src/stores/send/sending_state.dart'; import 'package:cake_wallet/src/stores/settings/settings_store.dart'; import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/src/domain/common/openalias_record.dart'; part 'send_store.g.dart'; @@ -32,6 +33,8 @@ abstract class SendStoreBase with Store { SettingsStore settingsStore; PriceStore priceStore; Box transactionDescriptions; + String recordName; + String recordAddress; @observable SendingState state; @@ -154,6 +157,16 @@ abstract class SendStoreBase with Store { } } + Future isOpenaliasRecord(String name) async { + final _openaliasRecord = await OpenaliasRecord + .fetchAddressAndName(OpenaliasRecord.formatDomainName(name)); + + recordAddress = _openaliasRecord.address; + recordName = _openaliasRecord.name; + + return recordAddress != name; + } + void validateAddress(String value, {CryptoCurrency cryptoCurrency}) { // XMR (95, 106), ADA (59, 92, 105), BCH (42), BNB (42), BTC (34, 42), DASH (34), EOS (42), // ETH (42), LTC (34), NANO (64, 65), TRX (34), USDT (42), XLM (56), XRP (34) diff --git a/lib/src/widgets/address_text_field.dart b/lib/src/widgets/address_text_field.dart index c457ee485..a13132e55 100644 --- a/lib/src/widgets/address_text_field.dart +++ b/lib/src/widgets/address_text_field.dart @@ -18,6 +18,7 @@ class AddressTextField extends StatelessWidget { AddressTextFieldOption.addressBook ], this.onURIScanned, + this.focusNode, this.validator}); static const prefixIconWidth = 34.0; @@ -30,6 +31,7 @@ class AddressTextField extends StatelessWidget { final Function(Uri) onURIScanned; final List options; final FormFieldValidator validator; + FocusNode focusNode; @override Widget build(BuildContext context) { @@ -37,6 +39,7 @@ class AddressTextField extends StatelessWidget { onFieldSubmitted: (_) => FocusScope.of(context).unfocus(), enabled: isActive, controller: controller, + focusNode: focusNode, decoration: InputDecoration( suffixIcon: SizedBox( width: prefixIconWidth * options.length + diff --git a/pubspec.lock b/pubspec.lock index ab6b8a29d..5c7088d15 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -43,6 +43,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.0.0" + basic_utils: + dependency: "direct main" + description: + name: basic_utils + url: "https://pub.dartlang.org" + source: hosted + version: "1.9.3" boolean_selector: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 318057f0c..58f13a7f5 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -53,6 +53,7 @@ dependencies: cupertino_icons: ^0.1.2 encrypt: ^4.0.0 password: ^1.0.0 + basic_utils: ^1.0.8 dev_dependencies: flutter_test: diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index 2dc78e7c7..c703b0a48 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -342,5 +342,8 @@ "incorrect_seed" : "Der eingegebene Text ist ungültig.", "biometric_auth_reason" : "Scannen Sie Ihren Fingerabdruck zur Authentifizierung", - "version" : "Ausführung ${currentVersion}" + "version" : "Ausführung ${currentVersion}", + + "openalias_alert_title" : "XMR-Empfänger erkannt", + "openalias_alert_content" : "Sie senden Geld an\n${recipient_name}" } \ No newline at end of file diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index 5d8b88eda..861ac43f1 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -342,5 +342,8 @@ "incorrect_seed" : "The text entered is not valid.", "biometric_auth_reason" : "Scan your fingerprint to authenticate", - "version" : "Version ${currentVersion}" + "version" : "Version ${currentVersion}", + + "openalias_alert_title" : "XMR Recipient Detected", + "openalias_alert_content" : "You will be sending funds to\n${recipient_name}" } \ No newline at end of file diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 308833a1a..ef9b83950 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -342,5 +342,8 @@ "incorrect_seed" : "El texto ingresado no es válido.", "biometric_auth_reason" : "Escanee su huella digital para autenticar", - "version" : "Versión ${currentVersion}" + "version" : "Versión ${currentVersion}", + + "openalias_alert_title" : "Destinatario XMR detectado", + "openalias_alert_content" : "Enviará fondos a\n${recipient_name}" } \ No newline at end of file diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index aa4a8545e..1e14ce24f 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -342,5 +342,8 @@ "incorrect_seed" : "दर्ज किया गया पाठ मान्य नहीं है।", "biometric_auth_reason" : "प्रमाणित करने के लिए अपने फ़िंगरप्रिंट को स्कैन करें", - "version" : "संस्करण ${currentVersion}" + "version" : "संस्करण ${currentVersion}", + + "openalias_alert_title" : "XMR प्राप्तकर्ता का पता लगाया", + "openalias_alert_content" : "आपको धनराशि भेजी जाएगी\n${recipient_name}" } \ No newline at end of file diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index a23b72f4c..e3be02c0c 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -342,5 +342,8 @@ "incorrect_seed" : "入力されたテキストは無効です。", "biometric_auth_reason" : "प指紋をスキャンして認証する", - "version" : "バージョン ${currentVersion}" + "version" : "バージョン ${currentVersion}", + + "openalias_alert_title" : "XMR受信者が検出されました", + "openalias_alert_content" : "に送金します\n${recipient_name}" } \ No newline at end of file diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index 699c6caa7..3204d82f3 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -342,9 +342,8 @@ "incorrect_seed" : "입력하신 텍스트가 유효하지 않습니다.", "biometric_auth_reason" : "지문을 스캔하여 인증", -<<<<<<< HEAD -======= + "version" : "버전 ${currentVersion}", ->>>>>>> 4848485be8cbc34cbec847abbb76dabd075841ae - "version" : "버전 ${currentVersion}" + "openalias_alert_title" : "XMR 수신자 감지", + "openalias_alert_content" : "당신은에 자금을 보낼 것입니다\n${recipient_name}" } \ No newline at end of file diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index 3784383dc..9a2097500 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -342,5 +342,8 @@ "incorrect_seed" : "De ingevoerde tekst is niet geldig.", "biometric_auth_reason" : "Scan uw vingerafdruk om te verifiëren", - "version" : "Versie ${currentVersion}" + "version" : "Versie ${currentVersion}", + + "openalias_alert_title" : "XMR-ontvanger gedetecteerd", + "openalias_alert_content" : "U stuurt geld naar\n${recipient_name}" } \ No newline at end of file diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index 966ce647c..065b11309 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -342,5 +342,8 @@ "incorrect_seed" : "Wprowadzony tekst jest nieprawidłowy.", "biometric_auth_reason" : "Zeskanuj swój odcisk palca, aby go uwierzytelnić", - "version" : "Wersja ${currentVersion}" + "version" : "Wersja ${currentVersion}", + + "openalias_alert_title" : "Wykryto odbiorcę XMR", + "openalias_alert_content" : "Będziesz wysyłać środki na\n${recipient_name}" } \ No newline at end of file diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index 8ef36326c..bd3d219a9 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -342,5 +342,8 @@ "incorrect_seed" : "O texto digitado não é válido.", "biometric_auth_reason" : "Digitalize sua impressão digital para autenticar", - "version" : "Versão ${currentVersion}" + "version" : "Versão ${currentVersion}", + + "openalias_alert_title" : "Destinatário XMR detectado", + "openalias_alert_content" : "Você enviará fundos para\n${recipient_name}" } diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index d88a7c35c..8524a8d40 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -342,5 +342,8 @@ "incorrect_seed" : "Введённый текст некорректный.", "biometric_auth_reason" : "Отсканируйте свой отпечаток пальца для аутентификации", - "version" : "Версия ${currentVersion}" -} + "version" : "Версия ${currentVersion}", + + "openalias_alert_title" : "Получатель XMR обнаружен", + "openalias_alert_content" : "Вы будете отправлять средства\n${recipient_name}" +} \ No newline at end of file diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index d19056644..a1391719f 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -342,5 +342,8 @@ "incorrect_seed" : "输入的文字无效。", "biometric_auth_reason" : "掃描指紋以進行身份驗證", - "version" : "版 ${currentVersion}" + "version" : "版 ${currentVersion}", + + "openalias_alert_title" : "檢測到XMR收件人", + "openalias_alert_content" : "您將匯款至\n${recipient_name}" } \ No newline at end of file