dev
dart 165 lines 6.77 KB
Raw
1 import 'dart:async';
2
3 import 'package:cake_wallet/di.dart';
4 import 'package:cake_wallet/entities/hardware_wallet/require_hardware_wallet_connection.dart';
5 import 'package:cake_wallet/entities/load_current_wallet.dart';
6 import 'package:cake_wallet/generated/i18n.dart';
7 import 'package:cake_wallet/monero/monero.dart';
8 import 'package:cake_wallet/routes.dart';
9 import 'package:cake_wallet/src/screens/connect_device/connect_device_page.dart';
10 import 'package:cake_wallet/src/screens/wallet_connect/services/bottom_sheet_service.dart';
11 import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
12 import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart';
13 import 'package:cake_wallet/store/authentication_store.dart';
14 import 'package:cake_wallet/store/settings_store.dart';
15 import 'package:cake_wallet/utils/exception_handler.dart';
16 import 'package:cake_wallet/utils/show_pop_up.dart';
17 import 'package:cake_wallet/view_model/hardware_wallet/ledger_view_model.dart';
18 import 'package:cake_wallet/view_model/link_view_model.dart';
19 import 'package:cw_core/wallet_info.dart';
20 import 'package:cw_core/wallet_type.dart';
21 import 'package:flutter/widgets.dart';
22 import 'package:mobx/mobx.dart';
23 import 'package:rxdart/subjects.dart';
24
25 ReactionDisposer? _onAuthenticationStateChange;
26
27 dynamic loginError;
28 StreamController<dynamic> authenticatedErrorStreamController = BehaviorSubject<dynamic>();
29
30 void startAuthenticationStateChange(
31 AuthenticationStore authenticationStore,
32 GlobalKey<NavigatorState> navigatorKey,
33 ) {
34 authenticatedErrorStreamController.stream.listen((event) {
35 if (authenticationStore.state == AuthenticationState.allowed) {
36 ExceptionHandler.showError(event.toString(), delayInSeconds: 3);
37 }
38 });
39
40 _onAuthenticationStateChange ??= autorun((_) async {
41 final state = authenticationStore.state;
42
43 if (state == AuthenticationState.installed && !SettingsStoreBase.walletPasswordDirectInput) {
44 try {
45 if (!(await requireHardwareWalletConnection())) await loadCurrentWallet();
46 } catch (error, stack) {
47 loginError = error;
48 await ExceptionHandler.resetLastPopupDate();
49 await ExceptionHandler.onError(FlutterErrorDetails(exception: error, stack: stack));
50 }
51 return;
52 }
53
54 if ([AuthenticationState.allowed, AuthenticationState.allowedCreate].contains(state)) {
55 if (state == AuthenticationState.allowed && (await requireHardwareWalletConnection())) {
56 await navigatorKey.currentState!.pushNamedAndRemoveUntil(
57 Routes.connectDevices,
58 (route) => false,
59 arguments: ConnectDevicePageParams(
60 walletType: WalletType.monero,
61 hardwareWalletType: HardwareWalletType.ledger,
62 onConnectDevice: (context, ledgerVM) async {
63 if (ledgerVM is LedgerViewModel) {
64 monero!.setGlobalLedgerConnection(ledgerVM.connection);
65 } else {
66 await showPopUp<void>(
67 context: context,
68 builder: (context) => AlertWithOneAction(
69 alertTitle: "Unexpected Error",
70 alertContent:
71 "Unexpected Error while trying to connect to the device (UnexpectedViewModel: ${ledgerVM.toString()})",
72 buttonText: S.of(context).try_again,
73 buttonAction: Navigator.of(context).pop,
74 ),
75 );
76 return;
77 }
78
79 ledgerVM.suppressMoneroReconnectPrompt = true;
80
81 if (!monero!.hasGlobalLedgerConnection()) {
82 await showPopUp<void>(
83 context: context,
84 builder: (context) => AlertWithOneAction(
85 alertTitle: "Unexpected Error",
86 alertContent:
87 "Unexpected Error while trying to connect to the device (has no global LedgerConnection)",
88 buttonText: S.of(context).try_again,
89 buttonAction: Navigator.of(context).pop,
90 ),
91 );
92 return;
93 }
94
95 showPopUp<void>(
96 context: context,
97 builder: (context) => AlertWithOneAction(
98 alertTitle: S.of(context).proceed_on_device,
99 alertContent: S.of(context).proceed_on_device_description,
100 buttonText: S.of(context).cancel,
101 alertBarrierDismissible: false,
102 buttonAction: () => Navigator.of(context).pop(),
103 ),
104 );
105
106 var isConnected = false;
107 var tryOpening = true;
108 while (tryOpening) {
109 try {
110 await loadCurrentWallet();
111 isConnected = true;
112 tryOpening = false;
113 } on Exception catch (e) {
114 final ledgerErrorMessage = ledgerVM.interpretErrorCode(e.toString());
115 if (ledgerErrorMessage != null && context.mounted) {
116 await showPopUp<void>(
117 context: context,
118 builder: (context) => AlertWithTwoActions(
119 alertTitle: "Ledger Error",
120 alertContent: ledgerErrorMessage,
121 leftButtonText: S.of(context).try_again,
122 alertBarrierDismissible: false,
123 actionLeftButton: () => Navigator.of(context).pop(),
124 rightButtonText: S.of(context).cancel,
125 actionRightButton: () {
126 tryOpening = false;
127 Navigator.of(context).pop();
128 },
129 ),
130 );
131 } else {
132 tryOpening = false;
133 rethrow;
134 }
135 }
136 }
137
138 getIt.get<BottomSheetService>().showNext();
139 if (isConnected) {
140 ledgerVM.suppressMoneroReconnectPrompt = false;
141 await navigatorKey.currentState!
142 .pushNamedAndRemoveUntil(Routes.dashboard, (route) => false);
143 }
144 },
145 allowChangeWallet: true,
146 ),
147 );
148 } else {
149 unawaited(
150 navigatorKey.currentState!.pushNamedAndRemoveUntil(Routes.dashboard, (route) => false),
151 );
152 }
153 WidgetsBinding.instance.addPostFrameCallback((_) {
154 final linkViewModel = getIt.get<LinkViewModel>();
155 linkViewModel.markReadyToOpenPage();
156 });
157
158 if (!(await authenticatedErrorStreamController.stream.isEmpty)) {
159 await ExceptionHandler.showError(
160 (await authenticatedErrorStreamController.stream.first).toString());
161 authenticatedErrorStreamController.stream.drain();
162 }
163 }
164 });
165 }