From f52c45b167e05f782040d3ae9a30d7283800fd29 Mon Sep 17 00:00:00 2001 From: M Date: Mon, 10 Apr 2023 19:16:13 -0400 Subject: [PATCH] Change encryption method for electrum wallets is wallet password provides directly. Add ability to user for repeat wallets password and compare with original wallet password before wallet creation for cases when wallet password provides directly. --- cw_bitcoin/lib/bitcoin_wallet.dart | 11 ++++- cw_bitcoin/lib/bitcoin_wallet_service.dart | 13 ++++-- .../lib/electrum_transaction_history.dart | 10 ++--- cw_bitcoin/lib/electrum_wallet.dart | 11 +++-- cw_bitcoin/lib/electrum_wallet_snapshot.dart | 6 +-- cw_bitcoin/lib/encryption_file_utils.dart | 42 +++++++++++++++++++ cw_bitcoin/lib/file.dart | 1 + cw_bitcoin/lib/litecoin_wallet.dart | 9 +++- cw_bitcoin/lib/litecoin_wallet_service.dart | 13 ++++-- cw_bitcoin/pubspec.lock | 25 +++++++++++ cw_bitcoin/pubspec.yaml | 5 +++ lib/bitcoin/cw_bitcoin.dart | 8 ++-- lib/di.dart | 6 ++- .../screens/new_wallet/new_wallet_page.dart | 38 ++++++++++++++++- .../wallet_restore_from_keys_form.dart | 24 ++++++++++- .../wallet_restore_from_seed_form.dart | 24 +++++++++-- .../screens/restore/wallet_restore_page.dart | 6 ++- lib/view_model/wallet_creation_vm.dart | 13 +++++- res/values/strings_ar.arb | 3 ++ res/values/strings_de.arb | 3 ++ res/values/strings_en.arb | 3 ++ res/values/strings_es.arb | 3 ++ res/values/strings_fr.arb | 3 ++ res/values/strings_hi.arb | 3 ++ res/values/strings_hr.arb | 3 ++ res/values/strings_it.arb | 3 ++ res/values/strings_ja.arb | 3 ++ res/values/strings_ko.arb | 3 ++ res/values/strings_my.arb | 3 ++ res/values/strings_nl.arb | 3 ++ res/values/strings_pl.arb | 3 ++ res/values/strings_pt.arb | 3 ++ res/values/strings_ru.arb | 3 ++ res/values/strings_th.arb | 3 ++ res/values/strings_tr.arb | 3 ++ res/values/strings_uk.arb | 3 ++ res/values/strings_zh.arb | 3 ++ tool/configure.dart | 4 +- 38 files changed, 287 insertions(+), 39 deletions(-) create mode 100644 cw_bitcoin/lib/encryption_file_utils.dart diff --git a/cw_bitcoin/lib/bitcoin_wallet.dart b/cw_bitcoin/lib/bitcoin_wallet.dart index c4675df1c..3e4601eb3 100644 --- a/cw_bitcoin/lib/bitcoin_wallet.dart +++ b/cw_bitcoin/lib/bitcoin_wallet.dart @@ -1,4 +1,5 @@ import 'package:cw_bitcoin/bitcoin_mnemonic.dart'; +import 'package:cw_bitcoin/encryption_file_utils.dart'; import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/unspent_coins_info.dart'; import 'package:hive/hive.dart'; @@ -23,6 +24,7 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store { required WalletInfo walletInfo, required Box unspentCoinsInfo, required Uint8List seedBytes, + required EncryptionFileUtils encryptionFileUtils, List? initialAddresses, ElectrumBalance? initialBalance, int initialRegularAddressIndex = 0, @@ -36,7 +38,8 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store { initialAddresses: initialAddresses, initialBalance: initialBalance, seedBytes: seedBytes, - currency: CryptoCurrency.btc) { + currency: CryptoCurrency.btc, + encryptionFileUtils: encryptionFileUtils) { walletAddresses = BitcoinWalletAddresses( walletInfo, electrumClient: electrumClient, @@ -54,6 +57,7 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store { required String password, required WalletInfo walletInfo, required Box unspentCoinsInfo, + required EncryptionFileUtils encryptionFileUtils, List? initialAddresses, ElectrumBalance? initialBalance, int initialRegularAddressIndex = 0, @@ -66,6 +70,7 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store { unspentCoinsInfo: unspentCoinsInfo, initialAddresses: initialAddresses, initialBalance: initialBalance, + encryptionFileUtils: encryptionFileUtils, seedBytes: await mnemonicToSeedBytes(mnemonic), initialRegularAddressIndex: initialRegularAddressIndex, initialChangeAddressIndex: initialChangeAddressIndex); @@ -76,8 +81,9 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store { required WalletInfo walletInfo, required Box unspentCoinsInfo, required String password, + required EncryptionFileUtils encryptionFileUtils }) async { - final snp = await ElectrumWallletSnapshot.load(name, walletInfo.type, password); + final snp = await ElectrumWallletSnapshot.load(encryptionFileUtils, name, walletInfo.type, password); return BitcoinWallet( mnemonic: snp.mnemonic, password: password, @@ -86,6 +92,7 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store { initialAddresses: snp.addresses, initialBalance: snp.balance, seedBytes: await mnemonicToSeedBytes(snp.mnemonic), + encryptionFileUtils: encryptionFileUtils, initialRegularAddressIndex: snp.regularAddressIndex, initialChangeAddressIndex: snp.changeAddressIndex); } diff --git a/cw_bitcoin/lib/bitcoin_wallet_service.dart b/cw_bitcoin/lib/bitcoin_wallet_service.dart index 398d68fc2..d9481b0b5 100644 --- a/cw_bitcoin/lib/bitcoin_wallet_service.dart +++ b/cw_bitcoin/lib/bitcoin_wallet_service.dart @@ -2,6 +2,7 @@ import 'dart:io'; import 'package:cw_bitcoin/bitcoin_mnemonic.dart'; import 'package:cw_bitcoin/bitcoin_mnemonic_is_incorrect_exception.dart'; import 'package:cw_bitcoin/bitcoin_wallet_creation_credentials.dart'; +import 'package:cw_bitcoin/encryption_file_utils.dart'; import 'package:cw_core/unspent_coins_info.dart'; import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/wallet_service.dart'; @@ -16,10 +17,11 @@ class BitcoinWalletService extends WalletService< BitcoinNewWalletCredentials, BitcoinRestoreWalletFromSeedCredentials, BitcoinRestoreWalletFromWIFCredentials> { - BitcoinWalletService(this.walletInfoSource, this.unspentCoinsInfoSource); + BitcoinWalletService(this.walletInfoSource, this.unspentCoinsInfoSource, this.isDirect); final Box walletInfoSource; final Box unspentCoinsInfoSource; + final bool isDirect; @override WalletType getType() => WalletType.bitcoin; @@ -30,7 +32,8 @@ class BitcoinWalletService extends WalletService< mnemonic: await generateMnemonic(), password: credentials.password!, walletInfo: credentials.walletInfo!, - unspentCoinsInfo: unspentCoinsInfoSource); + unspentCoinsInfo: unspentCoinsInfoSource, + encryptionFileUtils: encryptionFileUtilsFor(isDirect)); await wallet.save(); await wallet.init(); return wallet; @@ -46,7 +49,8 @@ class BitcoinWalletService extends WalletService< (info) => info.id == WalletBase.idFor(name, getType()))!; final wallet = await BitcoinWalletBase.open( password: password, name: name, walletInfo: walletInfo, - unspentCoinsInfo: unspentCoinsInfoSource); + unspentCoinsInfo: unspentCoinsInfoSource, + encryptionFileUtils: encryptionFileUtilsFor(isDirect)); await wallet.init(); return wallet; } @@ -72,7 +76,8 @@ class BitcoinWalletService extends WalletService< password: credentials.password!, mnemonic: credentials.mnemonic, walletInfo: credentials.walletInfo!, - unspentCoinsInfo: unspentCoinsInfoSource); + unspentCoinsInfo: unspentCoinsInfoSource, + encryptionFileUtils: encryptionFileUtilsFor(isDirect)); await wallet.save(); await wallet.init(); return wallet; diff --git a/cw_bitcoin/lib/electrum_transaction_history.dart b/cw_bitcoin/lib/electrum_transaction_history.dart index 9174fb3f8..b8b7ad5ee 100644 --- a/cw_bitcoin/lib/electrum_transaction_history.dart +++ b/cw_bitcoin/lib/electrum_transaction_history.dart @@ -1,10 +1,9 @@ import 'dart:convert'; +import 'package:cw_bitcoin/encryption_file_utils.dart'; import 'package:cw_core/pathForWallet.dart'; import 'package:cw_core/wallet_info.dart'; -import 'package:flutter/foundation.dart'; import 'package:mobx/mobx.dart'; import 'package:cw_core/transaction_history.dart'; -import 'package:cw_bitcoin/file.dart'; import 'package:cw_bitcoin/electrum_transaction_info.dart'; part 'electrum_transaction_history.g.dart'; @@ -17,13 +16,14 @@ class ElectrumTransactionHistory = ElectrumTransactionHistoryBase abstract class ElectrumTransactionHistoryBase extends TransactionHistoryBase with Store { ElectrumTransactionHistoryBase( - {required this.walletInfo, required String password}) + {required this.walletInfo, required String password, required this.encryptionFileUtils}) : _password = password, _height = 0 { transactions = ObservableMap(); } final WalletInfo walletInfo; + final EncryptionFileUtils encryptionFileUtils; String _password; int _height; @@ -45,7 +45,7 @@ abstract class ElectrumTransactionHistoryBase final path = '$dirPath/$_transactionsHistoryFileName'; final data = json.encode({'height': _height, 'transactions': transactions}); - await writeData(path: path, password: _password, data: data); + await encryptionFileUtils.write(path: path, password: _password, data: data); } catch (e) { print('Error while save bitcoin transaction history: ${e.toString()}'); } @@ -60,7 +60,7 @@ abstract class ElectrumTransactionHistoryBase final dirPath = await pathForWalletDir(name: walletInfo.name, type: walletInfo.type); final path = '$dirPath/$_transactionsHistoryFileName'; - final content = await read(path: path, password: _password); + final content = await encryptionFileUtils.read(path: path, password: _password); return json.decode(content) as Map; } diff --git a/cw_bitcoin/lib/electrum_wallet.dart b/cw_bitcoin/lib/electrum_wallet.dart index a36654dbb..460bc5542 100644 --- a/cw_bitcoin/lib/electrum_wallet.dart +++ b/cw_bitcoin/lib/electrum_wallet.dart @@ -2,6 +2,7 @@ import 'dart:async'; import 'dart:convert'; import 'dart:math'; import 'dart:typed_data'; +import 'package:cw_bitcoin/encryption_file_utils.dart'; import 'package:cw_core/unspent_coins_info.dart'; import 'package:hive/hive.dart'; import 'package:cw_bitcoin/electrum_wallet_addresses.dart'; @@ -22,7 +23,6 @@ import 'package:cw_bitcoin/bitcoin_transaction_priority.dart'; import 'package:cw_bitcoin/bitcoin_transaction_wrong_balance_exception.dart'; import 'package:cw_bitcoin/bitcoin_unspent.dart'; import 'package:cw_bitcoin/bitcoin_wallet_keys.dart'; -import 'package:cw_bitcoin/file.dart'; import 'package:cw_bitcoin/pending_bitcoin_transaction.dart'; import 'package:cw_bitcoin/script_hash.dart'; import 'package:cw_bitcoin/utils.dart'; @@ -49,6 +49,7 @@ abstract class ElectrumWalletBase extends WalletBase? initialAddresses, ElectrumClient? electrumClient, ElectrumBalance? initialBalance, @@ -70,7 +71,10 @@ abstract class ElectrumWalletBase extends WalletBase @@ -78,6 +82,7 @@ abstract class ElectrumWalletBase extends WalletBase unspentCoinsInfo; @@ -428,7 +433,7 @@ abstract class ElectrumWalletBase extends WalletBase save() async { final path = await makePath(); - await write(path: path, password: _password, data: toJSON()); + await encryptionFileUtils.write(path: path, password: _password, data: toJSON()); await transactionHistory.save(); } diff --git a/cw_bitcoin/lib/electrum_wallet_snapshot.dart b/cw_bitcoin/lib/electrum_wallet_snapshot.dart index 3755e7d18..9276efaf7 100644 --- a/cw_bitcoin/lib/electrum_wallet_snapshot.dart +++ b/cw_bitcoin/lib/electrum_wallet_snapshot.dart @@ -1,7 +1,7 @@ import 'dart:convert'; import 'package:cw_bitcoin/bitcoin_address_record.dart'; import 'package:cw_bitcoin/electrum_balance.dart'; -import 'package:cw_bitcoin/file.dart'; +import 'package:cw_bitcoin/encryption_file_utils.dart'; import 'package:cw_core/pathForWallet.dart'; import 'package:cw_core/wallet_type.dart'; @@ -26,9 +26,9 @@ class ElectrumWallletSnapshot { int regularAddressIndex; int changeAddressIndex; - static Future load(String name, WalletType type, String password) async { + static Future load(EncryptionFileUtils encryptionFileUtils, String name, WalletType type, String password) async { final path = await pathForWallet(name: name, type: type); - final jsonSource = await read(path: path, password: password); + final jsonSource = await encryptionFileUtils.read(path: path, password: password); final data = json.decode(jsonSource) as Map; final addressesTmp = data['addresses'] as List? ?? []; final mnemonic = data['mnemonic'] as String; diff --git a/cw_bitcoin/lib/encryption_file_utils.dart b/cw_bitcoin/lib/encryption_file_utils.dart new file mode 100644 index 000000000..95f000f04 --- /dev/null +++ b/cw_bitcoin/lib/encryption_file_utils.dart @@ -0,0 +1,42 @@ +import 'dart:io'; +import 'dart:typed_data'; +import 'package:cw_bitcoin/file.dart' as bf; +import 'package:cake_backup/backup.dart' as cwb; + +EncryptionFileUtils encryptionFileUtilsFor(bool direct) + => direct + ? XChaCha20EncryptionFileUtils() + : Salsa20EncryhptionFileUtils(); + +abstract class EncryptionFileUtils { + Future write({required String path, required String password, required String data}); + Future read({required String path, required String password}); +} + +class Salsa20EncryhptionFileUtils extends EncryptionFileUtils { + // Requires legacy complex key + iv as password + @override + Future write({required String path, required String password, required String data}) async + => await bf.write(path: path, password: password, data: data); + + // Requires legacy complex key + iv as password + @override + Future read({required String path, required String password}) async + => await bf.read(path: path, password: password); +} + +class XChaCha20EncryptionFileUtils extends EncryptionFileUtils { + @override + Future write({required String path, required String password, required String data}) async { + final encrypted = await cwb.encrypt(password, Uint8List.fromList(data.codeUnits)); + await File(path).writeAsBytes(encrypted); + } + + @override + Future read({required String path, required String password}) async { + final file = File(path); + final encrypted = await file.readAsBytes(); + final bytes = await cwb.decrypt(password, encrypted); + return String.fromCharCodes(bytes); + } +} \ No newline at end of file diff --git a/cw_bitcoin/lib/file.dart b/cw_bitcoin/lib/file.dart index 8fd236ec3..49b7d895e 100644 --- a/cw_bitcoin/lib/file.dart +++ b/cw_bitcoin/lib/file.dart @@ -2,6 +2,7 @@ import 'dart:io'; import 'package:cw_core/key.dart'; import 'package:encrypt/encrypt.dart' as encrypt; +// Do not use directly, move to Salsa20EncryhptionFile Future write( {required String path, required String password, diff --git a/cw_bitcoin/lib/litecoin_wallet.dart b/cw_bitcoin/lib/litecoin_wallet.dart index 6bf1c5735..6d5171fd7 100644 --- a/cw_bitcoin/lib/litecoin_wallet.dart +++ b/cw_bitcoin/lib/litecoin_wallet.dart @@ -1,5 +1,6 @@ import 'package:cw_bitcoin/bitcoin_mnemonic.dart'; import 'package:cw_bitcoin/bitcoin_transaction_priority.dart'; +import 'package:cw_bitcoin/encryption_file_utils.dart'; import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/unspent_coins_info.dart'; import 'package:cw_bitcoin/litecoin_wallet_addresses.dart'; @@ -26,6 +27,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store { required WalletInfo walletInfo, required Box unspentCoinsInfo, required Uint8List seedBytes, + required EncryptionFileUtils encryptionFileUtils, List? initialAddresses, ElectrumBalance? initialBalance, int initialRegularAddressIndex = 0, @@ -39,6 +41,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store { initialAddresses: initialAddresses, initialBalance: initialBalance, seedBytes: seedBytes, + encryptionFileUtils: encryptionFileUtils, currency: CryptoCurrency.ltc) { walletAddresses = LitecoinWalletAddresses( walletInfo, @@ -58,6 +61,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store { required String password, required WalletInfo walletInfo, required Box unspentCoinsInfo, + required EncryptionFileUtils encryptionFileUtils, List? initialAddresses, ElectrumBalance? initialBalance, int initialRegularAddressIndex = 0, @@ -71,6 +75,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store { initialAddresses: initialAddresses, initialBalance: initialBalance, seedBytes: await mnemonicToSeedBytes(mnemonic), + encryptionFileUtils: encryptionFileUtils, initialRegularAddressIndex: initialRegularAddressIndex, initialChangeAddressIndex: initialChangeAddressIndex); } @@ -80,8 +85,9 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store { required WalletInfo walletInfo, required Box unspentCoinsInfo, required String password, + required EncryptionFileUtils encryptionFileUtils }) async { - final snp = await ElectrumWallletSnapshot.load (name, walletInfo.type, password); + final snp = await ElectrumWallletSnapshot.load(encryptionFileUtils, name, walletInfo.type, password); return LitecoinWallet( mnemonic: snp.mnemonic, password: password, @@ -90,6 +96,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store { initialAddresses: snp.addresses, initialBalance: snp.balance, seedBytes: await mnemonicToSeedBytes(snp.mnemonic), + encryptionFileUtils: encryptionFileUtils, initialRegularAddressIndex: snp.regularAddressIndex, initialChangeAddressIndex: snp.changeAddressIndex); } diff --git a/cw_bitcoin/lib/litecoin_wallet_service.dart b/cw_bitcoin/lib/litecoin_wallet_service.dart index 2093647fd..56a5ff152 100644 --- a/cw_bitcoin/lib/litecoin_wallet_service.dart +++ b/cw_bitcoin/lib/litecoin_wallet_service.dart @@ -1,4 +1,5 @@ import 'dart:io'; +import 'package:cw_bitcoin/encryption_file_utils.dart'; import 'package:cw_core/unspent_coins_info.dart'; import 'package:hive/hive.dart'; import 'package:cw_bitcoin/bitcoin_mnemonic.dart'; @@ -16,10 +17,11 @@ class LitecoinWalletService extends WalletService< BitcoinNewWalletCredentials, BitcoinRestoreWalletFromSeedCredentials, BitcoinRestoreWalletFromWIFCredentials> { - LitecoinWalletService(this.walletInfoSource, this.unspentCoinsInfoSource); + LitecoinWalletService(this.walletInfoSource, this.unspentCoinsInfoSource, this.isDirect); final Box walletInfoSource; final Box unspentCoinsInfoSource; + final bool isDirect; @override WalletType getType() => WalletType.litecoin; @@ -30,7 +32,8 @@ class LitecoinWalletService extends WalletService< mnemonic: await generateMnemonic(), password: credentials.password!, walletInfo: credentials.walletInfo!, - unspentCoinsInfo: unspentCoinsInfoSource); + unspentCoinsInfo: unspentCoinsInfoSource, + encryptionFileUtils: encryptionFileUtilsFor(isDirect)); await wallet.save(); await wallet.init(); @@ -47,7 +50,8 @@ class LitecoinWalletService extends WalletService< (info) => info.id == WalletBase.idFor(name, getType()))!; final wallet = await LitecoinWalletBase.open( password: password, name: name, walletInfo: walletInfo, - unspentCoinsInfo: unspentCoinsInfoSource); + unspentCoinsInfo: unspentCoinsInfoSource, + encryptionFileUtils: encryptionFileUtilsFor(isDirect)); await wallet.init(); return wallet; } @@ -73,7 +77,8 @@ class LitecoinWalletService extends WalletService< password: credentials.password!, mnemonic: credentials.mnemonic, walletInfo: credentials.walletInfo!, - unspentCoinsInfo: unspentCoinsInfoSource); + unspentCoinsInfo: unspentCoinsInfoSource, + encryptionFileUtils: encryptionFileUtilsFor(isDirect)); await wallet.save(); await wallet.init(); return wallet; diff --git a/cw_bitcoin/pubspec.lock b/cw_bitcoin/pubspec.lock index 182e5c1d3..301cdf477 100644 --- a/cw_bitcoin/pubspec.lock +++ b/cw_bitcoin/pubspec.lock @@ -155,6 +155,15 @@ packages: url: "https://pub.dev" source: hosted version: "8.4.4" + cake_backup: + dependency: "direct main" + description: + path: "." + ref: main + resolved-ref: "3aba867dcab6737f6707782f5db15d71f303db38" + url: "https://github.com/cake-tech/cake_backup.git" + source: git + version: "1.0.0+1" characters: dependency: transitive description: @@ -219,6 +228,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.5.0" + cupertino_icons: + dependency: transitive + description: + name: cupertino_icons + sha256: e35129dc44c9118cee2a5603506d823bab99c68393879edb440e0090d07586be + url: "https://pub.dev" + source: hosted + version: "1.0.5" cw_core: dependency: "direct main" description: @@ -681,6 +698,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.1" + tuple: + dependency: transitive + description: + name: tuple + sha256: "0ea99cd2f9352b2586583ab2ce6489d1f95a5f6de6fb9492faaf97ae2060f0aa" + url: "https://pub.dev" + source: hosted + version: "2.0.1" typed_data: dependency: transitive description: diff --git a/cw_bitcoin/pubspec.yaml b/cw_bitcoin/pubspec.yaml index 455ceb4a7..4c9d2e44c 100644 --- a/cw_bitcoin/pubspec.yaml +++ b/cw_bitcoin/pubspec.yaml @@ -27,6 +27,11 @@ dependencies: unorm_dart: ^0.2.0 cryptography: ^2.0.5 encrypt: ^5.0.1 + cake_backup: + git: + url: https://github.com/cake-tech/cake_backup.git + ref: main + version: 1.0.0 dev_dependencies: flutter_test: diff --git a/lib/bitcoin/cw_bitcoin.dart b/lib/bitcoin/cw_bitcoin.dart index 40fa670da..cb66a0f4b 100644 --- a/lib/bitcoin/cw_bitcoin.dart +++ b/lib/bitcoin/cw_bitcoin.dart @@ -138,12 +138,12 @@ class CWBitcoin extends Bitcoin { await bitcoinWallet.updateUnspent(); } - WalletService createBitcoinWalletService(Box walletInfoSource, Box unspentCoinSource) { - return BitcoinWalletService(walletInfoSource, unspentCoinSource); + WalletService createBitcoinWalletService(Box walletInfoSource, Box unspentCoinSource, bool isDirect) { + return BitcoinWalletService(walletInfoSource, unspentCoinSource, isDirect); } - WalletService createLitecoinWalletService(Box walletInfoSource, Box unspentCoinSource) { - return LitecoinWalletService(walletInfoSource, unspentCoinSource); + WalletService createLitecoinWalletService(Box walletInfoSource, Box unspentCoinSource, bool isDirect) { + return LitecoinWalletService(walletInfoSource, unspentCoinSource, isDirect); } @override diff --git a/lib/di.dart b/lib/di.dart index 2ab451d14..589397f22 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -583,10 +583,12 @@ Future setup( return monero!.createMoneroWalletService(_walletInfoSource); case WalletType.bitcoin: return bitcoin!.createBitcoinWalletService( - _walletInfoSource, _unspentCoinsInfoSource!); + _walletInfoSource, _unspentCoinsInfoSource!, + SettingsStoreBase.walletPasswordDirectInput); case WalletType.litecoin: return bitcoin!.createLitecoinWalletService( - _walletInfoSource, _unspentCoinsInfoSource!); + _walletInfoSource, _unspentCoinsInfoSource!, + SettingsStoreBase.walletPasswordDirectInput); default: throw Exception('Unexpected token: ${param1.toString()} for generating of WalletService'); } diff --git a/lib/src/screens/new_wallet/new_wallet_page.dart b/lib/src/screens/new_wallet/new_wallet_page.dart index 18a9c2424..be128ee6a 100644 --- a/lib/src/screens/new_wallet/new_wallet_page.dart +++ b/lib/src/screens/new_wallet/new_wallet_page.dart @@ -50,7 +50,8 @@ class _WalletNameFormState extends State { : _formKey = GlobalKey(), _languageSelectorKey = GlobalKey(), _nameController = TextEditingController(), - _passwordController = _walletNewVM.hasWalletPassword ? TextEditingController() : null; + _passwordController = _walletNewVM.hasWalletPassword ? TextEditingController() : null, + _repeatedPasswordController = _walletNewVM.hasWalletPassword ? TextEditingController() : null; static const aspectRatioImage = 1.22; @@ -59,6 +60,7 @@ class _WalletNameFormState extends State { final WalletNewVM _walletNewVM; final TextEditingController _nameController; final TextEditingController? _passwordController; + final TextEditingController? _repeatedPasswordController; ReactionDisposer? _stateReaction; @override @@ -171,7 +173,7 @@ class _WalletNameFormState extends State { validator: WalletNameValidator(), ), if (_walletNewVM.hasWalletPassword) - TextFormField( + ...[TextFormField( onChanged: (value) => _walletNewVM.walletPassword = value, controller: _passwordController, textAlign: TextAlign.center, @@ -203,6 +205,38 @@ class _WalletNameFormState extends State { ) ) ), + TextFormField( + onChanged: (value) => _walletNewVM.repeatedWalletPassword = value, + controller: _repeatedPasswordController, + textAlign: TextAlign.center, + obscureText: true, + style: TextStyle( + fontSize: 20.0, + fontWeight: FontWeight.w600, + color: Theme.of(context).primaryTextTheme!.headline6!.color!), + decoration: InputDecoration( + hintStyle: TextStyle( + fontSize: 18.0, + fontWeight: FontWeight.w500, + color: Theme.of(context).accentTextTheme!.headline2!.color!), + hintText: S.of(context).repeate_wallet_password, + focusedBorder: UnderlineInputBorder( + borderSide: BorderSide( + color: Theme.of(context) + .accentTextTheme! + .headline2! + .decorationColor!, + width: 1.0)), + enabledBorder: UnderlineInputBorder( + borderSide: BorderSide( + color: Theme.of(context) + .accentTextTheme! + .headline2! + .decorationColor!, + width: 1.0), + ) + ) + )], ], ), ), diff --git a/lib/src/screens/restore/wallet_restore_from_keys_form.dart b/lib/src/screens/restore/wallet_restore_from_keys_form.dart index 0096973d0..1d1288b23 100644 --- a/lib/src/screens/restore/wallet_restore_from_keys_form.dart +++ b/lib/src/screens/restore/wallet_restore_from_keys_form.dart @@ -15,6 +15,7 @@ class WalletRestoreFromKeysFrom extends StatefulWidget { WalletRestoreFromKeysFrom({ required this.walletRestoreViewModel, required this.displayWalletPassword, + required this.onRepeatedPasswordChange, this.onPasswordChange, Key? key, this.onHeightOrDateEntered,}) @@ -24,6 +25,7 @@ class WalletRestoreFromKeysFrom extends StatefulWidget { final WalletRestoreViewModel walletRestoreViewModel; final bool displayWalletPassword; final void Function(String)? onPasswordChange; + final void Function(String)? onRepeatedPasswordChange; @override WalletRestoreFromKeysFromState createState() => @@ -39,7 +41,8 @@ class WalletRestoreFromKeysFromState extends State { viewKeyController = TextEditingController(), spendKeyController = TextEditingController(), nameTextEditingController = TextEditingController(), - passwordTextEditingController = displayWalletPassword ? TextEditingController() : null; + passwordTextEditingController = displayWalletPassword ? TextEditingController() : null, + repeatedPasswordTextEditingController = displayWalletPassword ? TextEditingController() : null; final GlobalKey formKey; final GlobalKey blockchainHeightKey; @@ -49,7 +52,9 @@ class WalletRestoreFromKeysFromState extends State { final TextEditingController spendKeyController; final TextEditingController nameTextEditingController; final TextEditingController? passwordTextEditingController; + final TextEditingController? repeatedPasswordTextEditingController; void Function()? passwordListener; + void Function()? repeatedPasswordListener; @override void initState() { @@ -57,6 +62,11 @@ class WalletRestoreFromKeysFromState extends State { passwordListener = () => widget.onPasswordChange?.call(passwordTextEditingController!.text); passwordTextEditingController?.addListener(passwordListener!); } + + if (repeatedPasswordTextEditingController != null) { + repeatedPasswordListener = () => widget.onRepeatedPasswordChange?.call(repeatedPasswordTextEditingController!.text); + repeatedPasswordTextEditingController?.addListener(repeatedPasswordListener!); + } super.initState(); } @@ -71,6 +81,10 @@ class WalletRestoreFromKeysFromState extends State { if (passwordListener != null) { passwordTextEditingController?.removeListener(passwordListener!); } + + if (repeatedPasswordListener != null) { + repeatedPasswordTextEditingController?.removeListener(repeatedPasswordListener!); + } super.dispose(); } @@ -121,12 +135,18 @@ class WalletRestoreFromKeysFromState extends State { ], ), if (widget.displayWalletPassword) - Container( + ...[Container( padding: EdgeInsets.only(top: 20.0), child: BaseTextFormField( controller: passwordTextEditingController, hintText: S.of(context).password, obscureText: true)), + Container( + padding: EdgeInsets.only(top: 20.0), + child: BaseTextFormField( + controller: repeatedPasswordTextEditingController, + hintText: S.of(context).repeate_wallet_password, + obscureText: true))], Container(height: 20), BaseTextFormField( controller: addressController, diff --git a/lib/src/screens/restore/wallet_restore_from_seed_form.dart b/lib/src/screens/restore/wallet_restore_from_seed_form.dart index f0fb7dfa2..d41d71a3f 100644 --- a/lib/src/screens/restore/wallet_restore_from_seed_form.dart +++ b/lib/src/screens/restore/wallet_restore_from_seed_form.dart @@ -23,7 +23,8 @@ class WalletRestoreFromSeedForm extends StatefulWidget { this.onHeightOrDateEntered, this.onSeedChange, this.onLanguageChange, - this.onPasswordChange}) + this.onPasswordChange, + this.onRepeatedPasswordChange}) : super(key: key); final WalletType type; @@ -35,6 +36,7 @@ class WalletRestoreFromSeedForm extends StatefulWidget { final void Function(String)? onSeedChange; final void Function(String)? onLanguageChange; final void Function(String)? onPasswordChange; + final void Function(String)? onRepeatedPasswordChange; @override WalletRestoreFromSeedFormState createState() => @@ -48,16 +50,19 @@ class WalletRestoreFromSeedFormState extends State { formKey = GlobalKey(), languageController = TextEditingController(), nameTextEditingController = TextEditingController(), - passwordTextEditingController = displayWalletPassword ? TextEditingController() : null; + passwordTextEditingController = displayWalletPassword ? TextEditingController() : null, + repeatedPasswordTextEditingController = displayWalletPassword ? TextEditingController() : null; final GlobalKey seedWidgetStateKey; final GlobalKey blockchainHeightKey; final TextEditingController languageController; final TextEditingController nameTextEditingController; final TextEditingController? passwordTextEditingController; + final TextEditingController? repeatedPasswordTextEditingController; final GlobalKey formKey; String language; void Function()? passwordListener; + void Function()? repeatedPasswordListener; @override void initState() { @@ -66,6 +71,11 @@ class WalletRestoreFromSeedFormState extends State { passwordListener = () => widget.onPasswordChange?.call(passwordTextEditingController!.text); passwordTextEditingController?.addListener(passwordListener!); } + + if (repeatedPasswordTextEditingController != null) { + repeatedPasswordListener = () => widget.onRepeatedPasswordChange?.call(repeatedPasswordTextEditingController!.text); + repeatedPasswordTextEditingController?.addListener(repeatedPasswordListener!); + } super.initState(); } @@ -74,6 +84,10 @@ class WalletRestoreFromSeedFormState extends State { if (passwordListener != null) { passwordTextEditingController?.removeListener(passwordListener!); } + + if (repeatedPasswordListener != null) { + repeatedPasswordTextEditingController?.removeListener(repeatedPasswordListener!); + } super.dispose(); } @@ -130,10 +144,14 @@ class WalletRestoreFromSeedFormState extends State { type: widget.type, onSeedChange: widget.onSeedChange), if (widget.displayWalletPassword) - BaseTextFormField( + ...[BaseTextFormField( controller: passwordTextEditingController, hintText: S.of(context).password, obscureText: true), + BaseTextFormField( + controller: repeatedPasswordTextEditingController, + hintText: S.of(context).repeate_wallet_password, + obscureText: true)], if (widget.displayLanguageSelector) GestureDetector( onTap: () async { diff --git a/lib/src/screens/restore/wallet_restore_page.dart b/lib/src/screens/restore/wallet_restore_page.dart index 1ee25320d..93ef93665 100644 --- a/lib/src/screens/restore/wallet_restore_page.dart +++ b/lib/src/screens/restore/wallet_restore_page.dart @@ -68,7 +68,8 @@ class WalletRestorePage extends BasePage { } }, displayWalletPassword: walletRestoreViewModel.hasWalletPassword, - onPasswordChange: (String password) => walletRestoreViewModel.walletPassword = password)); + onPasswordChange: (String password) => walletRestoreViewModel.walletPassword = password, + onRepeatedPasswordChange: (String repeatedPassword) => walletRestoreViewModel.repeatedWalletPassword = repeatedPassword)); break; case WalletRestoreMode.keys: _pages.add(WalletRestoreFromKeysFrom( @@ -76,6 +77,7 @@ class WalletRestorePage extends BasePage { walletRestoreViewModel: walletRestoreViewModel, displayWalletPassword: walletRestoreViewModel.hasWalletPassword, onPasswordChange: (String password) => walletRestoreViewModel.walletPassword = password, + onRepeatedPasswordChange: (String repeatedPassword) => walletRestoreViewModel.repeatedWalletPassword = repeatedPassword, onHeightOrDateEntered: (value) => walletRestoreViewModel.isButtonEnabled = value)); break; default: @@ -124,6 +126,8 @@ class WalletRestorePage extends BasePage { reaction((_) => walletRestoreViewModel.mode, (WalletRestoreMode mode) { walletRestoreViewModel.isButtonEnabled = false; + walletRestoreViewModel.walletPassword = null; + walletRestoreViewModel.repeatedWalletPassword = null; walletRestoreFromSeedFormKey .currentState!.blockchainHeightKey.currentState!.restoreHeightController.text = ''; diff --git a/lib/view_model/wallet_creation_vm.dart b/lib/view_model/wallet_creation_vm.dart index 65968cd30..9a28045b0 100644 --- a/lib/view_model/wallet_creation_vm.dart +++ b/lib/view_model/wallet_creation_vm.dart @@ -1,6 +1,6 @@ import 'package:cake_wallet/core/wallet_creation_service.dart'; +import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/store/settings_store.dart'; -import 'package:flutter/foundation.dart'; import 'package:hive/hive.dart'; import 'package:mobx/mobx.dart'; import 'package:cake_wallet/core/execution_state.dart'; @@ -31,6 +31,9 @@ abstract class WalletCreationVMBase with Store { @observable String? walletPassword; + @observable + String? repeatedWalletPassword; + bool get hasWalletPassword => SettingsStoreBase.walletPasswordDirectInput; WalletType type; @@ -52,6 +55,14 @@ abstract class WalletCreationVMBase with Store { name = await generateName(); } + if (hasWalletPassword && (walletPassword?.isEmpty ?? true)) { + throw Exception(S.current.wallet_password_is_empty); + } + + if (hasWalletPassword && walletPassword != repeatedWalletPassword) { + throw Exception(S.current.repeated_password_is_incorrect); + } + walletCreationService.checkIfExists(name); final dirPath = await pathForWalletDir(name: name, type: type); final path = await pathForWallet(name: name, type: type); diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index b55134597..f6dff063b 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -346,6 +346,9 @@ "invalid_password" : "رمز مرور خاطئ", "unlock" : "الغاء القفل", "enter_wallet_password" : "أدخل كلمة مرور المحفظة", + "repeate_wallet_password" : "كرر كلمة مرور المحفظة", + "wallet_password_is_empty" : "كلمة مرور المحفظة فارغة. يجب ألا تكون كلمة مرور المحفظة فارغة", + "repeated_password_is_incorrect" : "كلمة المرور المتكررة غير صحيحة. يرجى إعادة كلمة مرور المحفظة مرة أخرى.", "full_balance":"الرصيد الكامل", "available_balance":"الرصيد المتوفر", diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index 4671529bc..6d4f9add7 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -346,6 +346,9 @@ "invalid_password" : "Ongeldig wachtwoord", "unlock" : "Freischalten", "enter_wallet_password" : "Geben Sie das Wallet-Passwort ein", + "repeat_wallet_password" : "Wiederholen Sie das Wallet-Passwort", + "wallet_password_is_empty" : "Wallet-Passwort ist leer. Wallet-Passwort darf nicht leer sein", + "repeated_password_is_incorrect" : "Wiederholtes Passwort ist falsch. Bitte wiederholen Sie das Wallet-Passwort noch einmal.", "full_balance" : "Gesamtguthaben", "available_balance" : "Verfügbares Guthaben", diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index dbacc1a7b..01bc959cf 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -346,6 +346,9 @@ "invalid_password" : "Invalid password", "unlock" : "Unlock", "enter_wallet_password" : "Enter the wallet password", + "repeate_wallet_password" : "Repeat the wallet password", + "wallet_password_is_empty" : "Wallet password is empty. Wallet password should not be empty", + "repeated_password_is_incorrect" : "Repeated password is incorrect. Please repeat the wallet password again.", "full_balance" : "Full Balance", "available_balance" : "Available Balance", diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 8c4577215..5228cb00c 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -346,6 +346,9 @@ "invalid_password" : "Contraseña invalida", "unlock" : "desbloquear", "enter_wallet_password" : "Ingrese la contraseña de la billetera", + "repeate_wallet_password" : "Repita la contraseña de la billetera", + "wallet_password_is_empty" : "La contraseña de la billetera está vacía. La contraseña de la billetera no debe estar vacía", + "repeated_password_is_incorrect" : "La contraseña repetida es incorrecta. Repita la contraseña de la billetera nuevamente.", "full_balance" : "Balance completo", "available_balance" : "Balance disponible", diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index 6ac2f8293..30da9b052 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -344,6 +344,9 @@ "invalid_password" : "Mot de passe incorrect", "unlock" : "Ouvrir", "enter_wallet_password" : "Entrez le mot de passe du portefeuille", + "repeate_wallet_password" : "Répétez le mot de passe du portefeuille", + "wallet_password_is_empty" : "Le mot de passe du portefeuille est vide. Le mot de passe du portefeuille ne doit pas être vide", + "repeated_password_is_incorrect" : "Le mot de passe répété est incorrect. Veuillez répéter le mot de passe du portefeuille.", "full_balance" : "Solde Complet", "available_balance" : "Solde Disponible", diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index b4001f6d1..85697f625 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -346,6 +346,9 @@ "invalid_password" : "अवैध पासवर्ड", "unlock" : "अनलॉक", "enter_wallet_password" : "वॉलेट पासवर्ड दर्ज करें", + "repeate_wallet_password" : "वॉलेट पासवर्ड दोहराएं", + "wallet_password_is_empty" : "वॉलेट पासवर्ड खाली है। वॉलेट पासवर्ड खाली नहीं होना चाहिए", + "repeated_password_is_incorrect" : "दोहराया गया पासवर्ड गलत है। कृपया वॉलेट पासवर्ड दोबारा दोहराएं।", "full_balance" : "पूर्ण संतुलन", "available_balance" : "उपलब्ध शेष राशि", diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index 14d22dc65..4d3a10738 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -346,6 +346,9 @@ "invalid_password" : "Érvénytelen jelszó", "unlock" : "Kinyit", "enter_wallet_password" : "Adja meg a pénztárca jelszavát", + "repeate_wallet_password" : "Az ismételt jelszó helytelen. Kérjük, ismételje meg újra a pénztárca jelszavát.", + "wallet_password_is_empty" : "A Wallet jelszó üres. A Wallet jelszó nem lehet üres", + "repeated_password_is_incorrect" : "Az ismételt jelszó helytelen. Kérjük, ismételje meg újra a pénztárca jelszavát.", "full_balance" : "Pun iznos", "available_balance" : "Raspoloživ iznos", diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index 75af0881e..67ec68b65 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -346,6 +346,9 @@ "invalid_password" : "Password non valida", "unlock" : "Sbloccare", "enter_wallet_password" : "Inserisci la password del portafoglio", + "repeate_wallet_password" : "Ripeti la password del portafoglio", + "wallet_password_is_empty" : "La password del portafoglio è vuota. La password del portafoglio non deve essere vuota", + "repeated_password_is_incorrect" : "La password ripetuta non è corretta. Ripeti di nuovo la password del portafoglio.", "full_balance" : "Saldo Completo", "available_balance" : "Saldo Disponibile", diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index 8cac3cc57..d6ba565fc 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -346,6 +346,9 @@ "invalid_password" : "無効なパスワード", "unlock" : "ロック解除", "enter_wallet_password" : "ウォレットのパスワードを入力してください", + "repeate_wallet_password" : "ウォレットのパスワードを繰り返す", + "wallet_password_is_empty" : "ウォレットのパスワードが空です。 ウォレットのパスワードを空にすることはできません", + "repeated_password_is_incorrect" : "繰り返されるパスワードが正しくありません。 ウォレットのパスワードをもう一度入力してください。", "full_balance" : "フルバランス", "available_balance" : "利用可能残高", diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index 7cf462fbc..fe72f4958 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -346,6 +346,9 @@ "invalid_password" : "유효하지 않은 비밀번호", "unlock" : "터놓다", "enter_wallet_password" : "지갑 비밀번호를 입력하세요", + "repeate_wallet_password" : "지갑 비밀번호를 반복하십시오", + "wallet_password_is_empty" : "지갑 비밀번호가 비어 있습니다. 월렛 비밀번호는 비워둘 수 없습니다.", + "repeated_password_is_incorrect" : "반복되는 비밀번호가 올바르지 않습니다. 지갑 비밀번호를 다시 한번 입력해주세요.", "full_balance" : "풀 밸런스", "available_balance" : "사용 가능한 잔액", diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index 34180697d..531ea9891 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -346,6 +346,9 @@ "invalid_password" : "စကားဝှက် မမှန်ကန်ပါ။", "unlock" : "သော့ဖွင့်ပါ။", "enter_wallet_password" : "ပိုက်ဆံအိတ်စကားဝှက်ကိုထည့်ပါ။", + "repeate_wallet_password" : "ပိုက်ဆံအိတ်စကားဝှက်ကို ပြန်လုပ်ပါ။", + "wallet_password_is_empty" : "ပိုက်ဆံအိတ်စကားဝှက်သည် ဗလာဖြစ်နေသည်။ ပိုက်ဆံအိတ်စကားဝှက်သည် ဗလာမဖြစ်သင့်ပါ။", + "repeated_password_is_incorrect" : "ထပ်ခါတလဲလဲ စကားဝှက် မမှန်ပါ။ ပိုက်ဆံအိတ်စကားဝှက်ကို ထပ်လုပ်ပါ။", "full_balance" : "Balance အပြည့်", "available_balance" : "လက်ကျန်ငွေ ရရှိနိုင်", diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index 3f30a99e6..590188fb4 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -346,6 +346,9 @@ "invalid_password" : "Ongeldig wachtwoord", "unlock" : "Ontgrendelen", "enter_wallet_password" : "Voer het portemonnee-wachtwoord in", + "repeate_wallet_password" : "Herhaal het wachtwoord van de portemonnee", + "wallet_password_is_empty" : "Wallet-wachtwoord is leeg. Wallet-wachtwoord mag niet leeg zijn", + "repeated_password_is_incorrect" : "Herhaald wachtwoord is onjuist. Herhaal het wachtwoord van de portemonnee nogmaals.", "full_balance" : "Volledig saldo", "available_balance" : "Beschikbaar saldo", diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index c006b0f53..2c8c8a575 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -346,6 +346,9 @@ "invalid_password" : "Nieprawidłowe hasło", "unlock" : "Odblokować", "enter_wallet_password" : "Wprowadź hasło do portfela", + "repeate_wallet_password" : "Powtórz hasło do portfela", + "wallet_password_is_empty" : "Hasło portfela jest puste. Hasło portfela nie powinno być puste", + "repeated_password_is_incorrect" : "Powtórzone hasło jest nieprawidłowe. Powtórz hasło do portfela jeszcze raz.", "full_balance" : "Pełne saldo", "available_balance" : "Dostępne środki", diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index 5ac447a46..27c2578f8 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -346,6 +346,9 @@ "invalid_password" : "Senha inválida", "unlock" : "desbloquear", "enter_wallet_password" : "Digite a senha da carteira", + "repeate_wallet_password" : "Repita a senha da carteira", + "wallet_password_is_empty" : "A senha da carteira está vazia. A senha da carteira não deve estar vazia", + "repeated_password_is_incorrect" : "A senha repetida está incorreta. Por favor, repita a senha da carteira novamente.", "full_balance" : "Saldo total", "available_balance" : "Saldo disponível", diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index 53a538b5d..4ed8faa59 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -346,6 +346,9 @@ "invalid_password" : "Invalid password", "unlock" : "Unlock", "enter_wallet_password" : "Enter the wallet password", + "repeate_wallet_password" : "Repeat the wallet password", + "wallet_password_is_empty" : "Wallet password is empty. Wallet password should not be empty", + "repeated_password_is_incorrect" : "Repeated password is incorrect. Please repeat the wallet password again.", "full_balance" : "Весь баланс", "available_balance" : "Доступный баланс", diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index 11ea7ca37..692fd39d9 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -344,6 +344,9 @@ "invalid_password" : "รหัสผ่านไม่ถูกต้อง", "unlock" : "ปลดล็อค", "enter_wallet_password" : "ป้อนรหัสผ่านกระเป๋าเงิน", + "repeate_wallet_password" : "ทำซ้ำรหัสผ่านกระเป๋าเงิน", + "wallet_password_is_empty" : "รหัสผ่าน Wallet ว่างเปล่า รหัสผ่าน Wallet ไม่ควรว่างเปล่า", + "repeated_password_is_incorrect" : "รหัสผ่านซ้ำไม่ถูกต้อง กรุณากรอกรหัสผ่านกระเป๋าเงินซ้ำอีกครั้ง", "full_balance" : "ยอดคงเหลือทั้งหมด", "available_balance" : "ยอดคงเหลือที่ใช้งานได้", diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index f1fe789f7..3389cc608 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -346,6 +346,9 @@ "invalid_password" : "Geçersiz şifre", "unlock" : "Kilidini aç", "enter_wallet_password" : "cüzdan şifresini girin", + "repeate_wallet_password" : "M-cüzdan şifresini tekrarla", + "wallet_password_is_empty" : "Cüzdan şifresi boş. Cüzdan şifresi boş olmamalıdır", + "repeated_password_is_incorrect" : "Tekrarlanan şifre yanlış. Lütfen cüzdan şifresini tekrar tekrarlayın.", "full_balance" : "Tüm bakiye", "available_balance" : "Kullanılabilir Bakiye", diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index 696eab10a..80d78113e 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -345,6 +345,9 @@ "invalid_password" : "Невірний пароль", "unlock" : "Розблокувати", "enter_wallet_password" : "Введіть пароль гаманця", + "repeate_wallet_password" : "Повторіть пароль гаманця", + "wallet_password_is_empty" : "Пароль гаманця порожній. Пароль гаманця не повинен бути порожнім", + "repeated_password_is_incorrect" : "Повторний пароль неправильний. Будь ласка, повторіть пароль гаманця ще раз.", "full_balance" : "Весь баланс", "available_balance" : "Доступний баланс", diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index c11896ad2..c97f42939 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -346,6 +346,9 @@ "invalid_password" : "无效的密码", "unlock" : "开锁", "enter_wallet_password" : "输入钱包密码", + "repeate_wallet_password" : "重复钱包密码", + "wallet_password_is_empty" : "钱包密码为空。 钱包密码不能为空", + "repeated_password_is_incorrect" : "重复的密码不正确。 请再次输入钱包密码。", "full_balance" : "全部余额", "available_balance" : "可用余额", diff --git a/tool/configure.dart b/tool/configure.dart index 3e441778a..d1ec6a569 100644 --- a/tool/configure.dart +++ b/tool/configure.dart @@ -94,8 +94,8 @@ abstract class Bitcoin { List getUnspents(Object wallet); void updateUnspents(Object wallet); - WalletService createBitcoinWalletService(Box walletInfoSource, Box unspentCoinSource); - WalletService createLitecoinWalletService(Box walletInfoSource, Box unspentCoinSource); + WalletService createBitcoinWalletService(Box walletInfoSource, Box unspentCoinSource, bool isDirect); + WalletService createLitecoinWalletService(Box walletInfoSource, Box unspentCoinSource, bool isDirect); TransactionPriority getBitcoinTransactionPriorityMedium(); TransactionPriority getLitecoinTransactionPriorityMedium(); TransactionPriority getBitcoinTransactionPrioritySlow();