mirror of
https://github.com/Such-Software/hash-wallet.git
synced 2026-10-26 06:08:40 +01:00
cw-1683-prepare-zano-removal (#3668)
* wip zano removal * add zano removal popup * constantly show popup if user keeps using deprecated wallet * add confirmation before viewing seed * fix viewed check * prevent wallet staying open after seed backup * Update lib/entities/default_settings_migration.dart Co-authored-by: Omar Hatem <omarh.ismail1@gmail.com> * add passphrase * make popup scrollable * delete deprecated seeds when wallet is deleted * encrypt seeds * also deprecate decred * remove decred from available types * remove backup logic * showArrow: false, * Remove deprecated wallet seeds deletion Removed deprecated wallet seeds deletion from delete method. --------- Co-authored-by: Omar Hatem <omarh.ismail1@gmail.com>
This commit is contained in:
@@ -66,7 +66,7 @@ Future<void> _initDb({String? pathOverride}) async {
|
||||
await db?.close();
|
||||
db = await openDatabase(
|
||||
dbFile.path,
|
||||
version: 14,
|
||||
version: 15,
|
||||
onUpgrade: (db, oldVersion, newVersion) async {
|
||||
printV("migrating: $oldVersion, $newVersion");
|
||||
if (oldVersion <= 1) {
|
||||
@@ -193,6 +193,9 @@ CREATE TABLE IF NOT EXISTS BalanceCardStyleSettings (
|
||||
|
||||
await _migrateBitcoinCardStylesForAccounts(db);
|
||||
}
|
||||
if(oldVersion <= 14) {
|
||||
await _createDeprecatedWalletSeedTable(db);
|
||||
}
|
||||
},
|
||||
onCreate: (Database db, int version) async {
|
||||
await db.execute('''
|
||||
@@ -299,6 +302,8 @@ CREATE TABLE BalanceCardStyleSettings (
|
||||
await _createTronTokenTable(db);
|
||||
await _createImportedNFTTable(db);
|
||||
await _createWalletInfoAccountTable(db);
|
||||
await _createDeprecatedWalletSeedTable(db);
|
||||
|
||||
},
|
||||
);
|
||||
}
|
||||
@@ -589,3 +594,15 @@ isDefault BOOLEAN DEFAULT FALSE
|
||||
);
|
||||
""");
|
||||
}
|
||||
|
||||
|
||||
Future<void> _createDeprecatedWalletSeedTable(Database db) async {
|
||||
await db.execute("""
|
||||
CREATE TABLE DeprecatedWalletSeeds (
|
||||
walletInfoId INTEGER PRIMARY KEY,
|
||||
seed TEXT NOT NULL,
|
||||
passphrase TEXT NOT NULL,
|
||||
FOREIGN KEY (walletInfoId) REFERENCES WalletInfo(walletInfoId)
|
||||
);
|
||||
""");
|
||||
}
|
||||
|
||||
@@ -793,7 +793,8 @@ class WalletInfo {
|
||||
}
|
||||
|
||||
static Future<int> delete(WalletInfo walletInfo) async {
|
||||
return await db!.delete(tableName, where: 'id = ?', whereArgs: [walletInfo.id]);
|
||||
final deleted = await db!.delete(tableName, where: 'id = ?', whereArgs: [walletInfo.id]);
|
||||
return deleted;
|
||||
}
|
||||
|
||||
static Future<List<WalletInfo>> selectList(String where, List<dynamic> whereArgs,
|
||||
|
||||
@@ -122,6 +122,7 @@ abstract class ZanoWalletBase
|
||||
bool _isTransactionUpdating;
|
||||
bool _hasSyncAfterStartup;
|
||||
Timer? _autoSaveTimer;
|
||||
bool _isClosed = false;
|
||||
|
||||
/// number of transactions in each request
|
||||
static final int _txChunkSize = (pow(2, 32) - 1).toInt();
|
||||
@@ -422,6 +423,7 @@ abstract class ZanoWalletBase
|
||||
|
||||
@override
|
||||
Future<void> close({bool shouldCleanup = true}) async {
|
||||
_isClosed = true;
|
||||
closeWallet(null);
|
||||
_updateSyncInfoTimer?.cancel();
|
||||
_autoSaveTimer?.cancel();
|
||||
@@ -534,6 +536,9 @@ abstract class ZanoWalletBase
|
||||
await walletAddresses.init();
|
||||
await walletAddresses.updateAddress(address);
|
||||
await updateTransactions();
|
||||
if (_isClosed) {
|
||||
return;
|
||||
}
|
||||
_autoSaveTimer = Timer.periodic(Duration(seconds: _autoSaveIntervalSeconds), (_) async {
|
||||
await save();
|
||||
});
|
||||
|
||||
@@ -458,6 +458,13 @@ mixin ZanoWalletApi {
|
||||
|
||||
static Map<String, CreateWalletResult> openWalletCache = {};
|
||||
|
||||
static Future<void> closeCachedWallet(String path) async {
|
||||
final cached = openWalletCache.remove(path);
|
||||
if (cached != null) {
|
||||
await _closeWallet(cached.walletId);
|
||||
}
|
||||
}
|
||||
|
||||
Future<TransferResult> transfer(
|
||||
List<Destination> destinations, BigInt fee, String comment) async {
|
||||
final params = TransferParams(
|
||||
|
||||
@@ -112,6 +112,7 @@ class ZanoWalletService extends WalletService<
|
||||
|
||||
@override
|
||||
Future<void> remove(String wallet) async {
|
||||
await ZanoWalletApi.closeCachedWallet(await pathForWallet(name: wallet, type: getType()));
|
||||
final path = await pathForWalletDir(name: wallet, type: getType());
|
||||
final file = Directory(path);
|
||||
final isExist = file.existsSync();
|
||||
|
||||
@@ -2,7 +2,10 @@ import 'dart:convert';
|
||||
import 'dart:io' show Directory, File, Platform;
|
||||
|
||||
import 'package:cake_wallet/bitcoin/bitcoin.dart';
|
||||
import "package:cake_wallet/core/key_service.dart";
|
||||
import 'package:cake_wallet/core/secure_storage.dart';
|
||||
import "package:cake_wallet/decred/decred.dart";
|
||||
import "package:cake_wallet/di.dart";
|
||||
import 'package:cake_wallet/entities/balance_display_mode.dart';
|
||||
import 'package:cake_wallet/entities/contact.dart';
|
||||
import 'package:cake_wallet/entities/exchange_api_mode.dart';
|
||||
@@ -14,6 +17,9 @@ import 'package:cake_wallet/entities/preferences_key.dart';
|
||||
import 'package:cake_wallet/entities/secret_store_key.dart';
|
||||
import 'package:cake_wallet/monero/monero.dart';
|
||||
import 'package:cake_wallet/new-ui/model/charts/charts_asset.dart';
|
||||
import "package:cake_wallet/store/settings_store.dart";
|
||||
import "package:cake_wallet/zano/zano.dart";
|
||||
import "package:cw_core/cake_hive.dart";
|
||||
import 'package:cake_wallet/wownero/wownero.dart';
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:cw_core/crypto_currency.dart';
|
||||
@@ -23,8 +29,10 @@ import 'package:cw_core/node_list.dart';
|
||||
import 'package:cw_core/pathForWallet.dart';
|
||||
import 'package:cw_core/root_dir.dart';
|
||||
import 'package:cw_core/spl_token.dart';
|
||||
import "package:cw_core/unspent_coins_info.dart";
|
||||
import 'package:cw_core/utils/print_verbose.dart';
|
||||
import 'package:cw_core/wallet_info.dart';
|
||||
import "package:cw_core/wallet_service.dart";
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:encrypt/encrypt.dart' as encrypt;
|
||||
import 'package:hive/hive.dart';
|
||||
@@ -1377,4 +1385,4 @@ Future<void> _addTbbTokenToExistingSolanaWallets() async {
|
||||
} catch (e) {
|
||||
printV("Error in TBB migration: $e");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,5 @@
|
||||
import "package:cw_core/wallet_type.dart";
|
||||
|
||||
class PreferencesKey {
|
||||
static const currentWalletType = 'current_wallet_type';
|
||||
static const currentWalletName = 'current_wallet_name';
|
||||
@@ -147,4 +149,6 @@ class PreferencesKey {
|
||||
static const balanceHideCounter = "balance_hide_counter";
|
||||
static const zcashMigrationModalViewed = "zcash_migration_modal_viewed";
|
||||
static const showCiBuildOverlay = "show_ci_build_overlay";
|
||||
static String deprecationPopupViewed(WalletType type) =>
|
||||
"deprecation_popup_viewed_${walletTypeToString(type)}";
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import "package:cake_wallet/new-ui/page_open_listener.dart";
|
||||
import 'package:cake_wallet/new-ui/pages/charts_page.dart';
|
||||
import 'package:cake_wallet/new-ui/pages/home_page.dart';
|
||||
import 'package:cake_wallet/new-ui/widgets/changelog_modal.dart';
|
||||
import "package:cake_wallet/new-ui/widgets/wallet_removal_popup.dart";
|
||||
import 'package:cake_wallet/src/screens/contact/contact_list_page.dart';
|
||||
import 'package:cake_wallet/src/screens/dashboard/pages/cake_features_page.dart';
|
||||
import 'package:cake_wallet/src/screens/dashboard/widgets/new_main_navbar_widget.dart';
|
||||
@@ -55,6 +56,7 @@ class _NewDashboardState extends State<NewDashboard> {
|
||||
setState(() {
|
||||
_selectedPage = 0;
|
||||
});
|
||||
_showWalletRemovalPopup(context);
|
||||
});
|
||||
|
||||
Future.delayed(Duration(milliseconds: 300)).then((_) {
|
||||
@@ -63,6 +65,7 @@ class _NewDashboardState extends State<NewDashboard> {
|
||||
});
|
||||
});
|
||||
_showVulnerableSeedsPopup(context);
|
||||
_showWalletRemovalPopup(context);
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -182,4 +185,14 @@ class _NewDashboardState extends State<NewDashboard> {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _showWalletRemovalPopup(BuildContext context) async {
|
||||
if(await widget.dashboardViewModel.shouldShowRemovalPopup()) {
|
||||
await Future.delayed(const Duration(seconds: 1));
|
||||
final toBeRemoved = await widget.dashboardViewModel.walletsToBeRemoved;
|
||||
if(context.mounted) {
|
||||
await showPopUp<void>(context: context, builder: (context)=>WalletRemovalPopup(affectedWallets: toBeRemoved,));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
import "package:cake_wallet/entities/new_ui_entities/list_item/list_item_regular_row.dart";
|
||||
import "package:cake_wallet/generated/i18n.dart";
|
||||
import "package:cake_wallet/new-ui/widgets/new_primary_button.dart";
|
||||
import "package:cake_wallet/src/widgets/cake_image_widget.dart";
|
||||
import "package:cake_wallet/src/widgets/new_list_row/new_list_section.dart";
|
||||
import "package:cake_wallet/themes/core/theme_extension.dart";
|
||||
import "package:cw_core/currency_for_wallet_type.dart";
|
||||
import "package:cw_core/wallet_info.dart";
|
||||
import "package:cw_core/wallet_type.dart";
|
||||
import "package:flutter/material.dart";
|
||||
|
||||
class WalletRemovalPopup extends StatelessWidget {
|
||||
const WalletRemovalPopup({required this.affectedWallets, super.key});
|
||||
|
||||
final List<WalletInfo> affectedWallets;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final types = affectedWallets.map((item) => item.type).toSet().toList();
|
||||
final iconPaths = types.map((item) => walletTypeToCryptoCurrency(item).iconPath ?? "").toList();
|
||||
final typeNames = types.map(walletTypeToDisplayName).toList();
|
||||
|
||||
return Center(
|
||||
child: Material(
|
||||
color: Colors.transparent,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 18),
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).colorScheme.surface,
|
||||
borderRadius: BorderRadius.circular(18),
|
||||
),
|
||||
child: SingleChildScrollView(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
spacing: 18,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
spacing: 8,
|
||||
children: iconPaths
|
||||
.map(
|
||||
(item) => CakeImageWidget(
|
||||
imageUrl: item,
|
||||
width: 64,
|
||||
height: 64,
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
),
|
||||
Text(
|
||||
textAlign: TextAlign.center,
|
||||
S.of(context).support_will_soon_be_removed(typeNames.join(", ")),
|
||||
style: const TextStyle(fontSize: 20, fontWeight: FontWeight.w500),
|
||||
),
|
||||
Text(
|
||||
textAlign: TextAlign.center,
|
||||
types.map(deprecationReasonForType).whereType<String>().join("\n\n"),
|
||||
),
|
||||
Text(
|
||||
textAlign: TextAlign.center,
|
||||
S.of(context).make_sure_you_migrated(typeNames.join("/")),
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.w500,
|
||||
color: context.currentTheme.customColors.warningOutlineColor,
|
||||
),
|
||||
),
|
||||
NewListSections(
|
||||
sections: {
|
||||
"": affectedWallets
|
||||
.map(
|
||||
(item) => ListItemRegularRow(
|
||||
iconPath: walletTypeToCryptoCurrency(item.type).iconPath ?? "",
|
||||
keyValue: item.name,
|
||||
label: item.name,
|
||||
showArrow: false,
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
},
|
||||
),
|
||||
NewPrimaryButton(
|
||||
onPressed: Navigator.of(context).pop,
|
||||
text: S.of(context).close,
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
textColor: Theme.of(context).colorScheme.onPrimary,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
String? deprecationReasonForType(WalletType type) =>
|
||||
switch (type) { WalletType.zano => S.current.zano_removal_reason, _ => null };
|
||||
}
|
||||
@@ -1697,4 +1697,25 @@ abstract class DashboardViewModelBase with Store {
|
||||
Future<void> refreshDashboard() async {
|
||||
reconnect();
|
||||
}
|
||||
|
||||
|
||||
static const walletTypesToBeRemoved = [
|
||||
WalletType.zano,
|
||||
WalletType.decred,
|
||||
];
|
||||
|
||||
Future<bool> shouldShowRemovalPopup() async {
|
||||
final show = (await WalletInfo.getAll()).any((item) =>
|
||||
walletTypesToBeRemoved.contains(item.type) &&
|
||||
!(sharedPreferences.getBool(PreferencesKey.deprecationPopupViewed(item.type)) ?? false),);
|
||||
for (final type in walletTypesToBeRemoved) {
|
||||
await sharedPreferences.setBool(PreferencesKey.deprecationPopupViewed(type), true);
|
||||
}
|
||||
// if user is actively using a wallet type that's about to be removed, keep nagging them
|
||||
return show || walletTypesToBeRemoved.contains(wallet.type);
|
||||
}
|
||||
|
||||
Future<List<WalletInfo>> get walletsToBeRemoved async => (await WalletInfo.getAll())
|
||||
.where((item) => walletTypesToBeRemoved.contains(item.type))
|
||||
.toList();
|
||||
}
|
||||
|
||||
@@ -668,6 +668,7 @@
|
||||
"low_fee_alert": "You currently are using a low network fee priority. This could cause long waits, different rates, or canceled trades. We recommend setting a higher fee for a better experience.",
|
||||
"low_kyc": "Low KYC",
|
||||
"made_easy": "made easy",
|
||||
"make_sure_you_migrated": "Please be sure you've backed up your seed phrase from Recovery & Keys in the meantime, and consider migrating to another ${walletTypes} wallet.",
|
||||
"manage_nodes": "Manage nodes",
|
||||
"manage_pow_nodes": "Manage PoW nodes",
|
||||
"manage_providers": "Manage providers",
|
||||
@@ -1180,6 +1181,7 @@
|
||||
"show_recovery_phrase": "Show me my Recovery Phrase",
|
||||
"show_recovery_phrase_and_keys": "Show my Recovery Phrase & Keys",
|
||||
"show_seed": "Show seed",
|
||||
"show_seed_confirmation": "View seed of this wallet?",
|
||||
"show_zcash_card": "Show zcash missing funds card",
|
||||
"sign_all": "Sign All",
|
||||
"sign_message": "Sign Message",
|
||||
@@ -1239,6 +1241,7 @@
|
||||
"support_title_guides": "Cake Wallet docs",
|
||||
"support_title_live_chat": "Live support",
|
||||
"support_title_other_links": "Other support links",
|
||||
"support_will_soon_be_removed": "Support for ${walletTypes} will soon be removed",
|
||||
"supported": "Supported",
|
||||
"swap": "Swap",
|
||||
"swap_from_network": "Swap from ${network}",
|
||||
@@ -1578,6 +1581,7 @@
|
||||
"youCanGoBackToYourDapp": "You can go back to your dApp now",
|
||||
"your": "Your",
|
||||
"yy": "YY",
|
||||
"zano_removal_reason": "Zano has undergone multiple hard-forks to resolve a critical network issue, including a rollback of the chain. Due to serious issues with the forks and the maintenance burden it brings to us, we will be removing Zano from Cake Wallet in a future release.",
|
||||
"zcash_card_description": "If you don't see your full balance Cake Wallet can attempt to sweep funds from internal change addresses used by some wallets.",
|
||||
"zcash_card_dismiss": "Dismiss",
|
||||
"zcash_card_enable_later": "You can always enable this card later in settings",
|
||||
|
||||
+6
-6
@@ -2077,13 +2077,13 @@ Future<void> generateWalletTypes({
|
||||
outputContent += '\tWalletType.nano,\n';
|
||||
}
|
||||
|
||||
if (hasDecred) {
|
||||
outputContent += '\tWalletType.decred,\n';
|
||||
}
|
||||
// if (hasDecred) {
|
||||
// outputContent += '\tWalletType.decred,\n';
|
||||
// }
|
||||
|
||||
if (hasZano) {
|
||||
outputContent += '\tWalletType.zano,\n';
|
||||
}
|
||||
// if (hasZano) {
|
||||
// outputContent += '\tWalletType.zano,\n';
|
||||
// }
|
||||
|
||||
if (hasBanano) {
|
||||
outputContent += '\tWalletType.banano,\n';
|
||||
|
||||
Reference in New Issue
Block a user