Release 4.4.3 (#415)
* Add ability for change password for wallets classes. * Update generateWalletPassword * Add WalletLoadingService * Add update monero password after wallet loading. * Update version for Cake Wallet to 4.4.2 (103) * Changed version for Cake Wallet to 4.4.3 (104). * Changed version for Cake Wallet android * Changed version for Monero.com ios and android.
mkyq committed
Jul 19, 2022 at 15:29 UTC
b72443a8c4f2fb50e34a7e5510afb52cf13f366d
25 files changed
+214
-41
cw_bitcoin/lib/electrum_transaction_history.dart
+6
-1
@@ -24,7 +24,7 @@ abstract class ElectrumTransactionHistoryBase
24
}
25
26
final WalletInfo walletInfo;
27
- final String _password;
27
+ String _password;
28
int _height;
29
30
Future<void> init() async => await _load();
@@ -51,6 +51,11 @@ abstract class ElectrumTransactionHistoryBase
51
}
52
}
53
54
+ Future<void> changePassword(String password) async {
55
+ _password = password;
56
+ await save();
57
+ }
58
+
59
Future<Map<String, Object>> _read() async {
60
final dirPath =
61
await pathForWalletDir(name: walletInfo.name, type: walletInfo.type);
cw_bitcoin/lib/electrum_wallet.dart
+8
-1
@@ -109,7 +109,7 @@ abstract class ElectrumWalletBase extends WalletBase<ElectrumBalance,
109
BitcoinWalletKeys get keys => BitcoinWalletKeys(
110
wif: hd.wif, privateKey: hd.privKey, publicKey: hd.pubKey);
111
112
- final String _password;
112
+ String _password;
113
List<BitcoinUnspent> unspentCoins;
114
List<int> _feeRates;
115
Map<String, BehaviorSubject<Object>> _scripthashesUpdateSubject;
@@ -392,6 +392,13 @@ abstract class ElectrumWalletBase extends WalletBase<ElectrumBalance,
392
await transactionHistory.save();
393
}
394
395
+ @override
396
+ Future<void> changePassword(String password) async {
397
+ _password = password;
398
+ await save();
399
+ await transactionHistory.changePassword(password);
400
+ }
401
+
402
bitcoin.ECPair keyPairFor({@required int index}) =>
403
generateKeyPair(hd: hd, index: index, network: networkType);
404
cw_core/lib/wallet_base.dart
+2
@@ -69,4 +69,6 @@ abstract class WalletBase<
69
Future<void> rescan({int height});
70
71
void close();
72
+
73
+ Future<void> changePassword(String password);
74
}
cw_haven/ios/Classes/haven_api.cpp
+10
@@ -565,6 +565,16 @@ extern "C"
565
store_lock.unlock();
566
}
567
568
+ bool set_password(char *password, Utf8Box &error) {
569
+ bool is_changed = get_current_wallet()->setPassword(std::string(password));
570
+
571
+ if (!is_changed) {
572
+ error = Utf8Box(strdup(get_current_wallet()->errorString().c_str()));
573
+ }
574
+
575
+ return is_changed;
576
+ }
577
+
578
bool transaction_create(char *address, char *asset_type, char *payment_id, char *amount,
579
uint8_t priority_raw, uint32_t subaddr_account, Utf8Box &error, PendingTransactionRaw &pendingTransaction)
580
{
cw_haven/lib/api/signatures.dart
+2
@@ -51,6 +51,8 @@ typedef set_recovering_from_seed = Void Function(Int8);
51
52
typedef store_c = Void Function(Pointer<Utf8>);
53
54
+typedef set_password = Int8 Function(Pointer<Utf8> password, Pointer<Utf8Box> error);
55
+
56
typedef set_listener = Void Function();
57
58
typedef get_syncing_height = Int64 Function();
cw_haven/lib/api/types.dart
+2
@@ -51,6 +51,8 @@ typedef SetRecoveringFromSeed = void Function(int);
51
52
typedef Store = void Function(Pointer<Utf8>);
53
54
+typedef SetPassword = int Function(Pointer<Utf8> password, Pointer<Utf8Box> error);
55
+
56
typedef SetListener = void Function();
57
58
typedef GetSyncingHeight = int Function();
cw_haven/lib/api/wallet.dart
+19
@@ -1,6 +1,7 @@
1
import 'dart:async';
2
import 'dart:ffi';
3
import 'package:ffi/ffi.dart';
4
+import 'package:cw_haven/api/structs/ut8_box.dart';
5
import 'package:cw_haven/api/convert_utf8_to_string.dart';
6
import 'package:cw_haven/api/signatures.dart';
7
import 'package:cw_haven/api/types.dart';
@@ -67,6 +68,9 @@ final setRecoveringFromSeedNative = havenApi
68
final storeNative =
69
havenApi.lookup<NativeFunction<store_c>>('store').asFunction<Store>();
70
71
+final setPasswordNative =
72
+ havenApi.lookup<NativeFunction<set_password>>('set_password').asFunction<SetPassword>();
73
+
74
final setListenerNative = havenApi
75
.lookup<NativeFunction<set_listener>>('set_listener')
76
.asFunction<SetListener>();
@@ -193,6 +197,21 @@ void storeSync() {
197
free(pathPointer);
198
}
199
200
+void setPasswordSync(String password) {
201
+ final passwordPointer = Utf8.toUtf8(password);
202
+ final errorMessagePointer = allocate<Utf8Box>();
203
+ final changed = setPasswordNative(passwordPointer, errorMessagePointer) != 0;
204
+ free(passwordPointer);
205
+
206
+ if (!changed) {
207
+ final message = errorMessagePointer.ref.getValue();
208
+ free(errorMessagePointer);
209
+ throw Exception(message);
210
+ }
211
+
212
+ free(errorMessagePointer);
213
+}
214
+
215
void closeCurrentWallet() => closeCurrentWalletNative();
216
217
String getSecretViewKey() =>
cw_haven/lib/haven_wallet.dart
+5
@@ -240,6 +240,11 @@ abstract class HavenWalletBase extends WalletBase<MoneroBalance,
240
await haven_wallet.store();
241
}
242
243
+ @override
244
+ Future<void> changePassword(String password) async {
245
+ haven_wallet.setPasswordSync(password);
246
+ }
247
+
248
Future<int> getNodeHeight() async => haven_wallet.getNodeHeight();
249
250
Future<bool> isConnected() async => haven_wallet.isConnected();
cw_monero/ios/Classes/monero_api.cpp
+10
@@ -467,6 +467,16 @@ extern "C"
467
store_lock.unlock();
468
}
469
470
+ bool set_password(char *password, Utf8Box &error) {
471
+ bool is_changed = get_current_wallet()->setPassword(std::string(password));
472
+
473
+ if (!is_changed) {
474
+ error = Utf8Box(strdup(get_current_wallet()->errorString().c_str()));
475
+ }
476
+
477
+ return is_changed;
478
+ }
479
+
480
bool transaction_create(char *address, char *payment_id, char *amount,
481
uint8_t priority_raw, uint32_t subaddr_account, Utf8Box &error, PendingTransactionRaw &pendingTransaction)
482
{
cw_monero/lib/api/signatures.dart
+2
@@ -47,6 +47,8 @@ typedef set_recovering_from_seed = Void Function(Int8);
47
48
typedef store_c = Void Function(Pointer<Utf8>);
49
50
+typedef set_password = Int8 Function(Pointer<Utf8> password, Pointer<Utf8Box> error);
51
+
52
typedef set_listener = Void Function();
53
54
typedef get_syncing_height = Int64 Function();
cw_monero/lib/api/types.dart
+2
@@ -47,6 +47,8 @@ typedef SetRecoveringFromSeed = void Function(int);
47
48
typedef Store = void Function(Pointer<Utf8>);
49
50
+typedef SetPassword = int Function(Pointer<Utf8> password, Pointer<Utf8Box> error);
51
+
52
typedef SetListener = void Function();
53
54
typedef GetSyncingHeight = int Function();
cw_monero/lib/api/wallet.dart
+19
@@ -1,6 +1,7 @@
1
import 'dart:async';
2
import 'dart:ffi';
3
import 'package:ffi/ffi.dart';
4
+import 'package:cw_monero/api/structs/ut8_box.dart';
5
import 'package:cw_monero/api/convert_utf8_to_string.dart';
6
import 'package:cw_monero/api/signatures.dart';
7
import 'package:cw_monero/api/types.dart';
@@ -67,6 +68,9 @@ final setRecoveringFromSeedNative = moneroApi
68
final storeNative =
69
moneroApi.lookup<NativeFunction<store_c>>('store').asFunction<Store>();
70
71
+final setPasswordNative =
72
+ moneroApi.lookup<NativeFunction<set_password>>('set_password').asFunction<SetPassword>();
73
+
74
final setListenerNative = moneroApi
75
.lookup<NativeFunction<set_listener>>('set_listener')
76
.asFunction<SetListener>();
@@ -197,6 +201,21 @@ void storeSync() {
201
free(pathPointer);
202
}
203
204
+void setPasswordSync(String password) {
205
+ final passwordPointer = Utf8.toUtf8(password);
206
+ final errorMessagePointer = allocate<Utf8Box>();
207
+ final changed = setPasswordNative(passwordPointer, errorMessagePointer) != 0;
208
+ free(passwordPointer);
209
+
210
+ if (!changed) {
211
+ final message = errorMessagePointer.ref.getValue();
212
+ free(errorMessagePointer);
213
+ throw Exception(message);
214
+ }
215
+
216
+ free(errorMessagePointer);
217
+}
218
+
219
void closeCurrentWallet() => closeCurrentWalletNative();
220
221
String getSecretViewKey() =>
cw_monero/lib/monero_wallet.dart
+5
@@ -258,6 +258,11 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance,
258
await monero_wallet.store();
259
}
260
261
+ @override
262
+ Future<void> changePassword(String password) async {
263
+ monero_wallet.setPasswordSync(password);
264
+ }
265
+
266
Future<int> getNodeHeight() async => monero_wallet.getNodeHeight();
267
268
Future<bool> isConnected() async => monero_wallet.isConnected();
lib/core/generate_wallet_password.dart
+2
-8
@@ -1,12 +1,6 @@
1
import 'package:uuid/uuid.dart';
2
import 'package:cw_core/key.dart';
3
-import 'package:cw_core/wallet_type.dart';
3
5
-String generateWalletPassword(WalletType type) {
6
- switch (type) {
7
- case WalletType.monero:
8
- return Uuid().v4();
9
- default:
10
- return generateKey();
11
- }
4
+String generateWalletPassword() {
5
+ return generateKey();
6
}
lib/core/wallet_creation_service.dart
+36
-6
@@ -1,5 +1,6 @@
1
import 'package:cake_wallet/di.dart';
2
import 'package:cw_core/wallet_info.dart';
3
+import 'package:cake_wallet/entities/preferences_key.dart';
4
import 'package:flutter/foundation.dart';
5
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
6
import 'package:hive/hive.dart';
@@ -31,6 +32,8 @@ class WalletCreationService {
32
final Box<WalletInfo> walletInfoSource;
33
WalletService _service;
34
35
+ static const _isNewMoneroWalletPasswordUpdated = true;
36
+
37
void changeWalletType({@required WalletType type}) {
38
this.type = type;
39
_service = getIt.get<WalletService>(param1: type);
@@ -51,28 +54,55 @@ class WalletCreationService {
54
55
Future<WalletBase> create(WalletCredentials credentials) async {
56
checkIfExists(credentials.name);
54
- final password = generateWalletPassword(type);
57
+ final password = generateWalletPassword();
58
credentials.password = password;
59
await keyService.saveWalletPassword(
60
password: password, walletName: credentials.name);
58
- return await _service.create(credentials);
61
+ final wallet = await _service.create(credentials);
62
+
63
+ if (wallet.type == WalletType.monero) {
64
+ await sharedPreferences
65
+ .setBool(
66
+ PreferencesKey.moneroWalletUpdateV1Key(wallet.name),
67
+ _isNewMoneroWalletPasswordUpdated);
68
+ }
69
+
70
+ return wallet;
71
}
72
73
Future<WalletBase> restoreFromKeys(WalletCredentials credentials) async {
74
checkIfExists(credentials.name);
63
- final password = generateWalletPassword(type);
75
+ final password = generateWalletPassword();
76
credentials.password = password;
77
await keyService.saveWalletPassword(
78
password: password, walletName: credentials.name);
67
- return await _service.restoreFromKeys(credentials);
79
+ final wallet = await _service.restoreFromKeys(credentials);
80
+
81
+ if (wallet.type == WalletType.monero) {
82
+ await sharedPreferences
83
+ .setBool(
84
+ PreferencesKey.moneroWalletUpdateV1Key(wallet.name),
85
+ _isNewMoneroWalletPasswordUpdated);
86
+ }
87
+
88
+ return wallet;
89
}
90
91
Future<WalletBase> restoreFromSeed(WalletCredentials credentials) async {
92
checkIfExists(credentials.name);
72
- final password = generateWalletPassword(type);
93
+ final password = generateWalletPassword();
94
credentials.password = password;
95
await keyService.saveWalletPassword(
96
password: password, walletName: credentials.name);
76
- return await _service.restoreFromSeed(credentials);
97
+ final wallet = await _service.restoreFromSeed(credentials);
98
+
99
+ if (wallet.type == WalletType.monero) {
100
+ await sharedPreferences
101
+ .setBool(
102
+ PreferencesKey.moneroWalletUpdateV1Key(wallet.name),
103
+ _isNewMoneroWalletPasswordUpdated);
104
+ }
105
+
106
+ return wallet;
107
}
108
}
lib/core/wallet_loading_service.dart
new
+52
@@ -0,0 +1,52 @@
1
+import 'package:cake_wallet/core/generate_wallet_password.dart';
2
+import 'package:cake_wallet/core/key_service.dart';
3
+import 'package:cake_wallet/entities/preferences_key.dart';
4
+import 'package:cw_core/wallet_base.dart';
5
+import 'package:cw_core/wallet_service.dart';
6
+import 'package:cw_core/wallet_type.dart';
7
+import 'package:shared_preferences/shared_preferences.dart';
8
+
9
+class WalletLoadingService {
10
+ WalletLoadingService(
11
+ this.sharedPreferences,
12
+ this.keyService,
13
+ this.walletServiceFactory);
14
+
15
+ final SharedPreferences sharedPreferences;
16
+ final KeyService keyService;
17
+ final WalletService Function(WalletType type) walletServiceFactory;
18
+
19
+ Future<WalletBase> load(WalletType type, String name) async {
20
+ if (walletServiceFactory == null) {
21
+ throw Exception('WalletLoadingService.walletServiceFactory is not set');
22
+ }
23
+ final walletService = walletServiceFactory?.call(type);
24
+ final password = await keyService.getWalletPassword(walletName: name);
25
+ final wallet = await walletService.openWallet(name, password);
26
+
27
+ if (type == WalletType.monero) {
28
+ await upateMoneroWalletPassword(wallet);
29
+ }
30
+
31
+ return wallet;
32
+ }
33
+
34
+ Future<void> upateMoneroWalletPassword(WalletBase wallet) async {
35
+ final key = PreferencesKey.moneroWalletUpdateV1Key(wallet.name);
36
+ var isPasswordUpdated = sharedPreferences.getBool(key) ?? false;
37
+
38
+ if (isPasswordUpdated) {
39
+ return;
40
+ }
41
+
42
+ final password = generateWalletPassword();
43
+ // Save new generated password with backup key for case
44
+ // if wallet will change password, but it will faild to updated in secure storage
45
+ final bakWalletName = '#__${wallet.name}_bak__#';
46
+ await keyService.saveWalletPassword(walletName: bakWalletName, password: password);
47
+ await wallet.changePassword(password);
48
+ await keyService.saveWalletPassword(walletName: wallet.name, password: password);
49
+ isPasswordUpdated = true;
50
+ await sharedPreferences.setBool(key, isPasswordUpdated);
51
+ }
52
+}
\ No newline at end of file
lib/di.dart
+8
-1
@@ -124,6 +124,7 @@ import 'package:cake_wallet/exchange/exchange_template.dart';
124
import 'package:cake_wallet/.secrets.g.dart' as secrets;
125
import 'package:cake_wallet/src/screens/dashboard/widgets/address_page.dart';
126
import 'package:cake_wallet/src/screens/receive/fullscreen_qr_page.dart';
127
+import 'package:cake_wallet/core/wallet_loading_service.dart';
128
129
final getIt = GetIt.instance;
130
@@ -218,6 +219,12 @@ Future setup(
219
sharedPreferences: getIt.get<SharedPreferences>(),
220
walletInfoSource: _walletInfoSource));
221
222
+ getIt.registerFactory<WalletLoadingService>(
223
+ () => WalletLoadingService(
224
+ getIt.get<SharedPreferences>(),
225
+ getIt.get<KeyService>(),
226
+ (WalletType type) => getIt.get<WalletService>(param1: type)));
227
+
228
getIt.registerFactoryParam<WalletNewVM, WalletType, void>((type, _) =>
229
WalletNewVM(getIt.get<AppStore>(),
230
getIt.get<WalletCreationService>(param1: type), _walletInfoSource,
@@ -352,7 +359,7 @@ Future setup(
359
getIt.registerFactory(() => WalletListViewModel(
360
_walletInfoSource,
361
getIt.get<AppStore>(),
355
- getIt.get<KeyService>()));
362
+ getIt.get<WalletLoadingService>()));
363
364
getIt.registerFactory(() =>
365
WalletListPage(walletListViewModel: getIt.get<WalletListViewModel>()));
lib/entities/load_current_wallet.dart
+3
-4
@@ -5,6 +5,7 @@ import 'package:cake_wallet/core/key_service.dart';
5
import 'package:cw_core/wallet_service.dart';
6
import 'package:cake_wallet/entities/preferences_key.dart';
7
import 'package:cw_core/wallet_type.dart';
8
+import 'package:cake_wallet/core/wallet_loading_service.dart';
9
10
Future<void> loadCurrentWallet() async {
11
final appStore = getIt.get<AppStore>();
@@ -15,9 +16,7 @@ Future<void> loadCurrentWallet() async {
16
getIt.get<SharedPreferences>().getInt(PreferencesKey.currentWalletType) ??
17
0;
18
final type = deserializeFromInt(typeRaw);
18
- final password =
19
- await getIt.get<KeyService>().getWalletPassword(walletName: name);
20
- final _service = getIt.get<WalletService>(param1: type);
21
- final wallet = await _service.openWallet(name, password);
19
+ final walletLoadingService = getIt.get<WalletLoadingService>();
20
+ final wallet = await walletLoadingService.load(type, name);
21
appStore.changeCurrentWallet(wallet);
22
}
lib/entities/preferences_key.dart
+4
@@ -22,4 +22,8 @@ class PreferencesKey {
22
static const bitcoinTransactionPriority = 'current_fee_priority_bitcoin';
23
static const shouldShowReceiveWarning = 'should_show_receive_warning';
24
static const shouldShowYatPopup = 'should_show_yat_popup';
25
+ static const moneroWalletPasswordUpdateV1Base = 'monero_wallet_update_v1';
26
+
27
+ static String moneroWalletUpdateV1Key(String name)
28
+ => '${PreferencesKey.moneroWalletPasswordUpdateV1Base}_${name}';
29
}
lib/view_model/wallet_list/wallet_list_view_model.dart
+6
-9
@@ -1,9 +1,9 @@
1
+import 'package:cake_wallet/core/wallet_loading_service.dart';
2
import 'package:cake_wallet/view_model/wallet_new_vm.dart';
3
import 'package:hive/hive.dart';
4
import 'package:mobx/mobx.dart';
5
import 'package:cake_wallet/di.dart';
6
import 'package:cake_wallet/store/app_store.dart';
6
-import 'package:cake_wallet/core/key_service.dart';
7
import 'package:cw_core/wallet_service.dart';
8
import 'package:cake_wallet/view_model/wallet_list/wallet_list_item.dart';
9
import 'package:cw_core/wallet_info.dart';
@@ -16,7 +16,7 @@ class WalletListViewModel = WalletListViewModelBase with _$WalletListViewModel;
16
17
abstract class WalletListViewModelBase with Store {
18
WalletListViewModelBase(this._walletInfoSource, this._appStore,
19
- this._keyService) {
19
+ this._walletLoadingService) {
20
wallets = ObservableList<WalletListItem>();
21
_updateList();
22
}
@@ -26,17 +26,14 @@ abstract class WalletListViewModelBase with Store {
26
27
final AppStore _appStore;
28
final Box<WalletInfo> _walletInfoSource;
29
- final KeyService _keyService;
29
+ final WalletLoadingService _walletLoadingService;
30
31
WalletType get currentWalletType => _appStore.wallet.type;
32
33
@action
34
- Future<void> loadWallet(WalletListItem wallet) async {
35
- final password =
36
- await _keyService.getWalletPassword(walletName: wallet.name);
37
- final walletService = getIt.get<WalletService>(param1: wallet.type);
38
- final loadedWallet = await walletService.openWallet(wallet.name, password);
39
- _appStore.changeCurrentWallet(loadedWallet);
34
+ Future<void> loadWallet(WalletListItem walletItem) async {
35
+ final wallet = await _walletLoadingService.load(walletItem.type, walletItem.name);
36
+ _appStore.changeCurrentWallet(wallet);
37
_updateList();
38
}
39
lib/view_model/wallet_restoration_from_keys_vm.dart
+1
-1
@@ -45,7 +45,7 @@ abstract class WalletRestorationFromKeysVMBase extends WalletCreationVM
45
46
@override
47
WalletCredentials getCredentials(dynamic options) {
48
- final password = generateWalletPassword(type);
48
+ final password = generateWalletPassword();
49
50
switch (type) {
51
case WalletType.monero:
lib/view_model/wallet_restoration_from_seed_vm.dart
+1
-1
@@ -36,7 +36,7 @@ abstract class WalletRestorationFromSeedVMBase extends WalletCreationVM
36
37
@override
38
WalletCredentials getCredentials(dynamic options) {
39
- final password = generateWalletPassword(type);
39
+ final password = generateWalletPassword();
40
41
switch (type) {
42
case WalletType.monero:
lib/view_model/wallet_restore_view_model.dart
+1
-1
@@ -53,7 +53,7 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store {
53
54
@override
55
WalletCredentials getCredentials(dynamic options) {
56
- final password = generateWalletPassword(type);
56
+ final password = generateWalletPassword();
57
final height = options['height'] as int;
58
name = options['name'] as String;
59
scripts/android/app_env.sh
+4
-4
@@ -14,14 +14,14 @@ TYPES=($MONERO_COM $CAKEWALLET $HAVEN)
14
APP_ANDROID_TYPE=$1
15
16
MONERO_COM_NAME="Monero.com"
17
-MONERO_COM_VERSION="1.0.6"
18
-MONERO_COM_BUILD_NUMBER=13
17
+MONERO_COM_VERSION="1.0.7"
18
+MONERO_COM_BUILD_NUMBER=14
19
MONERO_COM_BUNDLE_ID="com.monero.app"
20
MONERO_COM_PACKAGE="com.monero.app"
21
22
CAKEWALLET_NAME="Cake Wallet"
23
-CAKEWALLET_VERSION="4.4.1"
24
-CAKEWALLET_BUILD_NUMBER=104
23
+CAKEWALLET_VERSION="4.4.3"
24
+CAKEWALLET_BUILD_NUMBER=105
25
CAKEWALLET_BUNDLE_ID="com.cakewallet.cake_wallet"
26
CAKEWALLET_PACKAGE="com.cakewallet.cake_wallet"
27
scripts/ios/app_env.sh
+4
-4
@@ -13,13 +13,13 @@ TYPES=($MONERO_COM $CAKEWALLET $HAVEN)
13
APP_IOS_TYPE=$1
14
15
MONERO_COM_NAME="Monero.com"
16
-MONERO_COM_VERSION="1.0.6"
17
-MONERO_COM_BUILD_NUMBER=16
16
+MONERO_COM_VERSION="1.0.7"
17
+MONERO_COM_BUILD_NUMBER=17
18
MONERO_COM_BUNDLE_ID="com.cakewallet.monero"
19
20
CAKEWALLET_NAME="Cake Wallet"
21
-CAKEWALLET_VERSION="4.4.1"
22
-CAKEWALLET_BUILD_NUMBER=100
21
+CAKEWALLET_VERSION="4.4.3"
22
+CAKEWALLET_BUILD_NUMBER=104
23
CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet"
24
25
HAVEN_NAME="Haven"