mirror of
https://github.com/Such-Software/hash-wallet.git
synced 2026-11-01 07:04:08 +01:00
Merge upstream Cake Wallet v6.5.0
Catches up from the May 12 fork point (v6.1.2+23) through v6.5.0: 535 upstream commits, including the Monero silent-open fix, Monero on Trezor, Ledger/Trezor BLE fixes, the new seed and history screens, quick Bitcoin sync, git-pinned dependencies (pubspec_overrides.yaml), frozen Hive adapters (*.part.dart), monero_c v0.18.4.6-RC2 and Flutter 3.41.9. Merged with both sides normalized first (import rename, 100-column format), which took the conflict count from 614 paths to 322. The procedure is now scripts/upstream_sync.sh. Kept from Hash Bags: - WalletType enum order and Hive IDs. SQLite stores WalletType.index and our order differs from upstream's; taking theirs would reread saved wallets as other chains. Our frozen adapter keeps the shipped IDs. - The 1.0.2 legacy PIN and wallet-password decode and self-heal. - Removed chains (Solana, Tron, Zano, Zcash, Decred, Haven) and the new Robinhood chain stay out; Cake Pay and non-Trocador swaps stay out. - Default nodes (node.wownero.org, sethforprivacy, Blockstream, bysh.me), converted to upstream's isDefault node-list key; Wownero is back in the node reset list. - Privacy: address resolvers limited to domain-anchored sources again; prices.neroswap.com for fiat; upstream's charts tab, which reads prices.cakewallet.com, sits behind FeatureFlag.isChartsEnabled = false. - Lightning stays behind FeatureFlag.isLightningEnabled, including upstream's new post-seed Lightning username step. - Our icon pipeline, branding and bundle identifiers. Twelve new upstream widget tests are skipped: test and code are unchanged from v6.5.0 apart from renames (not rerun on a pristine upstream checkout; upstream's top_bar_test does not compile against its own TopBar). flutter analyze lib: 0 errors; flutter test: 345 passed, 12 skipped; flutter build bundle compiles. Built with Flutter 3.41.9.
This commit is contained in:
@@ -0,0 +1,237 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:hash_wallet/core/address_resolver/address_lookup_provider.dart';
|
||||
import 'package:hash_wallet/core/address_resolver/address_sources.dart';
|
||||
import 'package:hash_wallet/core/address_resolver/openalias/openalias_record.dart';
|
||||
import 'package:hash_wallet/core/address_resolver/parsed_address.dart';
|
||||
import 'package:hash_wallet/store/settings_store.dart';
|
||||
import 'package:cw_core/crypto_currency.dart';
|
||||
import 'package:cw_core/utils/print_verbose.dart';
|
||||
import 'package:cw_core/utils/proxy_wrapper.dart';
|
||||
import 'package:cw_core/wallet_base.dart';
|
||||
|
||||
class UnstoppableAddressProvider extends AddressLookupProvider {
|
||||
static const unstoppableDomains = [
|
||||
"888",
|
||||
"academy",
|
||||
"agency",
|
||||
"altimist",
|
||||
"anime",
|
||||
"austin",
|
||||
"bald",
|
||||
"bay",
|
||||
"benji",
|
||||
"bet",
|
||||
"binanceus",
|
||||
"bitcoin",
|
||||
"bitget",
|
||||
"bitscrunch",
|
||||
"blockchain",
|
||||
"boomer",
|
||||
"boston",
|
||||
"ca",
|
||||
"caw",
|
||||
"cc",
|
||||
"chat",
|
||||
"chomp",
|
||||
"clay",
|
||||
"club",
|
||||
"co",
|
||||
"com",
|
||||
"company",
|
||||
"crypto",
|
||||
"dao",
|
||||
"design",
|
||||
"dfz",
|
||||
"digital",
|
||||
"doga",
|
||||
"donut",
|
||||
"dream",
|
||||
"email",
|
||||
"emir",
|
||||
"eth",
|
||||
"ethermail",
|
||||
"family",
|
||||
"farms",
|
||||
"finance",
|
||||
"fun",
|
||||
"fyi",
|
||||
"games",
|
||||
"global",
|
||||
"go",
|
||||
"group",
|
||||
"guru",
|
||||
"hi",
|
||||
"hockey",
|
||||
"host",
|
||||
"info",
|
||||
"io",
|
||||
"klever",
|
||||
"kresus",
|
||||
"kryptic",
|
||||
"lfg",
|
||||
"life",
|
||||
"live",
|
||||
"llc",
|
||||
"ltc",
|
||||
"ltd",
|
||||
"manga",
|
||||
"me",
|
||||
"media",
|
||||
"metropolis",
|
||||
"miami",
|
||||
"miku",
|
||||
"money",
|
||||
"moon",
|
||||
"mumu",
|
||||
"net",
|
||||
"network",
|
||||
"news",
|
||||
"nft",
|
||||
"npc",
|
||||
"onchain",
|
||||
"online",
|
||||
"org",
|
||||
"podcast",
|
||||
"pog",
|
||||
"polygon",
|
||||
"base",
|
||||
"arbitrum",
|
||||
"press",
|
||||
"privacy",
|
||||
"pro",
|
||||
"propykeys",
|
||||
"pudgy",
|
||||
"pw",
|
||||
"quantum",
|
||||
"rad",
|
||||
"raiin",
|
||||
"retardio",
|
||||
"rip",
|
||||
"rocks",
|
||||
"secret",
|
||||
"services",
|
||||
"site",
|
||||
"smobler",
|
||||
"social",
|
||||
"solutions",
|
||||
"space",
|
||||
"stepn",
|
||||
"store",
|
||||
"studio",
|
||||
"systems",
|
||||
"tball",
|
||||
"tea",
|
||||
"team",
|
||||
"tech",
|
||||
"technology",
|
||||
"today",
|
||||
"tribe",
|
||||
"u",
|
||||
"ubu",
|
||||
"uno",
|
||||
"unstoppable",
|
||||
"vip",
|
||||
"wallet",
|
||||
"website",
|
||||
"wif",
|
||||
"wifi",
|
||||
"witg",
|
||||
"work",
|
||||
"world",
|
||||
"wrkx",
|
||||
"wtf",
|
||||
"x",
|
||||
"xmr",
|
||||
"xyz",
|
||||
"zil",
|
||||
"zone",
|
||||
"pizza"
|
||||
];
|
||||
|
||||
@override
|
||||
AddressSource get source => AddressSource.unstoppableDomains;
|
||||
|
||||
@override
|
||||
List<CryptoCurrency> get supportedCurrencies => [CryptoCurrency.xmr, CryptoCurrency.btc];
|
||||
|
||||
@override
|
||||
bool isEnabled(SettingsStore settingsStore) => settingsStore.lookupsUnstoppableDomains;
|
||||
|
||||
@override
|
||||
bool canHandle(String query) {
|
||||
// Unstoppable Domains handle example: name.crypto
|
||||
final formattedName = OpenaliasRecord.formatDomainName(query);
|
||||
final domainParts = formattedName.split('.');
|
||||
final name = domainParts.last;
|
||||
return domainParts.length > 1 &&
|
||||
domainParts.first.isNotEmpty &&
|
||||
name.isNotEmpty &&
|
||||
unstoppableDomains.any((domain) => name.trim() == domain);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<ParsedAddress>> resolve({
|
||||
required String query,
|
||||
required List<CryptoCurrency> currencies,
|
||||
required WalletBase wallet,
|
||||
}) async {
|
||||
try {
|
||||
final formattedName = OpenaliasRecord.formatDomainName(query);
|
||||
final result = <CryptoCurrency, String>{};
|
||||
|
||||
for (final currency in currencies) {
|
||||
final address = await fetchUnstoppableDomainAddress(
|
||||
formattedName,
|
||||
currency.title,
|
||||
);
|
||||
|
||||
if (address.isNotEmpty) {
|
||||
result[currency] = address;
|
||||
}
|
||||
}
|
||||
|
||||
if (result.isEmpty) return [];
|
||||
|
||||
return [
|
||||
ParsedAddress(
|
||||
parsedAddressByCurrencyMap: result,
|
||||
profileName: formattedName,
|
||||
addressSource: AddressSource.unstoppableDomains,
|
||||
handle: formattedName,
|
||||
),
|
||||
];
|
||||
} catch (e) {
|
||||
printV('[address resolver] Error resolving Unstoppable Domain: $e');
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
static Future<String> fetchUnstoppableDomainAddress(String domain, String ticker) async {
|
||||
var address = '';
|
||||
|
||||
try {
|
||||
final uri = Uri.parse(
|
||||
"https://api.unstoppabledomains.com/profile/public/${Uri.encodeQueryComponent(domain)}?fields=records");
|
||||
final response = await ProxyWrapper().get(clearnetUri: uri);
|
||||
|
||||
final jsonParsed = json.decode(response.body) as Map<String, dynamic>;
|
||||
if (jsonParsed["records"] == null) {
|
||||
throw Exception(".records response from $uri is empty");
|
||||
}
|
||||
;
|
||||
final records = jsonParsed["records"] as Map<String, dynamic>;
|
||||
final key = "crypto.${ticker.toUpperCase()}.address";
|
||||
if (records[key] == null) {
|
||||
throw Exception(".records.${key} response from $uri is empty");
|
||||
}
|
||||
|
||||
return records[key] as String? ?? '';
|
||||
} catch (e) {
|
||||
printV('Unstoppable domain error: ${e.toString()}');
|
||||
address = '';
|
||||
}
|
||||
|
||||
return address;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user