From 4b4d8a4840309ec746accbca82ea097d00a5bf6a Mon Sep 17 00:00:00 2001 From: Omar Hatem Date: Fri, 4 Oct 2024 20:01:46 +0300 Subject: [PATCH] Add passphrase support for Eth, Polygon, and Tron (#1719) * Add passphrase support for Eth, Polygon, and Tron * move passphrase to advanced settings even for restore --- .../lib/src/bitcoin_cash_wallet.dart | 2 +- .../lib/src/bitcoin_cash_wallet_service.dart | 2 +- cw_ethereum/lib/ethereum_wallet.dart | 5 +- cw_ethereum/lib/ethereum_wallet_service.dart | 2 + cw_evm/lib/evm_chain_wallet.dart | 16 +++- ...evm_chain_wallet_creation_credentials.dart | 25 +++--- cw_nano/lib/nano_wallet.dart | 4 + .../lib/nano_wallet_creation_credentials.dart | 6 +- cw_polygon/lib/polygon_wallet.dart | 5 +- cw_polygon/lib/polygon_wallet_service.dart | 2 + cw_solana/lib/solana_wallet.dart | 5 +- .../solana_wallet_creation_credentials.dart | 20 +++-- cw_tron/lib/tron_wallet.dart | 13 ++- .../lib/tron_wallet_creation_credentials.dart | 20 +++-- cw_tron/lib/tron_wallet_service.dart | 7 +- lib/entities/unstoppable_domain_address.dart | 3 - lib/ethereum/cw_ethereum.dart | 10 ++- lib/nano/cw_nano.dart | 4 + lib/polygon/cw_polygon.dart | 23 +++-- lib/solana/cw_solana.dart | 10 ++- .../advanced_privacy_settings_page.dart | 90 +++++++++---------- .../wallet_restore_from_seed_form.dart | 29 ------ .../screens/restore/wallet_restore_page.dart | 5 +- lib/tron/cw_tron.dart | 10 ++- .../advanced_privacy_settings_view_model.dart | 3 + .../restore/restore_from_qr_vm.dart | 39 ++++++-- lib/view_model/wallet_new_vm.dart | 5 ++ lib/view_model/wallet_restore_view_model.dart | 19 ++-- tool/configure.dart | 19 ++-- 29 files changed, 249 insertions(+), 154 deletions(-) diff --git a/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart index b1e5e7bf69..825c80d4a8 100644 --- a/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart +++ b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart @@ -83,7 +83,7 @@ abstract class BitcoinCashWalletBase extends ElectrumWallet with Store { unspentCoinsInfo: unspentCoinsInfo, initialAddresses: initialAddresses, initialBalance: initialBalance, - seedBytes: await MnemonicBip39.toSeed(mnemonic, passphrase: passphrase), + seedBytes: MnemonicBip39.toSeed(mnemonic, passphrase: passphrase), encryptionFileUtils: encryptionFileUtils, initialRegularAddressIndex: initialRegularAddressIndex, initialChangeAddressIndex: initialChangeAddressIndex, diff --git a/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_service.dart b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_service.dart index ab5117aa8d..d14dc582df 100644 --- a/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_service.dart +++ b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_service.dart @@ -36,7 +36,7 @@ class BitcoinCashWalletService extends WalletService< final strength = credentials.seedPhraseLength == 24 ? 256 : 128; final wallet = await BitcoinCashWalletBase.create( - mnemonic: credentials.mnemonic ?? await MnemonicBip39.generate(strength: strength), + mnemonic: credentials.mnemonic ?? MnemonicBip39.generate(strength: strength), password: credentials.password!, walletInfo: credentials.walletInfo!, unspentCoinsInfo: unspentCoinsInfoSource, diff --git a/cw_ethereum/lib/ethereum_wallet.dart b/cw_ethereum/lib/ethereum_wallet.dart index e8a9e85fad..765ace0523 100644 --- a/cw_ethereum/lib/ethereum_wallet.dart +++ b/cw_ethereum/lib/ethereum_wallet.dart @@ -27,6 +27,7 @@ class EthereumWallet extends EVMChainWallet { super.initialBalance, super.privateKey, required super.encryptionFileUtils, + super.passphrase, }) : super(nativeCurrency: CryptoCurrency.eth); @override @@ -150,8 +151,9 @@ class EthereumWallet extends EVMChainWallet { if (!hasKeysFile) { final mnemonic = data!['mnemonic'] as String?; final privateKey = data['private_key'] as String?; + final passphrase = data['passphrase'] as String?; - keysData = WalletKeysData(mnemonic: mnemonic, privateKey: privateKey); + keysData = WalletKeysData(mnemonic: mnemonic, privateKey: privateKey, passphrase: passphrase); } else { keysData = await WalletKeysFile.readKeysFile( name, @@ -166,6 +168,7 @@ class EthereumWallet extends EVMChainWallet { password: password, mnemonic: keysData.mnemonic, privateKey: keysData.privateKey, + passphrase: keysData.passphrase, initialBalance: balance, client: EthereumClient(), encryptionFileUtils: encryptionFileUtils, diff --git a/cw_ethereum/lib/ethereum_wallet_service.dart b/cw_ethereum/lib/ethereum_wallet_service.dart index 51d6ecf427..858416055c 100644 --- a/cw_ethereum/lib/ethereum_wallet_service.dart +++ b/cw_ethereum/lib/ethereum_wallet_service.dart @@ -27,6 +27,7 @@ class EthereumWalletService extends EVMChainWalletService { walletInfo: credentials.walletInfo!, mnemonic: mnemonic, password: credentials.password!, + passphrase: credentials.passphrase, client: client, encryptionFileUtils: encryptionFileUtilsFor(isDirect), ); @@ -144,6 +145,7 @@ class EthereumWalletService extends EVMChainWalletService { password: credentials.password!, mnemonic: credentials.mnemonic, walletInfo: credentials.walletInfo!, + passphrase: credentials.passphrase, client: client, encryptionFileUtils: encryptionFileUtilsFor(isDirect), ); diff --git a/cw_evm/lib/evm_chain_wallet.dart b/cw_evm/lib/evm_chain_wallet.dart index 0ade2215e0..9bc18d14b2 100644 --- a/cw_evm/lib/evm_chain_wallet.dart +++ b/cw_evm/lib/evm_chain_wallet.dart @@ -70,6 +70,7 @@ abstract class EVMChainWalletBase required String password, EVMChainERC20Balance? initialBalance, required this.encryptionFileUtils, + this.passphrase, }) : syncStatus = const NotConnectedSyncStatus(), _password = password, _mnemonic = mnemonic, @@ -178,6 +179,7 @@ abstract class EVMChainWalletBase mnemonic: _mnemonic, privateKey: _hexPrivateKey, password: _password, + passphrase: passphrase, ); walletAddresses.address = _evmChainPrivateKey.address.hexEip55; } @@ -545,6 +547,7 @@ abstract class EVMChainWalletBase 'mnemonic': _mnemonic, 'private_key': privateKey, 'balance': balance[currency]!.toJSON(), + 'passphrase': passphrase, }); Future _updateBalance() async { @@ -574,15 +577,19 @@ abstract class EVMChainWalletBase } } - Future getPrivateKey( - {String? mnemonic, String? privateKey, required String password}) async { + Future getPrivateKey({ + String? mnemonic, + String? privateKey, + required String password, + String? passphrase, + }) async { assert(mnemonic != null || privateKey != null); if (privateKey != null) { return EthPrivateKey.fromHex(privateKey); } - final seed = bip39.mnemonicToSeed(mnemonic!); + final seed = bip39.mnemonicToSeed(mnemonic!, passphrase: passphrase ?? ''); final root = bip32.BIP32.fromSeed(seed); @@ -716,4 +723,7 @@ abstract class EVMChainWalletBase @override String get password => _password; + + @override + final String? passphrase; } diff --git a/cw_evm/lib/evm_chain_wallet_creation_credentials.dart b/cw_evm/lib/evm_chain_wallet_creation_credentials.dart index d7a33f6b30..5075e62895 100644 --- a/cw_evm/lib/evm_chain_wallet_creation_credentials.dart +++ b/cw_evm/lib/evm_chain_wallet_creation_credentials.dart @@ -4,28 +4,25 @@ import 'package:cw_core/wallet_info.dart'; class EVMChainNewWalletCredentials extends WalletCredentials { EVMChainNewWalletCredentials({ - required String name, - WalletInfo? walletInfo, - String? password, - String? parentAddress, + required super.name, + super.walletInfo, + super.password, + super.parentAddress, this.mnemonic, - }) : super( - name: name, - walletInfo: walletInfo, - password: password, - parentAddress: parentAddress, - ); + super.passphrase, + }); final String? mnemonic; } class EVMChainRestoreWalletFromSeedCredentials extends WalletCredentials { EVMChainRestoreWalletFromSeedCredentials({ - required String name, - required String password, + required super.name, + required super.password, required this.mnemonic, - WalletInfo? walletInfo, - }) : super(name: name, password: password, walletInfo: walletInfo); + super.walletInfo, + super.passphrase, + }); final String mnemonic; } diff --git a/cw_nano/lib/nano_wallet.dart b/cw_nano/lib/nano_wallet.dart index 700710c2e8..040fc95223 100644 --- a/cw_nano/lib/nano_wallet.dart +++ b/cw_nano/lib/nano_wallet.dart @@ -42,6 +42,7 @@ abstract class NanoWalletBase required String password, NanoBalance? initialBalance, required EncryptionFileUtils encryptionFileUtils, + this.passphrase, }) : syncStatus = NotConnectedSyncStatus(), _password = password, _mnemonic = mnemonic, @@ -548,4 +549,7 @@ abstract class NanoWalletBase } return await NanoSignatures.verifyMessage(message, signature, address); } + + @override + final String? passphrase; } diff --git a/cw_nano/lib/nano_wallet_creation_credentials.dart b/cw_nano/lib/nano_wallet_creation_credentials.dart index 9958fad7c2..59789aec7a 100644 --- a/cw_nano/lib/nano_wallet_creation_credentials.dart +++ b/cw_nano/lib/nano_wallet_creation_credentials.dart @@ -9,13 +9,15 @@ class NanoNewWalletCredentials extends WalletCredentials { DerivationType? derivationType, this.mnemonic, String? parentAddress, + String? passphrase, }) : super( name: name, password: password, walletInfo: walletInfo, parentAddress: parentAddress, + passphrase: passphrase, ); - + final String? mnemonic; } @@ -25,10 +27,12 @@ class NanoRestoreWalletFromSeedCredentials extends WalletCredentials { required this.mnemonic, String? password, required DerivationType derivationType, + String? passphrase, }) : super( name: name, password: password, derivationInfo: DerivationInfo(derivationType: derivationType), + passphrase: passphrase, ); final String mnemonic; diff --git a/cw_polygon/lib/polygon_wallet.dart b/cw_polygon/lib/polygon_wallet.dart index eb59a746e1..f9aff16c39 100644 --- a/cw_polygon/lib/polygon_wallet.dart +++ b/cw_polygon/lib/polygon_wallet.dart @@ -27,6 +27,7 @@ class PolygonWallet extends EVMChainWallet { super.privateKey, required super.client, required super.encryptionFileUtils, + super.passphrase, }) : super(nativeCurrency: CryptoCurrency.maticpoly); @override @@ -128,8 +129,9 @@ class PolygonWallet extends EVMChainWallet { if (!hasKeysFile) { final mnemonic = data!['mnemonic'] as String?; final privateKey = data['private_key'] as String?; + final passphrase = data['passphrase'] as String?; - keysData = WalletKeysData(mnemonic: mnemonic, privateKey: privateKey); + keysData = WalletKeysData(mnemonic: mnemonic, privateKey: privateKey, passphrase: passphrase); } else { keysData = await WalletKeysFile.readKeysFile( name, @@ -144,6 +146,7 @@ class PolygonWallet extends EVMChainWallet { password: password, mnemonic: keysData.mnemonic, privateKey: keysData.privateKey, + passphrase: keysData.passphrase, initialBalance: balance, client: PolygonClient(), encryptionFileUtils: encryptionFileUtils, diff --git a/cw_polygon/lib/polygon_wallet_service.dart b/cw_polygon/lib/polygon_wallet_service.dart index 514e73314b..994912e8d7 100644 --- a/cw_polygon/lib/polygon_wallet_service.dart +++ b/cw_polygon/lib/polygon_wallet_service.dart @@ -30,6 +30,7 @@ class PolygonWalletService extends EVMChainWalletService { walletInfo: credentials.walletInfo!, mnemonic: mnemonic, password: credentials.password!, + passphrase: credentials.passphrase, client: client, encryptionFileUtils: encryptionFileUtilsFor(isDirect), ); @@ -125,6 +126,7 @@ class PolygonWalletService extends EVMChainWalletService { password: credentials.password!, mnemonic: credentials.mnemonic, walletInfo: credentials.walletInfo!, + passphrase: credentials.passphrase, client: client, encryptionFileUtils: encryptionFileUtilsFor(isDirect), ); diff --git a/cw_solana/lib/solana_wallet.dart b/cw_solana/lib/solana_wallet.dart index 4e69db3b8c..3c3078f2e1 100644 --- a/cw_solana/lib/solana_wallet.dart +++ b/cw_solana/lib/solana_wallet.dart @@ -33,7 +33,6 @@ import 'package:solana/base58.dart'; import 'package:solana/metaplex.dart' as metaplex; import 'package:solana/solana.dart'; import 'package:solana/src/crypto/ed25519_hd_keypair.dart'; -import 'package:cryptography/cryptography.dart'; part 'solana_wallet.g.dart'; @@ -49,6 +48,7 @@ abstract class SolanaWalletBase required String password, SolanaBalance? initialBalance, required this.encryptionFileUtils, + this.passphrase, }) : syncStatus = const NotConnectedSyncStatus(), _password = password, _mnemonic = mnemonic, @@ -632,4 +632,7 @@ abstract class SolanaWalletBase @override String get password => _password; + + @override + final String? passphrase; } diff --git a/cw_solana/lib/solana_wallet_creation_credentials.dart b/cw_solana/lib/solana_wallet_creation_credentials.dart index f0901df79e..121ef2b445 100644 --- a/cw_solana/lib/solana_wallet_creation_credentials.dart +++ b/cw_solana/lib/solana_wallet_creation_credentials.dart @@ -8,22 +8,30 @@ class SolanaNewWalletCredentials extends WalletCredentials { String? password, String? parentAddress, this.mnemonic, + String? passphrase, }) : super( name: name, walletInfo: walletInfo, password: password, parentAddress: parentAddress, + passphrase: passphrase, ); final String? mnemonic; } class SolanaRestoreWalletFromSeedCredentials extends WalletCredentials { - SolanaRestoreWalletFromSeedCredentials( - {required String name, - required String password, - required this.mnemonic, - WalletInfo? walletInfo}) - : super(name: name, password: password, walletInfo: walletInfo); + SolanaRestoreWalletFromSeedCredentials({ + required String name, + required String password, + required this.mnemonic, + WalletInfo? walletInfo, + String? passphrase, + }) : super( + name: name, + password: password, + walletInfo: walletInfo, + passphrase: passphrase, + ); final String mnemonic; } diff --git a/cw_tron/lib/tron_wallet.dart b/cw_tron/lib/tron_wallet.dart index f5841d894e..9012ef5287 100644 --- a/cw_tron/lib/tron_wallet.dart +++ b/cw_tron/lib/tron_wallet.dart @@ -47,6 +47,7 @@ abstract class TronWalletBase required String password, TronBalance? initialBalance, required this.encryptionFileUtils, + this.passphrase, }) : syncStatus = const NotConnectedSyncStatus(), _password = password, _mnemonic = mnemonic, @@ -113,6 +114,7 @@ abstract class TronWalletBase mnemonic: _mnemonic, privateKey: _hexPrivateKey, password: _password, + passphrase: passphrase, ); _tronPublicKey = _tronPrivateKey.publicKey(); @@ -149,8 +151,9 @@ abstract class TronWalletBase if (!hasKeysFile) { final mnemonic = data!['mnemonic'] as String?; final privateKey = data['private_key'] as String?; + final passphrase = data['passphrase'] as String?; - keysData = WalletKeysData(mnemonic: mnemonic, privateKey: privateKey); + keysData = WalletKeysData(mnemonic: mnemonic, privateKey: privateKey, passphrase: passphrase); } else { keysData = await WalletKeysFile.readKeysFile( name, @@ -165,6 +168,7 @@ abstract class TronWalletBase password: password, mnemonic: keysData.mnemonic, privateKey: keysData.privateKey, + passphrase: keysData.passphrase, initialBalance: balance, encryptionFileUtils: encryptionFileUtils, ); @@ -190,12 +194,13 @@ abstract class TronWalletBase String? mnemonic, String? privateKey, required String password, + String? passphrase, }) async { assert(mnemonic != null || privateKey != null); if (privateKey != null) return TronPrivateKey(privateKey); - final seed = bip39.mnemonicToSeed(mnemonic!); + final seed = bip39.mnemonicToSeed(mnemonic!, passphrase: passphrase ?? ''); // Derive a TRON private key from the seed final bip44 = Bip44.fromSeed(seed, Bip44Coins.tron); @@ -463,6 +468,7 @@ abstract class TronWalletBase 'mnemonic': _mnemonic, 'private_key': privateKey, 'balance': balance[currency]!.toJSON(), + 'passphrase': passphrase, }); Future _updateBalance() async { @@ -607,4 +613,7 @@ abstract class TronWalletBase @override String get password => _password; + + @override + final String? passphrase; } diff --git a/cw_tron/lib/tron_wallet_creation_credentials.dart b/cw_tron/lib/tron_wallet_creation_credentials.dart index 5055c8a8de..fd9066acd4 100644 --- a/cw_tron/lib/tron_wallet_creation_credentials.dart +++ b/cw_tron/lib/tron_wallet_creation_credentials.dart @@ -8,23 +8,31 @@ class TronNewWalletCredentials extends WalletCredentials { String? password, this.mnemonic, String? parentAddress, + String? passphrase, }) : super( name: name, walletInfo: walletInfo, password: password, parentAddress: parentAddress, + passphrase: passphrase, ); final String? mnemonic; } class TronRestoreWalletFromSeedCredentials extends WalletCredentials { - TronRestoreWalletFromSeedCredentials( - {required String name, - required String password, - required this.mnemonic, - WalletInfo? walletInfo}) - : super(name: name, password: password, walletInfo: walletInfo); + TronRestoreWalletFromSeedCredentials({ + required String name, + required String password, + required this.mnemonic, + WalletInfo? walletInfo, + String? passphrase, + }) : super( + name: name, + password: password, + walletInfo: walletInfo, + passphrase: passphrase, + ); final String mnemonic; } diff --git a/cw_tron/lib/tron_wallet_service.dart b/cw_tron/lib/tron_wallet_service.dart index 200653eb9d..c732a87c48 100644 --- a/cw_tron/lib/tron_wallet_service.dart +++ b/cw_tron/lib/tron_wallet_service.dart @@ -33,10 +33,7 @@ class TronWalletService extends WalletService< WalletType getType() => WalletType.tron; @override - Future create( - TronNewWalletCredentials credentials, { - bool? isTestnet, - }) async { + Future create(TronNewWalletCredentials credentials, {bool? isTestnet}) async { final strength = credentials.seedPhraseLength == 24 ? 256 : 128; final mnemonic = credentials.mnemonic ?? bip39.generateMnemonic(strength: strength); @@ -45,6 +42,7 @@ class TronWalletService extends WalletService< walletInfo: credentials.walletInfo!, mnemonic: mnemonic, password: credentials.password!, + passphrase: credentials.passphrase, encryptionFileUtils: encryptionFileUtilsFor(isDirect), ); @@ -120,6 +118,7 @@ class TronWalletService extends WalletService< password: credentials.password!, mnemonic: credentials.mnemonic, walletInfo: credentials.walletInfo!, + passphrase: credentials.passphrase, encryptionFileUtils: encryptionFileUtilsFor(isDirect), ); diff --git a/lib/entities/unstoppable_domain_address.dart b/lib/entities/unstoppable_domain_address.dart index 0f56517b84..6966fdd75b 100644 --- a/lib/entities/unstoppable_domain_address.dart +++ b/lib/entities/unstoppable_domain_address.dart @@ -1,10 +1,7 @@ import 'dart:convert'; -import 'package:flutter/services.dart'; import 'package:http/http.dart' as http; -const channel = MethodChannel('com.cake_wallet/native_utils'); - Future fetchUnstoppableDomainAddress(String domain, String ticker) async { var address = ''; diff --git a/lib/ethereum/cw_ethereum.dart b/lib/ethereum/cw_ethereum.dart index 7796e1c600..e2c3d13580 100644 --- a/lib/ethereum/cw_ethereum.dart +++ b/lib/ethereum/cw_ethereum.dart @@ -14,6 +14,7 @@ class CWEthereum extends Ethereum { String? parentAddress, WalletInfo? walletInfo, String? password, + String? passphrase, }) => EVMChainNewWalletCredentials( name: name, @@ -21,6 +22,7 @@ class CWEthereum extends Ethereum { password: password, parentAddress: parentAddress, mnemonic: mnemonic, + passphrase: passphrase, ); @override @@ -28,8 +30,14 @@ class CWEthereum extends Ethereum { required String name, required String mnemonic, required String password, + String? passphrase, }) => - EVMChainRestoreWalletFromSeedCredentials(name: name, password: password, mnemonic: mnemonic); + EVMChainRestoreWalletFromSeedCredentials( + name: name, + password: password, + mnemonic: mnemonic, + passphrase: passphrase, + ); @override WalletCredentials createEthereumRestoreWalletFromPrivateKey({ diff --git a/lib/nano/cw_nano.dart b/lib/nano/cw_nano.dart index 83702a8ce8..9e47edc048 100644 --- a/lib/nano/cw_nano.dart +++ b/lib/nano/cw_nano.dart @@ -95,6 +95,7 @@ class CWNano extends Nano { String? password, String? mnemonic, String? parentAddress, + String? passphrase, }) => NanoNewWalletCredentials( name: name, @@ -102,6 +103,7 @@ class CWNano extends Nano { mnemonic: mnemonic, parentAddress: parentAddress, walletInfo: walletInfo, + passphrase: passphrase, ); @override @@ -110,6 +112,7 @@ class CWNano extends Nano { required String password, required String mnemonic, required DerivationType derivationType, + String? passphrase, }) { if (mnemonic.split(" ").length == 12 && derivationType != DerivationType.bip39) { throw Exception("Invalid mnemonic for derivation type!"); @@ -120,6 +123,7 @@ class CWNano extends Nano { password: password, mnemonic: mnemonic, derivationType: derivationType, + passphrase: passphrase, ); } diff --git a/lib/polygon/cw_polygon.dart b/lib/polygon/cw_polygon.dart index 307107dd49..299c8278a1 100644 --- a/lib/polygon/cw_polygon.dart +++ b/lib/polygon/cw_polygon.dart @@ -8,18 +8,21 @@ class CWPolygon extends Polygon { PolygonWalletService(walletInfoSource, isDirect, client: PolygonClient()); @override - WalletCredentials createPolygonNewWalletCredentials( - {required String name, - String? mnemonic, - String? parentAddress, - WalletInfo? walletInfo, - String? password}) => + WalletCredentials createPolygonNewWalletCredentials({ + required String name, + String? mnemonic, + String? parentAddress, + WalletInfo? walletInfo, + String? password, + String? passphrase, + }) => EVMChainNewWalletCredentials( name: name, walletInfo: walletInfo, password: password, mnemonic: mnemonic, parentAddress: parentAddress, + passphrase: passphrase, ); @override @@ -27,8 +30,14 @@ class CWPolygon extends Polygon { required String name, required String mnemonic, required String password, + String? passphrase, }) => - EVMChainRestoreWalletFromSeedCredentials(name: name, password: password, mnemonic: mnemonic); + EVMChainRestoreWalletFromSeedCredentials( + name: name, + password: password, + mnemonic: mnemonic, + passphrase: passphrase, + ); @override WalletCredentials createPolygonRestoreWalletFromPrivateKey({ diff --git a/lib/solana/cw_solana.dart b/lib/solana/cw_solana.dart index 22cc478b64..7894f77edb 100644 --- a/lib/solana/cw_solana.dart +++ b/lib/solana/cw_solana.dart @@ -14,6 +14,7 @@ class CWSolana extends Solana { String? parentAddress, WalletInfo? walletInfo, String? password, + String? passphrase, }) => SolanaNewWalletCredentials( name: name, @@ -21,6 +22,7 @@ class CWSolana extends Solana { password: password, mnemonic: mnemonic, parentAddress: parentAddress, + passphrase: passphrase, ); @override @@ -28,8 +30,14 @@ class CWSolana extends Solana { required String name, required String mnemonic, required String password, + String? passphrase, }) => - SolanaRestoreWalletFromSeedCredentials(name: name, password: password, mnemonic: mnemonic); + SolanaRestoreWalletFromSeedCredentials( + name: name, + password: password, + mnemonic: mnemonic, + passphrase: passphrase, + ); @override WalletCredentials createSolanaRestoreWalletFromPrivateKey({ diff --git a/lib/src/screens/new_wallet/advanced_privacy_settings_page.dart b/lib/src/screens/new_wallet/advanced_privacy_settings_page.dart index 8b7be18a14..26c96fb74c 100644 --- a/lib/src/screens/new_wallet/advanced_privacy_settings_page.dart +++ b/lib/src/screens/new_wallet/advanced_privacy_settings_page.dart @@ -189,7 +189,7 @@ class _AdvancedPrivacySettingsBodyState extends State<_AdvancedPrivacySettingsBo ), ); }), - if (!widget.isFromRestore) ...[ + if (!widget.isFromRestore) Observer(builder: (_) { if (widget.privacySettingsViewModel.hasSeedPhraseLengthOption) return SettingsPickerCell( @@ -202,54 +202,53 @@ class _AdvancedPrivacySettingsBodyState extends State<_AdvancedPrivacySettingsBo ); return Container(); }), - if (widget.privacySettingsViewModel.hasPassphraseOption) - Padding( - padding: EdgeInsets.all(24), - child: Form( - key: _passphraseFormKey, - child: Column( - children: [ - BaseTextFormField( - hintText: S.of(context).passphrase, - controller: passphraseController, - obscureText: obscurePassphrase, - suffixIcon: GestureDetector( - onTap: () => setState(() { - obscurePassphrase = !obscurePassphrase; - }), - child: Icon( - Icons.remove_red_eye, - color: obscurePassphrase ? Colors.black54 : Colors.black26, - ), + if (widget.privacySettingsViewModel.hasPassphraseOption) + Padding( + padding: EdgeInsets.all(24), + child: Form( + key: _passphraseFormKey, + child: Column( + children: [ + BaseTextFormField( + hintText: S.of(context).passphrase, + controller: passphraseController, + obscureText: obscurePassphrase, + suffixIcon: GestureDetector( + onTap: () => setState(() { + obscurePassphrase = !obscurePassphrase; + }), + child: Icon( + Icons.remove_red_eye, + color: obscurePassphrase ? Colors.black54 : Colors.black26, ), ), - const SizedBox(height: 10), - BaseTextFormField( - hintText: S.of(context).confirm_passphrase, - controller: confirmPassphraseController, - obscureText: obscurePassphrase, - validator: (text) { - if (text == passphraseController.text) { - return null; - } + ), + const SizedBox(height: 10), + BaseTextFormField( + hintText: S.of(context).confirm_passphrase, + controller: confirmPassphraseController, + obscureText: obscurePassphrase, + validator: (text) { + if (text == passphraseController.text) { + return null; + } - return S.of(context).passphrases_doesnt_match; - }, - suffixIcon: GestureDetector( - onTap: () => setState(() { - obscurePassphrase = !obscurePassphrase; - }), - child: Icon( - Icons.remove_red_eye, - color: obscurePassphrase ? Colors.black54 : Colors.black26, - ), + return S.of(context).passphrases_doesnt_match; + }, + suffixIcon: GestureDetector( + onTap: () => setState(() { + obscurePassphrase = !obscurePassphrase; + }), + child: Icon( + Icons.remove_red_eye, + color: obscurePassphrase ? Colors.black54 : Colors.black26, ), ), - ], - ), + ), + ], ), ), - ], + ), Observer(builder: (_) { return Column( children: [ @@ -311,13 +310,14 @@ class _AdvancedPrivacySettingsBodyState extends State<_AdvancedPrivacySettingsBo widget.nodeViewModel.save(); } if (passphraseController.text.isNotEmpty) { - if (_passphraseFormKey.currentState != null && !_passphraseFormKey.currentState!.validate()) { + if (_passphraseFormKey.currentState != null && + !_passphraseFormKey.currentState!.validate()) { return; } - - widget.seedTypeViewModel.setPassphrase(passphraseController.text); } + widget.seedTypeViewModel.setPassphrase(passphraseController.text); + Navigator.pop(context); }, text: S.of(context).continue_text, diff --git a/lib/src/screens/restore/wallet_restore_from_seed_form.dart b/lib/src/screens/restore/wallet_restore_from_seed_form.dart index 897a6bed01..c8a75cf400 100644 --- a/lib/src/screens/restore/wallet_restore_from_seed_form.dart +++ b/lib/src/screens/restore/wallet_restore_from_seed_form.dart @@ -19,7 +19,6 @@ class WalletRestoreFromSeedForm extends StatefulWidget { WalletRestoreFromSeedForm({Key? key, required this.displayLanguageSelector, required this.displayBlockHeightSelector, - required this.displayPassphrase, required this.type, required this.displayWalletPassword, required this.seedSettingsViewModel, @@ -35,7 +34,6 @@ class WalletRestoreFromSeedForm extends StatefulWidget { final bool displayLanguageSelector; final bool displayBlockHeightSelector; final bool displayWalletPassword; - final bool displayPassphrase; final SeedSettingsViewModel seedSettingsViewModel; final FocusNode? blockHeightFocusNode; final Function(bool)? onHeightOrDateEntered; @@ -60,7 +58,6 @@ class WalletRestoreFromSeedFormState extends State { repeatedPasswordTextEditingController = displayWalletPassword ? TextEditingController() : null, - passphraseController = TextEditingController(), seedTypeController = TextEditingController(); final GlobalKey seedWidgetStateKey; @@ -70,15 +67,11 @@ class WalletRestoreFromSeedFormState extends State { final TextEditingController? passwordTextEditingController; final TextEditingController? repeatedPasswordTextEditingController; final TextEditingController seedTypeController; - final TextEditingController passphraseController; final GlobalKey formKey; late ReactionDisposer moneroSeedTypeReaction; String language; void Function()? passwordListener; void Function()? repeatedPasswordListener; - void Function()? passphraseListener; - - bool obscurePassphrase = true; @override void initState() { @@ -96,9 +89,6 @@ class WalletRestoreFromSeedFormState extends State { repeatedPasswordTextEditingController?.addListener(repeatedPasswordListener!); } - passphraseListener = () => widget.seedSettingsViewModel.setPassphrase(passphraseController.text); - passphraseController.addListener(passphraseListener!); - moneroSeedTypeReaction = reaction((_) => widget.seedSettingsViewModel.moneroSeedType, (MoneroSeedType item) { _setSeedType(item); @@ -120,8 +110,6 @@ class WalletRestoreFromSeedFormState extends State { repeatedPasswordTextEditingController?.removeListener(repeatedPasswordListener!); } - passphraseController.removeListener(passphraseListener!); - super.dispose(); } @@ -280,23 +268,6 @@ class WalletRestoreFromSeedFormState extends State { hasDatePicker: widget.type == WalletType.monero || widget.type == WalletType.wownero, walletType: widget.type, ), - if (widget.displayPassphrase) ...[ - const SizedBox(height: 10), - BaseTextFormField( - hintText: S.current.passphrase, - controller: passphraseController, - obscureText: obscurePassphrase, - suffixIcon: GestureDetector( - onTap: () => setState(() { - obscurePassphrase = !obscurePassphrase; - }), - child: Icon( - Icons.remove_red_eye, - color: obscurePassphrase ? Colors.black54 : Colors.black26, - ), - ), - ), - ] ])); } diff --git a/lib/src/screens/restore/wallet_restore_page.dart b/lib/src/screens/restore/wallet_restore_page.dart index 4a4e27b3d7..6215e26c35 100644 --- a/lib/src/screens/restore/wallet_restore_page.dart +++ b/lib/src/screens/restore/wallet_restore_page.dart @@ -37,7 +37,6 @@ class WalletRestorePage extends BasePage { displayBlockHeightSelector: walletRestoreViewModel.hasBlockchainHeightLanguageSelector, displayLanguageSelector: walletRestoreViewModel.hasSeedLanguageSelector, - displayPassphrase: walletRestoreViewModel.hasPassphrase, type: walletRestoreViewModel.type, key: walletRestoreFromSeedFormKey, blockHeightFocusNode: _blockHeightFocusNode, @@ -320,9 +319,7 @@ class WalletRestorePage extends BasePage { -1; } - if (walletRestoreViewModel.hasPassphrase) { - credentials['passphrase'] = seedSettingsViewModel.passphrase; - } + credentials['passphrase'] = seedSettingsViewModel.passphrase; credentials['name'] = walletRestoreFromSeedFormKey.currentState!.nameTextEditingController.text; diff --git a/lib/tron/cw_tron.dart b/lib/tron/cw_tron.dart index b4aed4235c..8bceafe01a 100644 --- a/lib/tron/cw_tron.dart +++ b/lib/tron/cw_tron.dart @@ -15,12 +15,14 @@ class CWTron extends Tron { String? password, String? mnemonic, String? parentAddress, + String? passphrase, }) => TronNewWalletCredentials( name: name, walletInfo: walletInfo, password: password, mnemonic: mnemonic, + passphrase: passphrase, parentAddress: parentAddress); @override @@ -28,8 +30,14 @@ class CWTron extends Tron { required String name, required String mnemonic, required String password, + String? passphrase, }) => - TronRestoreWalletFromSeedCredentials(name: name, password: password, mnemonic: mnemonic); + TronRestoreWalletFromSeedCredentials( + name: name, + password: password, + mnemonic: mnemonic, + passphrase: passphrase, + ); @override WalletCredentials createTronRestoreWalletFromPrivateKey({ diff --git a/lib/view_model/advanced_privacy_settings_view_model.dart b/lib/view_model/advanced_privacy_settings_view_model.dart index b97c796f79..85b9dbead1 100644 --- a/lib/view_model/advanced_privacy_settings_view_model.dart +++ b/lib/view_model/advanced_privacy_settings_view_model.dart @@ -75,6 +75,9 @@ abstract class AdvancedPrivacySettingsViewModelBase with Store { WalletType.bitcoin, WalletType.litecoin, WalletType.bitcoinCash, + WalletType.ethereum, + WalletType.polygon, + WalletType.tron, ].contains(type); @computed diff --git a/lib/view_model/restore/restore_from_qr_vm.dart b/lib/view_model/restore/restore_from_qr_vm.dart index 6701b639d1..798105b9d0 100644 --- a/lib/view_model/restore/restore_from_qr_vm.dart +++ b/lib/view_model/restore/restore_from_qr_vm.dart @@ -13,7 +13,7 @@ import 'package:hive/hive.dart'; import 'package:mobx/mobx.dart'; import 'package:cake_wallet/monero/monero.dart'; import 'package:cake_wallet/store/app_store.dart'; -import 'package:cw_core/wallet_base.dart'; +import 'package:cw_core/wallet_base.dart'; import 'package:cake_wallet/core/generate_wallet_password.dart'; import 'package:cake_wallet/core/wallet_creation_service.dart'; import 'package:cw_core/wallet_credentials.dart'; @@ -26,14 +26,19 @@ part 'restore_from_qr_vm.g.dart'; class WalletRestorationFromQRVM = WalletRestorationFromQRVMBase with _$WalletRestorationFromQRVM; abstract class WalletRestorationFromQRVMBase extends WalletCreationVM with Store { - WalletRestorationFromQRVMBase(AppStore appStore, WalletCreationService walletCreationService, - Box walletInfoSource, WalletType type, SeedSettingsViewModel seedSettingsViewModel) + WalletRestorationFromQRVMBase( + AppStore appStore, + WalletCreationService walletCreationService, + Box walletInfoSource, + WalletType type, + SeedSettingsViewModel seedSettingsViewModel) : height = 0, viewKey = '', spendKey = '', wif = '', address = '', - super(appStore, walletInfoSource, walletCreationService, seedSettingsViewModel, type: type, isRecovery: true); + super(appStore, walletInfoSource, walletCreationService, seedSettingsViewModel, + type: type, isRecovery: true); @observable int height; @@ -124,26 +129,44 @@ abstract class WalletRestorationFromQRVMBase extends WalletCreationVM with Store name: name, mnemonic: restoreWallet.mnemonicSeed ?? '', password: password, + passphrase: restoreWallet.passphrase, ); case WalletType.ethereum: return ethereum!.createEthereumRestoreWalletFromSeedCredentials( - name: name, mnemonic: restoreWallet.mnemonicSeed ?? '', password: password); + name: name, + mnemonic: restoreWallet.mnemonicSeed ?? '', + password: password, + passphrase: restoreWallet.passphrase, + ); case WalletType.nano: return nano!.createNanoRestoreWalletFromSeedCredentials( name: name, mnemonic: restoreWallet.mnemonicSeed ?? '', password: password, derivationType: derivationInfo!.derivationType!, + passphrase: restoreWallet.passphrase, ); case WalletType.polygon: return polygon!.createPolygonRestoreWalletFromSeedCredentials( - name: name, mnemonic: restoreWallet.mnemonicSeed ?? '', password: password); + name: name, + mnemonic: restoreWallet.mnemonicSeed ?? '', + password: password, + passphrase: restoreWallet.passphrase, + ); case WalletType.solana: return solana!.createSolanaRestoreWalletFromSeedCredentials( - name: name, mnemonic: restoreWallet.mnemonicSeed ?? '', password: password); + name: name, + mnemonic: restoreWallet.mnemonicSeed ?? '', + password: password, + passphrase: restoreWallet.passphrase, + ); case WalletType.tron: return tron!.createTronRestoreWalletFromSeedCredentials( - name: name, mnemonic: restoreWallet.mnemonicSeed ?? '', password: password); + name: name, + mnemonic: restoreWallet.mnemonicSeed ?? '', + password: password, + passphrase: restoreWallet.passphrase, + ); case WalletType.wownero: return wownero!.createWowneroRestoreWalletFromSeedCredentials( name: name, diff --git a/lib/view_model/wallet_new_vm.dart b/lib/view_model/wallet_new_vm.dart index 2919afcace..be30811d95 100644 --- a/lib/view_model/wallet_new_vm.dart +++ b/lib/view_model/wallet_new_vm.dart @@ -106,6 +106,7 @@ abstract class WalletNewVMBase extends WalletCreationVM with Store { password: walletPassword, mnemonic: newWalletArguments!.mnemonic, parentAddress: newWalletArguments!.parentAddress, + passphrase: passphrase, ); case WalletType.bitcoinCash: return bitcoinCash!.createBitcoinCashNewWalletCredentials( @@ -122,6 +123,7 @@ abstract class WalletNewVMBase extends WalletCreationVM with Store { password: walletPassword, mnemonic: newWalletArguments!.mnemonic, parentAddress: newWalletArguments!.parentAddress, + passphrase: passphrase, ); case WalletType.polygon: return polygon!.createPolygonNewWalletCredentials( @@ -129,6 +131,7 @@ abstract class WalletNewVMBase extends WalletCreationVM with Store { password: walletPassword, mnemonic: newWalletArguments!.mnemonic, parentAddress: newWalletArguments!.parentAddress, + passphrase: passphrase, ); case WalletType.solana: return solana!.createSolanaNewWalletCredentials( @@ -136,6 +139,7 @@ abstract class WalletNewVMBase extends WalletCreationVM with Store { password: walletPassword, mnemonic: newWalletArguments!.mnemonic, parentAddress: newWalletArguments!.parentAddress, + passphrase: passphrase, ); case WalletType.tron: return tron!.createTronNewWalletCredentials( @@ -143,6 +147,7 @@ abstract class WalletNewVMBase extends WalletCreationVM with Store { password: walletPassword, mnemonic: newWalletArguments!.mnemonic, parentAddress: newWalletArguments!.parentAddress, + passphrase: passphrase, ); case WalletType.wownero: return wownero!.createWowneroNewWalletCredentials( diff --git a/lib/view_model/wallet_restore_view_model.dart b/lib/view_model/wallet_restore_view_model.dart index 5462ce4c88..d37b69f746 100644 --- a/lib/view_model/wallet_restore_view_model.dart +++ b/lib/view_model/wallet_restore_view_model.dart @@ -78,9 +78,6 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store { final bool hasBlockchainHeightLanguageSelector; final bool hasRestoreFromPrivateKey; - bool get hasPassphrase => - [WalletType.bitcoin, WalletType.litecoin, WalletType.bitcoinCash].contains(type); - @observable WalletRestoreMode mode; @@ -116,10 +113,18 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store { name: name, height: height, mnemonic: seed, password: password); case WalletType.ethereum: return ethereum!.createEthereumRestoreWalletFromSeedCredentials( - name: name, mnemonic: seed, password: password); + name: name, + mnemonic: seed, + password: password, + passphrase: passphrase, + ); case WalletType.bitcoinCash: return bitcoinCash!.createBitcoinCashRestoreWalletFromSeedCredentials( - name: name, mnemonic: seed, password: password); + name: name, + mnemonic: seed, + password: password, + passphrase: passphrase, + ); case WalletType.nano: case WalletType.banano: return nano!.createNanoRestoreWalletFromSeedCredentials( @@ -127,24 +132,28 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store { mnemonic: seed, password: password, derivationType: derivationInfo!.derivationType!, + passphrase: passphrase, ); case WalletType.polygon: return polygon!.createPolygonRestoreWalletFromSeedCredentials( name: name, mnemonic: seed, password: password, + passphrase: passphrase, ); case WalletType.solana: return solana!.createSolanaRestoreWalletFromSeedCredentials( name: name, mnemonic: seed, password: password, + passphrase: passphrase, ); case WalletType.tron: return tron!.createTronRestoreWalletFromSeedCredentials( name: name, mnemonic: seed, password: password, + passphrase: passphrase, ); case WalletType.wownero: return wownero!.createWowneroRestoreWalletFromSeedCredentials( diff --git a/tool/configure.dart b/tool/configure.dart index d54ec153d0..c3d84c4f65 100644 --- a/tool/configure.dart +++ b/tool/configure.dart @@ -843,8 +843,8 @@ import 'package:eth_sig_util/util/utils.dart'; abstract class Ethereum { List getEthereumWordList(String language); WalletService createEthereumWalletService(Box walletInfoSource, bool isDirect); - WalletCredentials createEthereumNewWalletCredentials({required String name, WalletInfo? walletInfo, String? password, String? mnemonic, String? parentAddress}); - WalletCredentials createEthereumRestoreWalletFromSeedCredentials({required String name, required String mnemonic, required String password}); + WalletCredentials createEthereumNewWalletCredentials({required String name, WalletInfo? walletInfo, String? password, String? mnemonic, String? parentAddress, String? passphrase}); + WalletCredentials createEthereumRestoreWalletFromSeedCredentials({required String name, required String mnemonic, required String password, String? passphrase}); WalletCredentials createEthereumRestoreWalletFromPrivateKey({required String name, required String privateKey, required String password}); WalletCredentials createEthereumHardwareWalletCredentials({required String name, required HardwareAccountData hwAccountData, WalletInfo? walletInfo}); String getAddress(WalletBase wallet); @@ -947,8 +947,8 @@ import 'package:eth_sig_util/util/utils.dart'; abstract class Polygon { List getPolygonWordList(String language); WalletService createPolygonWalletService(Box walletInfoSource, bool isDirect); - WalletCredentials createPolygonNewWalletCredentials({required String name, WalletInfo? walletInfo, String? password, String? mnemonic, String? parentAddress}); - WalletCredentials createPolygonRestoreWalletFromSeedCredentials({required String name, required String mnemonic, required String password}); + WalletCredentials createPolygonNewWalletCredentials({required String name, WalletInfo? walletInfo, String? password, String? mnemonic, String? parentAddress, String? passphrase}); + WalletCredentials createPolygonRestoreWalletFromSeedCredentials({required String name, required String mnemonic, required String password, String? passphrase}); WalletCredentials createPolygonRestoreWalletFromPrivateKey({required String name, required String privateKey, required String password}); WalletCredentials createPolygonHardwareWalletCredentials({required String name, required HardwareAccountData hwAccountData, WalletInfo? walletInfo}); String getAddress(WalletBase wallet); @@ -1119,6 +1119,7 @@ abstract class Nano { String? mnemonic, String? parentAddress, WalletInfo? walletInfo, + String? passphrase, }); WalletCredentials createNanoRestoreWalletFromSeedCredentials({ @@ -1126,6 +1127,7 @@ abstract class Nano { required String password, required String mnemonic, required DerivationType derivationType, + String? passphrase, }); WalletCredentials createNanoRestoreWalletFromKeysCredentials({ @@ -1234,9 +1236,9 @@ abstract class Solana { List getSolanaWordList(String language); WalletService createSolanaWalletService(Box walletInfoSource, bool isDirect); WalletCredentials createSolanaNewWalletCredentials( - {required String name, WalletInfo? walletInfo, String? password, String? mnemonic, String? parentAddress,}); + {required String name, WalletInfo? walletInfo, String? password, String? mnemonic, String? parentAddress, String? passphrase}); WalletCredentials createSolanaRestoreWalletFromSeedCredentials( - {required String name, required String mnemonic, required String password}); + {required String name, required String mnemonic, required String password, String? passphrase}); WalletCredentials createSolanaRestoreWalletFromPrivateKey( {required String name, required String privateKey, required String password}); @@ -1320,9 +1322,8 @@ import 'package:cw_tron/tron_wallet_service.dart'; abstract class Tron { List getTronWordList(String language); WalletService createTronWalletService(Box walletInfoSource, bool isDirect); - WalletCredentials createTronNewWalletCredentials({required String name, WalletInfo? walletInfo, String? password, String? mnemonic, - String? parentAddress}); - WalletCredentials createTronRestoreWalletFromSeedCredentials({required String name, required String mnemonic, required String password}); + WalletCredentials createTronNewWalletCredentials({required String name, WalletInfo? walletInfo, String? password, String? mnemonic, String? parentAddress, String? passphrase}); + WalletCredentials createTronRestoreWalletFromSeedCredentials({required String name, required String mnemonic, required String password, String? passphrase}); WalletCredentials createTronRestoreWalletFromPrivateKey({required String name, required String privateKey, required String password}); String getAddress(WalletBase wallet);