popup ui for wownero deprecation (#3186)

* fix: add "support for coin removed" to exception handler ignored list * wownero deprecation popup --------- Co-authored-by: Czarek Nakamoto <cyjan@mrcyjanek.net>

malik1004x committed May 6, 2026 at 23:18 UTC b5cec3576c16fd52ee58d0eeba322c8cf3dc0bb5
3 files changed +93 -5
cw_wownero/lib/wownero_wallet_service.dart
+13 -2
@@ -1,5 +1,6 @@
1 import 'dart:ffi';
2 import 'dart:io';
3 +import 'package:cw_core/crypto_currency.dart';
4 import 'package:cw_core/monero_wallet_utils.dart';
5 import 'package:cw_core/pathForWallet.dart';
6 import 'package:cw_core/unspent_coins_info.dart';
@@ -20,6 +21,16 @@ import 'package:hive/hive.dart';
21 import 'package:polyseed/polyseed.dart';
22 import 'package:monero/wownero.dart' as wownero;
23
24 +class WalletDeprecationException implements Exception {
25 + final String seed;
26 + final CryptoCurrency curr;
27 +
28 + @override
29 + String toString() => "Wallet type no longer supported";
30 +
31 + WalletDeprecationException({required this.seed, required this.curr});
32 +}
33 +
34 class WowneroNewWalletCredentials extends WalletCredentials {
35 WowneroNewWalletCredentials(
36 {required String name, required this.language, required this.isPolyseed, this.passphrase, String? password})
@@ -138,8 +149,8 @@ class WowneroWalletService extends WalletService<
149 }
150
151 wallet = WowneroWallet(walletInfo: walletInfo, derivationInfo: await walletInfo.getDerivationInfo(), unspentCoinsInfo: unspentCoinsInfoSource, password: password);
141 - throw Exception("support for coin removed, your seedphrase: ${wallet.seed}");
142 -
152 + throw WalletDeprecationException(seed: wallet.seed, curr: wallet.currency);
153 +
154 final isValid = wallet.walletAddresses.validate();
155
156 if (!isValid) {
lib/core/wallet_loading_service.dart
+8 -3
@@ -5,6 +5,7 @@ import 'package:cake_wallet/core/key_service.dart';
5 import 'package:cake_wallet/entities/preferences_key.dart';
6 import 'package:cake_wallet/generated/i18n.dart';
7 import 'package:cake_wallet/main.dart';
8 +import 'package:cake_wallet/new-ui/widgets/wallet_deprecation_popup.dart';
9 import 'package:cake_wallet/reactions/on_authentication_state_change.dart';
10 import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart';
11 import 'package:cake_wallet/utils/exception_handler.dart';
@@ -15,6 +16,7 @@ import 'package:cw_core/wallet_base.dart';
16 import 'package:cw_core/wallet_info.dart';
17 import 'package:cw_core/wallet_service.dart';
18 import 'package:cw_core/wallet_type.dart';
19 +import 'package:cw_wownero/wownero_wallet_service.dart';
20 import 'package:flutter/material.dart';
21 import 'package:flutter/services.dart';
22 import 'package:shared_preferences/shared_preferences.dart';
@@ -73,9 +75,12 @@ class WalletLoadingService {
75 return wallet;
76 } catch (error, stack) {
77 String corruptedWalletsSeeds = "Corrupted wallets seeds (if retrievable, empty otherwise):";
76 -
77 - if ([WalletType.wownero, WalletType.haven].contains(type)) {
78 - corruptedWalletsSeeds += "\n\n$type $name: $error";
78 +
79 + if(error is WalletDeprecationException) {
80 + if(navigatorKey.currentContext != null) {
81 + showModalBottomSheet(
82 + context: navigatorKey.currentContext!, builder: (context)=>WalletDeprecationPopup(type: type, seed: error.seed,));
83 + }
84 } else {
85 await ExceptionHandler.resetLastPopupDate();
86 final isLedgerError = await ExceptionHandler.isLedgerError(error);
lib/new-ui/widgets/wallet_deprecation_popup.dart new
+72
@@ -0,0 +1,72 @@
1 +import 'package:cake_wallet/new-ui/widgets/animated_dropdown.dart';
2 +import 'package:cake_wallet/new-ui/widgets/new_primary_button.dart';
3 +import 'package:cake_wallet/new-ui/widgets/receive_page/receive_top_bar.dart';
4 +import 'package:cake_wallet/src/widgets/cake_image_widget.dart';
5 +import 'package:cw_core/currency_for_wallet_type.dart';
6 +import 'package:cw_core/wallet_type.dart';
7 +import 'package:flutter/material.dart';
8 +
9 +class WalletDeprecationPopup extends StatelessWidget {
10 + const WalletDeprecationPopup({super.key, required this.type, this.seed});
11 +
12 + final WalletType type;
13 + final String? seed;
14 +
15 + @override
16 + Widget build(BuildContext context) {
17 + final curr = walletTypeToCryptoCurrency(type);
18 +
19 + return Container(
20 + decoration: BoxDecoration(
21 + borderRadius: BorderRadius.vertical(top: Radius.circular(20)),
22 + color: Theme.of(context).colorScheme.surface),
23 + child: SafeArea(
24 + child: Column(
25 + mainAxisSize: MainAxisSize.min,
26 + children: [
27 + ModalTopBar(
28 + title: "",
29 + leadingIcon: Icon(Icons.close),
30 + onLeadingPressed: Navigator.of(context).pop,
31 + ),
32 + Padding(
33 + padding: const EdgeInsets.symmetric(horizontal: 12.0),
34 + child: Column(
35 + spacing: 24,
36 + children: [
37 + CakeImageWidget(
38 + imageUrl: curr.iconSvgPath ?? curr.iconPath,
39 + width: 64,
40 + height: 64,
41 + ),
42 + Text(
43 + "${curr.fullName} is no longer supported",
44 + style: TextStyle(fontSize: 20, fontWeight: FontWeight.w600),
45 + textAlign: TextAlign.center,
46 + ),
47 + Text(
48 + "Apologies for the inconvenience.",
49 + textAlign: TextAlign.center,
50 + ),
51 + if (seed != null) ...[
52 + Text(
53 + "If you need to migrate your seed, you can see it below.",
54 + textAlign: TextAlign.center,
55 + ),
56 + AnimatedDropdown(content: Text(seed!), dropdownText: "Tap to show seed"),
57 + ],
58 + NewPrimaryButton(
59 + onPressed: Navigator.of(context).pop,
60 + text: "Close",
61 + color: Theme.of(context).colorScheme.primary,
62 + textColor: Theme.of(context).colorScheme.onPrimary),
63 + SizedBox()
64 + ],
65 + ),
66 + )
67 + ],
68 + ),
69 + ),
70 + );
71 + }
72 +}