Reformat the whole codebase with 100 line width (#3403)

This commit is contained in:
Omar Hatem
2026-07-15 01:20:33 +03:00
committed by GitHub
parent 1241b28bec
commit 16ddc0837a
801 changed files with 17517 additions and 17091 deletions
@@ -5,7 +5,6 @@ import 'package:cw_core/crypto_currency.dart';
import 'package:cw_core/wallet_base.dart';
abstract class AddressLookupProvider {
AddressSource get source;
List<CryptoCurrency> get supportedCurrencies;
@@ -104,7 +104,8 @@ class AddressResolverService {
if (results.isNotEmpty) {
final parsedAddress = results.first.parsedAddressByCurrencyMap[currency];
final parsedAddressStr = parsedAddress == null || parsedAddress.isEmpty ? 'N/A' : parsedAddress;
final parsedAddressStr =
parsedAddress == null || parsedAddress.isEmpty ? 'N/A' : parsedAddress;
printV('[address resolver service] resolved $src - $cur - $parsedAddressStr');
return [results.first];
}
@@ -14,7 +14,8 @@ class AddressResolverUtils {
final result = <CryptoCurrency, String>{};
for (final currency in currencies) {
final address = await UnstoppableAddressProvider.fetchUnstoppableDomainAddress(domain, currency.title);
final address =
await UnstoppableAddressProvider.fetchUnstoppableDomainAddress(domain, currency.title);
if (address.isNotEmpty) {
result[currency] = address;
}
@@ -54,15 +54,17 @@ class Bip353AddressProvider extends AddressLookupProvider {
printV('Bip353Record.fetchDnsProof error: $e');
}
return [ParsedAddress(
parsedAddressByCurrencyMap: result,
addressSource: AddressSource.bip353,
handle: query,
bip353DnsProof: dnsProof ?? '',
)];
return [
ParsedAddress(
parsedAddressByCurrencyMap: result,
addressSource: AddressSource.bip353,
handle: query,
bip353DnsProof: dnsProof ?? '',
)
];
} catch (e) {
printV('[address resolver] Error resolving BIP353 address: $e');
return [];
}
}
}
}
@@ -99,5 +99,4 @@ class Bip353Record {
return result;
}
}
}
}
+12 -12
View File
@@ -9,10 +9,10 @@ import 'package:web3dart/web3dart.dart';
class EnsRecord {
static Future<String> fetchEnsAddress(
String name,
CryptoCurrency cur, {
WalletBase? wallet,
}) async {
String name,
CryptoCurrency cur, {
WalletBase? wallet,
}) async {
Web3Client? _client;
if (wallet?.type == WalletType.ethereum || wallet?.type == WalletType.polygon) {
@@ -45,11 +45,11 @@ class EnsRecord {
}
static CoinType? getEnsCoinType(CryptoCurrency cur) => switch (cur) {
CryptoCurrency.xmr => CoinType.XMR,
CryptoCurrency.btc => CoinType.BTC,
CryptoCurrency.ltc => CoinType.LTC,
CryptoCurrency.eth => CoinType.ETH,
CryptoCurrency.matic => CoinType.MATIC,
_ => null,
};
}
CryptoCurrency.xmr => CoinType.XMR,
CryptoCurrency.btc => CoinType.BTC,
CryptoCurrency.ltc => CoinType.LTC,
CryptoCurrency.eth => CoinType.ETH,
CryptoCurrency.matic => CoinType.MATIC,
_ => null,
};
}
@@ -34,23 +34,23 @@ class FioAddressProvider extends AddressLookupProvider {
}) async {
final Map<CryptoCurrency, String> result = {};
try {
final bool isFioRegistered = await FioAddressProvider.checkAvail(query);
if (!isFioRegistered) return [];
final bool isFioRegistered = await FioAddressProvider.checkAvail(query);
if (!isFioRegistered) return [];
for (final cur in currencies) {
final address = await FioAddressProvider.getPubAddress(query, cur.title);
if (address != null && address.isNotEmpty) {
result[cur] = address;
for (final cur in currencies) {
final address = await FioAddressProvider.getPubAddress(query, cur.title);
if (address != null && address.isNotEmpty) {
result[cur] = address;
}
}
}
if (result.isNotEmpty) {
return [
ParsedAddress(
parsedAddressByCurrencyMap: result, addressSource: AddressSource.fio, handle: query)
];
}
return [];
if (result.isNotEmpty) {
return [
ParsedAddress(
parsedAddressByCurrencyMap: result, addressSource: AddressSource.fio, handle: query)
];
}
return [];
} catch (e) {
printV('FioAddressProvider.resolve error: $e');
return [];
@@ -16,7 +16,8 @@ class LNUrlPayAddressProvider extends AddressLookupProvider {
List<CryptoCurrency> get supportedCurrencies => [CryptoCurrency.btcln];
@override
bool canHandle(String q) => q.contains('.') && q.contains('@'); // LNURL-pay handle example: user@domain.com
bool canHandle(String q) =>
q.contains('.') && q.contains('@'); // LNURL-pay handle example: user@domain.com
@override
bool isEnabled(SettingsStore settingsStore) => settingsStore.lookupsLNUrl;
@@ -63,4 +64,4 @@ class LNUrlPayAddressProvider extends AddressLookupProvider {
return [];
}
}
}
}
@@ -13,7 +13,7 @@ class LNUrlPayRecord {
final String address;
static Future<String?> checkWellKnownUsername(String username, CryptoCurrency currency,
{bool allowRethrow = false}) async {
{bool allowRethrow = false}) async {
if (![CryptoCurrency.btc, CryptoCurrency.btcln].contains(currency)) return null;
// split the string by the @ symbol:
@@ -21,7 +21,6 @@ class MastodonAPI {
);
final response = await ProxyWrapper().get(clearnetUri: uri);
if (response.statusCode != 200) return null;
@@ -49,7 +48,6 @@ class MastodonAPI {
);
final response = await ProxyWrapper().get(clearnetUri: uri);
if (response.statusCode != 200) {
throw Exception('Unexpected HTTP status: ${response.statusCode}');
@@ -15,12 +15,11 @@ class MastodonUser {
factory MastodonUser.fromJson(Map<String, dynamic> json) {
return MastodonUser(
id: json['id'] as String,
username: json['username'] as String? ?? '',
acct: json['acct'] as String,
note: json['note'] as String,
profileImageUrl: json['avatar'] as String? ?? ''
);
id: json['id'] as String,
username: json['username'] as String? ?? '',
acct: json['acct'] as String,
note: json['note'] as String,
profileImageUrl: json['avatar'] as String? ?? '');
}
}
@@ -21,9 +21,9 @@ class NostrProfileHandler {
}
static Future<UserMetadata?> processRelays(
ProfilePointer profile,
String nip05Address,
) async {
ProfilePointer profile,
String nip05Address,
) async {
final userDomain = _extractDomain(nip05Address);
const int metaKind = 0;
@@ -124,4 +124,4 @@ class NostrProfileHandler {
return '';
}
}
}
}
@@ -1,4 +1,3 @@
class UserMetadata {
final String name;
final String lnurl;
@@ -32,4 +31,4 @@ class UserMetadata {
website: json['website'] as String? ?? '',
);
}
}
}
@@ -66,4 +66,4 @@ class OpenaliasRecord {
return OpenaliasRecord(address: address, name: name, description: note);
}
}
}
@@ -19,4 +19,4 @@ class ParsedAddress {
final String profileName;
final String description;
final String? bip353DnsProof;
}
}
@@ -11,7 +11,6 @@ import 'package:cw_core/utils/print_verbose.dart';
import 'package:cw_core/wallet_base.dart';
class TwitterAddressProvider extends AddressLookupProvider {
@override
AddressSource get source => AddressSource.twitter;
@@ -23,14 +23,14 @@ class TwitterApi {
path: userPath + userName,
queryParameters: queryParams);
final response = await ProxyWrapper().get(clearnetUri: uri, headers: headers).catchError((error) {
final response =
await ProxyWrapper().get(clearnetUri: uri, headers: headers).catchError((error) {
throw Exception('HTTP request failed: $error');
});
if (response.statusCode != 200) {
throw Exception('Unexpected http status: ${response.statusCode}');
}
final Map<String, dynamic> responseJSON = jsonDecode(response.body) as Map<String, dynamic>;
if (responseJSON['errors'] != null &&
@@ -211,13 +211,15 @@ class UnstoppableAddressProvider extends AddressLookupProvider {
var address = '';
try {
final uri = Uri.parse("https://api.unstoppabledomains.com/profile/public/${Uri.encodeQueryComponent(domain)}?fields=records");
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) {
@@ -20,9 +20,9 @@ class WellKnownRecord {
static const _jsonLocation = {CryptoCurrency.nano: 'nano-currency'};
static Future<WellKnownRecord?> fetch(
String username,
CryptoCurrency currency,
) async {
String username,
CryptoCurrency currency,
) async {
final location = _jsonLocation[currency];
if (location == null) {
printV('well-known: unsupported coin $currency');
@@ -75,4 +75,4 @@ class WellKnownRecord {
}
return null;
}
}
}
@@ -16,4 +16,4 @@ class YatRecord {
@override
String toString() => 'YatRecord(tag: $tag, address: $address)';
}
}
@@ -11,8 +11,7 @@ class YatService {
static const apiReleaseUrl = "https://a.y.at";
static const apiDevUrl = 'https://a.yat.fyi';
static String lookupEmojiUrl(String emojiId) =>
"$apiUrl/emoji_id/$emojiId/payment";
static String lookupEmojiUrl(String emojiId) => "$apiUrl/emoji_id/$emojiId/payment";
static const String MONERO_SUB_ADDRESS = '0x1002';
static const String MONERO_STD_ADDRESS = '0x1001';
@@ -23,9 +22,9 @@ class YatService {
};
static Future<List<YatRecord>> fetchYatAddress(
String emojiId,
String ticker,
) async {
String emojiId,
String ticker,
) async {
final tagQuery = tags[ticker.toUpperCase()];
if (tagQuery == null) return const [];
@@ -48,9 +47,7 @@ class YatService {
records.add(YatRecord.fromJson(data, tag.toString()));
}
});
}
else if (res is List) {
} else if (res is List) {
for (final item in res) {
if (item is Map<String, dynamic>) {
final tag = item['tag']?.toString() ?? '';
@@ -64,4 +61,4 @@ class YatService {
return const [];
}
}
}
}
+30 -34
View File
@@ -25,29 +25,28 @@ class YatLink {
static const requestReleaseUrl = ''; //'https://a.y.at/emoji_id/';
static const startFlowUrl = ''; // 'https://www.y03btrk.com/4RQSJ/6JHXF/';
static const isDevMode = true;
static const tags = <String, List<String>>{"XMR" : ['0x1001', '0x1002'],
"BTC" : ['0x1003'], "LTC" : ['0x1019']};
static const tags = <String, List<String>>{
"XMR": ['0x1001', '0x1002'],
"BTC": ['0x1003'],
"LTC": ['0x1019']
};
static String get apiUrl => YatLink.isDevMode
? YatLink.apiDevUrl
: YatLink.apiReleaseUrl;
static String get apiUrl => YatLink.isDevMode ? YatLink.apiDevUrl : YatLink.apiReleaseUrl;
static String get emojiIdUrl => apiUrl + '/emoji_id/';
static String get baseUrl => YatLink.isDevMode
? YatLink.baseDevUrl
: YatLink.baseReleaseUrl;
static String get baseUrl => YatLink.isDevMode ? YatLink.baseDevUrl : YatLink.baseReleaseUrl;
}
Future<List<String>> fetchYatAddress(String emojiId, String ticker) async {
throw Exception();
//final url = YatLink.emojiIdUrl + emojiId + '/payment';
//final response = await get(url);
//if (response.statusCode != 200) {
// throw YatException(text: response.body.toString());
//}
//final addresses = <String>[];
//final currency = ticker.toUpperCase();
//final responseJSON = json.decode(response.body) as Map<String, dynamic>;
@@ -55,7 +54,7 @@ Future<List<String>> fetchYatAddress(String emojiId, String ticker) async {
//result.forEach((dynamic key, dynamic value) {
// final tag = key as String ?? '';
// final record = value as Map<String, dynamic>;
// if (YatLink.tags[currency]?.contains(tag) ?? false) {
// final address = record['address'] as String;
// if (address?.isNotEmpty ?? false) {
@@ -80,11 +79,11 @@ Future<String> fetchYatAccessToken(String refreshToken) async {
// 'Accept': '*/*'
// },
// body: bodyJson);
// if (response.statusCode != 200) {
// throw YatException(text: response.body.toString());
// }
// final responseJSON = json.decode(response.body) as Map<String, dynamic>;
// return responseJSON['access_token'] as String;
//}catch(_) {
@@ -110,7 +109,7 @@ Future<String> fetchYatApiKey(String accessKey) async {
// if (response.statusCode != 200) {
// throw YatException(text: response.body.toString());
// }
// final responseJSON = json.decode(response.body) as Map<String, dynamic>;
// return responseJSON['api_key'] as String;
//}catch(_) {
@@ -119,7 +118,8 @@ Future<String> fetchYatApiKey(String accessKey) async {
return '';
}
Future<void> updateEmojiIdAddress(String emojiId, String address, String apiKey, WalletType type) async {
Future<void> updateEmojiIdAddress(
String emojiId, String address, String apiKey, WalletType type) async {
throw Exception();
//final url = YatLink.emojiIdUrl + emojiId;
//final cur = walletTypeToCryptoCurrency(type);
@@ -166,15 +166,13 @@ Future<String> visualisationForEmojiId(String emojiId) async {
class YatStore = YatStoreBase with _$YatStore;
abstract class YatStoreBase with Store {
YatStoreBase({
required this.appStore,
required this.secureStorage})
: _wallet = appStore.wallet,
emoji = appStore.wallet?.walletInfo?.yatEmojiId ?? '',
refreshToken = '',
accessToken = '',
apiKey = '',
emojiIncommingSC = StreamController<String>.broadcast() {
YatStoreBase({required this.appStore, required this.secureStorage})
: _wallet = appStore.wallet,
emoji = appStore.wallet?.walletInfo?.yatEmojiId ?? '',
refreshToken = '',
accessToken = '',
apiKey = '',
emojiIncommingSC = StreamController<String>.broadcast() {
//reaction((_) => appStore.wallet, _onWalletChange);
//reaction((_) => emoji, (String _) => _onEmojiChange());
//reaction((_) => refreshToken, (String _) => _onRefreshTokenChange());
@@ -209,24 +207,22 @@ abstract class YatStoreBase with Store {
Stream<String> get emojiIncommingStream => emojiIncommingSC.stream;
@observable
WalletBase<Balance, TransactionHistoryBase<TransactionInfo>, TransactionInfo>?
_wallet;
WalletBase<Balance, TransactionHistoryBase<TransactionInfo>, TransactionInfo>? _wallet;
Future<void> init() async {
if (_wallet == null) {
return;
}
refreshToken = await secureStorage.read(key: yatRefreshTokenKey(_wallet!.walletInfo.name)) ?? '';
refreshToken =
await secureStorage.read(key: yatRefreshTokenKey(_wallet!.walletInfo.name)) ?? '';
accessToken = await secureStorage.read(key: yatAccessTokenKey(_wallet!.walletInfo.name)) ?? '';
apiKey = await secureStorage.read(key: yatApiKey(_wallet!.walletInfo.name)) ?? '';
}
@action
void _onWalletChange(
WalletBase<Balance, TransactionHistoryBase<TransactionInfo>,
TransactionInfo>
wallet) {
WalletBase<Balance, TransactionHistoryBase<TransactionInfo>, TransactionInfo> wallet) {
this._wallet = wallet;
emoji = wallet?.walletInfo?.yatEmojiId ?? '';
init();
@@ -252,7 +248,7 @@ abstract class YatStoreBase with Store {
@action
Future<void> _onRefreshTokenChange() async {
throw Exception();
//try {
// await secureStorage.write(key: yatRefreshTokenKey(_wallet.walletInfo.name), value: refreshToken);
// accessToken = await fetchYatAccessToken(refreshToken);
@@ -269,7 +265,7 @@ abstract class YatStoreBase with Store {
//final result = <String, String>{};
//final tags = YatLink.tags[_wallet.currency.toString().toUpperCase()];
//String tag = tags.first;
//if (_wallet.type == WalletType.monero
// && _wallet.walletAddresses.address.startsWith('4')) {
// tag = tags.last;
@@ -277,7 +273,7 @@ abstract class YatStoreBase with Store {
//result[tag] = '${_wallet.walletAddresses.address}|${_wallet.name}';
//final addressJson = json.encode([result]);
//final addressJsonBytes = utf8.encode(addressJson);
//return base64.encode(addressJsonBytes);
return '';
}
@@ -10,7 +10,6 @@ import 'package:cw_core/utils/proxy_wrapper.dart';
import 'package:cw_core/wallet_base.dart';
class ZanoAliasAddressProvider extends AddressLookupProvider {
@override
AddressSource get source => AddressSource.zanoAlias;
@@ -67,8 +67,7 @@ class ZcashNamesRecord {
}
static bool _isValidZcashAddress(String address) {
final pattern =
AddressValidator.getAddressFromStringPattern(CryptoCurrency.zec);
final pattern = AddressValidator.getAddressFromStringPattern(CryptoCurrency.zec);
if (pattern == null) return false;
return RegExp('^(?:$pattern)\$').hasMatch(address);
}
+28 -29
View File
@@ -12,29 +12,29 @@ const AFTER_REGEX = '(\$|\\s)';
class AddressValidator extends TextValidator {
AddressValidator({required CryptoCurrency type, bool isTestnet = false})
: super(
errorMessage: S.current.error_text_address,
useAdditionalValidation: [CryptoCurrency.btc, CryptoCurrency.ltc].contains(type)
? (String txt) {
final RegExp lightningInvoiceRegex = RegExp(
r'^(lightning:)?(lnbc|lntb|lnbs|lnbcrt|lnurl)[a-z0-9]+$',
caseSensitive: false);
if (lightningInvoiceRegex.hasMatch(txt)) return true;
errorMessage: S.current.error_text_address,
useAdditionalValidation: [CryptoCurrency.btc, CryptoCurrency.ltc].contains(type)
? (String txt) {
final RegExp lightningInvoiceRegex = RegExp(
r'^(lightning:)?(lnbc|lntb|lnbs|lnbcrt|lnurl)[a-z0-9]+$',
caseSensitive: false);
if (lightningInvoiceRegex.hasMatch(txt)) return true;
return BitcoinAddressUtils.validateAddress(
address: txt,
network: type == CryptoCurrency.btc
? isTestnet
? BitcoinNetwork.testnet
: BitcoinNetwork.mainnet
: LitecoinNetwork.mainnet,
);
}
: type == CryptoCurrency.zano
? zano?.validateAddress
: null,
pattern: getPattern(type, isTestnet: isTestnet),
length: getLength(type),
);
return BitcoinAddressUtils.validateAddress(
address: txt,
network: type == CryptoCurrency.btc
? isTestnet
? BitcoinNetwork.testnet
: BitcoinNetwork.mainnet
: LitecoinNetwork.mainnet,
);
}
: type == CryptoCurrency.zano
? zano?.validateAddress
: null,
pattern: getPattern(type, isTestnet: isTestnet),
length: getLength(type),
);
static const List<CryptoCurrency> reliableValidateCurrencies = [
CryptoCurrency.xmr,
@@ -170,8 +170,7 @@ class AddressValidator extends TextValidator {
case CryptoCurrency.hbar:
pattern = '[0-9a-zA-Z.]+';
case CryptoCurrency.zec:
pattern =
'(?:'
pattern = '(?:'
't1[0-9A-Za-z]{33}'
'|t3[0-9A-Za-z]{33}'
'|zs[a-z0-9]{76}'
@@ -195,7 +194,8 @@ class AddressValidator extends TextValidator {
case CryptoCurrency.pivx:
pattern = 'D([1-9a-km-zA-HJ-NP-Z]){33}';
case CryptoCurrency.btcln:
pattern = r'(lightning:)?(lnbc|lntb|lnbs|lnbcrt|lnurl|LNBC|LNTB|LNBS|LNBCRT|LNURL)[a-zA-Z0-9]+';
pattern =
r'(lightning:)?(lnbc|lntb|lnbs|lnbcrt|lnurl|LNBC|LNTB|LNBS|LNBCRT|LNURL)[a-zA-Z0-9]+';
case CryptoCurrency.zano:
pattern = r'([1-9A-HJ-NP-Za-km-z]{90,200})|(@[\w\d.-]+)';
case CryptoCurrency.doge:
@@ -369,7 +369,7 @@ class AddressValidator extends TextValidator {
'|([0-9a-zA-Z]{106})';
case CryptoCurrency.btc:
pattern =
'${P2pkhAddress.regex.pattern}|${P2shAddress.regex.pattern}|${P2wpkhAddress.regex.pattern}|${P2trAddress.regex.pattern}|${P2wshAddress.regex.pattern}|${SilentPaymentAddress.regex.pattern}';
'${P2pkhAddress.regex.pattern}|${P2shAddress.regex.pattern}|${P2wpkhAddress.regex.pattern}|${P2trAddress.regex.pattern}|${P2wshAddress.regex.pattern}|${SilentPaymentAddress.regex.pattern}';
case CryptoCurrency.ltc:
pattern = '([^0-9a-zA-Z]|^)^L[a-zA-Z0-9]{26,33}([^0-9a-zA-Z]|\$)'
'|([^0-9a-zA-Z]|^)[LM][a-km-zA-HJ-NP-Z1-9]{26,33}([^0-9a-zA-Z]|\$)'
@@ -394,8 +394,7 @@ class AddressValidator extends TextValidator {
case CryptoCurrency.zano:
pattern = '([1-9A-HJ-NP-Za-km-z]{90,200})|(@[\w\d.-]+)';
case CryptoCurrency.zec:
pattern =
'(?:'
pattern = '(?:'
't1[0-9A-Za-z]{33}'
'|t3[0-9A-Za-z]{33}'
'|zs[a-z0-9]{76}'
@@ -419,4 +418,4 @@ class AddressValidator extends TextValidator {
return pattern != null ? "($pattern)" : null;
}
}
}
+3 -3
View File
@@ -12,9 +12,9 @@ class AmountValidator extends TextValidator {
String? minValue,
String? maxValue,
}) {
symbolsAmountValidator =
SymbolsAmountValidator(isAutovalidate: isAutovalidate);
decimalAmountValidator = DecimalAmountValidator(currency: currency,isAutovalidate: isAutovalidate);
symbolsAmountValidator = SymbolsAmountValidator(isAutovalidate: isAutovalidate);
decimalAmountValidator =
DecimalAmountValidator(currency: currency, isAutovalidate: isAutovalidate);
amountMinValidator = AmountMinValidator(
minValue: minValue,
-1
View File
@@ -17,4 +17,3 @@ class AuthenticationBanned extends AuthState {
final String error;
}
+26 -21
View File
@@ -25,8 +25,8 @@ import 'package:cake_wallet/wallet_types.g.dart';
import 'package:cake_backup/backup.dart' as cake_backup;
class $BackupService {
$BackupService(this._secureStorage, this.transactionDescriptionBox,
this.keyService, this.sharedPreferences)
$BackupService(
this._secureStorage, this.transactionDescriptionBox, this.keyService, this.sharedPreferences)
: cipher = Cryptography.instance.chacha20Poly1305Aead(),
correctWallets = <WalletInfo>[];
@@ -42,7 +42,6 @@ class $BackupService {
final KeyService keyService;
List<WalletInfo> correctWallets;
Future<void> importBackupV1(Uint8List data, String password, {required String nonce}) async {
final appDir = await getAppDir();
final decryptedData = await _decryptV1(data, password, nonce);
@@ -59,7 +58,8 @@ class $BackupService {
} else {
Directory('${appDir.path}/' + filename)..create(recursive: true);
}
};
}
;
await verifyWallets();
await _importKeychainDumpV1(password, nonce: nonce);
@@ -101,7 +101,8 @@ class $BackupService {
dir.createSync(recursive: true);
}
}
};
}
;
await verifyWallets();
await importKeychainDumpV2(password);
@@ -112,7 +113,9 @@ class $BackupService {
Future<void> verifyWallets() async {
await performHiveMigration(); // for backups made before sqlite migration
await performTradeHiveMigration(_secureStorage);
correctWallets = (await WalletInfo.getAll()).where((info) => availableWalletTypes.contains(info.type)).toList();
correctWallets = (await WalletInfo.getAll())
.where((info) => availableWalletTypes.contains(info.type))
.toList();
if (correctWallets.isEmpty) {
printV('Correct wallets not detected');
@@ -133,12 +136,11 @@ class $BackupService {
MapEntry(key, TransactionDescription.fromJson(value as Map<String, dynamic>)));
var box = transactionDescriptionBox;
if (!box.isOpen) {
final transactionDescriptionsBoxKey =
await getEncryptionKey(secureStorage: _secureStorage, forKey: TransactionDescription.boxKey);
box = await CakeHive.openBox<TransactionDescription>(
TransactionDescription.boxName,
encryptionKey: transactionDescriptionsBoxKey);
}
final transactionDescriptionsBoxKey = await getEncryptionKey(
secureStorage: _secureStorage, forKey: TransactionDescription.boxKey);
box = await CakeHive.openBox<TransactionDescription>(TransactionDescription.boxName,
encryptionKey: transactionDescriptionsBoxKey);
}
await box.putAll(descriptionsMap);
}
@@ -152,7 +154,8 @@ class $BackupService {
final data = json.decode(preferencesFile.readAsStringSync()) as Map<String, dynamic>;
try { // shouldn't throw an error but just in case, so it doesn't stop the backup restore
try {
// shouldn't throw an error but just in case, so it doesn't stop the backup restore
for (var entry in data.entries) {
String key = entry.key;
dynamic value = entry.value;
@@ -170,7 +173,8 @@ class $BackupService {
await sharedPreferences.setStringList(key, value);
} else {
if (kDebugMode) {
printV('Skipping individual save for key "$key": Unsupported type (${value.runtimeType}). Value: $value');
printV(
'Skipping individual save for key "$key": Unsupported type (${value.runtimeType}). Value: $value');
}
}
}
@@ -187,9 +191,7 @@ class $BackupService {
currentWalletName = correctWallets.first.name;
currentWalletType = serializeToInt(correctWallets.first.type);
}
} catch (e) {
}
} catch (e) {}
if (DeviceInfo.instance.isDesktop) {
await sharedPreferences.setInt(PreferencesKey.currentTheme, ThemeList.darkTheme.raw);
@@ -247,8 +249,8 @@ class $BackupService {
for (var key in (keychainJSON['_all'] as Map<String, dynamic>).keys) {
try {
if (!key.startsWith('MONERO_WALLET_')) continue;
final decodedPassword = decodeWalletPassword(
password: keychainJSON['_all'][key].toString());
final decodedPassword =
decodeWalletPassword(password: keychainJSON['_all'][key].toString());
final walletName = key.split('_WALLET_')[1];
final walletType = key.split('_WALLET_')[0].toLowerCase();
await importWalletKeychainInfo({
@@ -294,8 +296,11 @@ class $BackupService {
}));
final backupPasswordKey = generateStoreKeyFor(key: SecretStoreKey.backupPassword);
final backupPassword = await _secureStorage.read(key: backupPasswordKey);
final data = utf8.encode(
json.encode({'wallets': wallets, backupPasswordKey: backupPassword, '_all': await _secureStorage.readAll()}));
final data = utf8.encode(json.encode({
'wallets': wallets,
backupPasswordKey: backupPassword,
'_all': await _secureStorage.readAll()
}));
final encrypted = await _encryptV2(Uint8List.fromList(data), '$keychainSalt$password');
return encrypted;
+33 -30
View File
@@ -73,6 +73,7 @@ class ChunkLength {
'plain': plain,
};
}
@override
String toString() {
return 'ChunkLength(encrypted: $encrypted, plain: $plain)';
@@ -124,7 +125,9 @@ class BackupMetadata {
return BackupMetadata(
version: BackupVersion.values[json['version'] as int],
sha512sum: json['sha512sum'] as String,
chunks: (json['chunks'] as List<dynamic>).map((chunk) => ChunkDetails.fromJson(chunk as Map<String, dynamic>)).toList(),
chunks: (json['chunks'] as List<dynamic>)
.map((chunk) => ChunkDetails.fromJson(chunk as Map<String, dynamic>))
.toList(),
cakeVersion: json['cakeVersion'] as String,
);
}
@@ -160,7 +163,8 @@ class IncompatibleBackupAppException implements Exception {
}
class BackupServiceV3 extends $BackupService {
BackupServiceV3(super.secureStorage, super.transactionDescriptionBox, super.keyService, super.sharedPreferences);
BackupServiceV3(super.secureStorage, super.transactionDescriptionBox, super.keyService,
super.sharedPreferences);
static BackupVersion get currentVersion => BackupVersion.v3;
@@ -170,12 +174,12 @@ class BackupServiceV3 extends $BackupService {
BackupVersion getVersionFile(File data) {
final raf = data.openSync(mode: FileMode.read);
try {
// Read first 4 bytes to check both version and zip signature
final buffer = Uint8List(1);
final bytesRead = raf.readIntoSync(buffer);
if (bytesRead == 0) {
throw Exception('Invalid backup file: empty file');
}
@@ -231,7 +235,7 @@ class BackupServiceV3 extends $BackupService {
}
Future<void> importBackupFileV3(File file, String password,
{String nonce = secrets.backupSalt,bool checkBackupApp = true}) async{
{String nonce = secrets.backupSalt, bool checkBackupApp = true}) async {
// Overall design of v3 backup is the following:
// 1. backup.zip - plaintext zip file that user can open with any archive manager
// 2. backup.zip/README.txt - text file to let user know what is inside of this file
@@ -259,14 +263,14 @@ class BackupServiceV3 extends $BackupService {
throw Exception('Invalid v3 backup: missing data.bin');
}
final dataStream = dataFile.rawContent!.getStream();
final decryptedData = File('${file.path}_decrypted'); // decrypted zip file
if (decryptedData.existsSync()) {
decryptedData.deleteSync();
}
decryptedData.createSync(recursive: true);
decryptedData.writeAsBytesSync(Uint8List(0), mode: FileMode.write, flush: true);
int chunkIndex = 0;
for (var chunk in metadata.chunks) {
chunkIndex++;
@@ -275,7 +279,8 @@ class BackupServiceV3 extends $BackupService {
// readBytes stores position internally, so we don't need to think about it.
if (chunk.sha512sum.encrypted != chunkChecksum) {
throw Exception('Invalid v3 backup: chunk (${chunk.length.encrypted} bytes) checksum mismatch at index $chunkIndex\n'
throw Exception(
'Invalid v3 backup: chunk (${chunk.length.encrypted} bytes) checksum mismatch at index $chunkIndex\n'
'expected: ${chunk.sha512sum.encrypted}\n'
'got: $chunkChecksum');
}
@@ -283,7 +288,6 @@ class BackupServiceV3 extends $BackupService {
decryptedData.writeAsBytesSync(decryptedChunk, mode: FileMode.append, flush: true);
}
final sha512sum = (await sha512.bind(decryptedData.openRead()).first).toString();
if (sha512sum.toString() != metadata.sha512sum) {
throw Exception('Invalid v3 backup: SHA512 checksum mismatch\n'
@@ -301,7 +305,6 @@ class BackupServiceV3 extends $BackupService {
final decryptedDataStream = InputFileStream(decryptedData.path);
final backupArchive = zip.decodeStream(decryptedDataStream);
final appDir = await getAppDir();
outer:
@@ -315,8 +318,7 @@ class BackupServiceV3 extends $BackupService {
}
printV("restoring: $filename");
if (file.isFile) {
final output = File('${appDir.path}/' + filename)
..createSync(recursive: true);
final output = File('${appDir.path}/' + filename)..createSync(recursive: true);
final outputStream = OutputFileStream(output.path);
file.writeContent(outputStream);
outputStream.flush();
@@ -326,7 +328,8 @@ class BackupServiceV3 extends $BackupService {
dir.createSync(recursive: true);
}
}
};
}
;
// Continue importing the backup the old way
await super.verifyWallets();
@@ -344,10 +347,10 @@ class BackupServiceV3 extends $BackupService {
{String keychainSalt = secrets.backupKeychainSalt}) async {
final appDir = await getAppDir();
final keychainDumpFile = File('${appDir.path}/~_keychain_dump');
final decryptedKeychainDumpFileData = await decryptV2(
keychainDumpFile.readAsBytesSync(), '$keychainSalt$password');
final keychainJSON = json.decode(utf8.decode(decryptedKeychainDumpFileData))
as Map<String, dynamic>;
final decryptedKeychainDumpFileData =
await decryptV2(keychainDumpFile.readAsBytesSync(), '$keychainSalt$password');
final keychainJSON =
json.decode(utf8.decode(decryptedKeychainDumpFileData)) as Map<String, dynamic>;
final keychainWalletsInfo = keychainJSON['wallets'] as List;
final expectedHardwareWallets = keychainWalletsInfo
@@ -358,10 +361,10 @@ class BackupServiceV3 extends $BackupService {
for (final expectedHardwareWallet in expectedHardwareWallets) {
final info = expectedHardwareWallet as Map<String, dynamic>;
final actualWalletInfo = await WalletInfo.get(info['name'] as String, WalletType.values.firstWhere((e) => e.toString() == info['type'] as String));
final actualWalletInfo = await WalletInfo.get(info['name'] as String,
WalletType.values.firstWhere((e) => e.toString() == info['type'] as String));
if (actualWalletInfo != null &&
info["hardwareWalletType"] !=
actualWalletInfo.hardwareWalletType?.index) {
info["hardwareWalletType"] != actualWalletInfo.hardwareWalletType?.index) {
actualWalletInfo.hardwareWalletType =
HardwareWalletType.values[info["hardwareWalletType"] as int];
await actualWalletInfo.save();
@@ -390,7 +393,8 @@ class BackupServiceV3 extends $BackupService {
final transactionDescriptionDumpFile =
File('${tmpDir.path}/~_transaction_descriptions_dump_TMP');
final transactionDescriptionData = super.transactionDescriptionBox
final transactionDescriptionData = super
.transactionDescriptionBox
.toMap()
.map((key, value) => MapEntry(key.toString(), value.toJson()));
final transactionDescriptionDump = jsonEncode(transactionDescriptionData);
@@ -443,15 +447,14 @@ class BackupServiceV3 extends $BackupService {
int chunkIndex = 0;
final stopwatch = Stopwatch()..start();
printV("Starting backup encryption...");
metadata.sha512sum = (await sha512.bind(dataBinUnencrypted.openRead()).first).toString();
final raf = await dataBinUnencrypted.open();
while (true) {
printV("Reading chunk ${chunkIndex++}");
stopwatch.reset();
final chunk = await raf.read(chunkSize);
printV("Chunk read completed in ${stopwatch.elapsed}");
@@ -459,13 +462,14 @@ class BackupServiceV3 extends $BackupService {
if (chunk.length == 0) {
break;
}
stopwatch.reset();
final encryptedChunk = await cake_backup.encrypt(password, chunk);
printV("Encryption completed in ${stopwatch.elapsed}");
stopwatch.reset();
final sha512sumEncryptedChunk = await sha512.bind(Stream.fromIterable([encryptedChunk])).first;
final sha512sumEncryptedChunk =
await sha512.bind(Stream.fromIterable([encryptedChunk])).first;
final sha512sumUnencryptedChunk = await sha512.bind(Stream.fromIterable([chunk])).first;
printV("Hashing completed in ${stopwatch.elapsed}");
@@ -481,7 +485,7 @@ class BackupServiceV3 extends $BackupService {
plain: chunk.length,
),
));
await dataBinWriter.flush();
printV("Writing completed in ${stopwatch.elapsed}");
}
@@ -495,7 +499,8 @@ class BackupServiceV3 extends $BackupService {
metadataFile.writeAsStringSync(JsonEncoder.withIndent(' ').convert(metadata.toJson()));
final readmeFile = File('${tmpDir.path}/README.txt');
readmeFile.writeAsStringSync('''This is a ${packageInfo.appName} backup. Do not modify this archive.
readmeFile
.writeAsStringSync('''This is a ${packageInfo.appName} backup. Do not modify this archive.
App version: ${packageInfo.version}
@@ -524,11 +529,9 @@ This backup was created on ${DateTime.now().toIso8601String()}
final sourceAppName = _extractBackupAppName(readmeString);
if (sourceAppName == null) return;
final currentAppName = (await PackageInfo.fromPlatform()).appName;
if (sourceAppName == currentAppName) return;
throw IncompatibleBackupAppException(
sourceAppName: sourceAppName,
currentAppName: currentAppName,
+4 -7
View File
@@ -73,12 +73,8 @@ class CsvExportService {
// Prefer tx.to/tx.from; fall back to address lists for chains that don't populate them.
final address = tx.direction == TransactionDirection.incoming
? (tx.from?.isNotEmpty == true
? tx.from!
: (tx.inputAddresses?.firstOrNull ?? ''))
: (tx.to?.isNotEmpty == true
? tx.to!
: (tx.outputAddresses?.firstOrNull ?? ''));
? (tx.from?.isNotEmpty == true ? tx.from! : (tx.inputAddresses?.firstOrNull ?? ''))
: (tx.to?.isNotEmpty == true ? tx.to! : (tx.outputAddresses?.firstOrNull ?? ''));
final fee = tx.fee != null && !tx.fee!.isZero ? tx.fee.toString() : '';
@@ -213,7 +209,8 @@ class CsvExportService {
String _isoDate(DateTime dt) => dt.toUtc().toIso8601String();
Future<void> exportToCsv(List<ActionListItem> items, BuildContext context) async {
final dataItems = items.whereType<ActionListItem>().where((e) => e is! DateSectionItem).toList();
final dataItems =
items.whereType<ActionListItem>().where((e) => e is! DateSectionItem).toList();
if (dataItems.isEmpty) {
await showBar<void>(context, S.current.csv_nothing_to_export);
+1 -2
View File
@@ -5,7 +5,6 @@ class EmailValidator extends TextValidator {
EmailValidator()
: super(
errorMessage: 'Invalid email address',
pattern:
'^[^@]+@[^@]+\.[^@]+',
pattern: '^[^@]+@[^@]+\.[^@]+',
);
}
+1 -1
View File
@@ -25,4 +25,4 @@ class AwaitingConfirmationState extends ExecutionState {
final String? message;
final Function()? onConfirm;
final Function()? onCancel;
}
}
+6 -12
View File
@@ -10,7 +10,6 @@ const _fiatApiOnionAuthority = '46wisoe2uwipcj2j4og6smiq7hbmj34fkkrquwlzbbsqtgat
const _fiatApiPath = '/v2/rates';
Future<double> _fetchPrice(String crypto, String fiat, bool torOnly) async {
final Map<String, String> queryParams = {
'interval_count': '1',
'base': crypto.split(".").first,
@@ -23,14 +22,10 @@ Future<double> _fetchPrice(String crypto, String fiat, bool torOnly) async {
final onionUri = Uri.http(_fiatApiOnionAuthority, _fiatApiPath, queryParams);
final clearnetUri = Uri.https(_fiatApiClearNetAuthority, _fiatApiPath, queryParams);
final response = await ProxyWrapper().get(
onionUri: onionUri,
clearnetUri: torOnly ? onionUri : clearnetUri,
headers: {
"x-api-key": secrets.fiatApiKey,
}
);
final response = await ProxyWrapper()
.get(onionUri: onionUri, clearnetUri: torOnly ? onionUri : clearnetUri, headers: {
"x-api-key": secrets.fiatApiKey,
});
if (response.statusCode != 200) {
return 0.0;
@@ -52,9 +47,8 @@ Future<double> _fetchPrice(String crypto, String fiat, bool torOnly) async {
/// Override specific [CryptoCurrency] to fix its price to the price of another
/// e.g. nDEPS should have the same price as DEPS, but only DEPS is tracked
CryptoCurrency _overrideCryptoCurrency(CryptoCurrency crypto) {
if (crypto.title == CryptoCurrency.ndeps.title)
return CryptoCurrency.deps;
return crypto;
if (crypto.title == CryptoCurrency.ndeps.title) return CryptoCurrency.deps;
return crypto;
}
class FiatConversionService {
+1 -1
View File
@@ -14,4 +14,4 @@ int mnemonicLength(WalletType type) {
default:
return 0;
}
}
}
+4 -4
View File
@@ -4,8 +4,8 @@ import 'package:cake_wallet/core/validator.dart';
class MoneroLabelValidator extends TextValidator {
MoneroLabelValidator()
: super(
errorMessage: S.current.error_text_account_name,
pattern: '^[a-zA-Z0-9_ ]{1,15}\$',
minLength: 1,
maxLength: 15);
errorMessage: S.current.error_text_account_name,
pattern: '^[a-zA-Z0-9_ ]{1,15}\$',
minLength: 1,
maxLength: 15);
}
@@ -9,8 +9,7 @@ import 'package:cw_core/utils/proxy_wrapper.dart';
class OpenCryptoPayService {
static bool isOpenCryptoPayQR(String value) =>
value.toLowerCase().contains("lightning=lnurl") ||
value.toLowerCase().startsWith("lnurl");
value.toLowerCase().contains("lightning=lnurl") || value.toLowerCase().startsWith("lnurl");
static bool requiresClientCommit(CryptoCurrency currency) =>
[CryptoCurrency.xmr, CryptoCurrency.zano, CryptoCurrency.sol].contains(currency) ||
@@ -71,8 +70,8 @@ class OpenCryptoPayService {
);
}
Future<(_OpenCryptoPayQuote, Map<String, List<OpenCryptoPayQuoteAsset>>)>
_getOpenCryptoPayParams(Uri uri) async {
Future<(_OpenCryptoPayQuote, Map<String, List<OpenCryptoPayQuoteAsset>>)> _getOpenCryptoPayParams(
Uri uri) async {
final response = await ProxyWrapper().get(clearnetUri: uri);
if (response.statusCode == 200) {
@@ -90,18 +89,15 @@ class OpenCryptoPayService {
final method = transferAmount['method'] as String;
methods[method] = [];
for (final assetJson in transferAmount['assets'] as List) {
final asset = OpenCryptoPayQuoteAsset.fromJson(
assetJson as Map<String, dynamic>);
final asset = OpenCryptoPayQuoteAsset.fromJson(assetJson as Map<String, dynamic>);
methods[method]?.add(asset);
}
}
log(responseBody.toString());
final quote = _OpenCryptoPayQuote.fromJson(
responseBody['callback'] as String,
responseBody['displayName'] as String?,
responseBody['quote'] as Map<String, dynamic>);
final quote = _OpenCryptoPayQuote.fromJson(responseBody['callback'] as String,
responseBody['displayName'] as String?, responseBody['quote'] as Map<String, dynamic>);
return (quote, methods);
} else {
@@ -110,8 +106,7 @@ class OpenCryptoPayService {
}
}
Future<Uri> getOpenCryptoPayAddress(
OpenCryptoPayRequest request, CryptoCurrency asset) async {
Future<Uri> getOpenCryptoPayAddress(OpenCryptoPayRequest request, CryptoCurrency asset) async {
final uri = Uri.parse(request.callbackUrl);
final queryParams = Map.of(uri.queryParameters);
@@ -135,8 +130,7 @@ class OpenCryptoPayService {
if (result.queryParameters['amount'] != null) return result;
final newQueryParameters =
Map<String, dynamic>.from(result.queryParameters);
final newQueryParameters = Map<String, dynamic>.from(result.queryParameters);
newQueryParameters['amount'] = _getAmountByAsset(request, asset);
return Uri(
+2 -3
View File
@@ -22,8 +22,7 @@ class SeedValidator extends Validator<MnemonicItem> {
final String language;
final List<String> _words;
static List<String> getWordList(
{required WalletType type, required String language}) {
static List<String> getWordList({required WalletType type, required String language}) {
switch (type) {
case WalletType.bitcoin:
return getBitcoinWordList(language);
@@ -49,7 +48,7 @@ class SeedValidator extends Validator<MnemonicItem> {
case WalletType.tron:
return tron!.getTronWordList(language);
case WalletType.wownero:
return wownero!.getWowneroWordList(language);
return wownero!.getWowneroWordList(language);
case WalletType.zano:
return zano!.getWordList(language);
case WalletType.decred:
-3
View File
@@ -5,7 +5,6 @@ abstract class SelectableItem {
class OptionTitle extends SelectableItem {
OptionTitle({required String title}) : super(title: title);
}
abstract class SelectableOption extends SelectableItem {
@@ -43,5 +42,3 @@ abstract class SelectableOption extends SelectableItem {
set isOptionSelected(bool isSelected) => false;
}
@@ -4,7 +4,6 @@ import 'package:cake_wallet/generated/i18n.dart';
class SocksProxyNodeAddressValidator extends TextValidator {
SocksProxyNodeAddressValidator()
: super(
errorMessage: S.current.error_text_node_proxy_address,
pattern:
'^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}:[0-9]+\$');
errorMessage: S.current.error_text_node_proxy_address,
pattern: '^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}:[0-9]+\$');
}
+5 -6
View File
@@ -4,9 +4,8 @@ import 'package:cake_wallet/generated/i18n.dart';
class TemplateValidator extends TextValidator {
TemplateValidator()
: super(
minLength: 0,
maxLength: 0,
pattern: '''^[^`,'"]{1,20}\$''',
errorMessage: S.current.error_text_template
);
}
minLength: 0,
maxLength: 0,
pattern: '''^[^`,'"]{1,20}\$''',
errorMessage: S.current.error_text_template);
}
+1 -1
View File
@@ -132,7 +132,7 @@ class UniversalAddressDetector {
pattern: RegExp(r'^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'),
currency: CryptoCurrency.btcln,
),
// Lightning Address (LNURL format)
_DetectionPattern(
pattern: RegExp(r'^(lightning:)?(lnurl)[a-z0-9]+$', caseSensitive: false),
+1 -2
View File
@@ -8,8 +8,7 @@ extension EnhancedList<T> on Iterable<T> {
}
}
String middleTruncate(String s, int head, int tail) {
if (s.length <= head + tail + 3) return s;
return s.substring(0, head) + '...' + s.substring(s.length - tail);
}
}
+3 -7
View File
@@ -18,9 +18,7 @@ class TextValidator extends Validator<String> {
String errorMessage = '',
this.length,
this.isAutovalidate = false,
}) : super(
errorMessage: errorMessage,
useAdditionalValidation: useAdditionalValidation);
}) : super(errorMessage: errorMessage, useAdditionalValidation: useAdditionalValidation);
final int? minLength;
final int? maxLength;
@@ -40,8 +38,7 @@ class TextValidator extends Validator<String> {
final lengthMatched = length?.contains(value.length) ?? true;
if (!lengthMatched) return false;
final lowerThanMaxLength =
(maxLength ?? 0) > 0 ? (value.length <= maxLength!) : true;
final lowerThanMaxLength = (maxLength ?? 0) > 0 ? (value.length <= maxLength!) : true;
if (!lowerThanMaxLength) return false;
if (pattern == null) return true;
@@ -54,6 +51,5 @@ class TextValidator extends Validator<String> {
return valueValidated;
}
bool match(String value) =>
pattern != null ? RegExp(pattern!).hasMatch(value) : false;
bool match(String value) => pattern != null ? RegExp(pattern!).hasMatch(value) : false;
}
+2 -1
View File
@@ -35,7 +35,8 @@ class WalletCreationService {
Future<bool> exists(String name) async {
final walletName = name.toLowerCase();
return (await WalletInfo.getAll()).any((walletInfo) => walletInfo.name.toLowerCase() == walletName);
return (await WalletInfo.getAll())
.any((walletInfo) => walletInfo.name.toLowerCase() == walletName);
}
Future<bool> typeExists(WalletType type) async {
+1 -1
View File
@@ -10,4 +10,4 @@ class WalletCreationFailure extends WalletCreationState {
WalletCreationFailure({required this.error});
final String error;
}
}
+43 -38
View File
@@ -58,10 +58,12 @@ class WalletLoadingService {
}
}
Future<WalletBase> load(WalletType type, String name, {String? password, bool isBackground = false}) async {
Future<WalletBase> load(WalletType type, String name,
{String? password, bool isBackground = false}) async {
try {
if (!isBackground) {
await sharedPreferences.setString(PreferencesKey.backgroundSyncLastTrigger(name), DateTime.now().toIso8601String());
await sharedPreferences.setString(
PreferencesKey.backgroundSyncLastTrigger(name), DateTime.now().toIso8601String());
}
final walletService = walletServiceFactory.call(type);
final walletPassword = password ?? (await keyService.getWalletPassword(walletName: name));
@@ -75,10 +77,14 @@ class WalletLoadingService {
} catch (error, stack) {
String corruptedWalletsSeeds = "Corrupted wallets seeds (if retrievable, empty otherwise):";
if(error is WalletDeprecationException) {
if(navigatorKey.currentContext != null) {
if (error is WalletDeprecationException) {
if (navigatorKey.currentContext != null) {
showModalBottomSheet(
context: navigatorKey.currentContext!, builder: (context)=>WalletDeprecationPopup(type: type, seed: error.seed,));
context: navigatorKey.currentContext!,
builder: (context) => WalletDeprecationPopup(
type: type,
seed: error.seed,
));
}
} else {
await ExceptionHandler.resetLastPopupDate();
@@ -106,8 +112,7 @@ class WalletLoadingService {
await updateMoneroWalletPassword(wallet);
}
await sharedPreferences.setString(
PreferencesKey.currentWalletName, wallet.name);
await sharedPreferences.setString(PreferencesKey.currentWalletName, wallet.name);
await sharedPreferences.setInt(
PreferencesKey.currentWalletType, serializeToInt(wallet.type));
@@ -130,22 +135,22 @@ class WalletLoadingService {
// if all user's wallets are corrupted throw exception
final msg = error.toString() + "\n" + corruptedWalletsSeeds;
if (navigatorKey.currentContext != null) {
await showPopUp<void>(
context: navigatorKey.currentContext!,
builder: (BuildContext context) {
return AlertWithTwoActions(
alertTitle: "Corrupted seeds",
alertContent: S.of(context).corrupted_seed_notice,
leftButtonText: S.of(context).cancel,
rightButtonText: S.of(context).show_seed,
actionLeftButton: () {
if (context.mounted && Navigator.of(context).canPop()) {
Navigator.of(context).pop();
}
},
actionRightButton: () => showSeedsPopup(context, msg),
);
});
await showPopUp<void>(
context: navigatorKey.currentContext!,
builder: (BuildContext context) {
return AlertWithTwoActions(
alertTitle: "Corrupted seeds",
alertContent: S.of(context).corrupted_seed_notice,
leftButtonText: S.of(context).cancel,
rightButtonText: S.of(context).show_seed,
actionLeftButton: () {
if (context.mounted && Navigator.of(context).canPop()) {
Navigator.of(context).pop();
}
},
actionRightButton: () => showSeedsPopup(context, msg),
);
});
} else {
throw msg;
}
@@ -159,21 +164,21 @@ class WalletLoadingService {
Future<void> showSeedsPopup(BuildContext context, String message) async {
Navigator.of(context).pop();
await showPopUp<void>(
context: context,
builder: (BuildContext context) {
return AlertWithTwoActions(
alertTitle: "Corrupted seeds",
alertContent: message,
leftButtonText: S.of(context).copy,
rightButtonText: S.of(context).ok,
actionLeftButton: () async {
await Clipboard.setData(ClipboardData(text: message));
},
actionRightButton: () async {
Navigator.of(context).pop();
},
);
});
context: context,
builder: (BuildContext context) {
return AlertWithTwoActions(
alertTitle: "Corrupted seeds",
alertContent: message,
leftButtonText: S.of(context).copy,
rightButtonText: S.of(context).ok,
actionLeftButton: () async {
await Clipboard.setData(ClipboardData(text: message));
},
actionRightButton: () async {
Navigator.of(context).pop();
},
);
});
}
Future<void> updateMoneroWalletPassword(WalletBase wallet) async {