CW-599-Extract-Secure-Storage (#1353)
* feat: Modify app to depend on secure storage abstraction instead of the direct package * chore: Revert command * Update configure.dart [skip ci] * Update configure.dart * Fix conflicts * clean up and fixes * minor fix --------- Co-authored-by: Omar Hatem <omarh.ismail1@gmail.com>
Adegoke David committed
May 8, 2024 at 21:23 UTC
bfb78eded98085b8f0a65f233b332490d8e4e5a7
23 files changed
+259
-199
.gitignore
+1
@@ -156,6 +156,7 @@ assets/images/app_logo.png
156
macos/Runner/Info.plist
157
macos/Runner/DebugProfile.entitlements
158
macos/Runner/Release.entitlements
159
+lib/core/secure_storage.dart
160
161
macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png
162
macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png
lib/core/auth_service.dart
+4
-10
@@ -1,5 +1,4 @@
1
import 'dart:async';
2
-import 'dart:io';
2
3
import 'package:cake_wallet/core/secure_storage.dart';
4
import 'package:cake_wallet/core/totp_request_details.dart';
@@ -7,7 +6,6 @@ import 'package:cake_wallet/routes.dart';
6
import 'package:cake_wallet/src/screens/auth/auth_page.dart';
7
import 'package:flutter/material.dart';
8
import 'package:mobx/mobx.dart';
10
-import 'package:flutter_secure_storage/flutter_secure_storage.dart';
9
import 'package:shared_preferences/shared_preferences.dart';
10
import 'package:cake_wallet/entities/preferences_key.dart';
11
import 'package:cake_wallet/entities/secret_store_key.dart';
@@ -35,14 +33,14 @@ class AuthService with Store {
33
Routes.restoreOptions,
34
];
35
38
- final FlutterSecureStorage secureStorage;
36
+ final SecureStorage secureStorage;
37
final SharedPreferences sharedPreferences;
38
final SettingsStore settingsStore;
39
40
Future<void> setPassword(String password) async {
41
final key = generateStoreKeyFor(key: SecretStoreKey.pinCodePassword);
42
final encodedPassword = encodedPinCode(pin: password);
45
- await writeSecureStorage(secureStorage, key: key, value: encodedPassword);
43
+ await secureStorage.write(key: key, value: encodedPassword);
44
}
45
46
Future<bool> canAuthenticate() async {
@@ -61,7 +59,7 @@ class AuthService with Store {
59
60
Future<bool> authenticate(String pin) async {
61
final key = generateStoreKeyFor(key: SecretStoreKey.pinCodePassword);
64
- final encodedPin = await readSecureStorage(secureStorage, key);
62
+ final encodedPin = await secureStorage.read(key: key);
63
final decodedPin = decodedPinCode(pin: encodedPin!);
64
65
return decodedPin == pin;
@@ -69,11 +67,7 @@ class AuthService with Store {
67
68
void saveLastAuthTime() {
69
int timestamp = DateTime.now().millisecondsSinceEpoch;
72
- writeSecureStorage(
73
- secureStorage,
74
- key: SecureKey.lastAuthTimeMilliseconds,
75
- value: timestamp.toString(),
76
- );
70
+ secureStorage.write(key: SecureKey.lastAuthTimeMilliseconds, value: timestamp.toString());
71
}
72
73
Future<bool> requireAuth() async {
lib/core/backup_service.dart
+8
-11
@@ -7,7 +7,6 @@ import 'package:cake_wallet/utils/device_info.dart';
7
import 'package:cw_core/wallet_type.dart';
8
import 'package:flutter/foundation.dart';
9
import 'package:hive/hive.dart';
10
-import 'package:flutter_secure_storage/flutter_secure_storage.dart';
10
import 'package:path_provider/path_provider.dart';
11
import 'package:cryptography/cryptography.dart';
12
import 'package:shared_preferences/shared_preferences.dart';
@@ -25,7 +24,7 @@ import 'package:cake_backup/backup.dart' as cake_backup;
24
25
class BackupService {
26
BackupService(
28
- this._flutterSecureStorage, this._walletInfoSource, this._keyService, this._sharedPreferences)
27
+ this._secureStorage, this._walletInfoSource, this._keyService, this._sharedPreferences)
28
: _cipher = Cryptography.instance.chacha20Poly1305Aead(),
29
_correctWallets = <WalletInfo>[];
30
@@ -35,7 +34,7 @@ class BackupService {
34
static const _v2 = 2;
35
36
final Cipher _cipher;
38
- final FlutterSecureStorage _flutterSecureStorage;
37
+ final SecureStorage _secureStorage;
38
final SharedPreferences _sharedPreferences;
39
final Box<WalletInfo> _walletInfoSource;
40
final KeyService _keyService;
@@ -374,15 +373,14 @@ class BackupService {
373
final backupPasswordKey = generateStoreKeyFor(key: SecretStoreKey.backupPassword);
374
final backupPassword = keychainJSON[backupPasswordKey] as String;
375
377
- await writeSecureStorage(_flutterSecureStorage, key: backupPasswordKey, value: backupPassword);
376
+ await _secureStorage.write(key: backupPasswordKey, value: backupPassword);
377
378
keychainWalletsInfo.forEach((dynamic rawInfo) async {
379
final info = rawInfo as Map<String, dynamic>;
380
await importWalletKeychainInfo(info);
381
});
382
384
- await writeSecureStorage(_flutterSecureStorage,
385
- key: pinCodeKey, value: encodedPinCode(pin: decodedPin));
383
+ await _secureStorage.write(key: pinCodeKey, value: encodedPinCode(pin: decodedPin));
384
385
keychainDumpFile.deleteSync();
386
}
@@ -401,15 +399,14 @@ class BackupService {
399
final backupPasswordKey = generateStoreKeyFor(key: SecretStoreKey.backupPassword);
400
final backupPassword = keychainJSON[backupPasswordKey] as String;
401
404
- await writeSecureStorage(_flutterSecureStorage, key: backupPasswordKey, value: backupPassword);
402
+ await _secureStorage.write(key: backupPasswordKey, value: backupPassword);
403
404
keychainWalletsInfo.forEach((dynamic rawInfo) async {
405
final info = rawInfo as Map<String, dynamic>;
406
await importWalletKeychainInfo(info);
407
});
408
411
- await writeSecureStorage(_flutterSecureStorage,
412
- key: pinCodeKey, value: encodedPinCode(pin: decodedPin));
409
+ await _secureStorage.write(key: pinCodeKey, value: encodedPinCode(pin: decodedPin));
410
411
keychainDumpFile.deleteSync();
412
}
@@ -429,7 +426,7 @@ class BackupService {
426
Future<Uint8List> _exportKeychainDumpV2(String password,
427
{String keychainSalt = secrets.backupKeychainSalt}) async {
428
final key = generateStoreKeyFor(key: SecretStoreKey.pinCodePassword);
432
- final encodedPin = await _flutterSecureStorage.read(key: key);
429
+ final encodedPin = await _secureStorage.read(key: key);
430
final decodedPin = decodedPinCode(pin: encodedPin!);
431
final wallets = await Future.wait(_walletInfoSource.values.map((walletInfo) async {
432
return {
@@ -439,7 +436,7 @@ class BackupService {
436
};
437
}));
438
final backupPasswordKey = generateStoreKeyFor(key: SecretStoreKey.backupPassword);
442
- final backupPassword = await _flutterSecureStorage.read(key: backupPasswordKey);
439
+ final backupPassword = await _secureStorage.read(key: backupPasswordKey);
440
final data = utf8.encode(
441
json.encode({'pin': decodedPin, 'wallets': wallets, backupPasswordKey: backupPassword}));
442
final encrypted = await _encryptV2(Uint8List.fromList(data), '$keychainSalt$password');
lib/core/key_service.dart
+9
-10
@@ -1,31 +1,30 @@
1
import 'package:cake_wallet/core/secure_storage.dart';
2
-import 'package:flutter_secure_storage/flutter_secure_storage.dart';
2
import 'package:cake_wallet/entities/secret_store_key.dart';
3
import 'package:cake_wallet/entities/encrypt.dart';
4
5
class KeyService {
6
KeyService(this._secureStorage);
7
9
- final FlutterSecureStorage _secureStorage;
8
+ final SecureStorage _secureStorage;
9
10
Future<String> getWalletPassword({required String walletName}) async {
12
- final key = generateStoreKeyFor(
13
- key: SecretStoreKey.moneroWalletPassword, walletName: walletName);
14
- final encodedPassword = await readSecureStorage(_secureStorage, key);
11
+ final key =
12
+ generateStoreKeyFor(key: SecretStoreKey.moneroWalletPassword, walletName: walletName);
13
+ final encodedPassword = await _secureStorage.read(key: key);
14
return decodeWalletPassword(password: encodedPassword!);
15
}
16
17
Future<void> saveWalletPassword({required String walletName, required String password}) async {
19
- final key = generateStoreKeyFor(
20
- key: SecretStoreKey.moneroWalletPassword, walletName: walletName);
18
+ final key =
19
+ generateStoreKeyFor(key: SecretStoreKey.moneroWalletPassword, walletName: walletName);
20
final encodedPassword = encodeWalletPassword(password: password);
21
23
- await writeSecureStorage(_secureStorage, key: key, value: encodedPassword);
22
+ await _secureStorage.write(key: key, value: encodedPassword);
23
}
24
25
Future<void> deleteWalletPassword({required String walletName}) async {
27
- final key = generateStoreKeyFor(
28
- key: SecretStoreKey.moneroWalletPassword, walletName: walletName);
26
+ final key =
27
+ generateStoreKeyFor(key: SecretStoreKey.moneroWalletPassword, walletName: walletName);
28
29
await _secureStorage.delete(key: key);
30
}
lib/core/secure_storage.dart
deleted
-38
@@ -1,38 +0,0 @@
1
-import 'dart:async';
2
-import 'dart:io';
3
-import 'package:flutter_secure_storage/flutter_secure_storage.dart';
4
-// For now, we can create a utility function to handle this.
5
-//
6
-// However, we could look into abstracting the entire FlutterSecureStorage package
7
-// so the app doesn't depend on the package directly but an absraction.
8
-// It'll make these kind of modifications to read/write come from a single point.
9
-
10
-Future<String?> readSecureStorage(FlutterSecureStorage secureStorage, String key) async {
11
- String? result;
12
- const maxWait = Duration(seconds: 3);
13
- const checkInterval = Duration(milliseconds: 200);
14
-
15
- DateTime start = DateTime.now();
16
-
17
- while (result == null && DateTime.now().difference(start) < maxWait) {
18
- result = await secureStorage.read(key: key);
19
-
20
- if (result != null) {
21
- break;
22
- }
23
-
24
- await Future.delayed(checkInterval);
25
- }
26
-
27
- return result;
28
-}
29
-
30
-Future<void> writeSecureStorage(FlutterSecureStorage secureStorage,
31
- {required String key, required String value}) async {
32
- // delete the value before writing on macOS because of a weird bug
33
- // https://github.com/mogol/flutter_secure_storage/issues/581
34
- if (Platform.isMacOS) {
35
- await secureStorage.delete(key: key);
36
- }
37
- await secureStorage.write(key: key, value: value);
38
-}
lib/core/wallet_creation_service.dart
+2
-2
@@ -1,8 +1,8 @@
1
+import 'package:cake_wallet/core/secure_storage.dart';
2
import 'package:cake_wallet/di.dart';
3
import 'package:cake_wallet/store/settings_store.dart';
4
import 'package:cw_core/wallet_info.dart';
5
import 'package:cake_wallet/entities/preferences_key.dart';
5
-import 'package:flutter_secure_storage/flutter_secure_storage.dart';
6
import 'package:hive/hive.dart';
7
import 'package:shared_preferences/shared_preferences.dart';
8
import 'package:cake_wallet/core/key_service.dart';
@@ -25,7 +25,7 @@ class WalletCreationService {
25
}
26
27
WalletType type;
28
- final FlutterSecureStorage secureStorage;
28
+ final SecureStorage secureStorage;
29
final SharedPreferences sharedPreferences;
30
final SettingsStore settingsStore;
31
final KeyService keyService;
lib/di.dart
+38
-12
@@ -236,6 +236,32 @@ import 'package:get_it/get_it.dart';
236
import 'package:hive/hive.dart';
237
import 'package:mobx/mobx.dart';
238
import 'package:shared_preferences/shared_preferences.dart';
239
+import 'package:cake_wallet/core/secure_storage.dart';
240
+import 'package:cake_wallet/core/wallet_creation_service.dart';
241
+import 'package:cake_wallet/store/app_store.dart';
242
+import 'package:cw_core/wallet_type.dart';
243
+import 'package:cake_wallet/view_model/wallet_new_vm.dart';
244
+import 'package:cake_wallet/store/authentication_store.dart';
245
+import 'package:cake_wallet/store/dashboard/trades_store.dart';
246
+import 'package:cake_wallet/store/dashboard/trade_filter_store.dart';
247
+import 'package:cake_wallet/store/dashboard/transaction_filter_store.dart';
248
+import 'package:cake_wallet/store/dashboard/fiat_conversion_store.dart';
249
+import 'package:cake_wallet/store/templates/send_template_store.dart';
250
+import 'package:cake_wallet/store/templates/exchange_template_store.dart';
251
+import 'package:cake_wallet/entities/template.dart';
252
+import 'package:cake_wallet/exchange/exchange_template.dart';
253
+import 'package:cake_wallet/.secrets.g.dart' as secrets;
254
+import 'package:cake_wallet/src/screens/dashboard/pages/address_page.dart';
255
+import 'package:cake_wallet/anypay/anypay_api.dart';
256
+import 'package:cake_wallet/view_model/ionia/ionia_gift_card_details_view_model.dart';
257
+import 'package:cake_wallet/src/screens/ionia/cards/ionia_payment_status_page.dart';
258
+import 'package:cake_wallet/view_model/ionia/ionia_payment_status_view_model.dart';
259
+import 'package:cake_wallet/anypay/any_pay_payment_committed_info.dart';
260
+import 'package:cake_wallet/ionia/ionia_any_pay_payment_info.dart';
261
+import 'package:cake_wallet/src/screens/receive/fullscreen_qr_page.dart';
262
+import 'package:cake_wallet/core/wallet_loading_service.dart';
263
+import 'package:cw_core/crypto_currency.dart';
264
+import 'package:cake_wallet/entities/qr_view_data.dart';
265
266
import 'buy/dfx/dfx_buy_provider.dart';
267
import 'core/totp_request_details.dart';
@@ -268,7 +294,7 @@ Future<void> setup({
294
required Box<Order> ordersSource,
295
required Box<UnspentCoinsInfo> unspentCoinsInfoSource,
296
required Box<AnonpayInvoiceInfo> anonpayInvoiceInfoSource,
271
- required FlutterSecureStorage secureStorage,
297
+ required SecureStorage secureStorage,
298
required GlobalKey<NavigatorState> navigatorKey,
299
}) async {
300
_walletInfoSource = walletInfoSource;
@@ -285,7 +311,7 @@ Future<void> setup({
311
312
if (!_isSetupFinished) {
313
getIt.registerSingletonAsync<SharedPreferences>(() => SharedPreferences.getInstance());
288
- getIt.registerSingleton<FlutterSecureStorage>(secureStorage);
314
+ getIt.registerSingleton<SecureStorage>(secureStorage);
315
}
316
if (!_isSetupFinished) {
317
getIt.registerFactory(() => BackgroundTasks());
@@ -333,22 +359,22 @@ Future<void> setup({
359
getIt.registerSingleton<ExchangeTemplateStore>(
360
ExchangeTemplateStore(templateSource: _exchangeTemplates));
361
getIt.registerSingleton<YatStore>(
336
- YatStore(appStore: getIt.get<AppStore>(), secureStorage: getIt.get<FlutterSecureStorage>())
362
+ YatStore(appStore: getIt.get<AppStore>(), secureStorage: getIt.get<SecureStorage>())
363
..init());
364
getIt.registerSingleton<AnonpayTransactionsStore>(
365
AnonpayTransactionsStore(anonpayInvoiceInfoSource: _anonpayInvoiceInfoSource));
366
341
- final secretStore = await SecretStoreBase.load(getIt.get<FlutterSecureStorage>());
367
+ final secretStore = await SecretStoreBase.load(getIt.get<SecureStorage>());
368
369
getIt.registerSingleton<SecretStore>(secretStore);
370
345
- getIt.registerFactory<KeyService>(() => KeyService(getIt.get<FlutterSecureStorage>()));
371
+ getIt.registerFactory<KeyService>(() => KeyService(getIt.get<SecureStorage>()));
372
373
getIt.registerFactoryParam<WalletCreationService, WalletType, void>((type, _) =>
374
WalletCreationService(
375
initialType: type,
376
keyService: getIt.get<KeyService>(),
351
- secureStorage: getIt.get<FlutterSecureStorage>(),
377
+ secureStorage: getIt.get<SecureStorage>(),
378
sharedPreferences: getIt.get<SharedPreferences>(),
379
settingsStore: getIt.get<SettingsStore>(),
380
walletInfoSource: _walletInfoSource));
@@ -403,7 +429,7 @@ Future<void> setup({
429
430
getIt.registerFactory<AuthService>(
431
() => AuthService(
406
- secureStorage: getIt.get<FlutterSecureStorage>(),
432
+ secureStorage: getIt.get<SecureStorage>(),
433
sharedPreferences: getIt.get<SharedPreferences>(),
434
settingsStore: getIt.get<SettingsStore>(),
435
),
@@ -980,16 +1006,16 @@ Future<void> setup({
1006
trades: _tradesSource,
1007
settingsStore: getIt.get<SettingsStore>()));
1008
983
- getIt.registerFactory(() => BackupService(getIt.get<FlutterSecureStorage>(), _walletInfoSource,
1009
+ getIt.registerFactory(() => BackupService(getIt.get<SecureStorage>(), _walletInfoSource,
1010
getIt.get<KeyService>(), getIt.get<SharedPreferences>()));
1011
1012
getIt.registerFactory(() => BackupViewModel(
987
- getIt.get<FlutterSecureStorage>(), getIt.get<SecretStore>(), getIt.get<BackupService>()));
1013
+ getIt.get<SecureStorage>(), getIt.get<SecretStore>(), getIt.get<BackupService>()));
1014
1015
getIt.registerFactory(() => BackupPage(getIt.get<BackupViewModel>()));
1016
1017
getIt.registerFactory(() =>
992
- EditBackupPasswordViewModel(getIt.get<FlutterSecureStorage>(), getIt.get<SecretStore>()));
1018
+ EditBackupPasswordViewModel(getIt.get<SecureStorage>(), getIt.get<SecretStore>()));
1019
1020
getIt.registerFactory(() => EditBackupPasswordPage(getIt.get<EditBackupPasswordViewModel>()));
1021
@@ -1038,7 +1064,7 @@ Future<void> setup({
1064
getIt.registerFactory(() => SupportPage(getIt.get<SupportViewModel>()));
1065
1066
getIt.registerFactory(() => SupportChatPage(getIt.get<SupportViewModel>(),
1041
- secureStorage: getIt.get<FlutterSecureStorage>()));
1067
+ secureStorage: getIt.get<SecureStorage>()));
1068
1069
getIt.registerFactory(() => SupportOtherLinksPage(getIt.get<SupportViewModel>()));
1070
@@ -1080,7 +1106,7 @@ Future<void> setup({
1106
getIt.registerFactory(() => AnyPayApi());
1107
1108
getIt.registerFactory<IoniaService>(
1083
- () => IoniaService(getIt.get<FlutterSecureStorage>(), getIt.get<IoniaApi>()));
1109
+ () => IoniaService(getIt.get<SecureStorage>(), getIt.get<IoniaApi>()));
1110
1111
getIt.registerFactory<IoniaAnyPay>(() => IoniaAnyPay(
1112
getIt.get<IoniaService>(), getIt.get<AnyPayApi>(), getIt.get<AppStore>().wallet!));
lib/entities/default_settings_migration.dart
+8
-7
@@ -1,10 +1,10 @@
1
import 'dart:io' show Directory, File, Platform;
2
import 'package:cake_wallet/bitcoin/bitcoin.dart';
3
+import 'package:cake_wallet/core/secure_storage.dart';
4
import 'package:cake_wallet/entities/exchange_api_mode.dart';
5
import 'package:cake_wallet/entities/fiat_api_mode.dart';
6
import 'package:cw_core/pathForWallet.dart';
7
import 'package:cake_wallet/entities/secret_store_key.dart';
7
-import 'package:flutter_secure_storage/flutter_secure_storage.dart';
8
import 'package:hive/hive.dart';
9
import 'package:path_provider/path_provider.dart';
10
import 'package:shared_preferences/shared_preferences.dart';
@@ -42,7 +42,7 @@ const newCakeWalletBitcoinUri = 'btc-electrum.cakewallet.com:50002';
42
Future<void> defaultSettingsMigration(
43
{required int version,
44
required SharedPreferences sharedPreferences,
45
- required FlutterSecureStorage secureStorage,
45
+ required SecureStorage secureStorage,
46
required Box<Node> nodes,
47
required Box<Node> powNodes,
48
required Box<WalletInfo> walletInfoSource,
@@ -485,7 +485,7 @@ Node? getTronDefaultNode({required Box<Node> nodes}) {
485
486
Future<void> insecureStorageMigration({
487
required SharedPreferences sharedPreferences,
488
- required FlutterSecureStorage secureStorage,
488
+ required SecureStorage secureStorage,
489
}) async {
490
bool? allowBiometricalAuthentication =
491
sharedPreferences.getBool(SecureKey.allowBiometricalAuthenticationKey);
@@ -559,7 +559,7 @@ Future<void> insecureStorageMigration({
559
}
560
}
561
562
-Future<void> rewriteSecureStoragePin({required FlutterSecureStorage secureStorage}) async {
562
+Future<void> rewriteSecureStoragePin({required SecureStorage secureStorage}) async {
563
// the bug only affects ios/mac:
564
if (!Platform.isIOS && !Platform.isMacOS) {
565
return;
@@ -585,8 +585,9 @@ Future<void> rewriteSecureStoragePin({required FlutterSecureStorage secureStorag
585
await secureStorage.write(
586
key: keyForPinCode,
587
value: encodedPin,
588
- iOptions: IOSOptions(accessibility: KeychainAccessibility.first_unlock),
589
- mOptions: MacOsOptions(accessibility: KeychainAccessibility.first_unlock),
588
+ // TODO: find a way to add those with the generated secure storage
589
+ // iOptions: IOSOptions(accessibility: KeychainAccessibility.first_unlock),
590
+ // mOptions: MacOsOptions(accessibility: KeychainAccessibility.first_unlock),
591
);
592
}
593
@@ -720,7 +721,7 @@ Future<void> updateDisplayModes(SharedPreferences sharedPreferences) async {
721
await sharedPreferences.setInt(PreferencesKey.currentBalanceDisplayModeKey, balanceDisplayMode);
722
}
723
723
-Future<void> generateBackupPassword(FlutterSecureStorage secureStorage) async {
724
+Future<void> generateBackupPassword(SecureStorage secureStorage) async {
725
final key = generateStoreKeyFor(key: SecretStoreKey.backupPassword);
726
727
if ((await secureStorage.read(key: key))?.isNotEmpty ?? false) {
lib/entities/fs_migration.dart
+24
-42
@@ -2,7 +2,6 @@ import 'dart:io';
2
import 'dart:convert';
3
import 'package:cake_wallet/core/secure_storage.dart';
4
import 'package:collection/collection.dart';
5
-import 'package:flutter_secure_storage/flutter_secure_storage.dart';
5
import 'package:shared_preferences/shared_preferences.dart';
6
import 'package:hive/hive.dart';
7
import 'package:path_provider/path_provider.dart';
@@ -11,8 +10,7 @@ import 'package:cake_wallet/entities/contact.dart';
10
import 'package:cw_core/crypto_currency.dart';
11
import 'package:cake_wallet/entities/encrypt.dart';
12
import 'package:cake_wallet/entities/fiat_currency.dart';
14
-import 'package:cake_wallet/entities/ios_legacy_helper.dart'
15
- as ios_legacy_helper;
13
+import 'package:cake_wallet/entities/ios_legacy_helper.dart' as ios_legacy_helper;
14
import 'package:cake_wallet/entities/preferences_key.dart';
15
import 'package:cake_wallet/entities/secret_store_key.dart';
16
import 'package:cw_core/wallet_info.dart';
@@ -30,8 +28,8 @@ Future<void> migrate_android_v1() async {
28
await android_migrate_wallets(appDocDir: appDocDir);
29
}
30
33
-Future<void> ios_migrate_v1(Box<WalletInfo> walletInfoSource,
34
- Box<Trade> tradeSource, Box<Contact> contactSource) async {
31
+Future<void> ios_migrate_v1(
32
+ Box<WalletInfo> walletInfoSource, Box<Trade> tradeSource, Box<Contact> contactSource) async {
33
final prefs = await SharedPreferences.getInstance();
34
35
if (prefs.getBool('ios_migration_v1_completed') ?? false) {
@@ -67,10 +65,7 @@ Future<void> ios_migrate_user_defaults() async {
65
if (activeCurrency != null) {
66
final convertedCurrency = convertFiatLegacy(activeCurrency);
67
70
- if (convertedCurrency != null) {
71
- await prefs.setString(
72
- 'current_fiat_currency', convertedCurrency.serialize());
73
- }
68
+ await prefs.setString('current_fiat_currency', convertedCurrency.serialize());
69
}
70
71
//translate fee priority
@@ -81,24 +76,21 @@ Future<void> ios_migrate_user_defaults() async {
76
}
77
78
//translate current balance mode
84
- final currentBalanceMode =
85
- await ios_legacy_helper.getInt('display_balance_mode');
79
+ final currentBalanceMode = await ios_legacy_helper.getInt('display_balance_mode');
80
if (currentBalanceMode != null) {
81
await prefs.setInt('current_balance_display_mode', currentBalanceMode);
82
}
83
84
//translate should save recipient address
91
- final shouldSave =
92
- await ios_legacy_helper.getBool('should_save_recipient_address');
93
-
85
+ final shouldSave = await ios_legacy_helper.getBool('should_save_recipient_address');
86
+
87
if (shouldSave != null) {
88
await prefs.setBool('save_recipient_address', shouldSave);
89
}
90
91
//translate biometric
99
- final biometricOn =
100
- await ios_legacy_helper.getBool('biometric_authentication_on');
101
-
92
+ final biometricOn = await ios_legacy_helper.getBool('biometric_authentication_on');
93
+
94
if (biometricOn != null) {
95
await prefs.setBool('allow_biometrical_authentication', biometricOn);
96
}
@@ -137,9 +129,8 @@ Future<void> ios_migrate_pin() async {
129
return;
130
}
131
140
- final flutterSecureStorage = FlutterSecureStorage();
141
- final pinPassword = await flutterSecureStorage.read(
142
- key: 'pin_password', iOptions: IOSOptions());
132
+ final flutterSecureStorage = secureStorageShared;
133
+ final pinPassword = await flutterSecureStorage.readNoIOptions(key: 'pin_password');
134
// No pin
135
if (pinPassword == null) {
136
await prefs.setBool('ios_migration_pin_completed', true);
@@ -148,7 +139,7 @@ Future<void> ios_migrate_pin() async {
139
140
final key = generateStoreKeyFor(key: SecretStoreKey.pinCodePassword);
141
final encodedPassword = encodedPinCode(pin: pinPassword);
151
- await writeSecureStorage(flutterSecureStorage, key: key, value: encodedPassword);
142
+ await flutterSecureStorage.write(key: key, value: encodedPassword);
143
144
await prefs.setBool('ios_migration_pin_completed', true);
145
}
@@ -161,7 +152,7 @@ Future<void> ios_migrate_wallet_passwords() async {
152
}
153
154
final appDocDir = await getApplicationDocumentsDirectory();
164
- final flutterSecureStorage = FlutterSecureStorage();
155
+ final flutterSecureStorage = secureStorageShared;
156
final keyService = KeyService(flutterSecureStorage);
157
final walletsDir = Directory('${appDocDir.path}/wallets');
158
final moneroWalletsDir = Directory('${walletsDir.path}/monero');
@@ -176,10 +167,8 @@ Future<void> ios_migrate_wallet_passwords() async {
167
if (item is Directory) {
168
final name = item.path.split('/').last;
169
final oldKey = 'wallet_monero_' + name + '_password';
179
- final password = await flutterSecureStorage.read(
180
- key: oldKey, iOptions: IOSOptions());
181
- await keyService.saveWalletPassword(
182
- walletName: name, password: password!);
170
+ final password = await flutterSecureStorage.readNoIOptions(key: oldKey);
171
+ await keyService.saveWalletPassword(walletName: name, password: password!);
172
}
173
} catch (e) {
174
print(e.toString());
@@ -311,18 +300,14 @@ Future<void> ios_migrate_wallet_info(Box<WalletInfo> walletsInfoSource) async {
300
return null;
301
}
302
314
- final config = json.decode(configFile.readAsStringSync())
315
- as Map<String, dynamic>;
316
- final isRecovery = config['isRecovery'] as bool ?? false;
303
+ final config = json.decode(configFile.readAsStringSync()) as Map<String, dynamic>;
304
+ final isRecovery = config['isRecovery'] as bool? ?? false;
305
final dateAsDouble = config['date'] as double;
306
final timestamp = dateAsDouble.toInt() * 1000;
307
final date = DateTime.fromMillisecondsSinceEpoch(timestamp);
320
- final id = walletTypeToString(WalletType.monero).toLowerCase() +
321
- '_' +
322
- name;
323
- final exist = walletsInfoSource.values
324
- .firstWhereOrNull((el) => el.id == id) != null;
325
-
308
+ final id = walletTypeToString(WalletType.monero).toLowerCase() + '_' + name;
309
+ final exist = walletsInfoSource.values.firstWhereOrNull((el) => el.id == id) != null;
310
+
311
if (exist) {
312
return null;
313
}
@@ -373,12 +358,10 @@ Future<void> ios_migrate_trades_list(Box<Trade> tradeSource) async {
358
}
359
360
final content = file.readAsBytesSync();
376
- final flutterSecureStorage = FlutterSecureStorage();
377
- final masterPassword = await flutterSecureStorage.read(
378
- key: 'master_password', iOptions: IOSOptions());
361
+ final flutterSecureStorage = secureStorageShared;
362
+ final masterPassword = await flutterSecureStorage.readNoIOptions(key: 'master_password');
363
final key = masterPassword!.replaceAll('-', '');
380
- final decoded =
381
- await ios_legacy_helper.decrypt(content, key: key, salt: secrets.salt);
364
+ final decoded = await ios_legacy_helper.decrypt(content, key: key, salt: secrets.salt);
365
final decodedJson = json.decode(decoded) as List<dynamic>;
366
final trades = decodedJson.map((dynamic el) {
367
final elAsMap = el as Map<String, dynamic>;
@@ -441,8 +424,7 @@ Future<void> ios_migrate_address_book(Box<Contact> contactSource) async {
424
final address = _item["address"] as String;
425
final name = _item["name"] as String;
426
444
- return Contact(
445
- address: address, name: name, type: CryptoCurrency.fromString(type));
427
+ return Contact(address: address, name: name, type: CryptoCurrency.fromString(type));
428
});
429
430
await contactSource.addAll(contacts);
lib/entities/get_encryption_key.dart
+2
-3
@@ -1,9 +1,8 @@
1
import 'package:cake_wallet/core/secure_storage.dart';
2
-import 'package:flutter_secure_storage/flutter_secure_storage.dart';
2
import 'package:cw_core/cake_hive.dart';
3
4
Future<List<int>> getEncryptionKey(
6
- {required String forKey, required FlutterSecureStorage secureStorage}) async {
5
+ {required String forKey, required SecureStorage secureStorage}) async {
6
final stringifiedKey = await secureStorage.read(key: 'transactionDescriptionsBoxKey');
7
List<int> key;
8
@@ -11,7 +10,7 @@ Future<List<int>> getEncryptionKey(
10
key = CakeHive.generateSecureKey();
11
final keyStringified = key.join(',');
12
String storageKey = 'transactionDescriptionsBoxKey';
14
- await writeSecureStorage(secureStorage, key: storageKey, value: keyStringified);
13
+ await secureStorage.write(key: storageKey, value: keyStringified);
14
} else {
15
key = stringifiedKey.split(',').map((i) => int.parse(i)).toList();
16
}
lib/entities/preferences_key.dart
+3
-3
@@ -61,9 +61,9 @@ class PreferencesKey {
61
static const defaultBananoRep = 'default_banano_representative';
62
static const lookupsTwitter = 'looks_up_twitter';
63
static const lookupsMastodon = 'looks_up_mastodon';
64
- static const lookupsYatService = 'looks_up_mastodon';
65
- static const lookupsUnstoppableDomains = 'looks_up_mastodon';
66
- static const lookupsOpenAlias = 'looks_up_mastodon';
64
+ static const lookupsYatService = 'looks_up_yat';
65
+ static const lookupsUnstoppableDomains = 'looks_up_unstoppable_domain';
66
+ static const lookupsOpenAlias = 'looks_up_open_alias';
67
static const lookupsENS = 'looks_up_ens';
68
69
static String moneroWalletUpdateV1Key(String name) =>
lib/entities/secret_store_key.dart
+4
-4
@@ -1,4 +1,4 @@
1
-import 'package:flutter_secure_storage/flutter_secure_storage.dart';
1
+import 'package:cake_wallet/core/secure_storage.dart';
2
import 'package:shared_preferences/shared_preferences.dart';
3
4
enum SecretStoreKey { moneroWalletPassword, pinCodePassword, backupPassword }
@@ -66,7 +66,7 @@ class SecureKey {
66
static const lastAuthTimeMilliseconds = 'last_auth_time_milliseconds';
67
68
static Future<int?> getInt({
69
- required FlutterSecureStorage secureStorage,
69
+ required SecureStorage secureStorage,
70
required SharedPreferences sharedPreferences,
71
required String key,
72
}) async {
@@ -76,7 +76,7 @@ class SecureKey {
76
}
77
78
static Future<bool?> getBool({
79
- required FlutterSecureStorage secureStorage,
79
+ required SecureStorage secureStorage,
80
required SharedPreferences sharedPreferences,
81
required String key,
82
}) async {
@@ -91,7 +91,7 @@ class SecureKey {
91
}
92
93
static Future<String?> getString({
94
- required FlutterSecureStorage secureStorage,
94
+ required SecureStorage secureStorage,
95
required SharedPreferences sharedPreferences,
96
required String key,
97
}) async {
lib/ionia/ionia_service.dart
+2
-2
@@ -1,7 +1,7 @@
1
+import 'package:cake_wallet/core/secure_storage.dart';
2
import 'package:cake_wallet/ionia/ionia_merchant.dart';
3
import 'package:cake_wallet/ionia/ionia_order.dart';
4
import 'package:cake_wallet/ionia/ionia_virtual_card.dart';
4
-import 'package:flutter_secure_storage/flutter_secure_storage.dart';
5
import 'package:cake_wallet/.secrets.g.dart' as secrets;
6
import 'package:cake_wallet/ionia/ionia_api.dart';
7
import 'package:cake_wallet/ionia/ionia_gift_card.dart';
@@ -16,7 +16,7 @@ class IoniaService {
16
17
static String get clientId => secrets.ioniaClientId;
18
19
- final FlutterSecureStorage secureStorage;
19
+ final SecureStorage secureStorage;
20
final IoniaApi ioniaApi;
21
22
// Create user
lib/main.dart
+4
-5
@@ -1,6 +1,7 @@
1
import 'dart:async';
2
import 'package:cake_wallet/anonpay/anonpay_invoice_info.dart';
3
import 'package:cake_wallet/core/auth_service.dart';
4
+import 'package:cake_wallet/core/secure_storage.dart';
5
import 'package:cake_wallet/entities/language_service.dart';
6
import 'package:cake_wallet/buy/order.dart';
7
import 'package:cake_wallet/locales/locale.dart';
@@ -18,7 +19,6 @@ import 'package:hive/hive.dart';
19
import 'package:cake_wallet/di.dart';
20
import 'package:path_provider/path_provider.dart';
21
import 'package:shared_preferences/shared_preferences.dart';
21
-import 'package:flutter_secure_storage/flutter_secure_storage.dart';
22
import 'package:flutter_mobx/flutter_mobx.dart';
23
import 'package:cake_wallet/themes/theme_base.dart';
24
import 'package:cake_wallet/router.dart' as Router;
@@ -138,9 +138,8 @@ Future<void> initializeAppConfigs() async {
138
CakeHive.registerAdapter(AnonpayInvoiceInfoAdapter());
139
}
140
141
- final secureStorage = FlutterSecureStorage(
142
- iOptions: IOSOptions(accessibility: KeychainAccessibility.first_unlock),
143
- );
141
+ final secureStorage = secureStorageShared;
142
+
143
final transactionDescriptionsBoxKey =
144
await getEncryptionKey(secureStorage: secureStorage, forKey: TransactionDescription.boxKey);
145
final tradesBoxKey = await getEncryptionKey(secureStorage: secureStorage, forKey: Trade.boxKey);
@@ -191,7 +190,7 @@ Future<void> initialSetup(
190
required Box<Template> templates,
191
required Box<ExchangeTemplate> exchangeTemplates,
192
required Box<TransactionDescription> transactionDescriptions,
194
- required FlutterSecureStorage secureStorage,
193
+ required SecureStorage secureStorage,
194
required Box<AnonpayInvoiceInfo> anonpayInvoiceInfo,
195
required Box<UnspentCoinsInfo> unspentCoinsInfoSource,
196
int initialMigrationVersion = 15}) async {
lib/src/screens/support_chat/support_chat_page.dart
+2
-2
@@ -1,16 +1,16 @@
1
+import 'package:cake_wallet/core/secure_storage.dart';
2
import 'package:cake_wallet/generated/i18n.dart';
3
import 'package:cake_wallet/src/screens/base_page.dart';
4
import 'package:cake_wallet/src/screens/support_chat/widgets/chatwoot_widget.dart';
5
import 'package:cake_wallet/view_model/support_view_model.dart';
6
import 'package:flutter/material.dart';
6
-import 'package:flutter_secure_storage/flutter_secure_storage.dart';
7
8
9
class SupportChatPage extends BasePage {
10
SupportChatPage(this.supportViewModel, {required this.secureStorage});
11
12
final SupportViewModel supportViewModel;
13
- final FlutterSecureStorage secureStorage;
13
+ final SecureStorage secureStorage;
14
15
@override
16
String get title => S.current.settings_support;
lib/src/screens/support_chat/widgets/chatwoot_widget.dart
+2
-3
@@ -3,14 +3,13 @@ import 'dart:convert';
3
import 'package:cake_wallet/core/secure_storage.dart';
4
import 'package:flutter/material.dart';
5
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
6
-import 'package:flutter_secure_storage/flutter_secure_storage.dart';
6
7
const COOKIE_KEY = 'chatwootCookie';
8
9
class ChatwootWidget extends StatefulWidget {
10
ChatwootWidget(this.secureStorage, {required this.supportUrl});
11
13
- final FlutterSecureStorage secureStorage;
12
+ final SecureStorage secureStorage;
13
final String supportUrl;
14
15
@override
@@ -59,6 +58,6 @@ class ChatwootWidgetState extends State<ChatwootWidget> {
58
}
59
60
Future<void> storeCookie(String value) async {
62
- await writeSecureStorage(widget.secureStorage, key: COOKIE_KEY, value: value);
61
+ await widget.secureStorage.write(key: COOKIE_KEY, value: value);
62
}
63
}
lib/store/secret_store.dart
+2
-3
@@ -1,6 +1,5 @@
1
+import 'package:cake_wallet/core/secure_storage.dart';
2
import 'package:cake_wallet/entities/secret_store_key.dart';
2
-import 'package:flutter/foundation.dart';
3
-import 'package:flutter_secure_storage/flutter_secure_storage.dart';
3
import 'package:mobx/mobx.dart';
4
5
part 'secret_store.g.dart';
@@ -8,7 +7,7 @@ part 'secret_store.g.dart';
7
class SecretStore = SecretStoreBase with _$SecretStore;
8
9
abstract class SecretStoreBase with Store {
11
- static Future<SecretStore> load(FlutterSecureStorage storage) async {
10
+ static Future<SecretStore> load(SecureStorage storage) async {
11
final secretStore = SecretStore();
12
final backupPasswordKey = generateStoreKeyFor(key: SecretStoreKey.backupPassword);
13
final backupPassword = await storage.read(key: backupPasswordKey);
lib/store/settings_store.dart
+21
-28
@@ -26,7 +26,6 @@ import 'package:cake_wallet/themes/theme_base.dart';
26
import 'package:cake_wallet/themes/theme_list.dart';
27
import 'package:device_info_plus/device_info_plus.dart';
28
import 'package:flutter/material.dart';
29
-import 'package:flutter_secure_storage/flutter_secure_storage.dart';
29
import 'package:hive/hive.dart';
30
import 'package:mobx/mobx.dart';
31
import 'package:package_info/package_info.dart';
@@ -48,7 +47,7 @@ class SettingsStore = SettingsStoreBase with _$SettingsStore;
47
48
abstract class SettingsStoreBase with Store {
49
SettingsStoreBase(
51
- {required FlutterSecureStorage secureStorage,
50
+ {required SecureStorage secureStorage,
51
required BackgroundTasks backgroundTasks,
52
required SharedPreferences sharedPreferences,
53
required bool initialShouldShowMarketPlaceInDashboard,
@@ -398,10 +397,8 @@ abstract class SettingsStoreBase with Store {
397
(bool usePolygonScan) =>
398
_sharedPreferences.setBool(PreferencesKey.usePolygonScan, usePolygonScan));
399
401
- reaction(
402
- (_) => useTronGrid,
403
- (bool useTronGrid) =>
404
- _sharedPreferences.setBool(PreferencesKey.useTronGrid, useTronGrid));
400
+ reaction((_) => useTronGrid,
401
+ (bool useTronGrid) => _sharedPreferences.setBool(PreferencesKey.useTronGrid, useTronGrid));
402
403
reaction((_) => defaultNanoRep,
404
(String nanoRep) => _sharedPreferences.setString(PreferencesKey.defaultNanoRep, nanoRep));
@@ -441,83 +438,79 @@ abstract class SettingsStoreBase with Store {
438
// secure storage keys:
439
reaction(
440
(_) => allowBiometricalAuthentication,
444
- (bool biometricalAuthentication) => writeSecureStorage(secureStorage,
441
+ (bool biometricalAuthentication) => secureStorage.write(
442
key: SecureKey.allowBiometricalAuthenticationKey,
443
value: biometricalAuthentication.toString()));
444
445
reaction(
446
(_) => selectedCake2FAPreset,
450
- (Cake2FAPresetsOptions selectedCake2FAPreset) => writeSecureStorage(secureStorage,
447
+ (Cake2FAPresetsOptions selectedCake2FAPreset) => secureStorage.write(
448
key: SecureKey.selectedCake2FAPreset,
449
value: selectedCake2FAPreset.serialize().toString()));
450
451
reaction(
452
(_) => shouldRequireTOTP2FAForAccessingWallet,
456
- (bool requireTOTP2FAForAccessingWallet) => writeSecureStorage(secureStorage,
453
+ (bool requireTOTP2FAForAccessingWallet) => secureStorage.write(
454
key: SecureKey.shouldRequireTOTP2FAForAccessingWallet,
455
value: requireTOTP2FAForAccessingWallet.toString()));
456
457
reaction(
458
(_) => shouldRequireTOTP2FAForSendsToContact,
462
- (bool requireTOTP2FAForSendsToContact) => writeSecureStorage(secureStorage,
459
+ (bool requireTOTP2FAForSendsToContact) => secureStorage.write(
460
key: SecureKey.shouldRequireTOTP2FAForSendsToContact,
461
value: requireTOTP2FAForSendsToContact.toString()));
462
463
reaction(
464
(_) => shouldRequireTOTP2FAForSendsToNonContact,
468
- (bool requireTOTP2FAForSendsToNonContact) => writeSecureStorage(secureStorage,
465
+ (bool requireTOTP2FAForSendsToNonContact) => secureStorage.write(
466
key: SecureKey.shouldRequireTOTP2FAForSendsToNonContact,
467
value: requireTOTP2FAForSendsToNonContact.toString()));
468
469
reaction(
470
(_) => shouldRequireTOTP2FAForSendsToInternalWallets,
474
- (bool requireTOTP2FAForSendsToInternalWallets) => writeSecureStorage(secureStorage,
471
+ (bool requireTOTP2FAForSendsToInternalWallets) => secureStorage.write(
472
key: SecureKey.shouldRequireTOTP2FAForSendsToInternalWallets,
473
value: requireTOTP2FAForSendsToInternalWallets.toString()));
474
475
reaction(
476
(_) => shouldRequireTOTP2FAForExchangesToInternalWallets,
480
- (bool requireTOTP2FAForExchangesToInternalWallets) => writeSecureStorage(secureStorage,
477
+ (bool requireTOTP2FAForExchangesToInternalWallets) => secureStorage.write(
478
key: SecureKey.shouldRequireTOTP2FAForExchangesToInternalWallets,
479
value: requireTOTP2FAForExchangesToInternalWallets.toString()));
480
481
reaction(
482
(_) => shouldRequireTOTP2FAForExchangesToExternalWallets,
486
- (bool requireTOTP2FAForExchangesToExternalWallets) => writeSecureStorage(secureStorage,
483
+ (bool requireTOTP2FAForExchangesToExternalWallets) => secureStorage.write(
484
key: SecureKey.shouldRequireTOTP2FAForExchangesToExternalWallets,
485
value: requireTOTP2FAForExchangesToExternalWallets.toString()));
486
487
reaction(
488
(_) => shouldRequireTOTP2FAForAddingContacts,
492
- (bool requireTOTP2FAForAddingContacts) => writeSecureStorage(secureStorage,
489
+ (bool requireTOTP2FAForAddingContacts) => secureStorage.write(
490
key: SecureKey.shouldRequireTOTP2FAForAddingContacts,
491
value: requireTOTP2FAForAddingContacts.toString()));
492
493
reaction(
494
(_) => shouldRequireTOTP2FAForCreatingNewWallets,
498
- (bool requireTOTP2FAForCreatingNewWallets) => writeSecureStorage(secureStorage,
495
+ (bool requireTOTP2FAForCreatingNewWallets) => secureStorage.write(
496
key: SecureKey.shouldRequireTOTP2FAForCreatingNewWallets,
497
value: requireTOTP2FAForCreatingNewWallets.toString()));
498
499
reaction(
500
(_) => shouldRequireTOTP2FAForAllSecurityAndBackupSettings,
504
- (bool requireTOTP2FAForAllSecurityAndBackupSettings) => writeSecureStorage(secureStorage,
501
+ (bool requireTOTP2FAForAllSecurityAndBackupSettings) => secureStorage.write(
502
key: SecureKey.shouldRequireTOTP2FAForAllSecurityAndBackupSettings,
503
value: requireTOTP2FAForAllSecurityAndBackupSettings.toString()));
504
508
- reaction(
509
- (_) => useTOTP2FA,
510
- (bool use) =>
511
- writeSecureStorage(secureStorage, key: SecureKey.useTOTP2FA, value: use.toString()));
505
+ reaction((_) => useTOTP2FA,
506
+ (bool use) => secureStorage.write(key: SecureKey.useTOTP2FA, value: use.toString()));
507
513
- reaction(
514
- (_) => totpSecretKey,
515
- (String totpKey) =>
516
- writeSecureStorage(secureStorage, key: SecureKey.totpSecretKey, value: totpKey));
508
+ reaction((_) => totpSecretKey,
509
+ (String totpKey) => secureStorage.write(key: SecureKey.totpSecretKey, value: totpKey));
510
511
reaction(
512
(_) => pinTimeOutDuration,
520
- (PinCodeRequiredDuration pinCodeInterval) => writeSecureStorage(secureStorage,
513
+ (PinCodeRequiredDuration pinCodeInterval) => secureStorage.write(
514
key: SecureKey.pinTimeOutDuration, value: pinCodeInterval.value.toString()));
515
516
reaction(
@@ -720,7 +713,7 @@ abstract class SettingsStoreBase with Store {
713
@observable
714
int customBitcoinFeeRate;
715
723
- final FlutterSecureStorage _secureStorage;
716
+ final SecureStorage _secureStorage;
717
final SharedPreferences _sharedPreferences;
718
final BackgroundTasks _backgroundTasks;
719
@@ -763,7 +756,7 @@ abstract class SettingsStoreBase with Store {
756
BalanceDisplayMode initialBalanceDisplayMode = BalanceDisplayMode.availableBalance,
757
ThemeBase? initialTheme}) async {
758
final sharedPreferences = await getIt.getAsync<SharedPreferences>();
766
- final secureStorage = await getIt.get<FlutterSecureStorage>();
759
+ final secureStorage = await getIt.get<SecureStorage>();
760
final backgroundTasks = getIt.get<BackgroundTasks>();
761
final currentFiatCurrency = FiatCurrency.deserialize(
762
raw: sharedPreferences.getString(PreferencesKey.currentFiatCurrencyKey)!);
lib/store/yat/yat_store.dart
+2
-2
@@ -1,3 +1,4 @@
1
+import 'package:cake_wallet/core/secure_storage.dart';
2
import 'package:cw_core/transaction_history.dart';
3
import 'package:cw_core/wallet_base.dart';
4
import 'package:cw_core/balance.dart';
@@ -10,7 +11,6 @@ import 'dart:convert';
11
import 'package:cake_wallet/store/yat/yat_exception.dart';
12
import 'package:http/http.dart';
13
import 'dart:async';
13
-import 'package:flutter_secure_storage/flutter_secure_storage.dart';
14
15
part 'yat_store.g.dart';
16
@@ -193,7 +193,7 @@ abstract class YatStoreBase with Store {
193
194
AppStore appStore;
195
196
- FlutterSecureStorage secureStorage;
196
+ SecureStorage secureStorage;
197
198
@observable
199
String emoji;
lib/view_model/backup_view_model.dart
+2
-3
@@ -1,10 +1,9 @@
1
import 'dart:io';
2
import 'package:cake_wallet/core/backup_service.dart';
3
import 'package:cake_wallet/core/execution_state.dart';
4
+import 'package:cake_wallet/core/secure_storage.dart';
5
import 'package:cake_wallet/entities/secret_store_key.dart';
6
import 'package:cake_wallet/store/secret_store.dart';
6
-import 'package:flutter/foundation.dart';
7
-import 'package:flutter_secure_storage/flutter_secure_storage.dart';
7
import 'package:mobx/mobx.dart';
8
import 'package:intl/intl.dart';
9
import 'package:cake_wallet/wallet_type_utils.dart';
@@ -34,7 +33,7 @@ abstract class BackupViewModelBase with Store {
33
}, fireImmediately: true);
34
}
35
37
- final FlutterSecureStorage secureStorage;
36
+ final SecureStorage secureStorage;
37
final SecretStore secretStore;
38
final BackupService backupService;
39
lib/view_model/edit_backup_password_view_model.dart
+2
-3
@@ -1,6 +1,5 @@
1
import 'package:cake_wallet/core/secure_storage.dart';
2
import 'package:mobx/mobx.dart';
3
-import 'package:flutter_secure_storage/flutter_secure_storage.dart';
3
import 'package:cake_wallet/entities/secret_store_key.dart';
4
import 'package:cake_wallet/store/secret_store.dart';
5
@@ -14,7 +13,7 @@ abstract class EditBackupPasswordViewModelBase with Store {
13
: backupPassword = secretStore.read(generateStoreKeyFor(key: SecretStoreKey.backupPassword)),
14
_originalPassword = '';
15
17
- final FlutterSecureStorage secureStorage;
16
+ final SecureStorage secureStorage;
17
final SecretStore secretStore;
18
19
@observable
@@ -38,7 +37,7 @@ abstract class EditBackupPasswordViewModelBase with Store {
37
@action
38
Future<void> save() async {
39
final key = generateStoreKeyFor(key: SecretStoreKey.backupPassword);
41
- await writeSecureStorage(secureStorage, key: key, value: backupPassword);
40
+ await secureStorage.write(key: key, value: backupPassword);
41
secretStore.write(key: key, value: backupPassword);
42
}
43
}
pubspec_base.yaml
-6
@@ -11,12 +11,6 @@ dependencies:
11
ref: cake-4.0.2
12
version: 4.0.2
13
shared_preferences: ^2.0.15
14
- flutter_secure_storage:
15
- git:
16
- url: https://github.com/cake-tech/flutter_secure_storage.git
17
- path: flutter_secure_storage
18
- ref: cake-9.0.0
19
- version: 9.0.0
14
# provider: ^6.0.3
15
rxdart: ^0.27.4
16
yaml: ^3.1.1
tool/configure.dart
+117
@@ -10,6 +10,7 @@ const polygonOutputPath = 'lib/polygon/polygon.dart';
10
const solanaOutputPath = 'lib/solana/solana.dart';
11
const tronOutputPath = 'lib/tron/tron.dart';
12
const walletTypesPath = 'lib/wallet_types.g.dart';
13
+const secureStoragePath = 'lib/core/secure_storage.dart';
14
const pubspecDefaultPath = 'pubspec_default.yaml';
15
const pubspecOutputPath = 'pubspec.yaml';
16
@@ -25,6 +26,7 @@ Future<void> main(List<String> args) async {
26
final hasPolygon = args.contains('${prefix}polygon');
27
final hasSolana = args.contains('${prefix}solana');
28
final hasTron = args.contains('${prefix}tron');
29
+ final excludeFlutterSecureStorage = args.contains('${prefix}excludeFlutterSecureStorage');
30
31
await generateBitcoin(hasBitcoin);
32
await generateMonero(hasMonero);
@@ -45,6 +47,7 @@ Future<void> main(List<String> args) async {
47
hasNano: hasNano,
48
hasBanano: hasBanano,
49
hasBitcoinCash: hasBitcoinCash,
50
+ hasFlutterSecureStorage: !excludeFlutterSecureStorage,
51
hasPolygon: hasPolygon,
52
hasSolana: hasSolana,
53
hasTron: hasTron,
@@ -61,6 +64,7 @@ Future<void> main(List<String> args) async {
64
hasSolana: hasSolana,
65
hasTron: hasTron,
66
);
67
+ await injectSecureStorage(!excludeFlutterSecureStorage);
68
}
69
70
Future<void> generateBitcoin(bool hasImplementation) async {
@@ -1142,6 +1146,7 @@ Future<void> generatePubspec(
1146
required bool hasNano,
1147
required bool hasBanano,
1148
required bool hasBitcoinCash,
1149
+ required bool hasFlutterSecureStorage,
1150
required bool hasPolygon,
1151
required bool hasSolana,
1152
required bool hasTron}) async {
@@ -1165,6 +1170,14 @@ Future<void> generatePubspec(
1170
cw_shared_external:
1171
path: ./cw_shared_external
1172
""";
1173
+ const flutterSecureStorage = """
1174
+ flutter_secure_storage:
1175
+ git:
1176
+ url: https://github.com/cake-tech/flutter_secure_storage.git
1177
+ path: flutter_secure_storage
1178
+ ref: cake-9.0.0
1179
+ version: 9.0.0
1180
+ """;
1181
const cwEthereum = """
1182
cw_ethereum:
1183
path: ./cw_ethereum
@@ -1246,6 +1259,10 @@ Future<void> generatePubspec(
1259
output += '\n$cwHaven';
1260
}
1261
1262
+ if (hasFlutterSecureStorage) {
1263
+ output += '\n$flutterSecureStorage\n';
1264
+ }
1265
+
1266
if (hasEthereum || hasPolygon) {
1267
output += '\n$cwEVM';
1268
}
@@ -1330,3 +1347,103 @@ Future<void> generateWalletTypes(
1347
outputContent += '];\n';
1348
await walletTypesFile.writeAsString(outputContent);
1349
}
1350
+
1351
+Future<void> injectSecureStorage(bool hasFlutterSecureStorage) async {
1352
+ const flutterSecureStorageHeader = """
1353
+import 'dart:async';
1354
+import 'dart:io';
1355
+import 'package:flutter_secure_storage/flutter_secure_storage.dart';
1356
+""";
1357
+ const abstractSecureStorage = """
1358
+abstract class SecureStorage {
1359
+ Future<String?> read({required String key});
1360
+ Future<void> write({required String key, required String? value});
1361
+ Future<void> delete({required String key});
1362
+ // Legacy
1363
+ Future<String?> readNoIOptions({required String key});
1364
+ }""";
1365
+ const defaultSecureStorage = """
1366
+class DefaultSecureStorage extends SecureStorage {
1367
+ DefaultSecureStorage._(this._secureStorage);
1368
+
1369
+ factory DefaultSecureStorage() => _instance;
1370
+
1371
+ static final _instance = DefaultSecureStorage._(FlutterSecureStorage(
1372
+ iOptions: IOSOptions(accessibility: KeychainAccessibility.first_unlock),
1373
+ ));
1374
+
1375
+ final FlutterSecureStorage _secureStorage;
1376
+
1377
+ @override
1378
+ Future<String?> read({required String key}) async => await _readInternal(key, false);
1379
+
1380
+ @override
1381
+ Future<void> write({required String key, required String? value}) async {
1382
+ // delete the value before writing on macOS because of a weird bug
1383
+ // https://github.com/mogol/flutter_secure_storage/issues/581
1384
+ if (Platform.isMacOS) {
1385
+ await _secureStorage.delete(key: key);
1386
+ }
1387
+ await _secureStorage.write(key: key, value: value);
1388
+ }
1389
+
1390
+ @override
1391
+ Future<void> delete({required String key}) async => _secureStorage.delete(key: key);
1392
+
1393
+ @override
1394
+ Future<String?> readNoIOptions({required String key}) async => await _readInternal(key, true);
1395
+
1396
+ Future<String?> _readInternal(String key, bool useNoIOptions) async {
1397
+ String? result;
1398
+
1399
+ const maxWait = Duration(seconds: 3);
1400
+ const checkInterval = Duration(milliseconds: 200);
1401
+
1402
+ DateTime start = DateTime.now();
1403
+
1404
+ while (result == null && DateTime.now().difference(start) < maxWait) {
1405
+ result = await _secureStorage.read(
1406
+ key: key,
1407
+ iOptions: useNoIOptions ? IOSOptions() : null,
1408
+ );
1409
+
1410
+ if (result != null) {
1411
+ break;
1412
+ }
1413
+
1414
+ await Future.delayed(checkInterval);
1415
+ }
1416
+
1417
+ return result;
1418
+ }
1419
+ }""";
1420
+ const fakeSecureStorage = """
1421
+class FakeSecureStorage extends SecureStorage {
1422
+ @override
1423
+ Future<String?> read({required String key}) async => null;
1424
+ @override
1425
+ Future<void> write({required String key, required String? value}) async {}
1426
+ @override
1427
+ Future<void> delete({required String key}) async {}
1428
+ @override
1429
+ Future<String?> readNoIOptions({required String key}) async => null;
1430
+ }""";
1431
+ final outputFile = File(secureStoragePath);
1432
+ final header = hasFlutterSecureStorage
1433
+ ? '${flutterSecureStorageHeader}\n\nfinal SecureStorage secureStorageShared = DefaultSecureStorage();\n'
1434
+ : 'final SecureStorage secureStorageShared = FakeSecureStorage();\n';
1435
+ var output = '';
1436
+ if (outputFile.existsSync()) {
1437
+ await outputFile.delete();
1438
+ }
1439
+
1440
+ output += '${header}\n${abstractSecureStorage}\n\n';
1441
+
1442
+ if (hasFlutterSecureStorage) {
1443
+ output += '${defaultSecureStorage}\n';
1444
+ } else {
1445
+ output += '${fakeSecureStorage}\n';
1446
+ }
1447
+
1448
+ await outputFile.writeAsString(output);
1449
+}