| 1 | import 'dart:io'; |
| 2 | import 'package:cake_wallet/core/backup_service_v3.dart'; |
| 3 | import 'package:cake_wallet/core/execution_state.dart'; |
| 4 | import 'package:cake_wallet/utils/exception_handler.dart'; |
| 5 | import 'package:flutter/material.dart'; |
| 6 | import 'package:hive/hive.dart'; |
| 7 | import 'package:mobx/mobx.dart'; |
| 8 | import 'package:cake_wallet/main.dart'; |
| 9 | import 'package:cake_wallet/di.dart'; |
| 10 | import 'package:cw_core/node.dart'; |
| 11 | import 'package:cake_wallet/store/app_store.dart'; |
| 12 | import 'package:cake_wallet/store/authentication_store.dart'; |
| 13 | |
| 14 | part 'restore_from_backup_view_model.g.dart'; |
| 15 | |
| 16 | class RestoreFromBackupViewModel = RestoreFromBackupViewModelBase with _$RestoreFromBackupViewModel; |
| 17 | |
| 18 | abstract class RestoreFromBackupViewModelBase with Store { |
| 19 | RestoreFromBackupViewModelBase(this.backupService) |
| 20 | : state = InitialExecutionState(), |
| 21 | filePath = ''; |
| 22 | |
| 23 | final BackupServiceV3 backupService; |
| 24 | |
| 25 | @observable |
| 26 | String filePath; |
| 27 | |
| 28 | @observable |
| 29 | ExecutionState state; |
| 30 | |
| 31 | @action |
| 32 | void reset() => filePath = ''; |
| 33 | |
| 34 | @action |
| 35 | Future<void> import(String password, {bool checkBackupApp = true}) async { |
| 36 | try { |
| 37 | state = IsExecutingState(); |
| 38 | |
| 39 | if (filePath.isEmpty) { |
| 40 | state = FailureState('Backup file is not selected.'); |
| 41 | return; |
| 42 | } |
| 43 | |
| 44 | final file = File(filePath); |
| 45 | |
| 46 | try { |
| 47 | await backupService.importBackupFile(file, password, checkBackupApp: checkBackupApp); |
| 48 | } on IncompatibleBackupAppException { |
| 49 | rethrow; |
| 50 | } catch (e, s) { |
| 51 | if (e.toString().contains("unknown_backup_version")) { |
| 52 | state = FailureState( |
| 53 | 'This is not a valid backup file, please make sure you have selected the correct one'); |
| 54 | } else { |
| 55 | state = FailureState(e.toString() + "\n" + s.toString()); |
| 56 | } |
| 57 | } |
| 58 | |
| 59 | try { |
| 60 | await initializeAppAtRoot(reInitializing: true); |
| 61 | } catch (e, s) { |
| 62 | state = FailureState('Failed app initialization, please try again'); |
| 63 | ExceptionHandler.onError(FlutterErrorDetails(exception: e, stack: s, silent: true)); |
| 64 | } |
| 65 | |
| 66 | final store = getIt.get<AppStore>(); |
| 67 | ReactionDisposer? reaction; |
| 68 | await store.settingsStore.reload(); |
| 69 | await store.themeStore.loadSavedTheme(isFromBackup: true); |
| 70 | reaction = autorun((_) { |
| 71 | final wallet = store.wallet; |
| 72 | |
| 73 | if (wallet != null) { |
| 74 | store.authenticationStore.state = AuthenticationState.allowed; |
| 75 | reaction?.reaction.dispose(); |
| 76 | } |
| 77 | }); |
| 78 | |
| 79 | state = ExecutedSuccessfullyState(); |
| 80 | } on IncompatibleBackupAppException { |
| 81 | state = InitialExecutionState(); |
| 82 | rethrow; |
| 83 | } catch (e, s) { |
| 84 | var msg = e.toString().toLowerCase(); |
| 85 | |
| 86 | // can't use a switch here because of .contains() / not an exact match |
| 87 | bool shouldBeMadeAware = false; |
| 88 | if (msg.contains("message authentication code (mac)")) { |
| 89 | msg = 'Incorrect backup password'; |
| 90 | } else if (msg.contains("faileddecryption")) { |
| 91 | msg = 'Failed to decrypt backup file, please check you entered the right password'; |
| 92 | } else if (msg.contains("failed_to_decode")) { |
| 93 | msg = 'Failed to decode backup file, please try again'; |
| 94 | shouldBeMadeAware = true; |
| 95 | } else if (msg.contains("failed_app_initialization")) { |
| 96 | msg = 'Failed to initialize app, please try again'; |
| 97 | shouldBeMadeAware = true; |
| 98 | } else { |
| 99 | shouldBeMadeAware = true; |
| 100 | } |
| 101 | |
| 102 | if (shouldBeMadeAware) { |
| 103 | await ExceptionHandler.onError(FlutterErrorDetails( |
| 104 | exception: e, |
| 105 | stack: s, |
| 106 | library: this.toString(), |
| 107 | )); |
| 108 | } |
| 109 | |
| 110 | state = FailureState(msg); |
| 111 | } |
| 112 | } |
| 113 | } |