From 7928c912e81d88df803e7ec5c3c1065b252ec9f6 Mon Sep 17 00:00:00 2001
From: Serhii <17529954+serhii-bor@users.noreply.github.com>
Date: Mon, 6 Jul 2026 16:48:30 +0300
Subject: [PATCH] Address resolver refactoring (#3291)
* restructure address resolver sources
* refactor address resolver into lookup service
* refactor address resolver to provider pattern
* use addressSource to drive providers & settings
* error handling
* add address source icons
* Update lib/core/address_validator.dart [skip ci]
Co-authored-by: Omar Hatem
* review fixes
* add validations to extractParsedAddress
* skip address resolver for valid addresses
* minor fix [skip ci]
* fix formattedName x[skip ci]
Co-authored-by: malik1004x
* fix formatted name zano [skip ci]
Co-authored-by: malik1004x
* address PR review comments
* add icons for new address source resolvers
* confirm parsed addresses in contacts
* minor fixes
* LNUrl for BTCLN only and contact name handling
---------
Co-authored-by: Omar Hatem
Co-authored-by: malik1004x
---
.../src/cards/cake_pay_buy_card_page.dart | 16 +-
.../address_lookup_provider.dart | 22 +
.../address_resolver_service.dart | 143 +++++
.../address_resolver_utils.dart | 104 ++++
.../address_resolver/address_sources.dart | 87 +++
.../bip_353/bip_353_address_provider.dart | 68 +++
.../bip_353}/bip_353_record.dart | 71 +--
.../ens/ens_address_provider.dart | 49 ++
lib/core/address_resolver/ens/ens_record.dart | 55 ++
.../fio/fio_address_provider.dart | 125 ++++
.../lnurl_pay/lnurl_pay_address_provider.dart | 66 +++
.../lnurl_pay}/lnurlpay_record.dart | 0
.../mastodon/mastodon_address_provider.dart | 93 +++
.../mastodon/mastodon_api.dart | 2 +-
.../mastodon/mastodon_user.dart | 0
.../nostr/nostr_address_provider.dart | 66 +++
.../address_resolver/nostr/nostr_api.dart | 127 ++++
.../address_resolver}/nostr/nostr_user.dart | 0
.../openalias/openalias_address_provider.dart | 64 ++
.../openalias/openalias_record.dart | 69 +++
lib/core/address_resolver/parsed_address.dart | 22 +
.../thorchain/thorchain_address_provider.dart | 65 +++
.../twitter/twitter_address_provider.dart | 97 ++++
.../twitter/twitter_api.dart | 2 +-
.../twitter/twitter_user.dart | 0
.../unstoppable_address_provider.dart | 235 ++++++++
.../wellknown/wellknown_address_provider.dart | 49 ++
.../wellknown/wellknown_record.dart | 78 +++
.../yat/yat_address_provider.dart | 59 ++
lib/core/address_resolver/yat/yat_record.dart | 19 +
.../address_resolver/yat/yat_service.dart | 67 +++
.../address_resolver}/yat/yat_store.dart | 0
.../zano/zano_alias_address_provider.dart | 75 +++
.../zcash/zcash_address_provider.dart | 49 ++
.../zcash/zcash_me_address_provider.dart | 74 +++
.../zcash}/zcash_names_record.dart | 0
lib/core/address_validator.dart | 87 ++-
lib/core/yat_service.dart | 55 --
lib/di.dart | 27 +-
lib/entities/ens_record.dart | 54 --
lib/entities/fio_address_provider.dart | 65 ---
lib/entities/openalias_record.dart | 89 ---
lib/entities/parse_address_from_domain.dart | 549 ------------------
lib/entities/parsed_address.dart | 212 -------
lib/entities/preferences_key.dart | 6 +
lib/entities/unstoppable_domain_address.dart | 30 -
lib/entities/wellknown_record.dart | 93 ---
lib/entities/yat_record.dart | 13 -
lib/entities/zano_alias.dart | 29 -
lib/new-ui/pages/send_page.dart | 59 +-
lib/new-ui/pages/swap_page.dart | 13 +-
.../lightning_username_bloc.dart | 2 +-
.../widgets/send_page/send_confirm_sheet.dart | 15 +-
lib/nostr/nostr_api.dart | 150 -----
lib/src/screens/buy/buy_sell_page.dart | 42 +-
.../screens/contact/contact_list_page.dart | 1 +
lib/src/screens/contact/contact_page.dart | 52 +-
lib/src/screens/exchange/exchange_page.dart | 10 +-
lib/src/screens/send/send_page.dart | 1 -
.../widgets/extract_address_from_parsed.dart | 150 -----
lib/src/screens/send/widgets/send_card.dart | 5 -
.../send/widgets/send_template_card.dart | 2 -
.../screens/settings/domain_lookups_page.dart | 57 +-
.../screens/wallet_list/filtered_list.dart | 3 +
lib/src/screens/yat/yat_popup.dart | 2 +-
lib/src/widgets/base_alert_dialog.dart | 6 +-
.../confirm_sending_bottom_sheet_widget.dart | 2 +-
lib/store/settings_store.dart | 69 ++-
lib/store/yat/yat_exception.dart | 10 -
.../contact_list/contact_view_model.dart | 61 +-
.../dashboard/dashboard_view_model.dart | 2 +-
.../restore/wallet_restore_from_qr_code.dart | 4 +-
lib/view_model/send/output.dart | 65 ++-
lib/view_model/send/send_view_model.dart | 50 +-
.../settings/connection_sync_view_model.dart | 139 ++++-
.../wallet_address_list_view_model.dart | 2 +-
pubspec_base.yaml | 1 +
res/pictures/address_sources/bip353.svg | 4 +
res/pictures/address_sources/ens.svg | 14 +
res/pictures/address_sources/fio.svg | 20 +
.../address_sources/icon-lnurl-pay.svg | 4 +
.../address_sources/icon-thorchain.svg | 16 +
.../address_sources/icon-zcash-me.svg | 230 ++++++++
.../address_sources/icon-zcashnames.svg | 52 ++
res/pictures/address_sources/mastodon.svg | 11 +
res/pictures/address_sources/nostr.svg | 4 +
res/pictures/address_sources/openalias.svg | 13 +
res/pictures/address_sources/unstoppable.svg | 5 +
res/pictures/address_sources/wellknown.svg | 4 +
res/pictures/address_sources/x.svg | 11 +
res/pictures/address_sources/yat.svg | 11 +
res/pictures/address_sources/zano.svg | 37 ++
.../parse_address_from_domain_test.dart | 2 +-
93 files changed, 3044 insertions(+), 1796 deletions(-)
create mode 100644 lib/core/address_resolver/address_lookup_provider.dart
create mode 100644 lib/core/address_resolver/address_resolver_service.dart
create mode 100644 lib/core/address_resolver/address_resolver_utils.dart
create mode 100644 lib/core/address_resolver/address_sources.dart
create mode 100644 lib/core/address_resolver/bip_353/bip_353_address_provider.dart
rename lib/{entities => core/address_resolver/bip_353}/bip_353_record.dart (59%)
create mode 100644 lib/core/address_resolver/ens/ens_address_provider.dart
create mode 100644 lib/core/address_resolver/ens/ens_record.dart
create mode 100644 lib/core/address_resolver/fio/fio_address_provider.dart
create mode 100644 lib/core/address_resolver/lnurl_pay/lnurl_pay_address_provider.dart
rename lib/{entities => core/address_resolver/lnurl_pay}/lnurlpay_record.dart (100%)
create mode 100644 lib/core/address_resolver/mastodon/mastodon_address_provider.dart
rename lib/{ => core/address_resolver}/mastodon/mastodon_api.dart (95%)
rename lib/{ => core/address_resolver}/mastodon/mastodon_user.dart (100%)
create mode 100644 lib/core/address_resolver/nostr/nostr_address_provider.dart
create mode 100644 lib/core/address_resolver/nostr/nostr_api.dart
rename lib/{ => core/address_resolver}/nostr/nostr_user.dart (100%)
create mode 100644 lib/core/address_resolver/openalias/openalias_address_provider.dart
create mode 100644 lib/core/address_resolver/openalias/openalias_record.dart
create mode 100644 lib/core/address_resolver/parsed_address.dart
create mode 100644 lib/core/address_resolver/thorchain/thorchain_address_provider.dart
create mode 100644 lib/core/address_resolver/twitter/twitter_address_provider.dart
rename lib/{ => core/address_resolver}/twitter/twitter_api.dart (96%)
rename lib/{ => core/address_resolver}/twitter/twitter_user.dart (100%)
create mode 100644 lib/core/address_resolver/unstoppable/unstoppable_address_provider.dart
create mode 100644 lib/core/address_resolver/wellknown/wellknown_address_provider.dart
create mode 100644 lib/core/address_resolver/wellknown/wellknown_record.dart
create mode 100644 lib/core/address_resolver/yat/yat_address_provider.dart
create mode 100644 lib/core/address_resolver/yat/yat_record.dart
create mode 100644 lib/core/address_resolver/yat/yat_service.dart
rename lib/{store => core/address_resolver}/yat/yat_store.dart (100%)
create mode 100644 lib/core/address_resolver/zano/zano_alias_address_provider.dart
create mode 100644 lib/core/address_resolver/zcash/zcash_address_provider.dart
create mode 100644 lib/core/address_resolver/zcash/zcash_me_address_provider.dart
rename lib/{entities => core/address_resolver/zcash}/zcash_names_record.dart (100%)
delete mode 100644 lib/core/yat_service.dart
delete mode 100644 lib/entities/ens_record.dart
delete mode 100644 lib/entities/fio_address_provider.dart
delete mode 100644 lib/entities/openalias_record.dart
delete mode 100644 lib/entities/parse_address_from_domain.dart
delete mode 100644 lib/entities/parsed_address.dart
delete mode 100644 lib/entities/unstoppable_domain_address.dart
delete mode 100644 lib/entities/wellknown_record.dart
delete mode 100644 lib/entities/yat_record.dart
delete mode 100644 lib/entities/zano_alias.dart
delete mode 100644 lib/nostr/nostr_api.dart
delete mode 100644 lib/src/screens/send/widgets/extract_address_from_parsed.dart
delete mode 100644 lib/store/yat/yat_exception.dart
create mode 100644 res/pictures/address_sources/bip353.svg
create mode 100644 res/pictures/address_sources/ens.svg
create mode 100644 res/pictures/address_sources/fio.svg
create mode 100644 res/pictures/address_sources/icon-lnurl-pay.svg
create mode 100644 res/pictures/address_sources/icon-thorchain.svg
create mode 100644 res/pictures/address_sources/icon-zcash-me.svg
create mode 100644 res/pictures/address_sources/icon-zcashnames.svg
create mode 100644 res/pictures/address_sources/mastodon.svg
create mode 100644 res/pictures/address_sources/nostr.svg
create mode 100644 res/pictures/address_sources/openalias.svg
create mode 100644 res/pictures/address_sources/unstoppable.svg
create mode 100644 res/pictures/address_sources/wellknown.svg
create mode 100644 res/pictures/address_sources/x.svg
create mode 100644 res/pictures/address_sources/yat.svg
create mode 100644 res/pictures/address_sources/zano.svg
diff --git a/lib/cake_pay/src/cards/cake_pay_buy_card_page.dart b/lib/cake_pay/src/cards/cake_pay_buy_card_page.dart
index 5442dcff1..8380897b9 100644
--- a/lib/cake_pay/src/cards/cake_pay_buy_card_page.dart
+++ b/lib/cake_pay/src/cards/cake_pay_buy_card_page.dart
@@ -11,8 +11,8 @@ import 'package:cake_wallet/cake_pay/src/widgets/link_extractor.dart';
import 'package:cake_wallet/cake_pay/src/widgets/rounded_overlay_cards_widget.dart';
import 'package:cake_wallet/cake_pay/src/widgets/text_icon_button.dart';
import 'package:cake_wallet/cake_pay/src/widgets/three_checkbox_alert_content_widget.dart';
+import 'package:cake_wallet/core/address_resolver/parsed_address.dart';
import 'package:cake_wallet/core/execution_state.dart';
-import 'package:cake_wallet/entities/parsed_address.dart';
import 'package:cake_wallet/generated/i18n.dart';
import 'package:cake_wallet/new-ui/widgets/keyboard_hide_overlay.dart';
import 'package:cake_wallet/routes.dart';
@@ -584,8 +584,11 @@ class CakePayBuyCardPage extends BasePage {
final displayingOutputs = _sendViewModel.outputs
.map((o) => o.OutputCopyWithParsedAddress(
parsedAddress: ParsedAddress(
- addresses: [o.address],
- name: 'Cake Pay',
+ parsedAddressByCurrencyMap: {
+ cakePayBuyCardViewModel.sendViewModel.selectedCryptoCurrency:
+ o.address,
+ },
+ handle: 'Cake Pay',
profileName: order?.cards.first.cardName ?? 'Cake Pay',
profileImageUrl: order?.cards.first.cardImagePath ?? '',
),
@@ -653,8 +656,11 @@ class CakePayBuyCardPage extends BasePage {
final displayingOutputs = outputsCopy
.map((o) => o.OutputCopyWithParsedAddress(
parsedAddress: ParsedAddress(
- addresses: [o.address],
- name: 'Cake Pay',
+ parsedAddressByCurrencyMap: {
+ cakePayBuyCardViewModel.sendViewModel.selectedCryptoCurrency:
+ o.address,
+ },
+ handle: 'Cake Pay',
profileName: order?.cards.first.cardName ?? 'Cake Pay',
profileImageUrl: order?.cards.first.cardImagePath ?? '',
),
diff --git a/lib/core/address_resolver/address_lookup_provider.dart b/lib/core/address_resolver/address_lookup_provider.dart
new file mode 100644
index 000000000..9feff5610
--- /dev/null
+++ b/lib/core/address_resolver/address_lookup_provider.dart
@@ -0,0 +1,22 @@
+import 'package:cake_wallet/core/address_resolver/address_sources.dart';
+import 'package:cake_wallet/core/address_resolver/parsed_address.dart';
+import 'package:cake_wallet/store/settings_store.dart';
+import 'package:cw_core/crypto_currency.dart';
+import 'package:cw_core/wallet_base.dart';
+
+abstract class AddressLookupProvider {
+
+ AddressSource get source;
+
+ List get supportedCurrencies;
+
+ bool isEnabled(SettingsStore settingsStore);
+
+ bool canHandle(String query);
+
+ Future> resolve({
+ required String query,
+ required List currencies,
+ required WalletBase wallet,
+ });
+}
diff --git a/lib/core/address_resolver/address_resolver_service.dart b/lib/core/address_resolver/address_resolver_service.dart
new file mode 100644
index 000000000..8592c53c6
--- /dev/null
+++ b/lib/core/address_resolver/address_resolver_service.dart
@@ -0,0 +1,143 @@
+import 'package:cake_wallet/core/address_resolver/address_lookup_provider.dart';
+import 'package:cake_wallet/core/address_resolver/address_sources.dart';
+import 'package:cake_wallet/core/address_resolver/bip_353/bip_353_address_provider.dart';
+import 'package:cake_wallet/core/address_resolver/ens/ens_address_provider.dart';
+import 'package:cake_wallet/core/address_resolver/fio/fio_address_provider.dart';
+import 'package:cake_wallet/core/address_resolver/lnurl_pay/lnurl_pay_address_provider.dart';
+import 'package:cake_wallet/core/address_resolver/mastodon/mastodon_address_provider.dart';
+import 'package:cake_wallet/core/address_resolver/nostr/nostr_address_provider.dart';
+import 'package:cake_wallet/core/address_resolver/openalias/openalias_address_provider.dart';
+import 'package:cake_wallet/core/address_resolver/parsed_address.dart';
+import 'package:cake_wallet/core/address_resolver/thorchain/thorchain_address_provider.dart';
+import 'package:cake_wallet/core/address_resolver/twitter/twitter_address_provider.dart';
+import 'package:cake_wallet/core/address_resolver/unstoppable/unstoppable_address_provider.dart';
+import 'package:cake_wallet/core/address_resolver/wellknown/wellknown_address_provider.dart';
+import 'package:cake_wallet/core/address_resolver/yat/yat_address_provider.dart';
+import 'package:cake_wallet/core/address_resolver/zano/zano_alias_address_provider.dart';
+import 'package:cake_wallet/core/address_resolver/zcash/zcash_address_provider.dart';
+import 'package:cake_wallet/core/address_resolver/zcash/zcash_me_address_provider.dart';
+import 'package:cake_wallet/store/settings_store.dart';
+import 'package:cw_core/crypto_currency.dart';
+import 'package:cw_core/utils/print_verbose.dart';
+import 'package:cw_core/wallet_base.dart';
+
+class AddressResolverService {
+ AddressResolverService({required this.settingsStore});
+
+ final SettingsStore settingsStore;
+
+// Sources available for address resolution and lookup settings.
+ static const supportedSources = [
+ AddressSource.lnurlPay,
+ AddressSource.twitter,
+ AddressSource.mastodon,
+ AddressSource.yatRecord,
+ AddressSource.unstoppableDomains,
+ AddressSource.openAlias,
+ AddressSource.ens,
+ AddressSource.zcashName,
+ AddressSource.zcashAddress,
+ AddressSource.wellKnown,
+ AddressSource.zanoAlias,
+ AddressSource.bip353,
+ AddressSource.fio,
+ AddressSource.thorChain,
+ AddressSource.nostr,
+ ];
+
+ List _buildProviders() {
+ final allProviders = [
+ LNUrlPayAddressProvider(),
+ TwitterAddressProvider(),
+ MastodonAddressProvider(),
+ YatAddressProvider(),
+ UnstoppableAddressProvider(),
+ OpenaliasAddressProvider(),
+ EnsAddressProvider(),
+ ZcashNameAddressProvider(),
+ ZcashMeAddressProvider(),
+ WellKnownAddressProvider(),
+ ZanoAliasAddressProvider(),
+ Bip353AddressProvider(),
+ FioAddressProvider(),
+ ThorchainAddressProvider(),
+ NostrAddressProvider(),
+ ];
+
+ return allProviders.where((provider) => supportedSources.contains(provider.source)).toList();
+ }
+
+ Future> resolve({
+ required String query,
+ required WalletBase wallet,
+ required CryptoCurrency currency,
+ }) async {
+ try {
+ final providers = _buildProviders();
+ // return first entry if currency is specified and provider supports it
+ if (currency != null) {
+ for (final provider in providers) {
+ final cur = currency.title;
+ final src = provider.source.label;
+
+ printV('[address resolver service] checking $src - $cur - $query');
+ if (!provider.isEnabled(settingsStore)) {
+ printV('[address resolver service] ...skipping $src (disabled)');
+ continue;
+ }
+ if (!provider.canHandle(query)) {
+ printV('[address resolver service] ...skipping $src (cannot handle)');
+ continue;
+ }
+ if (!provider.supportedCurrencies.contains(currency)) {
+ printV('[address resolver service] ...skipping $src (unsupported currency)');
+ continue;
+ }
+
+ try {
+ printV('[address resolver service] ...resolving $src - $cur - $query');
+ final results = await provider.resolve(
+ query: query,
+ currencies: [currency],
+ wallet: wallet,
+ );
+
+ if (results.isNotEmpty) {
+ final parsedAddress = results.first.parsedAddressByCurrencyMap[currency];
+ final parsedAddressStr = parsedAddress == null || parsedAddress.isEmpty ? 'N/A' : parsedAddress;
+ printV('[address resolver service] resolved $src - $cur - $parsedAddressStr');
+ return [results.first];
+ }
+ } catch (e) {
+ printV('[address resolver service] Error resolving $src: $e');
+ }
+ }
+
+ return [];
+ }
+
+ return []; // TODO: Implement multi-currency resolution if no specific currency is provided.
+
+ final tasks = >>[];
+
+ for (final provider in providers) {
+ if (!provider.isEnabled(settingsStore)) continue;
+ if (!provider.canHandle(query)) continue;
+
+ tasks.add(
+ provider.resolve(
+ query: query,
+ currencies: provider.supportedCurrencies,
+ wallet: wallet,
+ ),
+ );
+ }
+
+ final results = await Future.wait(tasks);
+ return results.expand((items) => items).toList();
+ } catch (e) {
+ printV('Error resolving address: $e');
+ return [];
+ }
+ }
+}
diff --git a/lib/core/address_resolver/address_resolver_utils.dart b/lib/core/address_resolver/address_resolver_utils.dart
new file mode 100644
index 000000000..f9f59240c
--- /dev/null
+++ b/lib/core/address_resolver/address_resolver_utils.dart
@@ -0,0 +1,104 @@
+import 'package:cake_wallet/core/address_resolver/unstoppable/unstoppable_address_provider.dart';
+import 'package:cake_wallet/core/address_validator.dart';
+import 'package:cw_core/crypto_currency.dart';
+import 'package:cw_core/utils/print_verbose.dart';
+
+class AddressResolverUtils {
+ static Future
', caseSensitive: false), '\n')
+ .replaceAll(RegExp(r'<[^>]*>'), ' ')
+ .trim();
+ }
+}
diff --git a/lib/core/address_resolver/address_sources.dart b/lib/core/address_resolver/address_sources.dart
new file mode 100644
index 000000000..729ef478a
--- /dev/null
+++ b/lib/core/address_resolver/address_sources.dart
@@ -0,0 +1,87 @@
+import 'package:cake_wallet/core/address_validator.dart';
+import 'package:cw_core/crypto_currency.dart';
+
+enum AddressSource {
+ twitter(label: 'X', iconPath: 'assets/new-ui/address_sources/x.svg', alias: '@username'),
+ unstoppableDomains(
+ label: 'Unstoppable Domains',
+ iconPath: 'assets/new-ui/address_sources/unstoppable.svg',
+ alias: 'domain.tld'),
+ openAlias(
+ label: 'OpenAlias',
+ iconPath: 'assets/new-ui/address_sources/openalias.svg',
+ alias: 'name.domain.tld'),
+ yatRecord(label: 'Yat', iconPath: 'assets/new-ui/address_sources/yat.svg', alias: '🎂🎂🎂'),
+ fio(label: 'FIO', iconPath: 'assets/new-ui/address_sources/fio.svg', alias: 'user@domain'),
+ ens(
+ label: 'Ethereum Name Service',
+ iconPath: 'assets/new-ui/address_sources/ens.svg',
+ alias: 'domain.eth'),
+ mastodon(
+ label: 'Mastodon',
+ iconPath: 'assets/new-ui/address_sources/mastodon.svg',
+ alias: '@username@domain.tld'),
+ nostr(
+ label: 'Nostr',
+ iconPath: 'assets/new-ui/address_sources/nostr.svg',
+ alias: 'user@domain.tld'),
+ thorChain(
+ label: 'ThorChain',
+ iconPath: 'assets/new-ui/address_sources/icon-thorchain.svg',
+ alias: 'name'),
+ wellKnown(
+ label: '.wellknown',
+ iconPath: 'assets/new-ui/address_sources/wellknown.svg',
+ alias: 'domain.tld'),
+ zanoAlias(
+ label: 'Zano Alias', iconPath: 'assets/new-ui/address_sources/zano.svg', alias: '@alias'),
+ bip353(
+ label: 'BIP353',
+ iconPath: 'assets/new-ui/address_sources/bip353.svg',
+ alias: 'user@domain.com'),
+ zcashAddress(
+ label: 'Zcash.me',
+ iconPath: 'assets/new-ui/address_sources/icon-zcash-me.svg',
+ alias: 'zcash.me/username'),
+ zcashName(
+ label: 'Zcash Names',
+ iconPath: 'assets/new-ui/address_sources/icon-zcashnames.svg',
+ alias: 'name.zec'),
+ lnurlPay(
+ label: 'LNURL Pay',
+ iconPath: 'assets/new-ui/address_sources/icon-lnurl-pay.svg',
+ alias: 'user@domain.com'),
+ contact(label: 'Contact', iconPath: ''),
+ notParsed(label: 'Unknown', iconPath: ''),
+ ;
+
+ const AddressSource({
+ required this.label,
+ required this.iconPath,
+ this.alias = '',
+ });
+
+ final String label;
+ final String iconPath;
+ final String alias;
+}
+
+extension AddressSourceIndex on AddressSource {
+ int get raw => index;
+
+ static AddressSource fromRaw(int raw) =>
+ AddressSource.values[raw.clamp(0, AddressSource.values.length - 1)];
+}
+
+extension AddressSourceNameParser on AddressSource {
+ static AddressSource fromLabel(String? text) {
+ if (text == null || text.trim().isEmpty) {
+ return AddressSource.notParsed;
+ }
+ final needle = text.trim().toLowerCase();
+ return AddressSource.values.firstWhere(
+ (src) => src.label.toLowerCase() == needle,
+ orElse: () => AddressSource.notParsed,
+ );
+ }
+}
diff --git a/lib/core/address_resolver/bip_353/bip_353_address_provider.dart b/lib/core/address_resolver/bip_353/bip_353_address_provider.dart
new file mode 100644
index 000000000..3a46f87a4
--- /dev/null
+++ b/lib/core/address_resolver/bip_353/bip_353_address_provider.dart
@@ -0,0 +1,68 @@
+import 'package:cake_wallet/core/address_resolver/address_lookup_provider.dart';
+import 'package:cake_wallet/core/address_resolver/address_sources.dart';
+import 'package:cake_wallet/core/address_resolver/bip_353/bip_353_record.dart';
+import 'package:cake_wallet/core/address_resolver/parsed_address.dart';
+import 'package:cake_wallet/store/settings_store.dart';
+import 'package:cw_core/crypto_currency.dart';
+import 'package:cw_core/utils/print_verbose.dart';
+import 'package:cw_core/wallet_base.dart';
+
+class Bip353AddressProvider extends AddressLookupProvider {
+ @override
+ AddressSource get source => AddressSource.bip353;
+
+ @override
+ List get supportedCurrencies => [CryptoCurrency.btc];
+
+ @override
+ bool isEnabled(SettingsStore settingsStore) => settingsStore.lookupsBip353;
+
+ @override
+ bool canHandle(String query) {
+ final value = query.trim();
+ return value.contains('@') && value.contains('.') && !value.startsWith('@');
+ }
+
+ @override
+ Future> resolve({
+ required String query,
+ required List currencies,
+ required WalletBase wallet,
+ }) async {
+ try {
+ final result = {};
+ String? dnsProof;
+
+ for (final cur in currencies) {
+ final bip353AddressMap = await Bip353Record.fetchUriByCryptoCurrency(query, cur.title);
+ if (bip353AddressMap == null || bip353AddressMap.isEmpty) continue;
+
+ final spAddress = bip353AddressMap['sp'];
+ final address = bip353AddressMap['address'];
+ final chosenAddress = spAddress?.isNotEmpty == true ? spAddress : address;
+
+ if (chosenAddress != null && chosenAddress.isNotEmpty) {
+ result[cur] = chosenAddress;
+ }
+ }
+
+ if (result.isEmpty) return [];
+
+ try {
+ dnsProof = await Bip353Record.fetchDnsProof(query);
+ } catch (e) {
+ printV('Bip353Record.fetchDnsProof error: $e');
+ }
+
+ return [ParsedAddress(
+ parsedAddressByCurrencyMap: result,
+ addressSource: AddressSource.bip353,
+ handle: query,
+ bip353DnsProof: dnsProof ?? '',
+ )];
+ } catch (e) {
+ printV('[address resolver] Error resolving BIP353 address: $e');
+ return [];
+ }
+ }
+}
\ No newline at end of file
diff --git a/lib/entities/bip_353_record.dart b/lib/core/address_resolver/bip_353/bip_353_record.dart
similarity index 59%
rename from lib/entities/bip_353_record.dart
rename to lib/core/address_resolver/bip_353/bip_353_record.dart
index 9a2a50e0a..257d76737 100644
--- a/lib/entities/bip_353_record.dart
+++ b/lib/core/address_resolver/bip_353/bip_353_record.dart
@@ -2,13 +2,9 @@ import 'dart:convert';
import 'dart:isolate';
import 'package:basic_utils/basic_utils.dart';
-import 'package:cake_wallet/generated/i18n.dart';
-import 'package:cake_wallet/src/widgets/alert_with_picker_option.dart';
-import 'package:cake_wallet/utils/show_pop_up.dart';
import 'package:cw_core/crypto_currency.dart';
import 'package:cw_core/utils/print_verbose.dart';
import 'package:dnssec_proof/dnssec_proof.dart';
-import 'package:flutter/material.dart';
class Bip353Record {
Bip353Record({
@@ -104,69 +100,4 @@ class Bip353Record {
}
}
- static Future pickBip353AddressChoice(
- BuildContext context,
- String bip353Name,
- Map addressMap,
- ) async {
- if (addressMap.length == 1) {
- return addressMap.values.first;
- }
-
- final chosenAddress = await _showAddressChoiceDialog(context, bip353Name, addressMap);
-
- return chosenAddress;
- }
-
- static Future _showAddressChoiceDialog(
- BuildContext context,
- String bip353Name,
- Map addressMap,
- ) async {
- final entriesList = addressMap.entries.toList();
- final List