import 'package:hash_wallet/bitcoin/bitcoin.dart'; import 'package:hash_wallet/bitcoin_cash/bitcoin_cash.dart'; import 'package:hash_wallet/core/generate_wallet_password.dart'; import 'package:hash_wallet/core/wallet_creation_service.dart'; import 'package:hash_wallet/di.dart'; import 'package:hash_wallet/dogecoin/dogecoin.dart'; import 'package:hash_wallet/evm/evm.dart'; import 'package:hash_wallet/monero/monero.dart'; import 'package:hash_wallet/nano/nano.dart'; import 'package:hash_wallet/reactions/wallet_connect.dart'; import 'package:hash_wallet/store/app_store.dart'; import 'package:hash_wallet/utils/feature_flag.dart'; import 'package:hash_wallet/view_model/restore/restore_mode.dart'; import 'package:hash_wallet/view_model/restore/restore_wallet.dart'; import 'package:hash_wallet/view_model/seed_settings_view_model.dart'; import 'package:hash_wallet/view_model/wallet_creation_vm.dart'; import 'package:hash_wallet/wownero/wownero.dart'; import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/wallet_credentials.dart'; import 'package:cw_core/wallet_info.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:mobx/mobx.dart'; part 'wallet_restore_view_model.g.dart'; class WalletRestoreViewModel = WalletRestoreViewModelBase with _$WalletRestoreViewModel; abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store { WalletRestoreViewModelBase(AppStore appStore, WalletCreationService walletCreationService, SeedSettingsViewModel seedSettingsViewModel, {required WalletType type, this.restoredWallet, this.hardwareWalletType}) : isButtonEnabled = restoredWallet != null, hasPassphrase = false, mode = restoredWallet?.restoreMode ?? WalletRestoreMode.seed, super(appStore, walletCreationService, seedSettingsViewModel, type: type, isRecovery: true) { switch (type) { case WalletType.monero: availableModes = WalletRestoreMode.values; break; case WalletType.nano: case WalletType.banano: case WalletType.wownero: case WalletType.ethereum: case WalletType.polygon: case WalletType.base: case WalletType.arbitrum: case WalletType.bsc: case WalletType.bitcoin: case WalletType.litecoin: availableModes = [WalletRestoreMode.seed, WalletRestoreMode.keys]; break; case WalletType.bitcoinCash: case WalletType.dogecoin: availableModes = [WalletRestoreMode.seed]; break; case WalletType.none: availableModes = []; } walletCreationService.changeWalletType(type: type); if (restoredWallet != null) { if (restoredWallet!.restoreMode == WalletRestoreMode.seed) { seedSettingsViewModel.setPassphrase(restoredWallet!.passphrase); } } } static const moneroSeedMnemonicLength = 25; late List availableModes; late final bool hasSeedLanguageSelector = [WalletType.monero, WalletType.wownero].contains(type); late final bool hasBlockchainHeightSelector = [WalletType.monero, WalletType.wownero].contains(type); late final bool hasRestoreFromPrivateKey = [ WalletType.ethereum, WalletType.polygon, WalletType.base, WalletType.arbitrum, WalletType.bsc, WalletType.nano, WalletType.banano, ].contains(type); late final bool onlyViewKeyRestore = [if (FeatureFlag.hasBitcoinViewOnly) WalletType.bitcoin].contains(type); final RestoredWallet? restoredWallet; final HardwareWalletType? hardwareWalletType; @observable WalletRestoreMode mode; @observable bool hasPassphrase; @observable bool isButtonEnabled; @override WalletCredentials getCredentials(dynamic options) { final password = walletPassword ?? generateWalletPassword(); String? passphrase = options['passphrase'] as String?; final height = options['height'] as int? ?? 0; name = options['name'] as String; DerivationInfo? derivationInfo = options["derivationInfo"] as DerivationInfo?; if (mode == WalletRestoreMode.seed) { final seed = options['seed'] as String; switch (type) { case WalletType.monero: return monero!.createMoneroRestoreWalletFromSeedCredentials( name: name, height: height, mnemonic: seed, password: password, passphrase: passphrase ?? ''); case WalletType.bitcoin: case WalletType.litecoin: return bitcoin!.createBitcoinRestoreWalletFromSeedCredentials( name: name, mnemonic: seed, password: password, passphrase: passphrase, derivationType: derivationInfo!.derivationType!, derivationPath: derivationInfo.derivationPath!, ); case WalletType.bitcoinCash: return bitcoinCash!.createBitcoinCashRestoreWalletFromSeedCredentials( name: name, mnemonic: seed, password: password, passphrase: passphrase, ); case WalletType.dogecoin: return dogecoin!.createDogeCoinRestoreWalletFromSeedCredentials( name: name, mnemonic: seed, password: password, passphrase: passphrase, ); case WalletType.nano: case WalletType.banano: return nano!.createNanoRestoreWalletFromSeedCredentials( name: name, mnemonic: seed, password: password, derivationType: derivationInfo!.derivationType!, passphrase: passphrase, ); case WalletType.ethereum: case WalletType.polygon: case WalletType.base: case WalletType.arbitrum: case WalletType.bsc: return evm!.createEVMRestoreWalletFromSeedCredentials( name: name, mnemonic: seed, password: password, passphrase: passphrase, ); case WalletType.wownero: return wownero!.createWowneroRestoreWalletFromSeedCredentials( name: name, mnemonic: seed, password: password, passphrase: passphrase ?? '', height: height, ); case WalletType.none: break; } } if (mode == WalletRestoreMode.keys) { final viewKey = options['viewKey'] as String?; final spendKey = options['spendKey'] as String?; final scanSecret = options['scanSecret'] as String?; final spendPubkey = options['spendPubkey'] as String?; final address = options['address'] as String?; switch (type) { case WalletType.bitcoin: return bitcoin!.createBitcoinWalletFromKeys( name: name, password: password, xpub: viewKey!, hardwareWalletType: hardwareWalletType, ); case WalletType.litecoin: return bitcoin!.createLitecoinWalletFromKeys( name: name, password: password, xpub: viewKey!, scanSecret: scanSecret!, spendPubkey: spendPubkey!, hardwareWalletType: hardwareWalletType, ); case WalletType.monero: return monero!.createMoneroRestoreWalletFromKeysCredentials( name: name, height: height, spendKey: spendKey!, viewKey: viewKey!, address: address!, password: password, language: 'English', hardwareWalletType: hardwareWalletType ); case WalletType.nano: return nano!.createNanoRestoreWalletFromKeysCredentials( name: name, password: password, seedKey: options['private_key'] as String, derivationType: derivationInfo!.derivationType!, ); case WalletType.ethereum: case WalletType.polygon: case WalletType.base: case WalletType.arbitrum: case WalletType.bsc: return evm!.createEVMRestoreWalletFromPrivateKey( name: name, password: password, privateKey: options['private_key'] as String, ); case WalletType.wownero: return wownero!.createWowneroRestoreWalletFromKeysCredentials( name: name, height: height, spendKey: spendKey!, viewKey: viewKey!, address: address!, password: password, language: 'English', ); default: break; } } throw Exception('Unexpected type: ${type.toString()}'); } Future> getDerivationInfo(dynamic credentials) async { var list = []; var walletType = credentials["walletType"] as WalletType; var appStore = getIt.get(); int? chainId; if (isEVMCompatibleChain(walletType)) { if (appStore.wallet != null) { chainId = evm!.getSelectedChainId(appStore.wallet!); } chainId ??= evm!.getChainIdByWalletType(walletType); } var node = appStore.settingsStore.getCurrentNode(walletType, chainId: chainId); switch (walletType) { case WalletType.bitcoin: case WalletType.litecoin: String? mnemonic = credentials['seed'] as String?; String? passphrase = credentials['passphrase'] as String?; if (mnemonic == null) break; return bitcoin!.getDerivationsFromMnemonic( mnemonic: mnemonic, node: node, passphrase: passphrase, ); case WalletType.nano: String? mnemonic = credentials['seed'] as String?; String? seedKey = credentials['private_key'] as String?; return nanoUtil!.getDerivationsFromMnemonic( mnemonic: mnemonic, seedKey: seedKey, node: node, ); default: break; } return list; } @override Future process(WalletCredentials credentials) async { if (mode == WalletRestoreMode.keys) { return walletCreationService.restoreFromKeys(credentials, isTestnet: useTestnet); } return walletCreationService.restoreFromSeed(credentials, isTestnet: useTestnet); } }