Cw 488 seed offset (#1631)

* CW-488 minor code cleanup * Add Derivation Path selector for BTC and LTC * CW-488 Initial Passphrase Impl * CW-488 Final Passphrase Impl * Quick Fix of language Service * CW-488 Implement PR Suggestions * CW-488 Implement PR Suggestions * CW-488 Implement Passphrase for Bitcoin Cash * CW-488 Implement Passphrase for Bitcoin Cash * CW-488 Implement Passphrase for Bitcoin Cash * remove monero and wownero support for passphrase until merged [skip ci] * CW-488 Apply requested change * CW-488 Add Passphrase to QR * CW-488 Fix Seed generation * CW-488 Implement Electrum Passphrases * CW-488 Add Seed Length Selector to BIP39 Seeds * CW-488 Minor fix [skip ci] --------- Co-authored-by: Omar Hatem <omarh.ismail1@gmail.com>

Konstantin Ullrich committed Aug 26, 2024 at 19:06 UTC ce21098e9824edf4f8d828f127e4d1aaeefee213
67 files changed +733 -430
cw_bitcoin/lib/bitcoin_mnemonic.dart
+8 -10
@@ -1,6 +1,7 @@
1 import 'dart:convert';
2 import 'dart:math';
3 import 'dart:typed_data';
4 +
5 import 'package:crypto/crypto.dart';
6 import 'package:cryptography/cryptography.dart' as cryptography;
7 import 'package:cw_core/sec_random_native.dart';
@@ -59,11 +60,7 @@ void maskBytes(Uint8List bytes, int bits) {
60 }
61 }
62
62 -String bufferToBin(Uint8List data) {
63 - final q1 = data.map((e) => e.toRadixString(2).padLeft(8, '0'));
64 - final q2 = q1.join('');
65 - return q2;
66 -}
63 +String bufferToBin(Uint8List data) => data.map((e) => e.toRadixString(2).padLeft(8, '0')).join('');
64
65 String encode(Uint8List data) {
66 final dataBitLen = data.length * 8;
@@ -112,17 +109,18 @@ Future<bool> checkIfMnemonicIsElectrum2(String mnemonic) async {
109 Future<String> getMnemonicHash(String mnemonic) async {
110 final hmacSha512 = Hmac(sha512, utf8.encode('Seed version'));
111 final digest = hmacSha512.convert(utf8.encode(normalizeText(mnemonic)));
115 - final hx = digest.toString();
116 - return hx;
112 + return digest.toString();
113 }
114
119 -Future<Uint8List> mnemonicToSeedBytes(String mnemonic, {String prefix = segwit}) async {
115 +Future<Uint8List> mnemonicToSeedBytes(String mnemonic,
116 + {String prefix = segwit, String passphrase = ''}) async {
117 final pbkdf2 =
118 cryptography.Pbkdf2(macAlgorithm: cryptography.Hmac.sha512(), iterations: 2048, bits: 512);
119 final text = normalizeText(mnemonic);
123 - // pbkdf2.deriveKey(secretKey: secretKey, nonce: nonce)
120 + final passphraseBytes = utf8.encode(normalizeText(passphrase));
121 final key = await pbkdf2.deriveKey(
125 - secretKey: cryptography.SecretKey(text.codeUnits), nonce: 'electrum'.codeUnits);
122 + secretKey: cryptography.SecretKey(text.codeUnits),
123 + nonce: [...'electrum'.codeUnits, ...passphraseBytes]);
124 final bytes = await key.extractBytes();
125 return Uint8List.fromList(bytes);
126 }
cw_bitcoin/lib/bitcoin_mnemonics_bip39.dart renamed
+2 -1
@@ -7,5 +7,6 @@ class MnemonicBip39 {
7 static String generate({int strength = 128}) => bip39.generateMnemonic(strength: strength);
8
9 /// Create root seed from mnemonic
10 - static Uint8List toSeed(String mnemonic) => bip39.mnemonicToSeed(mnemonic);
10 + static Uint8List toSeed(String mnemonic, {String? passphrase}) =>
11 + bip39.mnemonicToSeed(mnemonic, passphrase: passphrase ?? '');
12 }
cw_bitcoin/lib/bitcoin_wallet.dart
+2 -2
@@ -115,7 +115,7 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
115 break;
116 case DerivationType.electrum:
117 default:
118 - seedBytes = await mnemonicToSeedBytes(mnemonic);
118 + seedBytes = await mnemonicToSeedBytes(mnemonic, passphrase: passphrase ?? "");
119 break;
120 }
121 return BitcoinWallet(
@@ -195,7 +195,7 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
195 if (mnemonic != null) {
196 switch (walletInfo.derivationInfo!.derivationType) {
197 case DerivationType.electrum:
198 - seedBytes = await mnemonicToSeedBytes(mnemonic);
198 + seedBytes = await mnemonicToSeedBytes(mnemonic, passphrase: passphrase ?? "");
199 break;
200 case DerivationType.bip39:
201 default:
cw_bitcoin/lib/bitcoin_wallet_creation_credentials.dart
+9 -7
@@ -3,16 +3,18 @@ import 'package:cw_core/wallet_credentials.dart';
3 import 'package:cw_core/wallet_info.dart';
4
5 class BitcoinNewWalletCredentials extends WalletCredentials {
6 - BitcoinNewWalletCredentials(
7 - {required String name,
8 - WalletInfo? walletInfo,
9 - String? password,
10 - DerivationType? derivationType,
11 - String? derivationPath})
12 - : super(
6 + BitcoinNewWalletCredentials({
7 + required String name,
8 + WalletInfo? walletInfo,
9 + String? password,
10 + DerivationType? derivationType,
11 + String? derivationPath,
12 + String? passphrase,
13 + }) : super(
14 name: name,
15 walletInfo: walletInfo,
16 password: password,
17 + passphrase: passphrase,
18 );
19 }
20
cw_bitcoin/lib/bitcoin_wallet_service.dart
+15 -1
@@ -1,6 +1,7 @@
1 import 'dart:io';
2 import 'package:bitcoin_base/bitcoin_base.dart';
3 import 'package:cw_bitcoin/bitcoin_mnemonic.dart';
4 +import 'package:cw_bitcoin/bitcoin_mnemonics_bip39.dart';
5 import 'package:cw_bitcoin/mnemonic_is_incorrect_exception.dart';
6 import 'package:cw_bitcoin/bitcoin_wallet_creation_credentials.dart';
7 import 'package:cw_core/encryption_file_utils.dart';
@@ -35,8 +36,21 @@ class BitcoinWalletService extends WalletService<
36 final network = isTestnet == true ? BitcoinNetwork.testnet : BitcoinNetwork.mainnet;
37 credentials.walletInfo?.network = network.value;
38
39 + final String mnemonic;
40 + switch ( credentials.walletInfo?.derivationInfo?.derivationType) {
41 + case DerivationType.bip39:
42 + final strength = credentials.seedPhraseLength == 24 ? 256 : 128;
43 +
44 + mnemonic = await MnemonicBip39.generate(strength: strength);
45 + break;
46 + case DerivationType.electrum:
47 + default:
48 + mnemonic = await generateElectrumMnemonic();
49 + break;
50 + }
51 +
52 final wallet = await BitcoinWalletBase.create(
39 - mnemonic: await generateElectrumMnemonic(),
53 + mnemonic: mnemonic,
54 password: credentials.password!,
55 passphrase: credentials.passphrase,
56 walletInfo: credentials.walletInfo!,
cw_bitcoin/lib/electrum_derivations.dart
+1 -2
@@ -109,5 +109,4 @@ Map<DerivationType, List<DerivationInfo>> electrum_derivations = {
109 ],
110 };
111
112 -
113 -String electrum_path = electrum_derivations[DerivationType.electrum]!.first.derivationPath!;
\ No newline at end of file
112 +String electrum_path = electrum_derivations[DerivationType.electrum]!.first.derivationPath!;
cw_bitcoin/lib/electrum_wallet.dart
+2
@@ -137,6 +137,8 @@ abstract class ElectrumWalletBase
137 Bip32Slip10Secp256k1 get sideHd => accountHD.childKey(Bip32KeyIndex(1));
138
139 final EncryptionFileUtils encryptionFileUtils;
140 +
141 + @override
142 final String? passphrase;
143
144 @override
cw_bitcoin/lib/litecoin_wallet.dart
+32 -2
@@ -7,6 +7,7 @@ import 'package:bip39/bip39.dart' as bip39;
7 import 'package:cw_bitcoin/bitcoin_address_record.dart';
8 import 'package:cw_bitcoin/bitcoin_mnemonic.dart';
9 import 'package:cw_bitcoin/bitcoin_transaction_priority.dart';
10 +import 'package:cw_bitcoin/electrum_derivations.dart';
11 import 'package:cw_core/encryption_file_utils.dart';
12 import 'package:cw_core/crypto_currency.dart';
13 import 'package:cw_core/unspent_coins_info.dart';
@@ -36,6 +37,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
37 required Box<UnspentCoinsInfo> unspentCoinsInfo,
38 required Uint8List seedBytes,
39 required EncryptionFileUtils encryptionFileUtils,
40 + String? passphrase,
41 String? addressPageType,
42 List<BitcoinAddressRecord>? initialAddresses,
43 ElectrumBalance? initialBalance,
@@ -51,6 +53,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
53 initialBalance: initialBalance,
54 seedBytes: seedBytes,
55 encryptionFileUtils: encryptionFileUtils,
56 + passphrase: passphrase,
57 currency: CryptoCurrency.ltc) {
58 walletAddresses = LitecoinWalletAddresses(
59 walletInfo,
@@ -89,7 +92,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
92 break;
93 case DerivationType.electrum:
94 default:
92 - seedBytes = await mnemonicToSeedBytes(mnemonic);
95 + seedBytes = await mnemonicToSeedBytes(mnemonic, passphrase: passphrase ?? "");
96 break;
97 }
98 return LitecoinWallet(
@@ -100,6 +103,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
103 initialAddresses: initialAddresses,
104 initialBalance: initialBalance,
105 encryptionFileUtils: encryptionFileUtils,
106 + passphrase: passphrase,
107 seedBytes: seedBytes,
108 initialRegularAddressIndex: initialRegularAddressIndex,
109 initialChangeAddressIndex: initialChangeAddressIndex,
@@ -143,6 +147,31 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
147 );
148 }
149
150 + walletInfo.derivationInfo ??= DerivationInfo();
151 +
152 + // set the default if not present:
153 + walletInfo.derivationInfo!.derivationPath ??= snp?.derivationPath ?? electrum_path;
154 + walletInfo.derivationInfo!.derivationType ??= snp?.derivationType ?? DerivationType.electrum;
155 +
156 + Uint8List? seedBytes = null;
157 + final mnemonic = keysData.mnemonic;
158 + final passphrase = keysData.passphrase;
159 +
160 + if (mnemonic != null) {
161 + switch (walletInfo.derivationInfo?.derivationType) {
162 + case DerivationType.bip39:
163 + seedBytes = await bip39.mnemonicToSeed(
164 + mnemonic,
165 + passphrase: passphrase ?? "",
166 + );
167 + break;
168 + case DerivationType.electrum:
169 + default:
170 + seedBytes = await mnemonicToSeedBytes(mnemonic, passphrase: passphrase ?? "");
171 + break;
172 + }
173 + }
174 +
175 return LitecoinWallet(
176 mnemonic: keysData.mnemonic!,
177 password: password,
@@ -150,7 +179,8 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
179 unspentCoinsInfo: unspentCoinsInfo,
180 initialAddresses: snp?.addresses,
181 initialBalance: snp?.balance,
153 - seedBytes: await mnemonicToSeedBytes(keysData.mnemonic!),
182 + seedBytes: seedBytes!,
183 + passphrase: passphrase,
184 encryptionFileUtils: encryptionFileUtils,
185 initialRegularAddressIndex: snp?.regularAddressIndex,
186 initialChangeAddressIndex: snp?.changeAddressIndex,
cw_bitcoin/lib/litecoin_wallet_service.dart
+15 -1
@@ -1,4 +1,5 @@
1 import 'dart:io';
2 +import 'package:cw_bitcoin/bitcoin_mnemonics_bip39.dart';
3 import 'package:cw_core/encryption_file_utils.dart';
4 import 'package:cw_core/unspent_coins_info.dart';
5 import 'package:hive/hive.dart';
@@ -30,8 +31,21 @@ class LitecoinWalletService extends WalletService<
31
32 @override
33 Future<LitecoinWallet> create(BitcoinNewWalletCredentials credentials, {bool? isTestnet}) async {
34 + final String mnemonic;
35 + switch ( credentials.walletInfo?.derivationInfo?.derivationType) {
36 + case DerivationType.bip39:
37 + final strength = credentials.seedPhraseLength == 24 ? 256 : 128;
38 +
39 + mnemonic = await MnemonicBip39.generate(strength: strength);
40 + break;
41 + case DerivationType.electrum:
42 + default:
43 + mnemonic = await generateElectrumMnemonic();
44 + break;
45 + }
46 +
47 final wallet = await LitecoinWalletBase.create(
34 - mnemonic: await generateElectrumMnemonic(),
48 + mnemonic: mnemonic,
49 password: credentials.password!,
50 passphrase: credentials.passphrase,
51 walletInfo: credentials.walletInfo!,
cw_bitcoin_cash/lib/src/bitcoin_cash_base.dart
-1
@@ -3,5 +3,4 @@ export 'bitcoin_cash_wallet_addresses.dart';
3 export 'bitcoin_cash_wallet_creation_credentials.dart';
4 export 'bitcoin_cash_wallet_service.dart';
5 export 'exceptions/exceptions.dart';
6 -export 'mnemonic.dart';
6 export 'bitcoin_cash_address_utils.dart';
cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart
+10 -4
@@ -1,13 +1,14 @@
1 import 'package:bitbox/bitbox.dart' as bitbox;
2 import 'package:bitcoin_base/bitcoin_base.dart';
3 import 'package:blockchain_utils/blockchain_utils.dart';
4 -import 'package:cw_core/encryption_file_utils.dart';
4 import 'package:cw_bitcoin/bitcoin_address_record.dart';
5 +import 'package:cw_bitcoin/bitcoin_mnemonics_bip39.dart';
6 import 'package:cw_bitcoin/bitcoin_transaction_priority.dart';
7 import 'package:cw_bitcoin/electrum_balance.dart';
8 import 'package:cw_bitcoin/electrum_wallet.dart';
9 import 'package:cw_bitcoin/electrum_wallet_snapshot.dart';
10 import 'package:cw_core/crypto_currency.dart';
11 +import 'package:cw_core/encryption_file_utils.dart';
12 import 'package:cw_core/transaction_priority.dart';
13 import 'package:cw_core/unspent_coins_info.dart';
14 import 'package:cw_core/wallet_info.dart';
@@ -30,6 +31,7 @@ abstract class BitcoinCashWalletBase extends ElectrumWallet with Store {
31 required Box<UnspentCoinsInfo> unspentCoinsInfo,
32 required Uint8List seedBytes,
33 required EncryptionFileUtils encryptionFileUtils,
34 + String? passphrase,
35 BitcoinAddressType? addressPageType,
36 List<BitcoinAddressRecord>? initialAddresses,
37 ElectrumBalance? initialBalance,
@@ -45,7 +47,8 @@ abstract class BitcoinCashWalletBase extends ElectrumWallet with Store {
47 initialBalance: initialBalance,
48 seedBytes: seedBytes,
49 currency: CryptoCurrency.bch,
48 - encryptionFileUtils: encryptionFileUtils) {
50 + encryptionFileUtils: encryptionFileUtils,
51 + passphrase: passphrase) {
52 walletAddresses = BitcoinCashWalletAddresses(
53 walletInfo,
54 initialAddresses: initialAddresses,
@@ -67,6 +70,7 @@ abstract class BitcoinCashWalletBase extends ElectrumWallet with Store {
70 required WalletInfo walletInfo,
71 required Box<UnspentCoinsInfo> unspentCoinsInfo,
72 required EncryptionFileUtils encryptionFileUtils,
73 + String? passphrase,
74 String? addressPageType,
75 List<BitcoinAddressRecord>? initialAddresses,
76 ElectrumBalance? initialBalance,
@@ -79,11 +83,12 @@ abstract class BitcoinCashWalletBase extends ElectrumWallet with Store {
83 unspentCoinsInfo: unspentCoinsInfo,
84 initialAddresses: initialAddresses,
85 initialBalance: initialBalance,
82 - seedBytes: await MnemonicBip39.toSeed(mnemonic),
86 + seedBytes: await MnemonicBip39.toSeed(mnemonic, passphrase: passphrase),
87 encryptionFileUtils: encryptionFileUtils,
88 initialRegularAddressIndex: initialRegularAddressIndex,
89 initialChangeAddressIndex: initialChangeAddressIndex,
90 addressPageType: P2pkhAddressType.p2pkh,
91 + passphrase: passphrase,
92 );
93 }
94
@@ -150,11 +155,12 @@ abstract class BitcoinCashWalletBase extends ElectrumWallet with Store {
155 }
156 }).toList(),
157 initialBalance: snp?.balance,
153 - seedBytes: await MnemonicBip39.toSeed(keysData.mnemonic!),
158 + seedBytes: await MnemonicBip39.toSeed(keysData.mnemonic!, passphrase: keysData.passphrase),
159 encryptionFileUtils: encryptionFileUtils,
160 initialRegularAddressIndex: snp?.regularAddressIndex,
161 initialChangeAddressIndex: snp?.changeAddressIndex,
162 addressPageType: P2pkhAddressType.p2pkh,
163 + passphrase: keysData.passphrase,
164 );
165 }
166
cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_creation_credentials.dart
+10 -8
@@ -2,17 +2,19 @@ import 'package:cw_core/wallet_credentials.dart';
2 import 'package:cw_core/wallet_info.dart';
3
4 class BitcoinCashNewWalletCredentials extends WalletCredentials {
5 - BitcoinCashNewWalletCredentials({required String name, WalletInfo? walletInfo, String? password})
6 - : super(name: name, walletInfo: walletInfo, password: password);
5 + BitcoinCashNewWalletCredentials(
6 + {required String name, WalletInfo? walletInfo, String? password, String? passphrase})
7 + : super(name: name, walletInfo: walletInfo, password: password, passphrase: passphrase);
8 }
9
10 class BitcoinCashRestoreWalletFromSeedCredentials extends WalletCredentials {
10 - BitcoinCashRestoreWalletFromSeedCredentials(
11 - {required String name,
12 - required String password,
13 - required this.mnemonic,
14 - WalletInfo? walletInfo})
15 - : super(name: name, password: password, walletInfo: walletInfo);
11 + BitcoinCashRestoreWalletFromSeedCredentials({
12 + required String name,
13 + required String password,
14 + required this.mnemonic,
15 + WalletInfo? walletInfo,
16 + String? passphrase,
17 + }) : super(name: name, password: password, walletInfo: walletInfo, passphrase: passphrase);
18
19 final String mnemonic;
20 }
cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_service.dart
+17 -13
@@ -1,6 +1,8 @@
1 import 'dart:io';
2
3 import 'package:bip39/bip39.dart';
4 +import 'package:collection/collection.dart';
5 +import 'package:cw_bitcoin/bitcoin_mnemonics_bip39.dart';
6 import 'package:cw_bitcoin_cash/cw_bitcoin_cash.dart';
7 import 'package:cw_core/encryption_file_utils.dart';
8 import 'package:cw_core/pathForWallet.dart';
@@ -9,7 +11,6 @@ import 'package:cw_core/wallet_base.dart';
11 import 'package:cw_core/wallet_info.dart';
12 import 'package:cw_core/wallet_service.dart';
13 import 'package:cw_core/wallet_type.dart';
12 -import 'package:collection/collection.dart';
14 import 'package:hive/hive.dart';
15
16 class BitcoinCashWalletService extends WalletService<
@@ -35,11 +36,12 @@ class BitcoinCashWalletService extends WalletService<
36 final strength = credentials.seedPhraseLength == 24 ? 256 : 128;
37
38 final wallet = await BitcoinCashWalletBase.create(
38 - mnemonic: await MnemonicBip39.generate(strength: strength),
39 + mnemonic: await MnemonicBip39.generate(strength: strength),
40 password: credentials.password!,
41 walletInfo: credentials.walletInfo!,
42 unspentCoinsInfo: unspentCoinsInfoSource,
43 encryptionFileUtils: encryptionFileUtilsFor(isDirect),
44 + passphrase: credentials.passphrase,
45 );
46 await wallet.save();
47 await wallet.init();
@@ -54,11 +56,11 @@ class BitcoinCashWalletService extends WalletService<
56
57 try {
58 final wallet = await BitcoinCashWalletBase.open(
57 - password: password,
58 - name: name,
59 - walletInfo: walletInfo,
60 - unspentCoinsInfo: unspentCoinsInfoSource,
61 - encryptionFileUtils: encryptionFileUtilsFor(isDirect),
59 + password: password,
60 + name: name,
61 + walletInfo: walletInfo,
62 + unspentCoinsInfo: unspentCoinsInfoSource,
63 + encryptionFileUtils: encryptionFileUtilsFor(isDirect),
64 );
65 await wallet.init();
66 saveBackup(name);
@@ -66,11 +68,11 @@ class BitcoinCashWalletService extends WalletService<
68 } catch (_) {
69 await restoreWalletFilesFromBackup(name);
70 final wallet = await BitcoinCashWalletBase.open(
69 - password: password,
70 - name: name,
71 - walletInfo: walletInfo,
72 - unspentCoinsInfo: unspentCoinsInfoSource,
73 - encryptionFileUtils: encryptionFileUtilsFor(isDirect),
71 + password: password,
72 + name: name,
73 + walletInfo: walletInfo,
74 + unspentCoinsInfo: unspentCoinsInfoSource,
75 + encryptionFileUtils: encryptionFileUtilsFor(isDirect),
76 );
77 await wallet.init();
78 return wallet;
@@ -130,7 +132,9 @@ class BitcoinCashWalletService extends WalletService<
132 mnemonic: credentials.mnemonic,
133 walletInfo: credentials.walletInfo!,
134 unspentCoinsInfo: unspentCoinsInfoSource,
133 - encryptionFileUtils: encryptionFileUtilsFor(isDirect));
135 + encryptionFileUtils: encryptionFileUtilsFor(isDirect),
136 + passphrase: credentials.passphrase
137 + );
138 await wallet.save();
139 await wallet.init();
140 return wallet;
cw_core/lib/wallet_base.dart
+2
@@ -46,6 +46,8 @@ abstract class WalletBase<BalanceType extends Balance, HistoryType extends Trans
46
47 String? get hexSeed => null;
48
49 + String? get passphrase => null;
50 +
51 Object get keys;
52
53 WalletAddresses get walletAddresses;
lib/bitcoin/cw_bitcoin.dart
+6 -5
@@ -29,8 +29,9 @@ class CWBitcoin extends Bitcoin {
29
30 @override
31 WalletCredentials createBitcoinNewWalletCredentials(
32 - {required String name, WalletInfo? walletInfo, String? password}) =>
33 - BitcoinNewWalletCredentials(name: name, walletInfo: walletInfo, password: password);
32 + {required String name, WalletInfo? walletInfo, String? password, String? passphrase}) =>
33 + BitcoinNewWalletCredentials(
34 + name: name, walletInfo: walletInfo, password: password, passphrase: passphrase);
35
36 @override
37 WalletCredentials createBitcoinHardwareWalletCredentials(
@@ -202,8 +203,8 @@ class CWBitcoin extends Bitcoin {
203 await bitcoinWallet.updateAllUnspents();
204 }
205
205 - WalletService createBitcoinWalletService(
206 - Box<WalletInfo> walletInfoSource, Box<UnspentCoinsInfo> unspentCoinSource, bool alwaysScan, bool isDirect) {
206 + WalletService createBitcoinWalletService(Box<WalletInfo> walletInfoSource,
207 + Box<UnspentCoinsInfo> unspentCoinSource, bool alwaysScan, bool isDirect) {
208 return BitcoinWalletService(walletInfoSource, unspentCoinSource, alwaysScan, isDirect);
209 }
210
@@ -315,7 +316,7 @@ class CWBitcoin extends Bitcoin {
316 for (DerivationType dType in electrum_derivations.keys) {
317 late Uint8List seedBytes;
318 if (dType == DerivationType.electrum) {
318 - seedBytes = await mnemonicToSeedBytes(mnemonic);
319 + seedBytes = await mnemonicToSeedBytes(mnemonic, passphrase: passphrase ?? "");
320 } else if (dType == DerivationType.bip39) {
321 seedBytes = bip39.mnemonicToSeed(mnemonic, passphrase: passphrase ?? '');
322 }
lib/bitcoin_cash/cw_bitcoin_cash.dart
+5 -3
@@ -15,14 +15,16 @@ class CWBitcoinCash extends BitcoinCash {
15 required String name,
16 WalletInfo? walletInfo,
17 String? password,
18 + String? passphrase,
19 }) =>
19 - BitcoinCashNewWalletCredentials(name: name, walletInfo: walletInfo, password: password);
20 + BitcoinCashNewWalletCredentials(
21 + name: name, walletInfo: walletInfo, password: password, passphrase: passphrase);
22
23 @override
24 WalletCredentials createBitcoinCashRestoreWalletFromSeedCredentials(
23 - {required String name, required String mnemonic, required String password}) =>
25 + {required String name, required String mnemonic, required String password, String? passphrase}) =>
26 BitcoinCashRestoreWalletFromSeedCredentials(
25 - name: name, mnemonic: mnemonic, password: password);
27 + name: name, mnemonic: mnemonic, password: password, passphrase: passphrase);
28
29 @override
30 TransactionPriority deserializeBitcoinCashTransactionPriority(int raw) =>
lib/core/wallet_creation_service.dart
+3 -3
@@ -75,8 +75,10 @@ class WalletCreationService {
75
76 bool get _hasSeedPhraseLengthOption {
77 switch (type) {
78 - case WalletType.ethereum:
78 + case WalletType.bitcoin:
79 + case WalletType.litecoin:
80 case WalletType.bitcoinCash:
81 + case WalletType.ethereum:
82 case WalletType.polygon:
83 case WalletType.solana:
84 case WalletType.tron:
@@ -84,8 +86,6 @@ class WalletCreationService {
86 case WalletType.monero:
87 case WalletType.wownero:
88 case WalletType.none:
87 - case WalletType.bitcoin:
88 - case WalletType.litecoin:
89 case WalletType.haven:
90 case WalletType.nano:
91 case WalletType.banano:
lib/di.dart
+22 -12
@@ -146,7 +146,7 @@ import 'package:cake_wallet/view_model/cake_pay/cake_pay_purchase_view_model.dar
146 import 'package:cake_wallet/view_model/nano_account_list/nano_account_edit_or_create_view_model.dart';
147 import 'package:cake_wallet/view_model/nano_account_list/nano_account_list_view_model.dart';
148 import 'package:cake_wallet/view_model/node_list/pow_node_list_view_model.dart';
149 -import 'package:cake_wallet/view_model/seed_type_view_model.dart';
149 +import 'package:cake_wallet/view_model/seed_settings_view_model.dart';
150 import 'package:cake_wallet/view_model/set_up_2fa_viewmodel.dart';
151 import 'package:cake_wallet/view_model/restore/restore_from_qr_vm.dart';
152 import 'package:cake_wallet/view_model/settings/display_settings_view_model.dart';
@@ -179,6 +179,7 @@ import 'package:cake_wallet/store/dashboard/trades_store.dart';
179 import 'package:cake_wallet/store/dashboard/transaction_filter_store.dart';
180 import 'package:cake_wallet/store/node_list_store.dart';
181 import 'package:cake_wallet/store/secret_store.dart';
182 +import 'package:cake_wallet/store/seed_settings_store.dart';
183 import 'package:cake_wallet/store/settings_store.dart';
184 import 'package:cake_wallet/store/templates/exchange_template_store.dart';
185 import 'package:cake_wallet/store/templates/send_template_store.dart';
@@ -331,6 +332,7 @@ Future<void> setup({
332 YatStore(appStore: getIt.get<AppStore>(), secureStorage: getIt.get<SecureStorage>())..init());
333 getIt.registerSingleton<AnonpayTransactionsStore>(
334 AnonpayTransactionsStore(anonpayInvoiceInfoSource: _anonpayInvoiceInfoSource));
335 + getIt.registerSingleton<SeedSettingsStore>(SeedSettingsStore());
336
337 getIt.registerLazySingleton(() => LedgerViewModel());
338
@@ -361,6 +363,7 @@ Future<void> setup({
363 getIt.get<WalletCreationService>(param1: type),
364 _walletInfoSource,
365 getIt.get<AdvancedPrivacySettingsViewModel>(param1: type),
366 + getIt.get<SeedSettingsViewModel>(),
367 type: type));
368
369 getIt.registerFactoryParam<WalletUnlockPage, WalletUnlockArguments, bool>((args, closable) {
@@ -422,14 +425,21 @@ Future<void> setup({
425 walletType: args.walletType ?? currentWalletType);
426 });
427
425 - getIt.registerFactoryParam<WalletRestorationFromQRVM, WalletType, void>((WalletType type, _) {
426 - return WalletRestorationFromQRVM(getIt.get<AppStore>(),
427 - getIt.get<WalletCreationService>(param1: type), _walletInfoSource, type);
428 - });
428 + getIt.registerFactoryParam<WalletRestorationFromQRVM, WalletType, void>((WalletType type, _) =>
429 + WalletRestorationFromQRVM(
430 + getIt.get<AppStore>(),
431 + getIt.get<WalletCreationService>(param1: type),
432 + _walletInfoSource,
433 + type,
434 + getIt.get<SeedSettingsViewModel>()));
435
436 getIt.registerFactoryParam<WalletHardwareRestoreViewModel, WalletType, void>((type, _) =>
431 - WalletHardwareRestoreViewModel(getIt.get<LedgerViewModel>(), getIt.get<AppStore>(),
432 - getIt.get<WalletCreationService>(param1: type), _walletInfoSource,
437 + WalletHardwareRestoreViewModel(
438 + getIt.get<LedgerViewModel>(),
439 + getIt.get<AppStore>(),
440 + getIt.get<WalletCreationService>(param1: type),
441 + _walletInfoSource,
442 + getIt.get<SeedSettingsViewModel>(),
443 type: type));
444
445 getIt.registerFactory<WalletAddressListViewModel>(() => WalletAddressListViewModel(
@@ -833,7 +843,7 @@ Future<void> setup({
843
844 getIt.registerFactory(() => WalletSeedViewModel(getIt.get<AppStore>().wallet!));
845
836 - getIt.registerFactory<SeedTypeViewModel>(() => SeedTypeViewModel(getIt.get<AppStore>()));
846 + getIt.registerFactory<SeedSettingsViewModel>(() => SeedSettingsViewModel(getIt.get<AppStore>(), getIt.get<SeedSettingsStore>()));
847
848 getIt.registerFactoryParam<WalletSeedPage, bool, void>((bool isWalletCreated, _) =>
849 WalletSeedPage(getIt.get<WalletSeedViewModel>(), isNewWalletCreated: isWalletCreated));
@@ -1018,12 +1028,12 @@ Future<void> setup({
1028 getIt.registerFactory(() => FaqPage(getIt.get<SettingsStore>()));
1029
1030 getIt.registerFactoryParam<WalletRestoreViewModel, WalletType, void>((type, _) =>
1021 - WalletRestoreViewModel(
1022 - getIt.get<AppStore>(), getIt.get<WalletCreationService>(param1: type), _walletInfoSource,
1031 + WalletRestoreViewModel(getIt.get<AppStore>(), getIt.get<WalletCreationService>(param1: type),
1032 + _walletInfoSource, getIt.get<SeedSettingsViewModel>(),
1033 type: type));
1034
1035 getIt.registerFactoryParam<WalletRestorePage, WalletType, void>((type, _) => WalletRestorePage(
1026 - getIt.get<WalletRestoreViewModel>(param1: type), getIt.get<SeedTypeViewModel>()));
1036 + getIt.get<WalletRestoreViewModel>(param1: type), getIt.get<SeedSettingsViewModel>()));
1037
1038 getIt.registerFactoryParam<WalletRestoreChooseDerivationViewModel, List<DerivationInfo>, void>(
1039 (derivations, _) => WalletRestoreChooseDerivationViewModel(derivationInfos: derivations));
@@ -1275,7 +1285,7 @@ Future<void> setup({
1285
1286 getIt.registerFactory(
1287 () => WalletConnectConnectionsView(web3walletService: getIt.get<Web3WalletService>()));
1278 -
1288 +
1289 getIt.registerFactory(() => NFTViewModel(appStore, getIt.get<BottomSheetService>()));
1290 getIt.registerFactory<TorPage>(() => TorPage(getIt.get<AppStore>()));
1291
lib/entities/language_service.dart
+1 -1
@@ -60,7 +60,7 @@ class LanguageService {
60 'yo': 'nga',
61 'ha': 'hau',
62 'tl': 'phl',
63 - 'hy': 'arm'
63 + 'hy': 'arm',
64 };
65
66 static final list = <String, String>{};
lib/entities/preferences_key.dart
+1
@@ -77,6 +77,7 @@ class PreferencesKey {
77 static const exchangeProvidersSelection = 'exchange-providers-selection';
78 static const autoGenerateSubaddressStatusKey = 'auto_generate_subaddress_status';
79 static const moneroSeedType = 'monero_seed_type';
80 + static const bitcoinSeedType = 'bitcoin_seed_type';
81 static const clearnetDonationLink = 'clearnet_donation_link';
82 static const onionDonationLink = 'onion_donation_link';
83 static const donationLinkWalletName = 'donation_link_wallet_name';
lib/entities/seed_type.dart
+36 -10
@@ -1,18 +1,19 @@
1 import 'package:cake_wallet/generated/i18n.dart';
2 import 'package:cw_core/enumerable_item.dart';
3 +import 'package:cw_core/wallet_info.dart';
4
4 -class SeedType extends EnumerableItem<int> with Serializable<int> {
5 - const SeedType({required String title, required int raw}) : super(title: title, raw: raw);
5 +class MoneroSeedType extends EnumerableItem<int> with Serializable<int> {
6 + const MoneroSeedType({required String title, required int raw}) : super(title: title, raw: raw);
7
7 - static const all = [SeedType.legacy, SeedType.polyseed];
8 + static const all = [MoneroSeedType.legacy, MoneroSeedType.polyseed];
9
10 static const defaultSeedType = polyseed;
11
11 - static const legacy = SeedType(raw: 0, title: 'Legacy (25 words)');
12 - static const polyseed = SeedType(raw: 1, title: 'Polyseed (16 words)');
13 - static const wowneroSeed = SeedType(raw: 2, title: 'Wownero (14 words)');
12 + static const legacy = MoneroSeedType(raw: 0, title: 'Legacy (25 words)');
13 + static const polyseed = MoneroSeedType(raw: 1, title: 'Polyseed (16 words)');
14 + static const wowneroSeed = MoneroSeedType(raw: 2, title: 'Wownero (14 words)');
15
15 - static SeedType deserialize({required int raw}) {
16 + static MoneroSeedType deserialize({required int raw}) {
17 switch (raw) {
18 case 0:
19 return legacy;
@@ -28,14 +29,39 @@ class SeedType extends EnumerableItem<int> with Serializable<int> {
29 @override
30 String toString() {
31 switch (this) {
31 - case SeedType.legacy:
32 + case MoneroSeedType.legacy:
33 return S.current.seedtype_legacy;
33 - case SeedType.polyseed:
34 + case MoneroSeedType.polyseed:
35 return S.current.seedtype_polyseed;
35 - case SeedType.wowneroSeed:
36 + case MoneroSeedType.wowneroSeed:
37 return S.current.seedtype_wownero;
38 default:
39 return '';
40 }
41 }
42 }
43 +
44 +class BitcoinSeedType extends EnumerableItem<int> with Serializable<int> {
45 + const BitcoinSeedType(this.type, {required String title, required int raw})
46 + : super(title: title, raw: raw);
47 +
48 + final DerivationType type;
49 +
50 + static const all = [BitcoinSeedType.electrum, BitcoinSeedType.bip39];
51 +
52 + static const defaultDerivationType = bip39;
53 +
54 + static const electrum = BitcoinSeedType(DerivationType.electrum, raw: 0, title: 'Electrum');
55 + static const bip39 = BitcoinSeedType(DerivationType.bip39, raw: 1, title: 'BIP39');
56 +
57 + static BitcoinSeedType deserialize({required int raw}) {
58 + switch (raw) {
59 + case 0:
60 + return electrum;
61 + case 1:
62 + return bip39;
63 + default:
64 + throw Exception('Unexpected token: $raw for SeedType deserialize');
65 + }
66 + }
67 +}
lib/router.dart
+47 -50
@@ -17,6 +17,8 @@ import 'package:cake_wallet/src/screens/backup/edit_backup_password_page.dart';
17 import 'package:cake_wallet/src/screens/buy/buy_options_page.dart';
18 import 'package:cake_wallet/src/screens/buy/buy_webview_page.dart';
19 import 'package:cake_wallet/src/screens/buy/webview_page.dart';
20 +import 'package:cake_wallet/src/screens/cake_pay/auth/cake_pay_account_page.dart';
21 +import 'package:cake_wallet/src/screens/cake_pay/cake_pay.dart';
22 import 'package:cake_wallet/src/screens/connect_device/connect_device_page.dart';
23 import 'package:cake_wallet/src/screens/connect_device/select_hardware_wallet_account_page.dart';
24 import 'package:cake_wallet/src/screens/contact/contact_list_page.dart';
@@ -27,8 +29,8 @@ import 'package:cake_wallet/src/screens/dashboard/edit_token_page.dart';
29 import 'package:cake_wallet/src/screens/dashboard/home_settings_page.dart';
30 import 'package:cake_wallet/src/screens/dashboard/pages/address_page.dart';
31 import 'package:cake_wallet/src/screens/dashboard/pages/nft_details_page.dart';
30 -import 'package:cake_wallet/src/screens/dashboard/sign_page.dart';
32 import 'package:cake_wallet/src/screens/dashboard/pages/transactions_page.dart';
33 +import 'package:cake_wallet/src/screens/dashboard/sign_page.dart';
34 import 'package:cake_wallet/src/screens/disclaimer/disclaimer_page.dart';
35 import 'package:cake_wallet/src/screens/exchange/exchange_page.dart';
36 import 'package:cake_wallet/src/screens/exchange/exchange_template_page.dart';
@@ -43,10 +45,9 @@ import 'package:cake_wallet/src/screens/new_wallet/new_wallet_page.dart';
45 import 'package:cake_wallet/src/screens/new_wallet/new_wallet_type_page.dart';
46 import 'package:cake_wallet/src/screens/nodes/node_create_or_edit_page.dart';
47 import 'package:cake_wallet/src/screens/nodes/pow_node_create_or_edit_page.dart';
46 -import 'package:cake_wallet/src/screens/receive/address_list_page.dart';
47 -import 'package:cake_wallet/src/screens/restore/sweeping_wallet_page.dart';
48 import 'package:cake_wallet/src/screens/order_details/order_details_page.dart';
49 import 'package:cake_wallet/src/screens/pin_code/pin_code_widget.dart';
50 +import 'package:cake_wallet/src/screens/receive/address_list_page.dart';
51 import 'package:cake_wallet/src/screens/receive/anonpay_invoice_page.dart';
52 import 'package:cake_wallet/src/screens/receive/anonpay_receive_page.dart';
53 import 'package:cake_wallet/src/screens/receive/fullscreen_qr_page.dart';
@@ -69,11 +70,9 @@ import 'package:cake_wallet/src/screens/settings/manage_nodes_page.dart';
70 import 'package:cake_wallet/src/screens/settings/other_settings_page.dart';
71 import 'package:cake_wallet/src/screens/settings/privacy_page.dart';
72 import 'package:cake_wallet/src/screens/settings/security_backup_page.dart';
72 -import 'package:cake_wallet/src/screens/cake_pay/auth/cake_pay_account_page.dart';
73 import 'package:cake_wallet/src/screens/settings/silent_payments_settings.dart';
74 import 'package:cake_wallet/src/screens/settings/tor_page.dart';
75 import 'package:cake_wallet/src/screens/settings/trocador_providers_page.dart';
76 -import 'package:cake_wallet/src/screens/settings/tor_page.dart';
76 import 'package:cake_wallet/src/screens/setup_2fa/modify_2fa_page.dart';
77 import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa.dart';
78 import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa_enter_code_page.dart';
@@ -85,19 +84,18 @@ import 'package:cake_wallet/src/screens/support/support_page.dart';
84 import 'package:cake_wallet/src/screens/support_chat/support_chat_page.dart';
85 import 'package:cake_wallet/src/screens/support_other_links/support_other_links_page.dart';
86 import 'package:cake_wallet/src/screens/trade_details/trade_details_page.dart';
88 -import 'package:cake_wallet/src/screens/transaction_details/transaction_details_page.dart';
87 import 'package:cake_wallet/src/screens/transaction_details/rbf_details_page.dart';
88 +import 'package:cake_wallet/src/screens/transaction_details/transaction_details_page.dart';
89 import 'package:cake_wallet/src/screens/unspent_coins/unspent_coins_details_page.dart';
90 import 'package:cake_wallet/src/screens/unspent_coins/unspent_coins_list_page.dart';
91 import 'package:cake_wallet/src/screens/wallet/wallet_edit_page.dart';
92 import 'package:cake_wallet/src/screens/wallet_connect/wc_connections_listing_view.dart';
93 import 'package:cake_wallet/src/screens/wallet_keys/wallet_keys_page.dart';
94 import 'package:cake_wallet/src/screens/wallet_list/wallet_list_page.dart';
95 +import 'package:cake_wallet/src/screens/wallet_unlock/wallet_unlock_arguments.dart';
96 import 'package:cake_wallet/src/screens/wallet_unlock/wallet_unlock_page.dart';
97 import 'package:cake_wallet/src/screens/welcome/create_welcome_page.dart';
98 import 'package:cake_wallet/store/settings_store.dart';
99 -import 'package:cake_wallet/src/screens/wallet_unlock/wallet_unlock_arguments.dart';
100 -import 'package:cake_wallet/store/settings_store.dart';
99 import 'package:cake_wallet/utils/payment_request.dart';
100 import 'package:cake_wallet/view_model/advanced_privacy_settings_view_model.dart';
101 import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart';
@@ -106,7 +104,7 @@ import 'package:cake_wallet/view_model/dashboard/sign_view_model.dart';
104 import 'package:cake_wallet/view_model/hardware_wallet/ledger_view_model.dart';
105 import 'package:cake_wallet/view_model/monero_account_list/account_list_item.dart';
106 import 'package:cake_wallet/view_model/node_list/node_create_or_edit_view_model.dart';
109 -import 'package:cake_wallet/view_model/seed_type_view_model.dart';
107 +import 'package:cake_wallet/view_model/seed_settings_view_model.dart';
108 import 'package:cake_wallet/view_model/wallet_hardware_restore_view_model.dart';
109 import 'package:cake_wallet/view_model/wallet_new_vm.dart';
110 import 'package:cake_wallet/wallet_type_utils.dart';
@@ -120,7 +118,7 @@ import 'package:cw_core/wallet_type.dart';
118 import 'package:flutter/cupertino.dart';
119 import 'package:flutter/material.dart';
120 import 'package:flutter/services.dart';
123 -import 'package:cake_wallet/src/screens/cake_pay/cake_pay.dart';
121 +
122 import 'src/screens/dashboard/pages/nft_import_page.dart';
123
124 late RouteSettings currentRouteSettings;
@@ -135,7 +133,8 @@ Route<dynamic> createRoute(RouteSettings settings) {
133 case Routes.newWalletFromWelcome:
134 if (SettingsStoreBase.walletPasswordDirectInput) {
135 if (availableWalletTypes.length == 1) {
138 - return createRoute(RouteSettings(name: Routes.newWallet, arguments: availableWalletTypes.first));
136 + return createRoute(
137 + RouteSettings(name: Routes.newWallet, arguments: availableWalletTypes.first));
138 } else {
139 return createRoute(RouteSettings(name: Routes.newWalletType));
140 }
@@ -162,10 +161,10 @@ Route<dynamic> createRoute(RouteSettings settings) {
161 case Routes.newWallet:
162 final type = settings.arguments as WalletType;
163 final walletNewVM = getIt.get<WalletNewVM>(param1: type);
165 - final seedTypeViewModel = getIt.get<SeedTypeViewModel>();
164 + final seedSettingsViewModel = getIt.get<SeedSettingsViewModel>();
165
166 return CupertinoPageRoute<void>(
168 - builder: (_) => NewWalletPage(walletNewVM, seedTypeViewModel));
167 + builder: (_) => NewWalletPage(walletNewVM, seedSettingsViewModel));
168
169 case Routes.chooseHardwareWalletAccount:
170 final arguments = settings.arguments as List<dynamic>;
@@ -348,16 +347,14 @@ Route<dynamic> createRoute(RouteSettings settings) {
347 case Routes.auth:
348 return MaterialPageRoute<void>(
349 fullscreenDialog: true,
351 - builder: (_)
352 - => SettingsStoreBase.walletPasswordDirectInput
353 - ? getIt.get<WalletUnlockPage>(
354 - param1: WalletUnlockArguments(
350 + builder: (_) => SettingsStoreBase.walletPasswordDirectInput
351 + ? getIt.get<WalletUnlockPage>(
352 + param1: WalletUnlockArguments(
353 callback: settings.arguments as OnAuthenticationFinished),
356 - instanceName: 'wallet_unlock_verifiable',
357 - param2: true)
358 - : getIt.get<AuthPage>(
359 - param1: settings.arguments as OnAuthenticationFinished,
360 - param2: true));
354 + instanceName: 'wallet_unlock_verifiable',
355 + param2: true)
356 + : getIt.get<AuthPage>(
357 + param1: settings.arguments as OnAuthenticationFinished, param2: true));
358
359 case Routes.totpAuthCodePage:
360 final args = settings.arguments as TotpAuthArgumentsModel;
@@ -371,28 +368,25 @@ Route<dynamic> createRoute(RouteSettings settings) {
368 case Routes.walletUnlockLoadable:
369 return MaterialPageRoute<void>(
370 fullscreenDialog: true,
374 - builder: (_)
375 - => getIt.get<WalletUnlockPage>(
371 + builder: (_) => getIt.get<WalletUnlockPage>(
372 param1: settings.arguments as WalletUnlockArguments,
377 - instanceName: 'wallet_unlock_loadable',
373 + instanceName: 'wallet_unlock_loadable',
374 param2: true));
375
376 case Routes.unlock:
377 return MaterialPageRoute<void>(
378 fullscreenDialog: true,
383 - builder: (_)
384 - => SettingsStoreBase.walletPasswordDirectInput
385 - ? WillPopScope(
386 - child: getIt.get<WalletUnlockPage>(
379 + builder: (_) => SettingsStoreBase.walletPasswordDirectInput
380 + ? WillPopScope(
381 + child: getIt.get<WalletUnlockPage>(
382 param1: WalletUnlockArguments(
388 - callback: settings.arguments as OnAuthenticationFinished),
383 + callback: settings.arguments as OnAuthenticationFinished),
384 param2: false,
385 instanceName: 'wallet_unlock_verifiable'),
391 - onWillPop: () async => false)
392 - : WillPopScope(
393 - child: getIt.get<AuthPage>(
394 - param1: settings.arguments as OnAuthenticationFinished,
395 - param2: false),
386 + onWillPop: () async => false)
387 + : WillPopScope(
388 + child: getIt.get<AuthPage>(
389 + param1: settings.arguments as OnAuthenticationFinished, param2: false),
390 onWillPop: () async => false));
391
392 case Routes.silentPaymentsSettings:
@@ -437,11 +431,12 @@ Route<dynamic> createRoute(RouteSettings settings) {
431 return CupertinoPageRoute<void>(
432 builder: (context) => WillPopScope(
433 child: SettingsStoreBase.walletPasswordDirectInput
440 - ? getIt.get<WalletUnlockPage>(instanceName: 'wallet_password_login')
441 - : getIt.get<AuthPage>(instanceName: 'login'),
434 + ? getIt.get<WalletUnlockPage>(instanceName: 'wallet_password_login')
435 + : getIt.get<AuthPage>(instanceName: 'login'),
436 onWillPop: () async =>
443 - // FIX-ME: Additional check does it works correctly
444 - (await SystemChannels.platform.invokeMethod<bool>('SystemNavigator.pop') ?? false)),
437 + // FIX-ME: Additional check does it works correctly
438 + (await SystemChannels.platform.invokeMethod<bool>('SystemNavigator.pop') ??
439 + false)),
440 fullscreenDialog: true);
441
442 case Routes.newPowNode:
@@ -537,8 +532,7 @@ Route<dynamic> createRoute(RouteSettings settings) {
532
533 case Routes.support:
534 return CupertinoPageRoute<void>(
540 - fullscreenDialog: true,
541 - builder: (_) => getIt.get<SupportPage>());
535 + fullscreenDialog: true, builder: (_) => getIt.get<SupportPage>());
536
537 case Routes.supportLiveChat:
538 return CupertinoPageRoute<void>(builder: (_) => getIt.get<SupportChatPage>());
@@ -567,8 +561,7 @@ Route<dynamic> createRoute(RouteSettings settings) {
561
562 case Routes.cakePayBuyCardPage:
563 final args = settings.arguments as List;
570 - return CupertinoPageRoute<void>(
571 - builder: (_) => getIt.get<CakePayBuyCardPage>(param1: args));
564 + return CupertinoPageRoute<void>(builder: (_) => getIt.get<CakePayBuyCardPage>(param1: args));
565
566 case Routes.cakePayBuyCardDetailPage:
567 final args = settings.arguments as List;
@@ -582,7 +575,8 @@ Route<dynamic> createRoute(RouteSettings settings) {
575
576 case Routes.cakePayVerifyOtpPage:
577 final args = settings.arguments as List;
585 - return CupertinoPageRoute<void>(builder: (_) => getIt.get<CakePayVerifyOtpPage>(param1: args));
578 + return CupertinoPageRoute<void>(
579 + builder: (_) => getIt.get<CakePayVerifyOtpPage>(param1: args));
580
581 case Routes.cakePayAccountPage:
582 return CupertinoPageRoute<void>(builder: (_) => getIt.get<CakePayAccountPage>());
@@ -597,16 +591,19 @@ Route<dynamic> createRoute(RouteSettings settings) {
591 case Routes.advancedPrivacySettings:
592 final args = settings.arguments as Map<String, dynamic>;
593 final type = args['type'] as WalletType;
594 + final isFromRestore = args['isFromRestore'] as bool? ?? false;
595 final useTestnet = args['useTestnet'] as bool;
596 final toggleTestnet = args['toggleTestnet'] as Function(bool? val);
597
598 return CupertinoPageRoute<void>(
599 builder: (_) => AdvancedPrivacySettingsPage(
605 - useTestnet,
606 - toggleTestnet,
607 - getIt.get<AdvancedPrivacySettingsViewModel>(param1: type),
608 - getIt.get<NodeCreateOrEditViewModel>(param1: type, param2: false),
609 - getIt.get<SeedTypeViewModel>(),
600 + isFromRestore: isFromRestore,
601 + useTestnet: useTestnet,
602 + toggleUseTestnet: toggleTestnet,
603 + advancedPrivacySettingsViewModel:
604 + getIt.get<AdvancedPrivacySettingsViewModel>(param1: type),
605 + nodeViewModel: getIt.get<NodeCreateOrEditViewModel>(param1: type, param2: false),
606 + seedSettingsViewModel: getIt.get<SeedSettingsViewModel>(),
607 ));
608
609 case Routes.anonPayInvoicePage:
@@ -709,7 +706,7 @@ Route<dynamic> createRoute(RouteSettings settings) {
706 getIt.get<SignViewModel>(),
707 ),
708 );
712 -
709 +
710 case Routes.connectDevices:
711 final params = settings.arguments as ConnectDevicePageParams;
712 return MaterialPageRoute<void>(
lib/src/screens/dashboard/widgets/verify_form.dart
-16
@@ -1,23 +1,7 @@
1 -import 'package:cake_wallet/core/wallet_name_validator.dart';
2 -import 'package:cake_wallet/entities/generate_name.dart';
3 -import 'package:cake_wallet/entities/seed_type.dart';
1 import 'package:cake_wallet/generated/i18n.dart';
2 import 'package:cake_wallet/src/widgets/address_text_field.dart';
6 -import 'package:cake_wallet/src/widgets/base_text_form_field.dart';
7 -import 'package:cake_wallet/src/widgets/blockchain_height_widget.dart';
8 -import 'package:cake_wallet/src/widgets/picker.dart';
9 -import 'package:cake_wallet/src/widgets/seed_language_picker.dart';
10 -import 'package:cake_wallet/src/widgets/seed_widget.dart';
11 -import 'package:cake_wallet/themes/extensions/address_theme.dart';
12 -import 'package:cake_wallet/themes/extensions/send_page_theme.dart';
13 -import 'package:cake_wallet/utils/show_bar.dart';
14 -import 'package:cake_wallet/utils/show_pop_up.dart';
15 -import 'package:cake_wallet/view_model/seed_type_view_model.dart';
3 import 'package:cw_core/wallet_type.dart';
4 import 'package:flutter/material.dart';
18 -import 'package:flutter/services.dart';
19 -import 'package:mobx/mobx.dart';
20 -import 'package:polyseed/polyseed.dart';
5
6 class VerifyForm extends StatefulWidget {
7 VerifyForm({
lib/src/screens/new_wallet/advanced_privacy_settings_page.dart
+91 -43
@@ -3,52 +3,61 @@ import 'package:cake_wallet/entities/exchange_api_mode.dart';
3 import 'package:cake_wallet/entities/fiat_api_mode.dart';
4 import 'package:cake_wallet/entities/seed_phrase_length.dart';
5 import 'package:cake_wallet/entities/seed_type.dart';
6 +import 'package:cake_wallet/generated/i18n.dart';
7 +import 'package:cake_wallet/src/screens/base_page.dart';
8 import 'package:cake_wallet/src/screens/nodes/widgets/node_form.dart';
9 import 'package:cake_wallet/src/screens/settings/widgets/settings_choices_cell.dart';
10 import 'package:cake_wallet/src/screens/settings/widgets/settings_picker_cell.dart';
11 import 'package:cake_wallet/src/screens/settings/widgets/settings_switcher_cell.dart';
12 +import 'package:cake_wallet/src/widgets/base_text_form_field.dart';
13 +import 'package:cake_wallet/src/widgets/primary_button.dart';
14 +import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart';
15 import 'package:cake_wallet/themes/extensions/new_wallet_theme.dart';
11 -import 'package:cake_wallet/view_model/node_list/node_create_or_edit_view_model.dart';
16 import 'package:cake_wallet/view_model/advanced_privacy_settings_view_model.dart';
13 -import 'package:cake_wallet/view_model/seed_type_view_model.dart';
17 +import 'package:cake_wallet/view_model/node_list/node_create_or_edit_view_model.dart';
18 +import 'package:cake_wallet/view_model/seed_settings_view_model.dart';
19 import 'package:cake_wallet/view_model/settings/choices_list_item.dart';
20 import 'package:cw_core/wallet_type.dart';
16 -import 'package:flutter_mobx/flutter_mobx.dart';
21 import 'package:flutter/material.dart';
18 -import 'package:cake_wallet/generated/i18n.dart';
19 -import 'package:cake_wallet/src/screens/base_page.dart';
20 -import 'package:cake_wallet/src/widgets/primary_button.dart';
21 -import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart';
22 +import 'package:flutter_mobx/flutter_mobx.dart';
23
24 class AdvancedPrivacySettingsPage extends BasePage {
24 - AdvancedPrivacySettingsPage(this.useTestnet, this.toggleUseTestnet,
25 - this.advancedPrivacySettingsViewModel, this.nodeViewModel, this.seedTypeViewModel);
25 + AdvancedPrivacySettingsPage({
26 + required this.isFromRestore,
27 + required this.useTestnet,
28 + required this.toggleUseTestnet,
29 + required this.advancedPrivacySettingsViewModel,
30 + required this.nodeViewModel,
31 + required this.seedSettingsViewModel,
32 + });
33
34 final AdvancedPrivacySettingsViewModel advancedPrivacySettingsViewModel;
35 final NodeCreateOrEditViewModel nodeViewModel;
29 - final SeedTypeViewModel seedTypeViewModel;
36 + final SeedSettingsViewModel seedSettingsViewModel;
37
38 @override
39 String get title => S.current.privacy_settings;
40
41 + final bool isFromRestore;
42 final bool useTestnet;
43 final Function(bool? val) toggleUseTestnet;
44
45 @override
38 - Widget body(BuildContext context) => AdvancedPrivacySettingsBody(useTestnet, toggleUseTestnet,
39 - advancedPrivacySettingsViewModel, nodeViewModel, seedTypeViewModel);
46 + Widget body(BuildContext context) => _AdvancedPrivacySettingsBody(isFromRestore, useTestnet,
47 + toggleUseTestnet, advancedPrivacySettingsViewModel, nodeViewModel, seedSettingsViewModel);
48 }
49
42 -class AdvancedPrivacySettingsBody extends StatefulWidget {
43 - const AdvancedPrivacySettingsBody(this.useTestnet, this.toggleUseTestnet,
50 +class _AdvancedPrivacySettingsBody extends StatefulWidget {
51 + const _AdvancedPrivacySettingsBody(this.isFromRestore, this.useTestnet, this.toggleUseTestnet,
52 this.privacySettingsViewModel, this.nodeViewModel, this.seedTypeViewModel,
53 {Key? key})
54 : super(key: key);
55
56 final AdvancedPrivacySettingsViewModel privacySettingsViewModel;
57 final NodeCreateOrEditViewModel nodeViewModel;
50 - final SeedTypeViewModel seedTypeViewModel;
58 + final SeedSettingsViewModel seedTypeViewModel;
59
60 + final bool isFromRestore;
61 final bool useTestnet;
62 final Function(bool? val) toggleUseTestnet;
63
@@ -56,15 +65,23 @@ class AdvancedPrivacySettingsBody extends StatefulWidget {
65 _AdvancedPrivacySettingsBodyState createState() => _AdvancedPrivacySettingsBodyState();
66 }
67
59 -class _AdvancedPrivacySettingsBodyState extends State<AdvancedPrivacySettingsBody> {
60 - _AdvancedPrivacySettingsBodyState();
61 -
68 +class _AdvancedPrivacySettingsBodyState extends State<_AdvancedPrivacySettingsBody> {
69 + final TextEditingController passphraseController = TextEditingController();
70 final _formKey = GlobalKey<FormState>();
71 bool? testnetValue;
72
73 + @override
74 + void initState() {
75 + passphraseController.text = widget.seedTypeViewModel.passphrase ?? '';
76 +
77 + passphraseController
78 + .addListener(() => widget.seedTypeViewModel.setPassphrase(passphraseController.text));
79 + super.initState();
80 + }
81 +
82 @override
83 Widget build(BuildContext context) {
67 - if (testnetValue == null && widget.useTestnet != null) {
84 + if (testnetValue == null && widget.useTestnet) {
85 testnetValue = widget.useTestnet;
86 }
87
@@ -97,6 +114,52 @@ class _AdvancedPrivacySettingsBodyState extends State<AdvancedPrivacySettingsBod
114 ),
115 );
116 }),
117 + if (widget.privacySettingsViewModel.hasSeedTypeOption)
118 + Observer(builder: (_) {
119 + return SettingsChoicesCell(
120 + ChoicesListItem<MoneroSeedType>(
121 + title: S.current.seedtype,
122 + items: MoneroSeedType.all,
123 + selectedItem: widget.seedTypeViewModel.moneroSeedType,
124 + onItemSelected: widget.seedTypeViewModel.setMoneroSeedType,
125 + ),
126 + );
127 + }),
128 + if ([WalletType.bitcoin, WalletType.litecoin]
129 + .contains(widget.privacySettingsViewModel.type))
130 + Observer(builder: (_) {
131 + return SettingsChoicesCell(
132 + ChoicesListItem<BitcoinSeedType>(
133 + title: S.current.seedtype,
134 + items: BitcoinSeedType.all,
135 + selectedItem: widget.seedTypeViewModel.bitcoinSeedType,
136 + onItemSelected: widget.seedTypeViewModel.setBitcoinSeedType,
137 + ),
138 + );
139 + }),
140 + if (!widget.isFromRestore) ...[
141 + Observer(builder: (_) {
142 + if (widget.privacySettingsViewModel.hasSeedPhraseLengthOption)
143 + return SettingsPickerCell<SeedPhraseLength>(
144 + title: S.current.seed_phrase_length,
145 + items: SeedPhraseLength.values,
146 + selectedItem: widget.privacySettingsViewModel.seedPhraseLength,
147 + onItemSelected: (SeedPhraseLength length) {
148 + widget.privacySettingsViewModel.setSeedPhraseLength(length);
149 + },
150 + );
151 + return Container();
152 + }),
153 + if (widget.privacySettingsViewModel.hasPassphraseOption)
154 + Padding(
155 + padding: EdgeInsets.all(24),
156 + child: BaseTextFormField(
157 + hintText: S.current.passphrase,
158 + controller: passphraseController,
159 + obscureText: true,
160 + ),
161 + ),
162 + ],
163 Observer(builder: (_) {
164 return Column(
165 children: [
@@ -122,31 +185,9 @@ class _AdvancedPrivacySettingsBodyState extends State<AdvancedPrivacySettingsBod
185 ],
186 );
187 }),
125 - if (widget.privacySettingsViewModel.hasSeedPhraseLengthOption)
126 - Observer(builder: (_) {
127 - return SettingsPickerCell<SeedPhraseLength>(
128 - title: S.current.seed_phrase_length,
129 - items: SeedPhraseLength.values,
130 - selectedItem: widget.privacySettingsViewModel.seedPhraseLength,
131 - onItemSelected: (SeedPhraseLength length) {
132 - widget.privacySettingsViewModel.setSeedPhraseLength(length);
133 - },
134 - );
135 - }),
136 - if (widget.privacySettingsViewModel.hasSeedTypeOption)
137 - Observer(builder: (_) {
138 - return SettingsChoicesCell(
139 - ChoicesListItem<SeedType>(
140 - title: S.current.seedtype,
141 - items: SeedType.all,
142 - selectedItem: widget.seedTypeViewModel.moneroSeedType,
143 - onItemSelected: widget.seedTypeViewModel.setMoneroSeedType,
144 - ),
145 - );
146 - }),
188 if (widget.privacySettingsViewModel.type == WalletType.bitcoin)
189 Builder(builder: (_) {
149 - final val = testnetValue!;
190 + final val = testnetValue ?? false;
191 return SettingsSwitcherCell(
192 title: S.current.use_testnet,
193 value: val,
@@ -154,7 +195,7 @@ class _AdvancedPrivacySettingsBodyState extends State<AdvancedPrivacySettingsBod
195 setState(() {
196 testnetValue = !val;
197 });
157 - widget.toggleUseTestnet!.call(testnetValue);
198 + widget.toggleUseTestnet.call(testnetValue);
199 });
200 }),
201 ],
@@ -203,4 +244,11 @@ class _AdvancedPrivacySettingsBodyState extends State<AdvancedPrivacySettingsBod
244 ),
245 );
246 }
247 +
248 + @override
249 + void dispose() {
250 + passphraseController
251 + .removeListener(() => widget.seedTypeViewModel.setPassphrase(passphraseController.text));
252 + super.dispose();
253 + }
254 }
lib/src/screens/new_wallet/new_wallet_page.dart
+30 -31
@@ -1,36 +1,35 @@
1 +import 'package:cake_wallet/core/execution_state.dart';
2 +import 'package:cake_wallet/core/wallet_name_validator.dart';
3 import 'package:cake_wallet/entities/generate_name.dart';
2 -import 'package:cake_wallet/src/screens/new_wallet/widgets/select_button.dart';
3 -import 'package:cake_wallet/src/widgets/picker.dart';
4 -import 'package:cake_wallet/themes/extensions/cake_text_theme.dart';
4 +import 'package:cake_wallet/entities/seed_type.dart';
5 +import 'package:cake_wallet/generated/i18n.dart';
6 import 'package:cake_wallet/main.dart';
7 import 'package:cake_wallet/routes.dart';
7 -import 'package:cake_wallet/themes/theme_base.dart';
8 -import 'package:cake_wallet/utils/responsive_layout_util.dart';
9 -import 'package:cake_wallet/utils/show_pop_up.dart';
10 -import 'package:cake_wallet/view_model/seed_type_view_model.dart';
11 -import 'package:mobx/mobx.dart';
12 -import 'package:flutter_mobx/flutter_mobx.dart';
13 -import 'package:flutter/material.dart';
14 -import 'package:cake_wallet/generated/i18n.dart';
15 -import 'package:cake_wallet/core/wallet_name_validator.dart';
16 -import 'package:cake_wallet/src/widgets/seed_language_selector.dart';
8 import 'package:cake_wallet/src/screens/base_page.dart';
9 +import 'package:cake_wallet/src/screens/new_wallet/widgets/select_button.dart';
10 +import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
11 +import 'package:cake_wallet/src/widgets/picker.dart';
12 import 'package:cake_wallet/src/widgets/primary_button.dart';
13 import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart';
14 import 'package:cake_wallet/src/widgets/seed_language_picker.dart';
21 -import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
22 -import 'package:cake_wallet/core/execution_state.dart';
23 -import 'package:cake_wallet/view_model/wallet_new_vm.dart';
15 +import 'package:cake_wallet/src/widgets/seed_language_selector.dart';
16 +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart';
17 import 'package:cake_wallet/themes/extensions/new_wallet_theme.dart';
18 import 'package:cake_wallet/themes/extensions/send_page_theme.dart';
26 -import 'package:cake_wallet/entities/seed_type.dart';
27 -
19 +import 'package:cake_wallet/themes/theme_base.dart';
20 +import 'package:cake_wallet/utils/responsive_layout_util.dart';
21 +import 'package:cake_wallet/utils/show_pop_up.dart';
22 +import 'package:cake_wallet/view_model/seed_settings_view_model.dart';
23 +import 'package:cake_wallet/view_model/wallet_new_vm.dart';
24 +import 'package:flutter/material.dart';
25 +import 'package:flutter_mobx/flutter_mobx.dart';
26 +import 'package:mobx/mobx.dart';
27
28 class NewWalletPage extends BasePage {
30 - NewWalletPage(this._walletNewVM, this._seedTypeViewModel);
29 + NewWalletPage(this._walletNewVM, this._seedSettingsViewModel);
30
31 final WalletNewVM _walletNewVM;
33 - final SeedTypeViewModel _seedTypeViewModel;
32 + final SeedSettingsViewModel _seedSettingsViewModel;
33
34 final walletNameImage = Image.asset('assets/images/wallet_name.png');
35
@@ -51,15 +50,15 @@ class NewWalletPage extends BasePage {
50 Widget body(BuildContext context) => WalletNameForm(
51 _walletNewVM,
52 currentTheme.type == ThemeType.dark ? walletNameImage : walletNameLightImage,
54 - _seedTypeViewModel);
53 + _seedSettingsViewModel);
54 }
55
56 class WalletNameForm extends StatefulWidget {
58 - WalletNameForm(this._walletNewVM, this.walletImage, this._seedTypeViewModel);
57 + WalletNameForm(this._walletNewVM, this.walletImage, this._seedSettingsViewModel);
58
59 final WalletNewVM _walletNewVM;
60 final Image walletImage;
62 - final SeedTypeViewModel _seedTypeViewModel;
61 + final SeedSettingsViewModel _seedSettingsViewModel;
62
63 @override
64 _WalletNameFormState createState() => _WalletNameFormState(_walletNewVM);
@@ -110,7 +109,7 @@ class _WalletNameFormState extends State<WalletNameForm> {
109 }
110 });
111
113 - _setSeedType(SeedType.defaultSeedType);
112 + _setSeedType(MoneroSeedType.defaultSeedType);
113 super.initState();
114 }
115
@@ -285,12 +284,12 @@ class _WalletNameFormState extends State<WalletNameForm> {
284 builder: (BuildContext build) => Padding(
285 padding: EdgeInsets.only(top: 24),
286 child: SelectButton(
288 - text: widget._seedTypeViewModel.moneroSeedType.title,
287 + text: widget._seedSettingsViewModel.moneroSeedType.title,
288 onTap: () async {
289 await showPopUp<void>(
290 context: context,
291 builder: (_) => Picker(
293 - items: SeedType.all,
292 + items: MoneroSeedType.all,
293 selectedAtIndex: isPolyseed ? 1 : 0,
294 onItemSelected: _setSeedType,
295 isSeparated: false,
@@ -308,8 +307,8 @@ class _WalletNameFormState extends State<WalletNameForm> {
307 key: _languageSelectorKey,
308 initialSelected: defaultSeedLanguage,
309 seedType: _walletNewVM.hasSeedType
311 - ? widget._seedTypeViewModel.moneroSeedType
312 - : SeedType.legacy,
310 + ? widget._seedSettingsViewModel.moneroSeedType
311 + : MoneroSeedType.legacy,
312 ),
313 ),
314 )
@@ -380,10 +379,10 @@ class _WalletNameFormState extends State<WalletNameForm> {
379 _formProcessing = false;
380 }
381
383 - bool get isPolyseed => widget._seedTypeViewModel.moneroSeedType == SeedType.polyseed;
382 + bool get isPolyseed => widget._seedSettingsViewModel.moneroSeedType == MoneroSeedType.polyseed;
383
385 - void _setSeedType(SeedType item) {
386 - widget._seedTypeViewModel.setMoneroSeedType(item);
384 + void _setSeedType(MoneroSeedType item) {
385 + widget._seedSettingsViewModel.setMoneroSeedType(item);
386 _languageSelectorKey.currentState?.selected = defaultSeedLanguage; // Reset Seed language
387 }
388 }
lib/src/screens/restore/wallet_restore_from_seed_form.dart
+95 -69
@@ -9,35 +9,34 @@ import 'package:cake_wallet/src/widgets/seed_language_picker.dart';
9 import 'package:cake_wallet/src/widgets/seed_widget.dart';
10 import 'package:cake_wallet/themes/extensions/send_page_theme.dart';
11 import 'package:cake_wallet/utils/show_pop_up.dart';
12 -import 'package:cake_wallet/view_model/seed_type_view_model.dart';
12 +import 'package:cake_wallet/view_model/seed_settings_view_model.dart';
13 import 'package:cw_core/wallet_type.dart';
14 import 'package:flutter/material.dart';
15 import 'package:mobx/mobx.dart';
16 import 'package:polyseed/polyseed.dart';
17
18 class WalletRestoreFromSeedForm extends StatefulWidget {
19 - WalletRestoreFromSeedForm(
20 - {Key? key,
21 - required this.displayLanguageSelector,
22 - required this.displayBlockHeightSelector,
23 - required this.displayPassphrase,
24 - required this.type,
25 - required this.displayWalletPassword,
26 - required this.seedTypeViewModel,
27 - this.blockHeightFocusNode,
28 - this.onHeightOrDateEntered,
29 - this.onSeedChange,
30 - this.onLanguageChange,
31 - this.onPasswordChange,
32 - this.onRepeatedPasswordChange})
33 - : super(key: key);
19 + WalletRestoreFromSeedForm({Key? key,
20 + required this.displayLanguageSelector,
21 + required this.displayBlockHeightSelector,
22 + required this.displayPassphrase,
23 + required this.type,
24 + required this.displayWalletPassword,
25 + required this.seedSettingsViewModel,
26 + this.blockHeightFocusNode,
27 + this.onHeightOrDateEntered,
28 + this.onSeedChange,
29 + this.onLanguageChange,
30 + this.onPasswordChange,
31 + this.onRepeatedPasswordChange,
32 + }) : super(key: key);
33
34 final WalletType type;
35 final bool displayLanguageSelector;
36 final bool displayBlockHeightSelector;
37 final bool displayWalletPassword;
38 final bool displayPassphrase;
40 - final SeedTypeViewModel seedTypeViewModel;
39 + final SeedSettingsViewModel seedSettingsViewModel;
40 final FocusNode? blockHeightFocusNode;
41 final Function(bool)? onHeightOrDateEntered;
42 final void Function(String)? onSeedChange;
@@ -58,7 +57,9 @@ class WalletRestoreFromSeedFormState extends State<WalletRestoreFromSeedForm> {
57 languageController = TextEditingController(),
58 nameTextEditingController = TextEditingController(),
59 passwordTextEditingController = displayWalletPassword ? TextEditingController() : null,
61 - repeatedPasswordTextEditingController = displayWalletPassword ? TextEditingController() : null,
60 + repeatedPasswordTextEditingController = displayWalletPassword
61 + ? TextEditingController()
62 + : null,
63 passphraseController = TextEditingController(),
64 seedTypeController = TextEditingController();
65
@@ -75,10 +76,11 @@ class WalletRestoreFromSeedFormState extends State<WalletRestoreFromSeedForm> {
76 String language;
77 void Function()? passwordListener;
78 void Function()? repeatedPasswordListener;
79 + void Function()? passphraseListener;
80
81 @override
82 void initState() {
81 - _setSeedType(widget.seedTypeViewModel.moneroSeedType);
83 + _setSeedType(widget.seedSettingsViewModel.moneroSeedType);
84 _setLanguageLabel(language);
85
86 if (passwordTextEditingController != null) {
@@ -87,14 +89,19 @@ class WalletRestoreFromSeedFormState extends State<WalletRestoreFromSeedForm> {
89 }
90
91 if (repeatedPasswordTextEditingController != null) {
90 - repeatedPasswordListener = () => widget.onRepeatedPasswordChange?.call(repeatedPasswordTextEditingController!.text);
92 + repeatedPasswordListener =
93 + () => widget.onRepeatedPasswordChange?.call(repeatedPasswordTextEditingController!.text);
94 repeatedPasswordTextEditingController?.addListener(repeatedPasswordListener!);
95 }
96 +
97 + passphraseListener = () => widget.seedSettingsViewModel.setPassphrase(passphraseController.text);
98 + passphraseController.addListener(passphraseListener!);
99 +
100 moneroSeedTypeReaction =
94 - reaction((_) => widget.seedTypeViewModel.moneroSeedType, (SeedType item) {
95 - _setSeedType(item);
96 - _changeLanguage('English');
97 - });
101 + reaction((_) => widget.seedSettingsViewModel.moneroSeedType, (MoneroSeedType item) {
102 + _setSeedType(item);
103 + _changeLanguage('English');
104 + });
105
106 super.initState();
107 }
@@ -110,6 +117,9 @@ class WalletRestoreFromSeedFormState extends State<WalletRestoreFromSeedForm> {
117 if (repeatedPasswordListener != null) {
118 repeatedPasswordTextEditingController?.removeListener(repeatedPasswordListener!);
119 }
120 +
121 + passphraseController.removeListener(passphraseListener!);
122 +
123 super.dispose();
124 }
125
@@ -118,11 +128,13 @@ class WalletRestoreFromSeedFormState extends State<WalletRestoreFromSeedForm> {
128 Polyseed.isValidSeed(seed)) {
129 final lang = PolyseedLang.getByPhrase(seed);
130
121 - _changeSeedType(SeedType.polyseed);
131 + _changeSeedType(MoneroSeedType.polyseed);
132 _changeLanguage(lang.nameEnglish);
133 }
124 - if (widget.type == WalletType.wownero && seed.split(" ").length == 14) {
125 - _changeSeedType(SeedType.wowneroSeed);
134 + if (widget.type == WalletType.wownero && seed
135 + .split(" ")
136 + .length == 14) {
137 + _changeSeedType(MoneroSeedType.wowneroSeed);
138 _changeLanguage("English");
139 }
140 widget.onSeedChange?.call(seed);
@@ -140,7 +152,9 @@ class WalletRestoreFromSeedFormState extends State<WalletRestoreFromSeedForm> {
152 children: [
153 BaseTextFormField(
154 controller: nameTextEditingController,
143 - hintText: S.of(context).wallet_name,
155 + hintText: S
156 + .of(context)
157 + .wallet_name,
158 suffixIcon: IconButton(
159 onPressed: () async {
160 final rName = await generateName();
@@ -156,7 +170,9 @@ class WalletRestoreFromSeedFormState extends State<WalletRestoreFromSeedForm> {
170 padding: const EdgeInsets.all(8),
171 decoration: BoxDecoration(
172 borderRadius: BorderRadius.circular(6.0),
159 - color: Theme.of(context).hintColor,
173 + color: Theme
174 + .of(context)
175 + .hintColor,
176 ),
177 width: 34,
178 height: 34,
@@ -183,13 +199,14 @@ class WalletRestoreFromSeedFormState extends State<WalletRestoreFromSeedForm> {
199 onTap: () async {
200 await showPopUp<void>(
201 context: context,
186 - builder: (_) => Picker(
202 + builder: (_) =>
203 + Picker(
204 items: _getItems(),
205 selectedAtIndex: isPolyseed
206 ? 1
207 : seedTypeController.value.text.contains("14")
191 - ? 2
192 - : 0,
208 + ? 2
209 + : 0,
210 mainAxisAlignment: MainAxisAlignment.start,
211 onItemSelected: _changeSeedType,
212 isSeparated: false,
@@ -211,37 +228,43 @@ class WalletRestoreFromSeedFormState extends State<WalletRestoreFromSeedForm> {
228 if (widget.displayWalletPassword)
229 ...[BaseTextFormField(
230 controller: passwordTextEditingController,
214 - hintText: S.of(context).password,
231 + hintText: S
232 + .of(context)
233 + .password,
234 obscureText: true),
235 BaseTextFormField(
236 controller: repeatedPasswordTextEditingController,
218 - hintText: S.of(context).repeat_wallet_password,
219 - obscureText: true)],
237 + hintText: S
238 + .of(context)
239 + .repeat_wallet_password,
240 + obscureText: true)
241 + ],
242 if (widget.displayLanguageSelector)
221 - if (!seedTypeController.value.text.contains("14") && widget.displayLanguageSelector)
222 - GestureDetector(
223 - onTap: () async {
224 - await showPopUp<void>(
225 - context: context,
226 - builder: (_) => SeedLanguagePicker(
227 - selected: language,
228 - onItemSelected: _changeLanguage,
229 - seedType: isPolyseed ? SeedType.polyseed : SeedType.legacy,
230 - ));
231 - },
232 - child: Container(
233 - color: Colors.transparent,
234 - padding: EdgeInsets.only(top: 20.0),
235 - child: IgnorePointer(
236 - child: BaseTextFormField(
237 - controller: languageController,
238 - enableInteractiveSelection: false,
239 - readOnly: true,
240 - suffixIcon: expandIcon,
243 + if (!seedTypeController.value.text.contains("14") && widget.displayLanguageSelector)
244 + GestureDetector(
245 + onTap: () async {
246 + await showPopUp<void>(
247 + context: context,
248 + builder: (_) =>
249 + SeedLanguagePicker(
250 + selected: language,
251 + onItemSelected: _changeLanguage,
252 + seedType: isPolyseed ? MoneroSeedType.polyseed : MoneroSeedType.legacy,
253 + ));
254 + },
255 + child: Container(
256 + color: Colors.transparent,
257 + padding: EdgeInsets.only(top: 20.0),
258 + child: IgnorePointer(
259 + child: BaseTextFormField(
260 + controller: languageController,
261 + enableInteractiveSelection: false,
262 + readOnly: true,
263 + suffixIcon: expandIcon,
264 + ),
265 ),
266 ),
267 ),
244 - ),
268 if ((!isPolyseed) && widget.displayBlockHeightSelector)
269 BlockchainHeightWidget(
270 focusNode: widget.blockHeightFocusNode,
@@ -262,17 +285,20 @@ class WalletRestoreFromSeedFormState extends State<WalletRestoreFromSeedForm> {
285 }
286
287 bool get isPolyseed =>
265 - widget.seedTypeViewModel.moneroSeedType == SeedType.polyseed &&
266 - (widget.type == WalletType.monero || widget.type == WalletType.wownero);
288 + widget.seedSettingsViewModel.moneroSeedType == MoneroSeedType.polyseed &&
289 + (widget.type == WalletType.monero || widget.type == WalletType.wownero);
290
268 - Widget get expandIcon => Container(
291 + Widget get expandIcon =>
292 + Container(
293 padding: EdgeInsets.all(18),
294 width: 24,
295 height: 24,
296 child: Image.asset(
297 'assets/images/arrow_bottom_purple_icon.png',
298 height: 8,
275 - color: Theme.of(context).hintColor,
299 + color: Theme
300 + .of(context)
301 + .hintColor,
302 ),
303 );
304
@@ -280,8 +306,8 @@ class WalletRestoreFromSeedFormState extends State<WalletRestoreFromSeedForm> {
306 final setLang = isPolyseed
307 ? "POLYSEED_$language"
308 : seedTypeController.value.text.contains("14")
283 - ? "WOWSEED_" + language
284 - : language;
309 + ? "WOWSEED_" + language
310 + : language;
311 setState(() {
312 this.language = setLang;
313 seedWidgetStateKey.currentState!.changeSeedLanguage(setLang);
@@ -293,24 +319,24 @@ class WalletRestoreFromSeedFormState extends State<WalletRestoreFromSeedForm> {
319 void _setLanguageLabel(String language) =>
320 languageController.text = '${language.replaceAll("POLYSEED_", "")} (Seed language)';
321
296 - void _changeSeedType(SeedType item) {
322 + void _changeSeedType(MoneroSeedType item) {
323 _setSeedType(item);
324 _changeLanguage('English');
299 - widget.seedTypeViewModel.setMoneroSeedType(item);
325 + widget.seedSettingsViewModel.setMoneroSeedType(item);
326 }
327
302 - void _setSeedType(SeedType item) {
328 + void _setSeedType(MoneroSeedType item) {
329 seedTypeController.text = item.toString();
330 }
331
306 - List<SeedType> _getItems() {
332 + List<MoneroSeedType> _getItems() {
333 switch (widget.type) {
334 case WalletType.monero:
309 - return [SeedType.legacy, SeedType.polyseed];
335 + return [MoneroSeedType.legacy, MoneroSeedType.polyseed];
336 case WalletType.wownero:
311 - return [SeedType.legacy, SeedType.polyseed, SeedType.wowneroSeed];
337 + return [MoneroSeedType.legacy, MoneroSeedType.polyseed, MoneroSeedType.wowneroSeed];
338 default:
313 - return [SeedType.legacy];
339 + return [MoneroSeedType.legacy];
340 }
341 }
342 }
lib/src/screens/restore/wallet_restore_page.dart
+7 -6
@@ -12,7 +12,7 @@ import 'package:cake_wallet/themes/extensions/wallet_list_theme.dart';
12 import 'package:cake_wallet/utils/responsive_layout_util.dart';
13 import 'package:cake_wallet/utils/show_pop_up.dart';
14 import 'package:cake_wallet/view_model/restore/restore_mode.dart';
15 -import 'package:cake_wallet/view_model/seed_type_view_model.dart';
15 +import 'package:cake_wallet/view_model/seed_settings_view_model.dart';
16 import 'package:cake_wallet/view_model/wallet_restore_view_model.dart';
17 import 'package:cw_core/wallet_info.dart';
18 import 'package:cw_core/wallet_type.dart';
@@ -23,7 +23,7 @@ import 'package:mobx/mobx.dart';
23 import 'package:smooth_page_indicator/smooth_page_indicator.dart';
24
25 class WalletRestorePage extends BasePage {
26 - WalletRestorePage(this.walletRestoreViewModel, this.seedTypeViewModel)
26 + WalletRestorePage(this.walletRestoreViewModel, this.seedSettingsViewModel)
27 : walletRestoreFromSeedFormKey = GlobalKey<WalletRestoreFromSeedFormState>(),
28 walletRestoreFromKeysFormKey = GlobalKey<WalletRestoreFromKeysFromState>(),
29 _pages = [],
@@ -33,7 +33,7 @@ class WalletRestorePage extends BasePage {
33 switch (mode) {
34 case WalletRestoreMode.seed:
35 _pages.add(WalletRestoreFromSeedForm(
36 - seedTypeViewModel: seedTypeViewModel,
36 + seedSettingsViewModel: seedSettingsViewModel,
37 displayBlockHeightSelector:
38 walletRestoreViewModel.hasBlockchainHeightLanguageSelector,
39 displayLanguageSelector: walletRestoreViewModel.hasSeedLanguageSelector,
@@ -96,7 +96,7 @@ class WalletRestorePage extends BasePage {
96 ));
97
98 final WalletRestoreViewModel walletRestoreViewModel;
99 - final SeedTypeViewModel seedTypeViewModel;
99 + final SeedSettingsViewModel seedSettingsViewModel;
100 final PageController _controller;
101 final List<Widget> _pages;
102 final GlobalKey<WalletRestoreFromSeedFormState> walletRestoreFromSeedFormKey;
@@ -233,6 +233,7 @@ class WalletRestorePage extends BasePage {
233 onTap: () {
234 Navigator.of(context)
235 .pushNamed(Routes.advancedPrivacySettings, arguments: {
236 + 'isFromRestore': true,
237 'type': walletRestoreViewModel.type,
238 'useTestnet': walletRestoreViewModel.useTestnet,
239 'toggleTestnet': walletRestoreViewModel.toggleUseTestnet
@@ -322,8 +323,7 @@ class WalletRestorePage extends BasePage {
323 }
324
325 if (walletRestoreViewModel.hasPassphrase) {
325 - credentials['passphrase'] =
326 - walletRestoreFromSeedFormKey.currentState!.passphraseController.text;
326 + credentials['passphrase'] = seedSettingsViewModel.passphrase;
327 }
328
329 credentials['name'] =
@@ -426,6 +426,7 @@ class WalletRestorePage extends BasePage {
426 }
427
428 await walletRestoreViewModel.create(options: _credentials());
429 + seedSettingsViewModel.setPassphrase(null);
430 } catch (e) {
431 _formProcessing = false;
432 rethrow;
lib/src/widgets/seed_language_picker.dart
+17 -17
@@ -11,36 +11,36 @@ class SeedLanguagePickerOption {
11 final String name;
12 final String nameLocalized;
13 final Image image;
14 - final List<SeedType> supportedSeedTypes;
14 + final List<MoneroSeedType> supportedSeedTypes;
15 }
16
17 final List<SeedLanguagePickerOption> seedLanguages = [
18 SeedLanguagePickerOption('English', S.current.seed_language_english,
19 - Image.asset('assets/images/flags/usa.png'), [SeedType.legacy, SeedType.polyseed]),
19 + Image.asset('assets/images/flags/usa.png'), [MoneroSeedType.legacy, MoneroSeedType.polyseed]),
20 SeedLanguagePickerOption('Chinese (Simplified)', S.current.seed_language_chinese,
21 - Image.asset('assets/images/flags/chn.png'), [SeedType.legacy, SeedType.polyseed]),
21 + Image.asset('assets/images/flags/chn.png'), [MoneroSeedType.legacy, MoneroSeedType.polyseed]),
22 SeedLanguagePickerOption('Chinese (Traditional)', S.current.seed_language_chinese_traditional,
23 - Image.asset('assets/images/flags/chn.png'), [SeedType.polyseed]),
23 + Image.asset('assets/images/flags/chn.png'), [MoneroSeedType.polyseed]),
24 SeedLanguagePickerOption('Dutch', S.current.seed_language_dutch,
25 - Image.asset('assets/images/flags/nld.png'), [SeedType.legacy]),
25 + Image.asset('assets/images/flags/nld.png'), [MoneroSeedType.legacy]),
26 SeedLanguagePickerOption('German', S.current.seed_language_german,
27 - Image.asset('assets/images/flags/deu.png'), [SeedType.legacy]),
27 + Image.asset('assets/images/flags/deu.png'), [MoneroSeedType.legacy]),
28 SeedLanguagePickerOption('Japanese', S.current.seed_language_japanese,
29 - Image.asset('assets/images/flags/jpn.png'), [SeedType.legacy, SeedType.polyseed]),
29 + Image.asset('assets/images/flags/jpn.png'), [MoneroSeedType.legacy, MoneroSeedType.polyseed]),
30 SeedLanguagePickerOption('Korean', S.current.seed_language_korean,
31 - Image.asset('assets/images/flags/kor.png'), [SeedType.polyseed]),
31 + Image.asset('assets/images/flags/kor.png'), [MoneroSeedType.polyseed]),
32 SeedLanguagePickerOption('Portuguese', S.current.seed_language_portuguese,
33 - Image.asset('assets/images/flags/prt.png'), [SeedType.legacy, SeedType.polyseed]),
33 + Image.asset('assets/images/flags/prt.png'), [MoneroSeedType.legacy, MoneroSeedType.polyseed]),
34 SeedLanguagePickerOption('Russian', S.current.seed_language_russian,
35 - Image.asset('assets/images/flags/rus.png'), [SeedType.legacy]),
35 + Image.asset('assets/images/flags/rus.png'), [MoneroSeedType.legacy]),
36 SeedLanguagePickerOption('Czech', S.current.seed_language_czech,
37 - Image.asset('assets/images/flags/czk.png'), [SeedType.polyseed]),
37 + Image.asset('assets/images/flags/czk.png'), [MoneroSeedType.polyseed]),
38 SeedLanguagePickerOption('Spanish', S.current.seed_language_spanish,
39 - Image.asset('assets/images/flags/esp.png'), [SeedType.legacy, SeedType.polyseed]),
39 + Image.asset('assets/images/flags/esp.png'), [MoneroSeedType.legacy, MoneroSeedType.polyseed]),
40 SeedLanguagePickerOption('French', S.current.seed_language_french,
41 - Image.asset('assets/images/flags/fra.png'), [SeedType.legacy, SeedType.polyseed]),
41 + Image.asset('assets/images/flags/fra.png'), [MoneroSeedType.legacy, MoneroSeedType.polyseed]),
42 SeedLanguagePickerOption('Italian', S.current.seed_language_italian,
43 - Image.asset('assets/images/flags/ita.png'), [SeedType.legacy, SeedType.polyseed]),
43 + Image.asset('assets/images/flags/ita.png'), [MoneroSeedType.legacy, MoneroSeedType.polyseed]),
44 ];
45
46 const defaultSeedLanguage = 'English';
@@ -51,11 +51,11 @@ class SeedLanguagePicker extends StatefulWidget {
51 SeedLanguagePicker(
52 {Key? key,
53 this.selected = defaultSeedLanguage,
54 - this.seedType = SeedType.defaultSeedType,
54 + this.seedType = MoneroSeedType.defaultSeedType,
55 required this.onItemSelected})
56 : super(key: key);
57
58 - final SeedType seedType;
58 + final MoneroSeedType seedType;
59 final String selected;
60 final Function(String) onItemSelected;
61
@@ -68,7 +68,7 @@ class SeedLanguagePickerState extends State<SeedLanguagePicker> {
68 SeedLanguagePickerState(
69 {required this.selected, required this.onItemSelected, required this.seedType});
70
71 - final SeedType seedType;
71 + final MoneroSeedType seedType;
72 final String selected;
73 final Function(String) onItemSelected;
74
lib/src/widgets/seed_language_selector.dart
+2 -2
@@ -7,11 +7,11 @@ import 'package:flutter/material.dart';
7
8 class SeedLanguageSelector extends StatefulWidget {
9 SeedLanguageSelector(
10 - {Key? key, required this.initialSelected, this.seedType = SeedType.defaultSeedType})
10 + {Key? key, required this.initialSelected, this.seedType = MoneroSeedType.defaultSeedType})
11 : super(key: key);
12
13 final String initialSelected;
14 - final SeedType seedType;
14 + final MoneroSeedType seedType;
15
16 @override
17 SeedLanguageSelectorState createState() => SeedLanguageSelectorState(selected: initialSelected);
lib/store/seed_settings_store.dart new
+11
@@ -0,0 +1,11 @@
1 +import 'package:mobx/mobx.dart';
2 +
3 +part 'seed_settings_store.g.dart';
4 +
5 +class SeedSettingsStore = SeedSettingsStoreBase with _$SeedSettingsStore;
6 +
7 +abstract class SeedSettingsStoreBase with Store {
8 +
9 + @observable
10 + String? passphrase;
11 +}
lib/store/settings_store.dart
+49 -24
@@ -1,45 +1,46 @@
1 import 'dart:io';
2 +
3 import 'package:cake_wallet/bitcoin/bitcoin.dart';
4 import 'package:cake_wallet/bitcoin_cash/bitcoin_cash.dart';
5 import 'package:cake_wallet/core/secure_storage.dart';
6 +import 'package:cake_wallet/di.dart';
7 +import 'package:cake_wallet/entities/action_list_display_mode.dart';
8 import 'package:cake_wallet/entities/auto_generate_subaddress_status.dart';
6 -import 'package:cake_wallet/entities/provider_types.dart';
7 -import 'package:cake_wallet/entities/cake_2fa_preset_options.dart';
9 import 'package:cake_wallet/entities/background_tasks.dart';
10 +import 'package:cake_wallet/entities/balance_display_mode.dart';
11 +import 'package:cake_wallet/entities/cake_2fa_preset_options.dart';
12 import 'package:cake_wallet/entities/exchange_api_mode.dart';
13 +import 'package:cake_wallet/entities/fiat_api_mode.dart';
14 +import 'package:cake_wallet/entities/fiat_currency.dart';
15 +import 'package:cake_wallet/entities/language_service.dart';
16 import 'package:cake_wallet/entities/pin_code_required_duration.dart';
17 import 'package:cake_wallet/entities/preferences_key.dart';
18 +import 'package:cake_wallet/entities/provider_types.dart';
19 import 'package:cake_wallet/entities/secret_store_key.dart';
20 import 'package:cake_wallet/entities/seed_phrase_length.dart';
21 import 'package:cake_wallet/entities/seed_type.dart';
22 import 'package:cake_wallet/entities/sort_balance_types.dart';
23 import 'package:cake_wallet/entities/wallet_list_order_types.dart';
17 -import 'package:cake_wallet/polygon/polygon.dart';
24 +import 'package:cake_wallet/ethereum/ethereum.dart';
25 import 'package:cake_wallet/exchange/provider/trocador_exchange_provider.dart';
19 -import 'package:cake_wallet/view_model/settings/sync_mode.dart';
26 +import 'package:cake_wallet/monero/monero.dart';
27 +import 'package:cake_wallet/polygon/polygon.dart';
28 +import 'package:cake_wallet/themes/theme_base.dart';
29 +import 'package:cake_wallet/themes/theme_list.dart';
30 import 'package:cake_wallet/utils/device_info.dart';
21 -import 'package:cake_wallet/ethereum/ethereum.dart';
31 +import 'package:cake_wallet/utils/package_info.dart';
32 +import 'package:cake_wallet/view_model/settings/sync_mode.dart';
33 import 'package:cake_wallet/wallet_type_utils.dart';
34 import 'package:cake_wallet/wownero/wownero.dart';
35 +import 'package:cw_core/node.dart';
36 +import 'package:cw_core/set_app_secure_native.dart';
37 import 'package:cw_core/transaction_priority.dart';
25 -import 'package:cake_wallet/themes/theme_base.dart';
26 -import 'package:cake_wallet/themes/theme_list.dart';
38 +import 'package:cw_core/wallet_type.dart';
39 import 'package:device_info_plus/device_info_plus.dart';
40 import 'package:flutter/material.dart';
41 import 'package:hive/hive.dart';
42 import 'package:mobx/mobx.dart';
31 -import 'package:cake_wallet/utils/package_info.dart';
32 -import 'package:cake_wallet/di.dart';
33 -import 'package:cw_core/wallet_type.dart';
43 import 'package:shared_preferences/shared_preferences.dart';
35 -import 'package:cake_wallet/entities/language_service.dart';
36 -import 'package:cake_wallet/entities/balance_display_mode.dart';
37 -import 'package:cake_wallet/entities/fiat_currency.dart';
38 -import 'package:cw_core/node.dart';
39 -import 'package:cake_wallet/monero/monero.dart';
40 -import 'package:cake_wallet/entities/action_list_display_mode.dart';
41 -import 'package:cake_wallet/entities/fiat_api_mode.dart';
42 -import 'package:cw_core/set_app_secure_native.dart';
44
45 part 'settings_store.g.dart';
46
@@ -55,7 +56,8 @@ abstract class SettingsStoreBase with Store {
56 required BalanceDisplayMode initialBalanceDisplayMode,
57 required bool initialSaveRecipientAddress,
58 required AutoGenerateSubaddressStatus initialAutoGenerateSubaddressStatus,
58 - required SeedType initialMoneroSeedType,
59 + required MoneroSeedType initialMoneroSeedType,
60 + required BitcoinSeedType initialBitcoinSeedType,
61 required bool initialAppSecure,
62 required bool initialDisableBuy,
63 required bool initialDisableSell,
@@ -128,6 +130,7 @@ abstract class SettingsStoreBase with Store {
130 shouldSaveRecipientAddress = initialSaveRecipientAddress,
131 autoGenerateSubaddressStatus = initialAutoGenerateSubaddressStatus,
132 moneroSeedType = initialMoneroSeedType,
133 + bitcoinSeedType = initialBitcoinSeedType,
134 fiatApiMode = initialFiatMode,
135 allowBiometricalAuthentication = initialAllowBiometricalAuthentication,
136 selectedCake2FAPreset = initialCake2FAPresetOptions,
@@ -329,9 +332,14 @@ abstract class SettingsStoreBase with Store {
332
333 reaction(
334 (_) => moneroSeedType,
332 - (SeedType moneroSeedType) =>
335 + (MoneroSeedType moneroSeedType) =>
336 sharedPreferences.setInt(PreferencesKey.moneroSeedType, moneroSeedType.raw));
337
338 + reaction(
339 + (_) => bitcoinSeedType,
340 + (BitcoinSeedType bitcoinSeedType) => sharedPreferences.setInt(
341 + PreferencesKey.bitcoinSeedType, bitcoinSeedType.raw));
342 +
343 reaction(
344 (_) => fiatApiMode,
345 (FiatApiMode mode) =>
@@ -555,7 +563,8 @@ abstract class SettingsStoreBase with Store {
563 static const defaultAutoGenerateSubaddressStatus = AutoGenerateSubaddressStatus.initialized;
564 static final walletPasswordDirectInput = Platform.isLinux;
565 static const defaultSeedPhraseLength = SeedPhraseLength.twelveWords;
558 - static const defaultMoneroSeedType = SeedType.defaultSeedType;
566 + static const defaultMoneroSeedType = MoneroSeedType.defaultSeedType;
567 + static const defaultBitcoinSeedType = BitcoinSeedType.defaultDerivationType;
568
569 @observable
570 FiatCurrency fiatCurrency;
@@ -585,7 +594,10 @@ abstract class SettingsStoreBase with Store {
594 AutoGenerateSubaddressStatus autoGenerateSubaddressStatus;
595
596 @observable
588 - SeedType moneroSeedType;
597 + MoneroSeedType moneroSeedType;
598 +
599 + @observable
600 + BitcoinSeedType bitcoinSeedType;
601
602 @observable
603 bool isAppSecure;
@@ -945,9 +957,15 @@ abstract class SettingsStoreBase with Store {
957 final _moneroSeedType = sharedPreferences.getInt(PreferencesKey.moneroSeedType);
958
959 final moneroSeedType = _moneroSeedType != null
948 - ? SeedType.deserialize(raw: _moneroSeedType)
960 + ? MoneroSeedType.deserialize(raw: _moneroSeedType)
961 : defaultMoneroSeedType;
962
963 + final _bitcoinSeedType = sharedPreferences.getInt(PreferencesKey.bitcoinSeedType);
964 +
965 + final bitcoinSeedType = _bitcoinSeedType != null
966 + ? BitcoinSeedType.deserialize(raw: _bitcoinSeedType)
967 + : defaultBitcoinSeedType;
968 +
969 final nodes = <WalletType, Node>{};
970 final powNodes = <WalletType, Node>{};
971
@@ -1111,6 +1129,7 @@ abstract class SettingsStoreBase with Store {
1129 initialSaveRecipientAddress: shouldSaveRecipientAddress,
1130 initialAutoGenerateSubaddressStatus: autoGenerateSubaddressStatus,
1131 initialMoneroSeedType: moneroSeedType,
1132 + initialBitcoinSeedType: bitcoinSeedType,
1133 initialAppSecure: isAppSecure,
1134 initialDisableBuy: disableBuy,
1135 initialDisableSell: disableSell,
@@ -1233,9 +1252,15 @@ abstract class SettingsStoreBase with Store {
1252 final _moneroSeedType = sharedPreferences.getInt(PreferencesKey.moneroSeedType);
1253
1254 moneroSeedType = _moneroSeedType != null
1236 - ? SeedType.deserialize(raw: _moneroSeedType)
1255 + ? MoneroSeedType.deserialize(raw: _moneroSeedType)
1256 : defaultMoneroSeedType;
1257
1258 + final _bitcoinSeedType = sharedPreferences.getInt(PreferencesKey.bitcoinSeedType);
1259 +
1260 + bitcoinSeedType = _bitcoinSeedType != null
1261 + ? BitcoinSeedType.deserialize(raw: _bitcoinSeedType)
1262 + : defaultBitcoinSeedType;
1263 +
1264 balanceDisplayMode = BalanceDisplayMode.deserialize(
1265 raw: sharedPreferences.getInt(PreferencesKey.currentBalanceDisplayModeKey)!);
1266 shouldSaveRecipientAddress =
lib/view_model/advanced_privacy_settings_view_model.dart
+14 -4
@@ -30,6 +30,7 @@ abstract class AdvancedPrivacySettingsViewModelBase with Store {
30
31 final SettingsStore _settingsStore;
32
33 + @computed
34 bool get hasSeedPhraseLengthOption {
35 // convert to switch case so that it give a syntax error when adding a new wallet type
36 // thus we don't forget about it
@@ -40,11 +41,14 @@ abstract class AdvancedPrivacySettingsViewModelBase with Store {
41 case WalletType.solana:
42 case WalletType.tron:
43 return true;
44 +
45 + case WalletType.bitcoin:
46 + case WalletType.litecoin:
47 + return _settingsStore.bitcoinSeedType == BitcoinSeedType.bip39;
48 +
49 case WalletType.monero:
50 case WalletType.wownero:
51 case WalletType.none:
46 - case WalletType.bitcoin:
47 - case WalletType.litecoin:
52 case WalletType.haven:
53 case WalletType.nano:
54 case WalletType.banano:
@@ -52,7 +56,13 @@ abstract class AdvancedPrivacySettingsViewModelBase with Store {
56 }
57 }
58
55 - bool get hasSeedTypeOption => type == WalletType.monero || type == WalletType.wownero;
59 + bool get hasSeedTypeOption => [WalletType.monero, WalletType.wownero].contains(type);
60 +
61 + bool get hasPassphraseOption => [
62 + WalletType.bitcoin,
63 + WalletType.litecoin,
64 + WalletType.bitcoinCash,
65 + ].contains(type);
66
67 @computed
68 bool get addCustomNode => _addCustomNode;
@@ -61,7 +71,7 @@ abstract class AdvancedPrivacySettingsViewModelBase with Store {
71 SeedPhraseLength get seedPhraseLength => _settingsStore.seedPhraseLength;
72
73 @computed
64 - bool get isPolySeed => _settingsStore.moneroSeedType == SeedType.polyseed;
74 + bool get isPolySeed => _settingsStore.moneroSeedType == MoneroSeedType.polyseed;
75
76 @action
77 void setFiatApiMode(FiatApiMode fiatApiMode) => _settingsStore.fiatApiMode = fiatApiMode;
lib/view_model/restore/restore_from_qr_vm.dart
+3 -2
@@ -7,6 +7,7 @@ import 'package:cake_wallet/solana/solana.dart';
7 import 'package:cake_wallet/tron/tron.dart';
8 import 'package:cake_wallet/view_model/restore/restore_mode.dart';
9 import 'package:cake_wallet/view_model/restore/restore_wallet.dart';
10 +import 'package:cake_wallet/view_model/seed_settings_view_model.dart';
11 import 'package:cake_wallet/wownero/wownero.dart';
12 import 'package:hive/hive.dart';
13 import 'package:mobx/mobx.dart';
@@ -26,13 +27,13 @@ class WalletRestorationFromQRVM = WalletRestorationFromQRVMBase with _$WalletRes
27
28 abstract class WalletRestorationFromQRVMBase extends WalletCreationVM with Store {
29 WalletRestorationFromQRVMBase(AppStore appStore, WalletCreationService walletCreationService,
29 - Box<WalletInfo> walletInfoSource, WalletType type)
30 + Box<WalletInfo> walletInfoSource, WalletType type, SeedSettingsViewModel seedSettingsViewModel)
31 : height = 0,
32 viewKey = '',
33 spendKey = '',
34 wif = '',
35 address = '',
35 - super(appStore, walletInfoSource, walletCreationService, type: type, isRecovery: true);
36 + super(appStore, walletInfoSource, walletCreationService, seedSettingsViewModel, type: type, isRecovery: true);
37
38 @observable
39 int height;
lib/view_model/seed_settings_view_model.dart new
+34
@@ -0,0 +1,34 @@
1 +import 'package:cake_wallet/entities/seed_type.dart';
2 +import 'package:cake_wallet/store/app_store.dart';
3 +import 'package:cake_wallet/store/seed_settings_store.dart';
4 +import 'package:mobx/mobx.dart';
5 +
6 +part 'seed_settings_view_model.g.dart';
7 +
8 +class SeedSettingsViewModel = SeedSettingsViewModelBase with _$SeedSettingsViewModel;
9 +
10 +abstract class SeedSettingsViewModelBase with Store {
11 + SeedSettingsViewModelBase(this._appStore, this._seedSettingsStore);
12 +
13 + @computed
14 + MoneroSeedType get moneroSeedType => _appStore.settingsStore.moneroSeedType;
15 +
16 + @action
17 + void setMoneroSeedType(MoneroSeedType seedType) => _appStore.settingsStore.moneroSeedType = seedType;
18 +
19 + @computed
20 + BitcoinSeedType get bitcoinSeedType => _appStore.settingsStore.bitcoinSeedType;
21 +
22 + @action
23 + void setBitcoinSeedType(BitcoinSeedType derivationType) =>
24 + _appStore.settingsStore.bitcoinSeedType = derivationType;
25 +
26 + @computed
27 + String? get passphrase => this._seedSettingsStore.passphrase;
28 +
29 + @action
30 + void setPassphrase(String? passphrase) => this._seedSettingsStore.passphrase = passphrase;
31 +
32 + final AppStore _appStore;
33 + final SeedSettingsStore _seedSettingsStore;
34 +}
lib/view_model/seed_type_view_model.dart deleted
-19
@@ -1,19 +0,0 @@
1 -import 'package:cake_wallet/entities/seed_type.dart';
2 -import 'package:cake_wallet/store/app_store.dart';
3 -import 'package:mobx/mobx.dart';
4 -
5 -part 'seed_type_view_model.g.dart';
6 -
7 -class SeedTypeViewModel = SeedTypeViewModelBase with _$SeedTypeViewModel;
8 -
9 -abstract class SeedTypeViewModelBase with Store {
10 - SeedTypeViewModelBase(this._appStore);
11 -
12 - @computed
13 - SeedType get moneroSeedType => _appStore.settingsStore.moneroSeedType;
14 -
15 - @action
16 - void setMoneroSeedType(SeedType seedType) => _appStore.settingsStore.moneroSeedType = seedType;
17 -
18 - final AppStore _appStore;
19 -}
lib/view_model/wallet_creation_vm.dart
+31 -11
@@ -1,20 +1,21 @@
1 import 'package:cake_wallet/bitcoin/bitcoin.dart';
2 +import 'package:cake_wallet/core/execution_state.dart';
3 import 'package:cake_wallet/core/wallet_creation_service.dart';
3 -import 'package:cake_wallet/generated/i18n.dart';
4 -import 'package:cake_wallet/store/settings_store.dart';
4 import 'package:cake_wallet/di.dart';
5 import 'package:cake_wallet/entities/background_tasks.dart';
6 +import 'package:cake_wallet/entities/generate_name.dart';
7 +import 'package:cake_wallet/generated/i18n.dart';
8 +import 'package:cake_wallet/store/app_store.dart';
9 +import 'package:cake_wallet/store/settings_store.dart';
10 import 'package:cake_wallet/view_model/restore/restore_wallet.dart';
8 -import 'package:hive/hive.dart';
9 -import 'package:mobx/mobx.dart';
10 -import 'package:cake_wallet/core/execution_state.dart';
11 +import 'package:cake_wallet/view_model/seed_settings_view_model.dart';
12 +import 'package:cw_core/pathForWallet.dart';
13 import 'package:cw_core/wallet_base.dart';
14 import 'package:cw_core/wallet_credentials.dart';
13 -import 'package:cw_core/pathForWallet.dart';
15 import 'package:cw_core/wallet_info.dart';
16 import 'package:cw_core/wallet_type.dart';
16 -import 'package:cake_wallet/store/app_store.dart';
17 -import 'package:cake_wallet/entities/generate_name.dart';
17 +import 'package:hive/hive.dart';
18 +import 'package:mobx/mobx.dart';
19 import 'package:polyseed/polyseed.dart';
20
21 part 'wallet_creation_vm.g.dart';
@@ -23,6 +24,7 @@ class WalletCreationVM = WalletCreationVMBase with _$WalletCreationVM;
24
25 abstract class WalletCreationVMBase with Store {
26 WalletCreationVMBase(this._appStore, this._walletInfoSource, this.walletCreationService,
27 + this.seedSettingsViewModel,
28 {required this.type, required this.isRecovery})
29 : state = InitialExecutionState(),
30 name = '';
@@ -44,7 +46,6 @@ abstract class WalletCreationVMBase with Store {
46
47 @observable
48 String? repeatedWalletPassword;
47 -
49 bool get hasWalletPassword => SettingsStoreBase.walletPasswordDirectInput;
50
51 WalletType type;
@@ -52,6 +53,7 @@ abstract class WalletCreationVMBase with Store {
53 final WalletCreationService walletCreationService;
54 final Box<WalletInfo> _walletInfoSource;
55 final AppStore _appStore;
56 + final SeedSettingsViewModel seedSettingsViewModel;
57
58 bool isPolyseed(String seed) =>
59 (type == WalletType.monero || type == WalletType.wownero) &&
@@ -109,17 +111,35 @@ abstract class WalletCreationVMBase with Store {
111 getIt.get<BackgroundTasks>().registerSyncTask();
112 _appStore.authenticationStore.allowed();
113 state = ExecutedSuccessfullyState();
112 - } catch (e, s) {
114 + } catch (e, _) {
115 state = FailureState(e.toString());
116 }
117 }
118
119 DerivationInfo? getDefaultDerivation() {
118 - switch (this.type) {
120 + final useBip39 = seedSettingsViewModel.bitcoinSeedType.type == DerivationType.bip39;
121 + switch (type) {
122 case WalletType.nano:
123 return DerivationInfo(derivationType: DerivationType.nano);
124 case WalletType.bitcoin:
125 + if (useBip39) {
126 + return DerivationInfo(
127 + derivationType: DerivationType.bip39,
128 + derivationPath: "m/84'/0'/0'",
129 + description: "Standard BIP84 native segwit",
130 + scriptType: "p2wpkh",
131 + );
132 + }
133 + return bitcoin!.getElectrumDerivations()[DerivationType.electrum]!.first;
134 case WalletType.litecoin:
135 + if (useBip39) {
136 + return DerivationInfo(
137 + derivationType: DerivationType.bip39,
138 + derivationPath: "m/84'/2'/0'",
139 + description: "Default Litecoin",
140 + scriptType: "p2wpkh",
141 + );
142 + }
143 return bitcoin!.getElectrumDerivations()[DerivationType.electrum]!.first;
144 default:
145 return null;
lib/view_model/wallet_hardware_restore_view_model.dart
+9 -3
@@ -5,6 +5,7 @@ import 'package:cake_wallet/generated/i18n.dart';
5 import 'package:cake_wallet/polygon/polygon.dart';
6 import 'package:cake_wallet/store/app_store.dart';
7 import 'package:cake_wallet/view_model/hardware_wallet/ledger_view_model.dart';
8 +import 'package:cake_wallet/view_model/seed_settings_view_model.dart';
9 import 'package:cake_wallet/view_model/wallet_creation_vm.dart';
10 import 'package:cw_core/hardware/hardware_account_data.dart';
11 import 'package:cw_core/wallet_base.dart';
@@ -25,10 +26,15 @@ abstract class WalletHardwareRestoreViewModelBase extends WalletCreationVM with
26
27 int _nextIndex = 0;
28
28 - WalletHardwareRestoreViewModelBase(this.ledgerViewModel, AppStore appStore,
29 - WalletCreationService walletCreationService, Box<WalletInfo> walletInfoSource,
29 + WalletHardwareRestoreViewModelBase(
30 + this.ledgerViewModel,
31 + AppStore appStore,
32 + WalletCreationService walletCreationService,
33 + Box<WalletInfo> walletInfoSource,
34 + SeedSettingsViewModel seedSettingsViewModel,
35 {required WalletType type})
31 - : super(appStore, walletInfoSource, walletCreationService, type: type, isRecovery: true);
36 + : super(appStore, walletInfoSource, walletCreationService, seedSettingsViewModel,
37 + type: type, isRecovery: true);
38
39 @observable
40 String name = "";
lib/view_model/wallet_keys_view_model.dart
+2 -1
@@ -276,7 +276,8 @@ abstract class WalletKeysViewModelBase with Store {
276 if (_appStore.wallet!.seed == null &&
277 _appStore.wallet!.privateKey != null)
278 'private_key': _appStore.wallet!.privateKey!,
279 - if (restoreHeightResult != null) ...{'height': restoreHeightResult}
279 + if (restoreHeightResult != null) ...{'height': restoreHeightResult},
280 + if (_appStore.wallet!.passphrase != null) 'passphrase': _appStore.wallet!.passphrase!
281 };
282 }
283
lib/view_model/wallet_new_vm.dart
+42 -24
@@ -1,35 +1,42 @@
1 -import 'package:cake_wallet/ethereum/ethereum.dart';
1 +import 'package:cake_wallet/bitcoin/bitcoin.dart';
2 import 'package:cake_wallet/bitcoin_cash/bitcoin_cash.dart';
3 -import 'package:cake_wallet/solana/solana.dart';
4 -import 'package:cake_wallet/tron/tron.dart';
5 -import 'package:cake_wallet/wownero/wownero.dart';
6 -import 'package:hive/hive.dart';
7 -import 'package:mobx/mobx.dart';
3 +import 'package:cake_wallet/core/wallet_creation_service.dart';
4 +import 'package:cake_wallet/entities/seed_type.dart';
5 +import 'package:cake_wallet/ethereum/ethereum.dart';
6 +import 'package:cake_wallet/haven/haven.dart';
7 import 'package:cake_wallet/monero/monero.dart';
8 import 'package:cake_wallet/nano/nano.dart';
9 +import 'package:cake_wallet/solana/solana.dart';
10 import 'package:cake_wallet/store/app_store.dart';
11 +import 'package:cake_wallet/tron/tron.dart';
12 +import 'package:cake_wallet/view_model/seed_settings_view_model.dart';
13 +import 'package:cake_wallet/view_model/wallet_creation_vm.dart';
14 +import 'package:cake_wallet/wownero/wownero.dart';
15 import 'package:cw_core/wallet_base.dart';
12 -import 'package:cake_wallet/core/wallet_creation_service.dart';
16 import 'package:cw_core/wallet_credentials.dart';
17 import 'package:cw_core/wallet_info.dart';
18 import 'package:cw_core/wallet_type.dart';
16 -import 'package:cake_wallet/view_model/wallet_creation_vm.dart';
17 -import 'package:cake_wallet/bitcoin/bitcoin.dart';
18 -import 'package:cake_wallet/haven/haven.dart';
19 -import 'advanced_privacy_settings_view_model.dart';
19 +import 'package:hive/hive.dart';
20 +import 'package:mobx/mobx.dart';
21
22 import '../polygon/polygon.dart';
23 +import 'advanced_privacy_settings_view_model.dart';
24
25 part 'wallet_new_vm.g.dart';
26
27 class WalletNewVM = WalletNewVMBase with _$WalletNewVM;
28
29 abstract class WalletNewVMBase extends WalletCreationVM with Store {
28 - WalletNewVMBase(AppStore appStore, WalletCreationService walletCreationService,
29 - Box<WalletInfo> walletInfoSource, this.advancedPrivacySettingsViewModel,
30 + WalletNewVMBase(
31 + AppStore appStore,
32 + WalletCreationService walletCreationService,
33 + Box<WalletInfo> walletInfoSource,
34 + this.advancedPrivacySettingsViewModel,
35 + SeedSettingsViewModel seedSettingsViewModel,
36 {required WalletType type})
37 : selectedMnemonicLanguage = '',
32 - super(appStore, walletInfoSource, walletCreationService, type: type, isRecovery: false);
38 + super(appStore, walletInfoSource, walletCreationService, seedSettingsViewModel,
39 + type: type, isRecovery: false);
40
41 final AdvancedPrivacySettingsViewModel advancedPrivacySettingsViewModel;
42
@@ -37,47 +44,58 @@ abstract class WalletNewVMBase extends WalletCreationVM with Store {
44 String selectedMnemonicLanguage;
45
46 bool get hasLanguageSelector =>
40 - type == WalletType.monero || type == WalletType.haven || type == WalletType.wownero;
47 + [WalletType.monero, WalletType.haven, WalletType.wownero].contains(type);
48
49 int get seedPhraseWordsLength {
50 switch (type) {
51 case WalletType.monero:
52 case WalletType.wownero:
46 - if (advancedPrivacySettingsViewModel.isPolySeed) {
47 - return 16;
48 - }
49 - return 25;
53 + return advancedPrivacySettingsViewModel.isPolySeed ? 16 : 25;
54 case WalletType.tron:
55 case WalletType.solana:
56 case WalletType.polygon:
57 case WalletType.ethereum:
58 case WalletType.bitcoinCash:
59 return advancedPrivacySettingsViewModel.seedPhraseLength.value;
60 + case WalletType.bitcoin:
61 + case WalletType.litecoin:
62 + return seedSettingsViewModel.bitcoinSeedType == BitcoinSeedType.bip39
63 + ? advancedPrivacySettingsViewModel.seedPhraseLength.value
64 + : 24;
65 default:
66 return 24;
67 }
68 }
69
61 - bool get hasSeedType => type == WalletType.monero || type == WalletType.wownero;
70 + bool get hasSeedType => [WalletType.monero, WalletType.wownero].contains(type);
71
72 @override
73 WalletCredentials getCredentials(dynamic _options) {
74 final options = _options as List<dynamic>?;
75 + final passphrase = seedSettingsViewModel.passphrase;
76 + seedSettingsViewModel.setPassphrase(null);
77 +
78 switch (type) {
79 case WalletType.monero:
80 return monero!.createMoneroNewWalletCredentials(
69 - name: name, language: options!.first as String, password: walletPassword, isPolyseed: options.last as bool);
81 + name: name,
82 + language: options!.first as String,
83 + password: walletPassword,
84 + isPolyseed: options.last as bool);
85 case WalletType.bitcoin:
71 - return bitcoin!.createBitcoinNewWalletCredentials(name: name, password: walletPassword);
86 + return bitcoin!.createBitcoinNewWalletCredentials(
87 + name: name, password: walletPassword, passphrase: passphrase);
88 case WalletType.litecoin:
73 - return bitcoin!.createBitcoinNewWalletCredentials(name: name, password: walletPassword);
89 + return bitcoin!.createBitcoinNewWalletCredentials(
90 + name: name, password: walletPassword, passphrase: passphrase);
91 case WalletType.haven:
92 return haven!.createHavenNewWalletCredentials(
93 name: name, language: options!.first as String, password: walletPassword);
94 case WalletType.ethereum:
95 return ethereum!.createEthereumNewWalletCredentials(name: name, password: walletPassword);
96 case WalletType.bitcoinCash:
80 - return bitcoinCash!.createBitcoinCashNewWalletCredentials(name: name, password: walletPassword);
97 + return bitcoinCash!.createBitcoinCashNewWalletCredentials(
98 + name: name, password: walletPassword, passphrase: passphrase);
99 case WalletType.nano:
100 case WalletType.banano:
101 return nano!.createNanoNewWalletCredentials(name: name);
lib/view_model/wallet_restore_view_model.dart
+18 -16
@@ -1,25 +1,26 @@
1 import 'package:cake_wallet/bitcoin/bitcoin.dart';
2 +import 'package:cake_wallet/bitcoin_cash/bitcoin_cash.dart';
3 +import 'package:cake_wallet/core/generate_wallet_password.dart';
4 +import 'package:cake_wallet/core/wallet_creation_service.dart';
5 import 'package:cake_wallet/di.dart';
3 -import 'package:cake_wallet/nano/nano.dart';
6 import 'package:cake_wallet/ethereum/ethereum.dart';
5 -import 'package:cake_wallet/wownero/wownero.dart';
6 -import 'package:cake_wallet/bitcoin_cash/bitcoin_cash.dart';
7 +import 'package:cake_wallet/haven/haven.dart';
8 +import 'package:cake_wallet/monero/monero.dart';
9 +import 'package:cake_wallet/nano/nano.dart';
10 import 'package:cake_wallet/polygon/polygon.dart';
11 import 'package:cake_wallet/solana/solana.dart';
9 -import 'package:cake_wallet/tron/tron.dart';
10 -import 'package:hive/hive.dart';
11 -import 'package:mobx/mobx.dart';
12 import 'package:cake_wallet/store/app_store.dart';
13 +import 'package:cake_wallet/tron/tron.dart';
14 +import 'package:cake_wallet/view_model/restore/restore_mode.dart';
15 +import 'package:cake_wallet/view_model/seed_settings_view_model.dart';
16 +import 'package:cake_wallet/view_model/wallet_creation_vm.dart';
17 +import 'package:cake_wallet/wownero/wownero.dart';
18 import 'package:cw_core/wallet_base.dart';
14 -import 'package:cake_wallet/core/generate_wallet_password.dart';
15 -import 'package:cake_wallet/core/wallet_creation_service.dart';
19 import 'package:cw_core/wallet_credentials.dart';
17 -import 'package:cw_core/wallet_type.dart';
20 import 'package:cw_core/wallet_info.dart';
19 -import 'package:cake_wallet/view_model/wallet_creation_vm.dart';
20 -import 'package:cake_wallet/monero/monero.dart';
21 -import 'package:cake_wallet/haven/haven.dart';
22 -import 'package:cake_wallet/view_model/restore/restore_mode.dart';
21 +import 'package:cw_core/wallet_type.dart';
22 +import 'package:hive/hive.dart';
23 +import 'package:mobx/mobx.dart';
24
25 part 'wallet_restore_view_model.g.dart';
26
@@ -27,7 +28,7 @@ class WalletRestoreViewModel = WalletRestoreViewModelBase with _$WalletRestoreVi
28
29 abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store {
30 WalletRestoreViewModelBase(AppStore appStore, WalletCreationService walletCreationService,
30 - Box<WalletInfo> walletInfoSource,
31 + Box<WalletInfo> walletInfoSource, SeedSettingsViewModel seedSettingsViewModel,
32 {required WalletType type})
33 : hasSeedLanguageSelector =
34 type == WalletType.monero || type == WalletType.haven || type == WalletType.wownero,
@@ -41,7 +42,7 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store {
42 type == WalletType.tron,
43 isButtonEnabled = false,
44 mode = WalletRestoreMode.seed,
44 - super(appStore, walletInfoSource, walletCreationService, type: type, isRecovery: true) {
45 + super(appStore, walletInfoSource, walletCreationService, seedSettingsViewModel, type: type, isRecovery: true) {
46 switch (type) {
47 case WalletType.monero:
48 availableModes = WalletRestoreMode.values;
@@ -76,7 +77,8 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store {
77 final bool hasBlockchainHeightLanguageSelector;
78 final bool hasRestoreFromPrivateKey;
79
79 - bool get hasPassphrase => [WalletType.bitcoin, WalletType.litecoin].contains(type);
80 + bool get hasPassphrase =>
81 + [WalletType.bitcoin, WalletType.litecoin, WalletType.bitcoinCash].contains(type);
82
83 @observable
84 WalletRestoreMode mode;
res/values/strings_ar.arb
+1
@@ -195,6 +195,7 @@
195 "delete_wallet_confirm_message": "هل أنت متأكد أنك تريد حذف محفظة ${wallet_name}؟",
196 "deleteConnectionConfirmationPrompt": "ـﺑ ﻝﺎﺼﺗﻻﺍ ﻑﺬﺣ ﺪﻳﺮﺗ ﻚﻧﺃ ﺪﻛﺄﺘﻣ ﺖﻧﺃ ﻞﻫ",
197 "denominations": "الطوائف",
198 + "derivationpath": "مسار الاشتقاق",
199 "descending": "النزول",
200 "description": "ﻒﺻﻭ",
201 "destination_tag": "علامة الوجهة:",
res/values/strings_bg.arb
+1
@@ -195,6 +195,7 @@
195 "delete_wallet_confirm_message": "Сигурни ли сте, че искате да изтриете протфейла ${wallet_name}?",
196 "deleteConnectionConfirmationPrompt": "Сигурни ли сте, че искате да изтриете връзката към",
197 "denominations": "Деноминации",
198 + "derivationpath": "Пътят на производно",
199 "descending": "Низходящ",
200 "description": "Описание",
201 "destination_tag": "Destination tag:",
res/values/strings_cs.arb
+1
@@ -195,6 +195,7 @@
195 "delete_wallet_confirm_message": "Opravdu chcete smazat ${wallet_name} peněženku?",
196 "deleteConnectionConfirmationPrompt": "Jste si jisti, že chcete smazat připojení k?",
197 "denominations": "Označení",
198 + "derivationpath": "Derivační cesta",
199 "descending": "Klesající",
200 "description": "Popis",
201 "destination_tag": "Destination Tag:",
res/values/strings_de.arb
+1
@@ -195,6 +195,7 @@
195 "delete_wallet_confirm_message": "Sind Sie sicher, dass Sie das ${wallet_name} Wallet löschen möchten?",
196 "deleteConnectionConfirmationPrompt": "Sind Sie sicher, dass Sie die Verbindung zu löschen möchten?",
197 "denominations": "Konfessionen",
198 + "derivationpath": "Ableitungspfad",
199 "descending": "Absteigend",
200 "description": "Beschreibung",
201 "destination_tag": "Ziel-Tag:",
res/values/strings_en.arb
+1
@@ -195,6 +195,7 @@
195 "delete_wallet_confirm_message": "Are you sure that you want to delete ${wallet_name} wallet?",
196 "deleteConnectionConfirmationPrompt": "Are you sure that you want to delete the connection to",
197 "denominations": "Denominations",
198 + "derivationpath": "Derivation Path",
199 "descending": "Descending",
200 "description": "Description",
201 "destination_tag": "Destination tag:",
res/values/strings_es.arb
+1
@@ -195,6 +195,7 @@
195 "delete_wallet_confirm_message": "¿Está seguro de que desea eliminar la billetera ${wallet_name}?",
196 "deleteConnectionConfirmationPrompt": "¿Está seguro de que desea eliminar la conexión a",
197 "denominations": "Denominaciones",
198 + "derivationpath": "Ruta de derivación",
199 "descending": "Descendente",
200 "description": "Descripción",
201 "destination_tag": "Etiqueta de destino:",
res/values/strings_fr.arb
+1
@@ -195,6 +195,7 @@
195 "delete_wallet_confirm_message": "Êtes-vous sûr de vouloir supprimer le portefeuille (wallet) ${wallet_name}?",
196 "deleteConnectionConfirmationPrompt": "Êtes-vous sûr de vouloir supprimer la connexion à",
197 "denominations": "Dénominations",
198 + "derivationpath": "Chemin de dérivation",
199 "descending": "Descendant",
200 "description": "Description",
201 "destination_tag": "Tag de destination :",
res/values/strings_ha.arb
+1
@@ -195,6 +195,7 @@
195 "delete_wallet_confirm_message": "Shin kun tabbata cewa kuna son share jakar ${wallet_name}?",
196 "deleteConnectionConfirmationPrompt": "Shin kun tabbata cewa kuna son share haɗin zuwa",
197 "denominations": "Denominations",
198 + "derivationpath": "Hanyar Nasara",
199 "descending": "Saukowa",
200 "description": "Bayani",
201 "destination_tag": "Tambarin makoma:",
res/values/strings_hi.arb
+1
@@ -195,6 +195,7 @@
195 "delete_wallet_confirm_message": "क्या आप वाकई ${wallet_name} वॉलेट हटाना चाहते हैं?",
196 "deleteConnectionConfirmationPrompt": "क्या आप वाकई कनेक्शन हटाना चाहते हैं?",
197 "denominations": "मूल्यवर्ग",
198 + "derivationpath": "व्युत्पत्ति पथ",
199 "descending": "अवरोही",
200 "description": "विवरण",
201 "destination_tag": "गंतव्य टैग:",
res/values/strings_hr.arb
+1
@@ -195,6 +195,7 @@
195 "delete_wallet_confirm_message": "Jeste li sigurni da želite izbrisati ${wallet_name} novčanik?",
196 "deleteConnectionConfirmationPrompt": "Jeste li sigurni da želite izbrisati vezu s",
197 "denominations": "Denominacije",
198 + "derivationpath": "Put derivacije",
199 "descending": "Silazni",
200 "description": "Opis",
201 "destination_tag": "Odredišna oznaka:",
res/values/strings_id.arb
+1
@@ -195,6 +195,7 @@
195 "delete_wallet_confirm_message": "Apakah Anda yakin ingin menghapus dompet ${wallet_name}?",
196 "deleteConnectionConfirmationPrompt": "Apakah Anda yakin ingin menghapus koneksi ke",
197 "denominations": "Denominasi",
198 + "derivationpath": "Jalur derivasi",
199 "descending": "Menurun",
200 "description": "Keterangan",
201 "destination_tag": "Tag tujuan:",
res/values/strings_it.arb
+1
@@ -196,6 +196,7 @@
196 "delete_wallet_confirm_message": "Sei sicuro di voler eliminare il portafoglio ${wallet_name}?",
197 "deleteConnectionConfirmationPrompt": "Sei sicuro di voler eliminare la connessione a",
198 "denominations": "Denominazioni",
199 + "derivationpath": "Percorso di derivazione",
200 "descending": "Discendente",
201 "description": "Descrizione",
202 "destination_tag": "Tag destinazione:",
res/values/strings_ja.arb
+1
@@ -195,6 +195,7 @@
195 "delete_wallet_confirm_message": "${wallet_name} ウォレットを削除してもよろしいですか?",
196 "deleteConnectionConfirmationPrompt": "への接続を削除してもよろしいですか?",
197 "denominations": "宗派",
198 + "derivationpath": "派生パス",
199 "descending": "下降",
200 "description": "説明",
201 "destination_tag": "宛先タグ:",
res/values/strings_ko.arb
+1
@@ -195,6 +195,7 @@
195 "delete_wallet_confirm_message": "${wallet_name} 지갑을 삭제하시겠습니까?",
196 "deleteConnectionConfirmationPrompt": "다음 연결을 삭제하시겠습니까?",
197 "denominations": "교파",
198 + "derivationpath": "파생 경로",
199 "descending": "내림차순",
200 "description": "설명",
201 "destination_tag": "목적지 태그:",
res/values/strings_my.arb
+1
@@ -195,6 +195,7 @@
195 "delete_wallet_confirm_message": "${wallet_name} ပိုက်ဆံအိတ်ကို ဖျက်လိုသည်မှာ သေချာပါသလား။",
196 "deleteConnectionConfirmationPrompt": "ချိတ်ဆက်မှုကို ဖျက်လိုသည်မှာ သေချာပါသလား။",
197 "denominations": "ဂိုဏ်းချုပ်ပစ္စည်းများ",
198 + "derivationpath": "derivation လမ်းကြောင်း",
199 "descending": "ဆင်း",
200 "description": "ဖော်ပြချက်",
201 "destination_tag": "ခရီးဆုံးအမှတ်-",
res/values/strings_nl.arb
+1
@@ -195,6 +195,7 @@
195 "delete_wallet_confirm_message": "Weet u zeker dat u de portemonnee van ${wallet_name} wilt verwijderen?",
196 "deleteConnectionConfirmationPrompt": "Weet u zeker dat u de verbinding met",
197 "denominations": "Denominaties",
198 + "derivationpath": "Afleidingspad",
199 "descending": "Aflopend",
200 "description": "Beschrijving",
201 "destination_tag": "Bestemmingstag:",
res/values/strings_pl.arb
+1
@@ -195,6 +195,7 @@
195 "delete_wallet_confirm_message": "Czy na pewno chcesz usunąć portfel ${wallet_name}?",
196 "deleteConnectionConfirmationPrompt": "Czy na pewno chcesz usunąć połączenie z",
197 "denominations": "Wyznaczenia",
198 + "derivationpath": "Ścieżka pochodna",
199 "descending": "Schodzenie",
200 "description": "Opis",
201 "destination_tag": "Tag docelowy:",
res/values/strings_pt.arb
+1
@@ -195,6 +195,7 @@
195 "delete_wallet_confirm_message": "Tem certeza de que deseja excluir a carteira ${wallet_name}?",
196 "deleteConnectionConfirmationPrompt": "Tem certeza de que deseja excluir a conexão com",
197 "denominations": "Denominações",
198 + "derivationpath": "Caminho de derivação",
199 "descending": "descendente",
200 "description": "Descrição",
201 "destination_tag": "Tag de destino:",
res/values/strings_ru.arb
+1
@@ -195,6 +195,7 @@
195 "delete_wallet_confirm_message": "Вы уверены, что хотите удалить кошелек ${wallet_name}?",
196 "deleteConnectionConfirmationPrompt": "Вы уверены, что хотите удалить подключение к",
197 "denominations": "Деноминации",
198 + "derivationpath": "Путь получения",
199 "descending": "Нисходящий",
200 "description": "Описание",
201 "destination_tag": "Целевой тег:",
res/values/strings_th.arb
+1
@@ -195,6 +195,7 @@
195 "delete_wallet_confirm_message": "คุณแน่ใจหรือว่าต้องการลบกระเป๋า${wallet_name}?",
196 "deleteConnectionConfirmationPrompt": "คุณแน่ใจหรือไม่ว่าต้องการลบการเชื่อมต่อไปยัง",
197 "denominations": "นิกาย",
198 + "derivationpath": "เส้นทางที่ได้มา",
199 "descending": "ลงมา",
200 "description": "คำอธิบาย",
201 "destination_tag": "แท็กปลายทาง:",
res/values/strings_tl.arb
+4 -3
@@ -195,6 +195,7 @@
195 "delete_wallet_confirm_message": "Sigurado ka ba na gusto mong tanggalin ang iyong ${wallet_name} wallet?",
196 "deleteConnectionConfirmationPrompt": "Sigurado ka bang gusto mong tanggalin ang koneksyon sa",
197 "denominations": "Mga Denominasyon",
198 + "derivationpath": "Landas ng derivation",
199 "descending": "Pababang",
200 "description": "Paglalarawan",
201 "destination_tag": "Tag ng patutunguhan:",
@@ -661,14 +662,14 @@
662 "show_details": "Ipakita ang mga detalye",
663 "show_keys": "Ipakita ang mga seed/key",
664 "show_market_place": "Ipakita ang Marketplace",
665 + "show_seed": "Ipakita ang seed",
666 "sign_message": "Mag -sign Message",
667 + "sign_up": "Mag-sign Up",
668 "sign_verify_message": "Mag -sign o i -verify ang mensahe",
669 "sign_verify_message_sub": "Mag -sign o i -verify ang isang mensahe gamit ang iyong pribadong key",
670 "sign_verify_title": "Mag -sign / Mag -verify",
671 "signature": "Lagda",
672 "signature_invalid_error": "Ang lagda ay hindi wasto para sa ibinigay na mensahe",
670 - "show_seed": "Ipakita ang seed",
671 - "sign_up": "Mag-sign Up",
673 "signTransaction": "Mag-sign ang Transaksyon",
674 "signup_for_card_accept_terms": "Mag-sign up para sa card at tanggapin ang mga tuntunin.",
675 "silent_payments": "Tahimik na pagbabayad",
@@ -827,9 +828,9 @@
828 "use_testnet": "Gumamit ng testnet",
829 "value": "Halaga",
830 "value_type": "Uri ng halaga",
830 - "verify_message": "I -verify ang mensahe",
831 "variable_pair_not_supported": "Ang variable na pares na ito ay hindi suportado sa mga napiling exchange",
832 "verification": "Pag-verify",
833 + "verify_message": "I -verify ang mensahe",
834 "verify_with_2fa": "Mag-verify sa Cake 2FA",
835 "version": "Bersyon ${currentVersion}",
836 "view_all": "Tingnan lahat",
res/values/strings_tr.arb
+1
@@ -195,6 +195,7 @@
195 "delete_wallet_confirm_message": "${wallet_name} isimli cüzdanını silmek istediğinden emin misin?",
196 "deleteConnectionConfirmationPrompt": "Bağlantıyı silmek istediğinizden emin misiniz?",
197 "denominations": "Mezhepler",
198 + "derivationpath": "Türev yolu",
199 "descending": "Azalan",
200 "description": "Tanım",
201 "destination_tag": "Hedef Etiketi:",
res/values/strings_uk.arb
+1
@@ -195,6 +195,7 @@
195 "delete_wallet_confirm_message": "Ви впевнені, що хочете видалити гаманець ${wallet_name}?",
196 "deleteConnectionConfirmationPrompt": "Ви впевнені, що хочете видалити з’єднання з",
197 "denominations": "Конфесія",
198 + "derivationpath": "Шлях виведення",
199 "descending": "Низхідний",
200 "description": "опис",
201 "destination_tag": "Тег призначення:",
res/values/strings_ur.arb
+1
@@ -195,6 +195,7 @@
195 "delete_wallet_confirm_message": "کیا آپ واقعی ${wallet_name} والیٹ کو حذف کرنا چاہتے ہیں؟",
196 "deleteConnectionConfirmationPrompt": "۔ﮟﯿﮨ ﮯﺘﮨﺎﭼ ﺎﻧﺮﮐ ﻑﺬﺣ ﻮﮐ ﻦﺸﮑﻨﮐ ﭖﺁ ﮧﮐ ﮯﮨ ﻦﯿﻘﯾ ﻮﮐ ﭖﺁ ﺎﯿﮐ",
197 "denominations": "فرق",
198 + "derivationpath": "مشتق راستہ",
199 "descending": "اترتے ہوئے",
200 "description": "ﻞﯿﺼﻔﺗ",
201 "destination_tag": "منزل کا ٹیگ:",
res/values/strings_yo.arb
+1
@@ -195,6 +195,7 @@
195 "delete_wallet_confirm_message": "Ṣó dá ẹ lójú pé ẹ fẹ́ pa àpamọ́wọ́ ${wallet_name}?",
196 "deleteConnectionConfirmationPrompt": "Ṣe o da ọ loju pe o fẹ paarẹ asopọ si",
197 "denominations": "Awọn ede",
198 + "derivationpath": "Ọna Deriji",
199 "descending": "Sọkalẹ",
200 "description": "Apejuwe",
201 "destination_tag": "Orúkọ tí ìbí tó a ránṣẹ́ sí:",
res/values/strings_zh.arb
+1
@@ -195,6 +195,7 @@
195 "delete_wallet_confirm_message": "您确定要删除 ${wallet_name} 钱包吗?",
196 "deleteConnectionConfirmationPrompt": "您确定要删除与",
197 "denominations": "教派",
198 + "derivationpath": "推导路径",
199 "descending": "下降",
200 "description": "描述",
201 "destination_tag": "目标Tag:",
tool/configure.dart
+3 -3
@@ -151,7 +151,7 @@ abstract class Bitcoin {
151 String? passphrase,
152 });
153 WalletCredentials createBitcoinRestoreWalletFromWIFCredentials({required String name, required String password, required String wif, WalletInfo? walletInfo});
154 - WalletCredentials createBitcoinNewWalletCredentials({required String name, WalletInfo? walletInfo, String? password});
154 + WalletCredentials createBitcoinNewWalletCredentials({required String name, WalletInfo? walletInfo, String? password, String? passphrase});
155 WalletCredentials createBitcoinHardwareWalletCredentials({required String name, required HardwareAccountData accountData, WalletInfo? walletInfo});
156 List<String> getWordList();
157 Map<String, String> getWalletKeys(Object wallet);
@@ -1021,10 +1021,10 @@ abstract class BitcoinCash {
1021 Box<WalletInfo> walletInfoSource, Box<UnspentCoinsInfo> unspentCoinSource, bool isDirect);
1022
1023 WalletCredentials createBitcoinCashNewWalletCredentials(
1024 - {required String name, WalletInfo? walletInfo, String? password});
1024 + {required String name, WalletInfo? walletInfo, String? password, String? passphrase});
1025
1026 WalletCredentials createBitcoinCashRestoreWalletFromSeedCredentials(
1027 - {required String name, required String mnemonic, required String password});
1027 + {required String name, required String mnemonic, required String password, String? passphrase});
1028
1029 TransactionPriority deserializeBitcoinCashTransactionPriority(int raw);
1030