diff --git a/cw_bitcoin/lib/bitcoin_derivations.dart b/cw_bitcoin/lib/electrum_derivations.dart similarity index 98% rename from cw_bitcoin/lib/bitcoin_derivations.dart rename to cw_bitcoin/lib/electrum_derivations.dart index 576db6d6c..e2450fc5f 100644 --- a/cw_bitcoin/lib/bitcoin_derivations.dart +++ b/cw_bitcoin/lib/electrum_derivations.dart @@ -1,6 +1,6 @@ import 'package:cw_core/wallet_info.dart'; -Map> bitcoin_derivations = { +Map> electrum_derivations = { DerivationType.electrum: [ DerivationInfo( derivationType: DerivationType.electrum, diff --git a/lib/bitcoin/cw_bitcoin.dart b/lib/bitcoin/cw_bitcoin.dart index aef36c45e..7ae01df1c 100644 --- a/lib/bitcoin/cw_bitcoin.dart +++ b/lib/bitcoin/cw_bitcoin.dart @@ -287,6 +287,18 @@ class CWBitcoin extends Bitcoin { }) async { List list = []; + List types = await compareDerivationMethods(mnemonic: mnemonic, node: node); + if (types.length == 1 && types.first == DerivationType.electrum) { + return [ + DerivationInfo( + derivationType: DerivationType.electrum, + derivationPath: "m/0'/0", + description: "Electrum", + scriptType: "p2wpkh", + ) + ]; + } + final electrumClient = ElectrumClient(); await electrumClient.connectToUri(node.uri); @@ -304,7 +316,7 @@ class CWBitcoin extends Bitcoin { break; } - for (DerivationType dType in bitcoin_derivations.keys) { + for (DerivationType dType in electrum_derivations.keys) { late Uint8List seedBytes; if (dType == DerivationType.electrum) { seedBytes = await mnemonicToSeedBytes(mnemonic); @@ -312,7 +324,7 @@ class CWBitcoin extends Bitcoin { seedBytes = bip39.mnemonicToSeed(mnemonic, passphrase: passphrase ?? ''); } - for (DerivationInfo dInfo in bitcoin_derivations[dType]!) { + for (DerivationInfo dInfo in electrum_derivations[dType]!) { try { DerivationInfo dInfoCopy = DerivationInfo( derivationType: dInfo.derivationType, @@ -325,7 +337,7 @@ class CWBitcoin extends Bitcoin { int derivationDepth = _countOccurrences(derivationPath, "/"); // the correct derivation depth is dependant on the derivation type: - // the derivation paths defined in bitcoin_derivations are at the ROOT level, i.e.: + // the derivation paths defined in electrum_derivations are at the ROOT level, i.e.: // electrum's format doesn't specify subaddresses, just subaccounts: // for BIP44 diff --git a/lib/nano/cw_nano.dart b/lib/nano/cw_nano.dart index 2d13dfcdf..13800cff6 100644 --- a/lib/nano/cw_nano.dart +++ b/lib/nano/cw_nano.dart @@ -106,7 +106,6 @@ class CWNano extends Nano { required String mnemonic, required DerivationType derivationType, }) { - if (mnemonic.split(" ").length == 12 && derivationType != DerivationType.bip39) { throw Exception("Invalid mnemonic for derivation type!"); } @@ -126,7 +125,6 @@ class CWNano extends Nano { required String seedKey, required DerivationType derivationType, }) { - if (seedKey.length == 128 && derivationType != DerivationType.bip39) { throw Exception("Invalid seed key length for derivation type!"); } @@ -192,7 +190,6 @@ class CWNano extends Nano { } class CWNanoUtil extends NanoUtil { - @override bool isValidBip39Seed(String seed) { return NanoDerivations.isValidBip39Seed(seed); @@ -346,4 +343,54 @@ class CWNanoUtil extends NanoUtil { return [DerivationType.nano, DerivationType.bip39]; } } + + @override + Future> getDerivationsFromMnemonic({ + String? mnemonic, + String? seedKey, + required Node node, + }) async { + List list = []; + + List possibleDerivationTypes = await compareDerivationMethods( + mnemonic: mnemonic, + privateKey: seedKey, + node: node, + ); + if (possibleDerivationTypes.length == 1) { + return [DerivationInfo(derivationType: possibleDerivationTypes.first)]; + } + + AccountInfoResponse? bip39Info = await nanoUtil!.getInfoFromSeedOrMnemonic( + DerivationType.bip39, + mnemonic: mnemonic, + seedKey: seedKey, + node: node, + ); + AccountInfoResponse? standardInfo = await nanoUtil!.getInfoFromSeedOrMnemonic( + DerivationType.nano, + mnemonic: mnemonic, + seedKey: seedKey, + node: node, + ); + + if (standardInfo?.confirmationHeight != null && standardInfo!.confirmationHeight > 0) { + list.add(DerivationInfo( + derivationType: DerivationType.nano, + balance: nanoUtil!.getRawAsUsableString(standardInfo.balance, nanoUtil!.rawPerNano), + address: standardInfo.address!, + transactionsCount: standardInfo.confirmationHeight, + )); + } + + if (bip39Info?.confirmationHeight != null && bip39Info!.confirmationHeight > 0) { + list.add(DerivationInfo( + derivationType: DerivationType.bip39, + balance: nanoUtil!.getRawAsUsableString(bip39Info.balance, nanoUtil!.rawPerNano), + address: bip39Info.address!, + transactionsCount: bip39Info.confirmationHeight, + )); + } + return list; + } } diff --git a/lib/view_model/wallet_creation_vm.dart b/lib/view_model/wallet_creation_vm.dart index 1da2c15dc..5c9c29a16 100644 --- a/lib/view_model/wallet_creation_vm.dart +++ b/lib/view_model/wallet_creation_vm.dart @@ -113,13 +113,19 @@ abstract class WalletCreationVMBase with Store { derivationType: DerivationType.nano, ); case WalletType.bitcoin: - case WalletType.litecoin: return DerivationInfo( derivationType: DerivationType.bip39, derivationPath: "m/84'/0'/0'/0", description: "Standard BIP84 native segwit", scriptType: "p2wpkh", ); + case WalletType.litecoin: + return DerivationInfo( + derivationType: DerivationType.bip39, + derivationPath: "m/84'/2'/0'/0", + description: "Standard BIP84 native segwit (litecoin)", + scriptType: "p2wpkh", + ); default: return null; } diff --git a/lib/view_model/wallet_restore_view_model.dart b/lib/view_model/wallet_restore_view_model.dart index 97c672682..06d86bb3d 100644 --- a/lib/view_model/wallet_restore_view_model.dart +++ b/lib/view_model/wallet_restore_view_model.dart @@ -212,65 +212,17 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store { case WalletType.nano: String? mnemonic = credentials['seed'] as String?; String? seedKey = credentials['private_key'] as String?; - AccountInfoResponse? bip39Info = await nanoUtil!.getInfoFromSeedOrMnemonic( - DerivationType.bip39, - mnemonic: mnemonic, - seedKey: seedKey, - node: node); - AccountInfoResponse? standardInfo = await nanoUtil!.getInfoFromSeedOrMnemonic( - DerivationType.nano, + return nanoUtil!.getDerivationsFromMnemonic( mnemonic: mnemonic, seedKey: seedKey, node: node, ); - - if (standardInfo?.balance != null) { - list.add(DerivationInfo( - derivationType: DerivationType.nano, - balance: nanoUtil!.getRawAsUsableString(standardInfo!.balance, nanoUtil!.rawPerNano), - address: standardInfo.address!, - transactionsCount: standardInfo.confirmationHeight, - )); - } - - if (bip39Info?.balance != null) { - list.add(DerivationInfo( - derivationType: DerivationType.bip39, - balance: nanoUtil!.getRawAsUsableString(bip39Info!.balance, nanoUtil!.rawPerNano), - address: bip39Info.address!, - transactionsCount: bip39Info.confirmationHeight, - )); - } - break; default: break; } return list; } - Future> getDerivationTypes(dynamic options) async { - final seedKey = options['private_key'] as String?; - final mnemonic = options['seed'] as String?; - WalletType walletType = options['walletType'] as WalletType; - var appStore = getIt.get(); - var node = appStore.settingsStore.getCurrentNode(walletType); - - switch (type) { - case WalletType.bitcoin: - case WalletType.litecoin: - return bitcoin!.compareDerivationMethods(mnemonic: mnemonic!, node: node); - case WalletType.nano: - return nanoUtil!.compareDerivationMethods( - mnemonic: mnemonic, - privateKey: seedKey, - node: node, - ); - default: - break; - } - return [DerivationType.def]; - } - @override Future process(WalletCredentials credentials) async { if (mode == WalletRestoreMode.keys) { diff --git a/tool/configure.dart b/tool/configure.dart index 03d4dbf3e..ceb0c9ccc 100644 --- a/tool/configure.dart +++ b/tool/configure.dart @@ -84,7 +84,7 @@ import 'package:hive/hive.dart'; const bitcoinCWHeaders = """ import 'package:cw_bitcoin/utils.dart'; import 'package:cw_bitcoin/litecoin_network.dart'; -import 'package:cw_bitcoin/bitcoin_derivations.dart'; +import 'package:cw_bitcoin/electrum_derivations.dart'; import 'package:cw_bitcoin/electrum.dart'; import 'package:cw_bitcoin/pending_bitcoin_transaction.dart'; import 'package:cw_bitcoin/bitcoin_receive_page_option.dart'; @@ -914,6 +914,11 @@ abstract class NanoUtil { String? privateKey, required Node node, }); + Future> getDerivationsFromMnemonic({ + String? mnemonic, + String? seedKey, + required Node node, + }); } """;