diff --git a/cw_bitcoin/lib/bitcoin_wallet_service.dart b/cw_bitcoin/lib/bitcoin_wallet_service.dart index df1e3b74b..f94067d12 100644 --- a/cw_bitcoin/lib/bitcoin_wallet_service.dart +++ b/cw_bitcoin/lib/bitcoin_wallet_service.dart @@ -96,9 +96,6 @@ class BitcoinWalletService extends WalletService<BitcoinNewWalletCredentials, @override Future<BitcoinWallet> restoreFromSeed(BitcoinRestoreWalletFromSeedCredentials credentials) async { - if (!validateMnemonic(credentials.mnemonic)) { - throw BitcoinMnemonicIsIncorrectException(); - } final wallet = await BitcoinWalletBase.create( password: credentials.password!, @@ -114,14 +111,10 @@ class BitcoinWalletService extends WalletService<BitcoinNewWalletCredentials, static Future<List<DerivationType>> compareDerivationMethods( {required String mnemonic, required Node node}) async { - if (!validateMnemonic(mnemonic)) { - throw BitcoinMnemonicIsIncorrectException(); - } - if (await checkIfMnemonicIsElectrum2(mnemonic)) { return [DerivationType.electrum2]; } - + return [DerivationType.bip39, DerivationType.electrum2]; } diff --git a/cw_bitcoin/pubspec.lock b/cw_bitcoin/pubspec.lock index bfcd9e5a6..843daa771 100644 --- a/cw_bitcoin/pubspec.lock +++ b/cw_bitcoin/pubspec.lock @@ -37,19 +37,19 @@ packages: dependency: transitive description: name: async - sha256: bfe67ef28df125b7dddcea62755991f807aa39a2492a23e1550161692950bbe0 + sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" url: "https://pub.dev" source: hosted - version: "2.10.0" + version: "2.11.0" bech32: dependency: transitive description: path: "." - ref: "cake-0.2.1" - resolved-ref: cafd1c270641e95017d57d69f55cca9831d4db56 + ref: "cake-0.2.2" + resolved-ref: "05755063b593aa6cca0a4820a318e0ce17de6192" url: "https://github.com/cake-tech/bech32.git" source: git - version: "0.2.1" + version: "0.2.2" bip32: dependency: transitive description: @@ -70,8 +70,8 @@ packages: dependency: "direct main" description: path: "." - ref: cake-update-v2 - resolved-ref: "8f86453761c0c26e368392d0ff2c6f12f3b7397b" + ref: cake-update-v3 + resolved-ref: df9204144011ed9419eff7d9ef3143102a40252d url: "https://github.com/cake-tech/bitcoin_flutter.git" source: git version: "2.0.2" @@ -159,10 +159,10 @@ packages: dependency: transitive description: name: characters - sha256: e6a326c8af69605aec75ed6c187d06b349707a27fbff8222ca9cc2cff167975c + sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" url: "https://pub.dev" source: hosted - version: "1.2.1" + version: "1.3.0" checked_yaml: dependency: transitive description: @@ -191,18 +191,18 @@ packages: dependency: transitive description: name: collection - sha256: cfc915e6923fe5ce6e153b0723c753045de46de1b4d63771530504004a45fae0 + sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c" url: "https://pub.dev" source: hosted - version: "1.17.0" + version: "1.17.1" convert: dependency: transitive description: name: convert - sha256: "196284f26f69444b7f5c50692b55ec25da86d9e500451dc09333bf2e3ad69259" + sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592" url: "https://pub.dev" source: hosted - version: "3.0.2" + version: "3.1.1" crypto: dependency: transitive description: @@ -344,10 +344,10 @@ packages: dependency: "direct main" description: name: http - sha256: "6aa2946395183537c8b880962d935877325d6a09a2867c3970c05c0fed6ac482" + sha256: "759d1a329847dd0f39226c688d3e06a6b8679668e350e2891a6474f8b4bb8525" url: "https://pub.dev" source: hosted - version: "0.13.5" + version: "1.1.0" http_multi_server: dependency: transitive description: @@ -368,10 +368,10 @@ packages: dependency: "direct main" description: name: intl - sha256: "910f85bce16fb5c6f614e117efa303e85a1731bb0081edf3604a2ae6e9a3cc91" + sha256: "3bc132a9dbce73a7e4a21a17d06e1878839ffbf975568bc875c60537824b0c4d" url: "https://pub.dev" source: hosted - version: "0.17.0" + version: "0.18.1" io: dependency: transitive description: @@ -384,10 +384,10 @@ packages: dependency: transitive description: name: js - sha256: "5528c2f391ededb7775ec1daa69e65a2d61276f7552de2b5f7b8d34ee9fd4ab7" + sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 url: "https://pub.dev" source: hosted - version: "0.6.5" + version: "0.6.7" json_annotation: dependency: transitive description: @@ -408,10 +408,10 @@ packages: dependency: transitive description: name: matcher - sha256: "16db949ceee371e9b99d22f88fa3a73c4e59fd0afed0bd25fc336eb76c198b72" + sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb" url: "https://pub.dev" source: hosted - version: "0.12.13" + version: "0.12.15" material_color_utilities: dependency: transitive description: @@ -424,10 +424,10 @@ packages: dependency: transitive description: name: meta - sha256: "6c268b42ed578a53088d834796959e4a1814b5e9e164f147f580a386e5decf42" + sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" url: "https://pub.dev" source: hosted - version: "1.8.0" + version: "1.9.1" mime: dependency: transitive description: @@ -464,10 +464,10 @@ packages: dependency: transitive description: name: path - sha256: db9d4f58c908a4ba5953fcee2ae317c94889433e5024c27ce74a37f94267945b + sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" url: "https://pub.dev" source: hosted - version: "1.8.2" + version: "1.8.3" path_provider: dependency: "direct main" description: @@ -669,10 +669,10 @@ packages: dependency: transitive description: name: test_api - sha256: ad540f65f92caa91bf21dfc8ffb8c589d6e4dc0c2267818b4cc2792857706206 + sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb url: "https://pub.dev" source: hosted - version: "0.4.16" + version: "0.5.1" timing: dependency: transitive description: @@ -746,5 +746,5 @@ packages: source: hosted version: "3.1.1" sdks: - dart: ">=2.19.0 <3.0.0" + dart: ">=3.0.0 <4.0.0" flutter: ">=3.0.0" diff --git a/lib/di.dart b/lib/di.dart index ce7408669..a50b7d933 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -841,9 +841,9 @@ Future<void> setup({ getIt.registerFactoryParam<WalletRestorePage, WalletType, void>( (type, _) => WalletRestorePage(getIt.get<WalletRestoreViewModel>(param1: type))); - getIt.registerFactoryParam<WalletRestoreChooseDerivationViewModel, dynamic, void>( - (credentials, _) => - WalletRestoreChooseDerivationViewModel(credentials: credentials)); + getIt.registerFactoryParam<WalletRestoreChooseDerivationViewModel, List<DerivationInfo>, void>( + (derivations, _) => + WalletRestoreChooseDerivationViewModel(derivationInfos: derivations)); getIt.registerFactoryParam<WalletRestoreChooseDerivationPage, dynamic, void>( (credentials, _) => diff --git a/lib/router.dart b/lib/router.dart index ee61e6eda..d28657e39 100644 --- a/lib/router.dart +++ b/lib/router.dart @@ -58,6 +58,7 @@ import 'package:cake_wallet/view_model/advanced_privacy_settings_view_model.dart import 'package:cake_wallet/wallet_type_utils.dart'; import 'package:cw_core/nano_account.dart'; import 'package:cw_core/pow_node.dart'; +import 'package:cw_core/wallet_info.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:cake_wallet/routes.dart'; @@ -202,7 +203,7 @@ Route<dynamic> createRoute(RouteSettings settings) { case Routes.restoreWalletChooseDerivation: return MaterialPageRoute<void>( builder: (_) => - getIt.get<WalletRestoreChooseDerivationPage>(param1: settings.arguments as dynamic)); + getIt.get<WalletRestoreChooseDerivationPage>(param1: settings.arguments as List<DerivationInfo>)); case Routes.sweepingWalletPage: return CupertinoPageRoute<void>(builder: (_) => getIt.get<SweepingWalletPage>()); diff --git a/lib/src/screens/restore/wallet_restore_page.dart b/lib/src/screens/restore/wallet_restore_page.dart index 839f8930e..9faf8ae83 100644 --- a/lib/src/screens/restore/wallet_restore_page.dart +++ b/lib/src/screens/restore/wallet_restore_page.dart @@ -1,9 +1,14 @@ +import 'package:cake_wallet/di.dart'; import 'package:cake_wallet/routes.dart'; +import 'package:cake_wallet/store/app_store.dart'; import 'package:cake_wallet/themes/extensions/keyboard_theme.dart'; import 'package:cake_wallet/src/widgets/keyboard_done_button.dart'; import 'package:cake_wallet/utils/responsive_layout_util.dart'; +import 'package:cw_bitcoin/bitcoin_wallet_service.dart'; import 'package:cw_core/wallet_info.dart'; import 'package:cw_core/wallet_type.dart'; +import 'package:cw_nano/nano_util.dart'; +import 'package:cw_nano/nano_wallet_service.dart'; import 'package:flutter/material.dart'; import 'package:keyboard_actions/keyboard_actions.dart'; import 'package:mobx/mobx.dart'; @@ -295,6 +300,60 @@ class WalletRestorePage extends BasePage { return credentials; } + Future<List<DerivationInfo>> getDerivationInfo(dynamic credentials) async { + var list = <DerivationInfo>[]; + var walletType = credentials["walletType"] as WalletType; + var appStore = getIt.get<AppStore>(); + var node = appStore.settingsStore.getCurrentNode(walletType); + switch (walletType) { + case WalletType.bitcoin: + String? mnemonic = credentials['seed'] as String?; + return await BitcoinWalletService.getDerivationsFromMnemonic( + mnemonic: mnemonic!, node: node); + case WalletType.nano: + String? mnemonic = credentials['seed'] as String?; + String? seedKey = credentials['private_key'] as String?; + dynamic bip39Info = await NanoWalletService.getInfoFromSeedOrMnemonic(DerivationType.bip39, + mnemonic: mnemonic, seedKey: seedKey, node: node); + dynamic standardInfo = await NanoWalletService.getInfoFromSeedOrMnemonic( + DerivationType.nano, + mnemonic: mnemonic, + seedKey: seedKey, + node: node, + ); + + if (standardInfo["balance"] != null) { + list.add(DerivationInfo( + derivationType: DerivationType.nano, + balance: NanoUtil.getRawAsUsableString( + standardInfo["balance"] as String, NanoUtil.rawPerNano), + address: standardInfo["address"] as String, + height: int.tryParse( + standardInfo["confirmation_height"] as String, + ) ?? + 0, + )); + } + + if (bip39Info["balance"] != null) { + list.add(DerivationInfo( + derivationType: DerivationType.bip39, + balance: + NanoUtil.getRawAsUsableString(bip39Info["balance"] as String, NanoUtil.rawPerNano), + address: bip39Info["address"] as String, + height: int.tryParse( + bip39Info["confirmation_height"] as String? ?? "", + ) ?? + 0, + )); + } + break; + default: + break; + } + return list; + } + Future<void> _confirmForm(BuildContext context) async { // Dismissing all visible keyboard to provide context for navigation FocusManager.instance.primaryFocus?.unfocus(); @@ -328,9 +387,29 @@ class WalletRestorePage extends BasePage { if (derivationTypes[0] == DerivationType.unknown || derivationTypes.length > 1) { // push screen to choose the derivation type: - var derivationInfo = await Navigator.of(context) - .pushNamed(Routes.restoreWalletChooseDerivation, arguments: _credentials()) - as DerivationInfo?; + List<DerivationInfo> derivations = await getDerivationInfo(_credentials()); + + int derivationsWithHistory = 0; + int derivationWithHistoryIndex = 0; + for (int i = 0; i < derivations.length; i++) { + if (derivations[i].height > 0) { + derivationsWithHistory++; + derivationWithHistoryIndex = i; + } + } + DerivationInfo? derivationInfo; + + if (derivationsWithHistory > 1) { + derivationInfo = await Navigator.of(context).pushNamed(Routes.restoreWalletChooseDerivation, + arguments: derivations) as DerivationInfo?; + } else if (derivationsWithHistory == 1) { + derivationInfo = derivations[derivationWithHistoryIndex]; + } else if (derivationsWithHistory == 0) { + // default derivation: + this.derivationType = derivationTypes[0]; + this.derivationPath = "m/0'/1"; + } + if (derivationInfo == null) { walletRestoreViewModel.state = InitialExecutionState(); return; diff --git a/lib/view_model/wallet_restore_choose_derivation_view_model.dart b/lib/view_model/wallet_restore_choose_derivation_view_model.dart index 9cd2ee173..494707fe4 100644 --- a/lib/view_model/wallet_restore_choose_derivation_view_model.dart +++ b/lib/view_model/wallet_restore_choose_derivation_view_model.dart @@ -14,98 +14,18 @@ class WalletRestoreChooseDerivationViewModel = WalletRestoreChooseDerivationView with _$WalletRestoreChooseDerivationViewModel; abstract class WalletRestoreChooseDerivationViewModelBase with Store { - WalletRestoreChooseDerivationViewModelBase({required this.credentials}) + WalletRestoreChooseDerivationViewModelBase({required this.derivationInfos}) : mode = WalletRestoreMode.seed {} - dynamic credentials; + @observable + List<DerivationInfo> derivationInfos; + + Future<List<DerivationInfo>> get derivations async { + return derivationInfos; + } @observable WalletRestoreMode mode; - Future<List<DerivationInfo>> get derivations async { - var list = <DerivationInfo>[]; - var walletType = credentials["walletType"] as WalletType; - var appStore = getIt.get<AppStore>(); - var node = appStore.settingsStore.getCurrentNode(walletType); - switch (walletType) { - case WalletType.bitcoin: - String? mnemonic = credentials['seed'] as String?; - var derivations = await BitcoinWalletService.getDerivationsFromMnemonic(mnemonic: mnemonic!, node: node); - int count = 0; - for (int i = 0; i < derivations.length; i++) { - if (derivations[i].height != 0) { - count += 1; - } - } - if (count == 1) { - for (int i = 0; i < derivations.length; i++) { - if (derivations[i].height != 0) { - list.add(derivations[i]); - } - } - } else { - return derivations; - } - - - // var standardInfo = await NanoWalletService.getInfoFromSeedOrMnemonic( - // DerivationType.nano, - // mnemonic: mnemonic, - // seedKey: seedKey, - // node: node, - // ); - - // list.add(DerivationInfo( - // balance: "0.00000", - // address: "address", - // height: 0, - // derivationType: DerivationType.bip39, - // )); - break; - case WalletType.nano: - String? mnemonic = credentials['seed'] as String?; - String? seedKey = credentials['private_key'] as String?; - var bip39Info = await NanoWalletService.getInfoFromSeedOrMnemonic(DerivationType.bip39, - mnemonic: mnemonic, seedKey: seedKey, node: node); - var standardInfo = await NanoWalletService.getInfoFromSeedOrMnemonic( - DerivationType.nano, - mnemonic: mnemonic, - seedKey: seedKey, - node: node, - ); - - if (standardInfo["balance"] != null) { - list.add(DerivationInfo( - derivationType: DerivationType.nano, - balance: NanoUtil.getRawAsUsableString( - standardInfo["balance"] as String, NanoUtil.rawPerNano), - address: standardInfo["address"] as String, - height: int.tryParse( - standardInfo["confirmation_height"] as String, - ) ?? - 0, - )); - } - - if (bip39Info["balance"] != null) { - list.add(DerivationInfo( - derivationType: DerivationType.bip39, - balance: - NanoUtil.getRawAsUsableString(bip39Info["balance"] as String, NanoUtil.rawPerNano), - address: bip39Info["address"] as String, - height: int.tryParse( - bip39Info["confirmation_height"] as String? ?? "", - ) ?? - 0, - )); - } - - break; - default: - break; - } - - return list; - } }