mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2024-12-22 11:39:22 +00:00
thor name to address lookup (#1390)
* thor name to address lookup * minor fix [skip ci] * Addressing code review comments * minor fix
This commit is contained in:
parent
cd41766e69
commit
3f3cd10158
6 changed files with 82 additions and 35 deletions
|
@ -5,6 +5,7 @@ import 'package:cake_wallet/entities/openalias_record.dart';
|
|||
import 'package:cake_wallet/entities/parsed_address.dart';
|
||||
import 'package:cake_wallet/entities/unstoppable_domain_address.dart';
|
||||
import 'package:cake_wallet/entities/emoji_string_extension.dart';
|
||||
import 'package:cake_wallet/exchange/provider/thorchain_exchange.provider.dart';
|
||||
import 'package:cake_wallet/mastodon/mastodon_api.dart';
|
||||
import 'package:cake_wallet/nostr/nostr_api.dart';
|
||||
import 'package:cake_wallet/store/settings_store.dart';
|
||||
|
@ -71,8 +72,8 @@ class AddressResolver {
|
|||
return emailRegex.hasMatch(address);
|
||||
}
|
||||
|
||||
// TODO: refactor this to take Crypto currency instead of ticker, or at least pass in the tag as well
|
||||
Future<ParsedAddress> resolve(BuildContext context, String text, String ticker) async {
|
||||
Future<ParsedAddress> resolve(BuildContext context, String text, CryptoCurrency currency) async {
|
||||
final ticker = currency.title;
|
||||
try {
|
||||
if (text.startsWith('@') && !text.substring(1).contains('@')) {
|
||||
if (settingsStore.lookupsTwitter) {
|
||||
|
@ -116,8 +117,7 @@ class AddressResolver {
|
|||
await MastodonAPI.lookupUserByUserName(userName: userName, apiHost: hostName);
|
||||
|
||||
if (mastodonUser != null) {
|
||||
String? addressFromBio = extractAddressByType(
|
||||
raw: mastodonUser.note, type: CryptoCurrency.fromString(ticker));
|
||||
String? addressFromBio = extractAddressByType(raw: mastodonUser.note, type: currency);
|
||||
|
||||
if (addressFromBio != null) {
|
||||
return ParsedAddress.fetchMastodonAddress(
|
||||
|
@ -131,8 +131,8 @@ class AddressResolver {
|
|||
|
||||
if (pinnedPosts.isNotEmpty) {
|
||||
final userPinnedPostsText = pinnedPosts.map((item) => item.content).join('\n');
|
||||
String? addressFromPinnedPost = extractAddressByType(
|
||||
raw: userPinnedPostsText, type: CryptoCurrency.fromString(ticker));
|
||||
String? addressFromPinnedPost =
|
||||
extractAddressByType(raw: userPinnedPostsText, type: currency);
|
||||
|
||||
if (addressFromPinnedPost != null) {
|
||||
return ParsedAddress.fetchMastodonAddress(
|
||||
|
@ -162,6 +162,16 @@ class AddressResolver {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
final thorChainAddress = await ThorChainExchangeProvider.lookupAddressByName(text);
|
||||
if (thorChainAddress != null) {
|
||||
String? address =
|
||||
thorChainAddress[ticker] ?? (ticker == 'RUNE' ? thorChainAddress['THOR'] : null);
|
||||
if (address != null) {
|
||||
return ParsedAddress.thorChainAddress(address: address, name: text);
|
||||
}
|
||||
}
|
||||
|
||||
final formattedName = OpenaliasRecord.formatDomainName(text);
|
||||
final domainParts = formattedName.split('.');
|
||||
final name = domainParts.last;
|
||||
|
@ -204,7 +214,7 @@ class AddressResolver {
|
|||
|
||||
if (nostrUserData != null) {
|
||||
String? addressFromBio = extractAddressByType(
|
||||
raw: nostrUserData.about, type: CryptoCurrency.fromString(ticker));
|
||||
raw: nostrUserData.about, type: currency);
|
||||
if (addressFromBio != null) {
|
||||
return ParsedAddress.nostrAddress(
|
||||
address: addressFromBio,
|
||||
|
|
|
@ -11,7 +11,8 @@ enum ParseFrom {
|
|||
ens,
|
||||
contact,
|
||||
mastodon,
|
||||
nostr
|
||||
nostr,
|
||||
thorChain
|
||||
}
|
||||
|
||||
class ParsedAddress {
|
||||
|
@ -133,6 +134,14 @@ class ParsedAddress {
|
|||
);
|
||||
}
|
||||
|
||||
factory ParsedAddress.thorChainAddress({required String address, required String name}) {
|
||||
return ParsedAddress(
|
||||
addresses: [address],
|
||||
name: name,
|
||||
parseFrom: ParseFrom.thorChain,
|
||||
);
|
||||
}
|
||||
|
||||
final List<String> addresses;
|
||||
final String name;
|
||||
final String description;
|
||||
|
|
|
@ -34,11 +34,13 @@ class ThorChainExchangeProvider extends ExchangeProvider {
|
|||
|
||||
static final isRefundAddressSupported = [CryptoCurrency.eth];
|
||||
|
||||
static const _baseURL = 'thornode.ninerealms.com';
|
||||
static const _baseNodeURL = 'thornode.ninerealms.com';
|
||||
static const _baseURL = 'midgard.ninerealms.com';
|
||||
static const _quotePath = '/thorchain/quote/swap';
|
||||
static const _txInfoPath = '/thorchain/tx/status/';
|
||||
static const _affiliateName = 'cakewallet';
|
||||
static const _affiliateBps = '175';
|
||||
static const _nameLookUpPath= 'v2/thorname/lookup/';
|
||||
|
||||
final Box<Trade> tradesStore;
|
||||
|
||||
|
@ -154,7 +156,7 @@ class ThorChainExchangeProvider extends ExchangeProvider {
|
|||
Future<Trade> findTradeById({required String id}) async {
|
||||
if (id.isEmpty) throw Exception('Trade id is empty');
|
||||
final formattedId = id.startsWith('0x') ? id.substring(2) : id;
|
||||
final uri = Uri.https(_baseURL, '$_txInfoPath$formattedId');
|
||||
final uri = Uri.https(_baseNodeURL, '$_txInfoPath$formattedId');
|
||||
final response = await http.get(uri);
|
||||
|
||||
if (response.statusCode == 404) {
|
||||
|
@ -206,8 +208,35 @@ class ThorChainExchangeProvider extends ExchangeProvider {
|
|||
);
|
||||
}
|
||||
|
||||
static Future<Map<String, String>?>? lookupAddressByName(String name) async {
|
||||
final uri = Uri.https(_baseURL, '$_nameLookUpPath$name');
|
||||
final response = await http.get(uri);
|
||||
|
||||
if (response.statusCode != 200) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final body = json.decode(response.body) as Map<String, dynamic>;
|
||||
final entries = body['entries'] as List<dynamic>?;
|
||||
|
||||
if (entries == null || entries.isEmpty) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Map<String, String> chainToAddressMap = {};
|
||||
|
||||
for (final entry in entries) {
|
||||
final chain = entry['chain'] as String;
|
||||
final address = entry['address'] as String;
|
||||
chainToAddressMap[chain] = address;
|
||||
}
|
||||
|
||||
return chainToAddressMap;
|
||||
}
|
||||
|
||||
|
||||
Future<Map<String, dynamic>> _getSwapQuote(Map<String, String> params) async {
|
||||
Uri uri = Uri.https(_baseURL, _quotePath, params);
|
||||
Uri uri = Uri.https(_baseNodeURL, _quotePath, params);
|
||||
|
||||
final response = await http.get(uri);
|
||||
|
||||
|
|
|
@ -330,10 +330,12 @@ class ExchangePage extends BasePage {
|
|||
|
||||
void applyTemplate(
|
||||
BuildContext context, ExchangeViewModel exchangeViewModel, ExchangeTemplate template) async {
|
||||
exchangeViewModel.changeDepositCurrency(
|
||||
currency: CryptoCurrency.fromString(template.depositCurrency));
|
||||
exchangeViewModel.changeReceiveCurrency(
|
||||
currency: CryptoCurrency.fromString(template.receiveCurrency));
|
||||
|
||||
final depositCryptoCurrency = CryptoCurrency.fromString(template.depositCurrency);
|
||||
final receiveCryptoCurrency = CryptoCurrency.fromString(template.receiveCurrency);
|
||||
|
||||
exchangeViewModel.changeDepositCurrency(currency: depositCryptoCurrency);
|
||||
exchangeViewModel.changeReceiveCurrency(currency: receiveCryptoCurrency);
|
||||
|
||||
exchangeViewModel.changeDepositAmount(amount: template.amount);
|
||||
exchangeViewModel.depositAddress = template.depositAddress;
|
||||
|
@ -342,12 +344,10 @@ class ExchangePage extends BasePage {
|
|||
exchangeViewModel.isFixedRateMode = false;
|
||||
|
||||
var domain = template.depositAddress;
|
||||
var ticker = template.depositCurrency.toLowerCase();
|
||||
exchangeViewModel.depositAddress = await fetchParsedAddress(context, domain, ticker);
|
||||
exchangeViewModel.depositAddress = await fetchParsedAddress(context, domain, depositCryptoCurrency);
|
||||
|
||||
domain = template.receiveAddress;
|
||||
ticker = template.receiveCurrency.toLowerCase();
|
||||
exchangeViewModel.receiveAddress = await fetchParsedAddress(context, domain, ticker);
|
||||
exchangeViewModel.receiveAddress = await fetchParsedAddress(context, domain, receiveCryptoCurrency);
|
||||
}
|
||||
|
||||
void _setReactions(BuildContext context, ExchangeViewModel exchangeViewModel) {
|
||||
|
@ -519,16 +519,14 @@ class ExchangePage extends BasePage {
|
|||
_depositAddressFocus.addListener(() async {
|
||||
if (!_depositAddressFocus.hasFocus && depositAddressController.text.isNotEmpty) {
|
||||
final domain = depositAddressController.text;
|
||||
final ticker = exchangeViewModel.depositCurrency.title.toLowerCase();
|
||||
exchangeViewModel.depositAddress = await fetchParsedAddress(context, domain, ticker);
|
||||
exchangeViewModel.depositAddress = await fetchParsedAddress(context, domain, exchangeViewModel.depositCurrency);
|
||||
}
|
||||
});
|
||||
|
||||
_receiveAddressFocus.addListener(() async {
|
||||
if (!_receiveAddressFocus.hasFocus && receiveAddressController.text.isNotEmpty) {
|
||||
final domain = receiveAddressController.text;
|
||||
final ticker = exchangeViewModel.receiveCurrency.title.toLowerCase();
|
||||
exchangeViewModel.receiveAddress = await fetchParsedAddress(context, domain, ticker);
|
||||
exchangeViewModel.receiveAddress = await fetchParsedAddress(context, domain, exchangeViewModel.receiveCurrency);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -575,8 +573,8 @@ class ExchangePage extends BasePage {
|
|||
}
|
||||
}
|
||||
|
||||
Future<String> fetchParsedAddress(BuildContext context, String domain, String ticker) async {
|
||||
final parsedAddress = await getIt.get<AddressResolver>().resolve(context, domain, ticker);
|
||||
Future<String> fetchParsedAddress(BuildContext context, String domain, CryptoCurrency currency) async {
|
||||
final parsedAddress = await getIt.get<AddressResolver>().resolve(context, domain, currency);
|
||||
final address = await extractAddressFromParsed(context, parsedAddress);
|
||||
return address;
|
||||
}
|
||||
|
@ -663,15 +661,13 @@ class ExchangePage extends BasePage {
|
|||
addressTextFieldValidator: AddressValidator(type: exchangeViewModel.depositCurrency),
|
||||
onPushPasteButton: (context) async {
|
||||
final domain = exchangeViewModel.depositAddress;
|
||||
final ticker = exchangeViewModel.depositCurrency.title.toLowerCase();
|
||||
exchangeViewModel.depositAddress =
|
||||
await fetchParsedAddress(context, domain, ticker);
|
||||
await fetchParsedAddress(context, domain, exchangeViewModel.depositCurrency);
|
||||
},
|
||||
onPushAddressBookButton: (context) async {
|
||||
final domain = exchangeViewModel.depositAddress;
|
||||
final ticker = exchangeViewModel.depositCurrency.title.toLowerCase();
|
||||
exchangeViewModel.depositAddress =
|
||||
await fetchParsedAddress(context, domain, ticker);
|
||||
await fetchParsedAddress(context, domain, exchangeViewModel.depositCurrency);
|
||||
},
|
||||
));
|
||||
|
||||
|
@ -712,15 +708,13 @@ class ExchangePage extends BasePage {
|
|||
addressTextFieldValidator: AddressValidator(type: exchangeViewModel.receiveCurrency),
|
||||
onPushPasteButton: (context) async {
|
||||
final domain = exchangeViewModel.receiveAddress;
|
||||
final ticker = exchangeViewModel.receiveCurrency.title.toLowerCase();
|
||||
exchangeViewModel.receiveAddress =
|
||||
await fetchParsedAddress(context, domain, ticker);
|
||||
await fetchParsedAddress(context, domain, exchangeViewModel.receiveCurrency);
|
||||
},
|
||||
onPushAddressBookButton: (context) async {
|
||||
final domain = exchangeViewModel.receiveAddress;
|
||||
final ticker = exchangeViewModel.receiveCurrency.title.toLowerCase();
|
||||
exchangeViewModel.receiveAddress =
|
||||
await fetchParsedAddress(context, domain, ticker);
|
||||
await fetchParsedAddress(context, domain, exchangeViewModel.receiveCurrency);
|
||||
},
|
||||
));
|
||||
|
||||
|
|
|
@ -56,6 +56,11 @@ Future<String> extractAddressFromParsed(
|
|||
profileImageUrl = parsedAddress.profileImageUrl;
|
||||
profileName = parsedAddress.profileName;
|
||||
break;
|
||||
case ParseFrom.thorChain:
|
||||
title = S.of(context).address_detected;
|
||||
content = S.of(context).extracted_address_content('${parsedAddress.name} (ThorChain)');
|
||||
address = parsedAddress.addresses.first;
|
||||
break;
|
||||
case ParseFrom.yatRecord:
|
||||
if (parsedAddress.name.isEmpty) {
|
||||
title = S.of(context).yat_error;
|
||||
|
|
|
@ -296,8 +296,8 @@ abstract class OutputBase with Store {
|
|||
|
||||
Future<void> fetchParsedAddress(BuildContext context) async {
|
||||
final domain = address;
|
||||
final ticker = cryptoCurrencyHandler().title.toLowerCase();
|
||||
parsedAddress = await getIt.get<AddressResolver>().resolve(context, domain, ticker);
|
||||
final currency = cryptoCurrencyHandler();
|
||||
parsedAddress = await getIt.get<AddressResolver>().resolve(context, domain, currency);
|
||||
extractedAddress = await extractAddressFromParsed(context, parsedAddress);
|
||||
note = parsedAddress.description;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue