mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2025-01-09 12:29:31 +00:00
Backup stuff.
This commit is contained in:
parent
9a79fcdc23
commit
47ceac2dd6
24 changed files with 459 additions and 253 deletions
|
@ -14,128 +14,58 @@ import 'package:cake_wallet/entities/encrypt.dart';
|
||||||
import 'package:cake_wallet/entities/preferences_key.dart';
|
import 'package:cake_wallet/entities/preferences_key.dart';
|
||||||
import 'package:cake_wallet/entities/secret_store_key.dart';
|
import 'package:cake_wallet/entities/secret_store_key.dart';
|
||||||
import 'package:cake_wallet/entities/wallet_info.dart';
|
import 'package:cake_wallet/entities/wallet_info.dart';
|
||||||
|
import 'package:cake_wallet/.secrets.g.dart' as secrets;
|
||||||
|
|
||||||
class BackupService {
|
class BackupService {
|
||||||
BackupService(this._flutterSecureStorage, this._authService,
|
BackupService(this._flutterSecureStorage, this._walletInfoSource,
|
||||||
this._walletInfoSource, this._keyService, this._sharedPreferences)
|
this._keyService, this._sharedPreferences)
|
||||||
: _cipher = chacha20Poly1305Aead;
|
: _cipher = chacha20Poly1305Aead;
|
||||||
|
|
||||||
|
static const currentVersion = _v1;
|
||||||
|
|
||||||
|
static const _v1 = 1;
|
||||||
|
|
||||||
final Cipher _cipher;
|
final Cipher _cipher;
|
||||||
final FlutterSecureStorage _flutterSecureStorage;
|
final FlutterSecureStorage _flutterSecureStorage;
|
||||||
final SharedPreferences _sharedPreferences;
|
final SharedPreferences _sharedPreferences;
|
||||||
final AuthService _authService;
|
|
||||||
final Box<WalletInfo> _walletInfoSource;
|
final Box<WalletInfo> _walletInfoSource;
|
||||||
final KeyService _keyService;
|
final KeyService _keyService;
|
||||||
|
|
||||||
Future<void> importBackup(Uint8List data, String password,
|
Future<void> importBackup(Uint8List data, String password,
|
||||||
{@required String nonce}) async {
|
{String nonce = secrets.backupSalt}) async {
|
||||||
final appDir = await getApplicationDocumentsDirectory();
|
final version = getVersion(data);
|
||||||
final decryptedData = await _decrypt(data, password, nonce);
|
final backupBytes = data.toList()..removeAt(0);
|
||||||
final zip = ZipDecoder().decodeBytes(decryptedData);
|
final backupData = Uint8List.fromList(backupBytes);
|
||||||
|
|
||||||
zip.files.forEach((file) {
|
switch (version) {
|
||||||
final filename = file.name;
|
case _v1:
|
||||||
|
await _importBackupV1(backupData, password, nonce: nonce);
|
||||||
if (file.isFile) {
|
break;
|
||||||
final data = file.content as List<int>;
|
default:
|
||||||
File('${appDir.path}/' + filename)
|
break;
|
||||||
..createSync(recursive: true)
|
|
||||||
..writeAsBytesSync(data);
|
|
||||||
} else {
|
|
||||||
Directory('${appDir.path}/' + filename)..create(recursive: true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
print(filename);
|
|
||||||
});
|
|
||||||
|
|
||||||
await importKeychainDump(password, nonce: nonce);
|
|
||||||
await importPreferencesDump();
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> importPreferencesDump() async {
|
|
||||||
final appDir = await getApplicationDocumentsDirectory();
|
|
||||||
final preferencesFile = File('${appDir.path}/~_preferences_dump');
|
|
||||||
|
|
||||||
if (!preferencesFile.existsSync()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final data =
|
|
||||||
json.decode(preferencesFile.readAsStringSync()) as Map<String, Object>;
|
|
||||||
print('data $data');
|
|
||||||
|
|
||||||
await _sharedPreferences.setString(PreferencesKey.currentWalletName,
|
|
||||||
data[PreferencesKey.currentWalletName] as String);
|
|
||||||
await _sharedPreferences.setInt(PreferencesKey.currentNodeIdKey,
|
|
||||||
data[PreferencesKey.currentNodeIdKey] as int);
|
|
||||||
await _sharedPreferences.setInt(PreferencesKey.currentBalanceDisplayModeKey,
|
|
||||||
data[PreferencesKey.currentBalanceDisplayModeKey] as int);
|
|
||||||
await _sharedPreferences.setInt(PreferencesKey.currentWalletType,
|
|
||||||
data[PreferencesKey.currentWalletType] as int);
|
|
||||||
await _sharedPreferences.setString(PreferencesKey.currentFiatCurrencyKey,
|
|
||||||
data[PreferencesKey.currentFiatCurrencyKey] as String);
|
|
||||||
await _sharedPreferences.setBool(
|
|
||||||
PreferencesKey.shouldSaveRecipientAddressKey,
|
|
||||||
data[PreferencesKey.shouldSaveRecipientAddressKey] as bool);
|
|
||||||
await _sharedPreferences.setInt(
|
|
||||||
PreferencesKey.currentTransactionPriorityKey,
|
|
||||||
data[PreferencesKey.currentTransactionPriorityKey] as int);
|
|
||||||
await _sharedPreferences.setBool(
|
|
||||||
PreferencesKey.allowBiometricalAuthenticationKey,
|
|
||||||
data[PreferencesKey.allowBiometricalAuthenticationKey] as bool);
|
|
||||||
await _sharedPreferences.setInt(
|
|
||||||
PreferencesKey.currentBitcoinElectrumSererIdKey,
|
|
||||||
data[PreferencesKey.currentBitcoinElectrumSererIdKey] as int);
|
|
||||||
await _sharedPreferences.setInt(PreferencesKey.currentLanguageCode,
|
|
||||||
data[PreferencesKey.currentLanguageCode] as int);
|
|
||||||
await _sharedPreferences.setInt(PreferencesKey.displayActionListModeKey,
|
|
||||||
data[PreferencesKey.displayActionListModeKey] as int);
|
|
||||||
await _sharedPreferences.setInt(
|
|
||||||
'current_theme', data['current_theme'] as int);
|
|
||||||
|
|
||||||
await preferencesFile.delete();
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> importKeychainDump(String password,
|
|
||||||
{@required String nonce}) async {
|
|
||||||
final appDir = await getApplicationDocumentsDirectory();
|
|
||||||
final keychainDumpFile = File('${appDir.path}/~_keychain_dump');
|
|
||||||
final decryptedKeychainDumpFileData =
|
|
||||||
await _decrypt(keychainDumpFile.readAsBytesSync(), password, nonce);
|
|
||||||
final keychainJSON = json.decode(utf8.decode(decryptedKeychainDumpFileData))
|
|
||||||
as Map<String, dynamic>;
|
|
||||||
final keychainWalletsInfo = keychainJSON['wallets'] as List;
|
|
||||||
final decodedPin = keychainJSON['pin'] as String;
|
|
||||||
final pinCodeKey = generateStoreKeyFor(key: SecretStoreKey.pinCodePassword);
|
|
||||||
|
|
||||||
keychainWalletsInfo.forEach((dynamic rawInfo) async {
|
|
||||||
final info = rawInfo as Map<String, dynamic>;
|
|
||||||
await importWalletKeychainInfo(info);
|
|
||||||
});
|
|
||||||
|
|
||||||
await _flutterSecureStorage.write(
|
|
||||||
key: pinCodeKey, value: encodedPinCode(pin: decodedPin));
|
|
||||||
|
|
||||||
keychainDumpFile.deleteSync();
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> importWalletKeychainInfo(Map<String, dynamic> info) async {
|
|
||||||
final name = info['name'] as String;
|
|
||||||
final password = info['password'] as String;
|
|
||||||
|
|
||||||
await _keyService.saveWalletPassword(walletName: name, password: password);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<Uint8List> exportBackup(String password,
|
Future<Uint8List> exportBackup(String password,
|
||||||
{@required String nonce}) async {
|
{String nonce = secrets.backupSalt, int version = currentVersion}) async {
|
||||||
|
switch (version) {
|
||||||
|
case _v1:
|
||||||
|
return await _exportBackupV1(password, nonce: nonce);
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<Uint8List> _exportBackupV1(String password,
|
||||||
|
{String nonce = secrets.backupSalt}) async {
|
||||||
final zipEncoder = ZipFileEncoder();
|
final zipEncoder = ZipFileEncoder();
|
||||||
final appDir = await getApplicationDocumentsDirectory();
|
final appDir = await getApplicationDocumentsDirectory();
|
||||||
final now = DateTime.now();
|
final now = DateTime.now();
|
||||||
final tmpDir = Directory('${appDir.path}/~_BACKUP_TMP');
|
final tmpDir = Directory('${appDir.path}/~_BACKUP_TMP');
|
||||||
final archivePath = '${tmpDir.path}/backup_${now.toString()}.zip';
|
final archivePath = '${tmpDir.path}/backup_${now.toString()}.zip';
|
||||||
final fileEntities = appDir.listSync(recursive: false);
|
final fileEntities = appDir.listSync(recursive: false);
|
||||||
final keychainDump = await exportKeychainDump(password, nonce: nonce);
|
final keychainDump = await _exportKeychainDump(password, nonce: nonce);
|
||||||
final preferencesDump = await exportPreferencesJSON();
|
final preferencesDump = await _exportPreferencesJSON();
|
||||||
final preferencesDumpFile = File('${tmpDir.path}/~_preferences_dump_TMP');
|
final preferencesDumpFile = File('${tmpDir.path}/~_preferences_dump_TMP');
|
||||||
final keychainDumpFile = File('${tmpDir.path}/~_keychain_dump_TMP');
|
final keychainDumpFile = File('${tmpDir.path}/~_keychain_dump_TMP');
|
||||||
|
|
||||||
|
@ -165,12 +95,120 @@ class BackupService {
|
||||||
|
|
||||||
final content = File(archivePath).readAsBytesSync();
|
final content = File(archivePath).readAsBytesSync();
|
||||||
tmpDir.deleteSync(recursive: true);
|
tmpDir.deleteSync(recursive: true);
|
||||||
|
final encryptedData = await _encrypt(content, password, nonce);
|
||||||
|
|
||||||
return await _encrypt(content, password, nonce);
|
return setVersion(encryptedData, currentVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<Uint8List> exportKeychainDump(String password,
|
Future<void> _importBackupV1(Uint8List data, String password,
|
||||||
{@required String nonce}) async {
|
{@required String nonce}) async {
|
||||||
|
final appDir = await getApplicationDocumentsDirectory();
|
||||||
|
final decryptedData = await _decrypt(data, password, nonce);
|
||||||
|
final zip = ZipDecoder().decodeBytes(decryptedData);
|
||||||
|
|
||||||
|
zip.files.forEach((file) {
|
||||||
|
final filename = file.name;
|
||||||
|
|
||||||
|
if (file.isFile) {
|
||||||
|
final content = file.content as List<int>;
|
||||||
|
File('${appDir.path}/' + filename)
|
||||||
|
..createSync(recursive: true)
|
||||||
|
..writeAsBytesSync(content);
|
||||||
|
} else {
|
||||||
|
Directory('${appDir.path}/' + filename)..create(recursive: true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
await _importKeychainDump(password, nonce: nonce);
|
||||||
|
await _importPreferencesDump();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _importPreferencesDump() async {
|
||||||
|
final appDir = await getApplicationDocumentsDirectory();
|
||||||
|
final preferencesFile = File('${appDir.path}/~_preferences_dump');
|
||||||
|
const defaultSettingsMigrationVersionKey = PreferencesKey.currentDefaultSettingsMigrationVersion;
|
||||||
|
|
||||||
|
if (!preferencesFile.existsSync()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final data =
|
||||||
|
json.decode(preferencesFile.readAsStringSync()) as Map<String, Object>;
|
||||||
|
|
||||||
|
await _sharedPreferences.setString(PreferencesKey.currentWalletName,
|
||||||
|
data[PreferencesKey.currentWalletName] as String);
|
||||||
|
await _sharedPreferences.setInt(PreferencesKey.currentNodeIdKey,
|
||||||
|
data[PreferencesKey.currentNodeIdKey] as int);
|
||||||
|
await _sharedPreferences.setInt(PreferencesKey.currentBalanceDisplayModeKey,
|
||||||
|
data[PreferencesKey.currentBalanceDisplayModeKey] as int);
|
||||||
|
await _sharedPreferences.setInt(PreferencesKey.currentWalletType,
|
||||||
|
data[PreferencesKey.currentWalletType] as int);
|
||||||
|
await _sharedPreferences.setString(PreferencesKey.currentFiatCurrencyKey,
|
||||||
|
data[PreferencesKey.currentFiatCurrencyKey] as String);
|
||||||
|
await _sharedPreferences.setBool(
|
||||||
|
PreferencesKey.shouldSaveRecipientAddressKey,
|
||||||
|
data[PreferencesKey.shouldSaveRecipientAddressKey] as bool);
|
||||||
|
await _sharedPreferences.setInt(
|
||||||
|
PreferencesKey.currentTransactionPriorityKey,
|
||||||
|
data[PreferencesKey.currentTransactionPriorityKey] as int);
|
||||||
|
await _sharedPreferences.setBool(
|
||||||
|
PreferencesKey.allowBiometricalAuthenticationKey,
|
||||||
|
data[PreferencesKey.allowBiometricalAuthenticationKey] as bool);
|
||||||
|
await _sharedPreferences.setInt(
|
||||||
|
PreferencesKey.currentBitcoinElectrumSererIdKey,
|
||||||
|
data[PreferencesKey.currentBitcoinElectrumSererIdKey] as int);
|
||||||
|
await _sharedPreferences.setInt(PreferencesKey.currentLanguageCode,
|
||||||
|
data[PreferencesKey.currentLanguageCode] as int);
|
||||||
|
await _sharedPreferences.setInt(PreferencesKey.displayActionListModeKey,
|
||||||
|
data[PreferencesKey.displayActionListModeKey] as int);
|
||||||
|
await _sharedPreferences.setInt(
|
||||||
|
'current_theme', data['current_theme'] as int);
|
||||||
|
await _sharedPreferences.setInt(defaultSettingsMigrationVersionKey,
|
||||||
|
data[defaultSettingsMigrationVersionKey] as int);
|
||||||
|
|
||||||
|
await preferencesFile.delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _importKeychainDump(String password,
|
||||||
|
{@required String nonce,
|
||||||
|
String keychainSalt = secrets.backupKeychainSalt}) async {
|
||||||
|
final appDir = await getApplicationDocumentsDirectory();
|
||||||
|
final keychainDumpFile = File('${appDir.path}/~_keychain_dump');
|
||||||
|
final decryptedKeychainDumpFileData = await _decrypt(
|
||||||
|
keychainDumpFile.readAsBytesSync(), '$keychainSalt$password', nonce);
|
||||||
|
final keychainJSON = json.decode(utf8.decode(decryptedKeychainDumpFileData))
|
||||||
|
as Map<String, dynamic>;
|
||||||
|
final keychainWalletsInfo = keychainJSON['wallets'] as List;
|
||||||
|
final decodedPin = keychainJSON['pin'] as String;
|
||||||
|
final pinCodeKey = generateStoreKeyFor(key: SecretStoreKey.pinCodePassword);
|
||||||
|
final backupPasswordKey =
|
||||||
|
generateStoreKeyFor(key: SecretStoreKey.backupPassword);
|
||||||
|
final backupPassword = keychainJSON[backupPasswordKey] as String;
|
||||||
|
|
||||||
|
await _flutterSecureStorage.write(
|
||||||
|
key: backupPasswordKey, value: backupPassword);
|
||||||
|
|
||||||
|
keychainWalletsInfo.forEach((dynamic rawInfo) async {
|
||||||
|
final info = rawInfo as Map<String, dynamic>;
|
||||||
|
await importWalletKeychainInfo(info);
|
||||||
|
});
|
||||||
|
|
||||||
|
await _flutterSecureStorage.write(
|
||||||
|
key: pinCodeKey, value: encodedPinCode(pin: decodedPin));
|
||||||
|
|
||||||
|
keychainDumpFile.deleteSync();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> importWalletKeychainInfo(Map<String, dynamic> info) async {
|
||||||
|
final name = info['name'] as String;
|
||||||
|
final password = info['password'] as String;
|
||||||
|
|
||||||
|
await _keyService.saveWalletPassword(walletName: name, password: password);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<Uint8List> _exportKeychainDump(String password,
|
||||||
|
{@required String nonce,
|
||||||
|
String keychainSalt = secrets.backupKeychainSalt}) async {
|
||||||
final key = generateStoreKeyFor(key: SecretStoreKey.pinCodePassword);
|
final key = generateStoreKeyFor(key: SecretStoreKey.pinCodePassword);
|
||||||
final encodedPin = await _flutterSecureStorage.read(key: key);
|
final encodedPin = await _flutterSecureStorage.read(key: key);
|
||||||
final decodedPin = decodedPinCode(pin: encodedPin);
|
final decodedPin = decodedPinCode(pin: encodedPin);
|
||||||
|
@ -183,15 +221,25 @@ class BackupService {
|
||||||
await _keyService.getWalletPassword(walletName: walletInfo.name)
|
await _keyService.getWalletPassword(walletName: walletInfo.name)
|
||||||
};
|
};
|
||||||
}));
|
}));
|
||||||
|
final backupPasswordKey =
|
||||||
final data =
|
generateStoreKeyFor(key: SecretStoreKey.backupPassword);
|
||||||
utf8.encode(json.encode({'pin': decodedPin, 'wallets': wallets}));
|
final backupPassword =
|
||||||
final encrypted = await _encrypt(Uint8List.fromList(data), password, nonce);
|
await _flutterSecureStorage.read(key: backupPasswordKey);
|
||||||
|
final data = utf8.encode(json.encode({
|
||||||
|
'pin': decodedPin,
|
||||||
|
'wallets': wallets,
|
||||||
|
backupPasswordKey: backupPassword
|
||||||
|
}));
|
||||||
|
final encrypted = await _encrypt(
|
||||||
|
Uint8List.fromList(data), '$keychainSalt$password', nonce);
|
||||||
|
|
||||||
return encrypted;
|
return encrypted;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<String> exportPreferencesJSON() async {
|
Future<String> _exportPreferencesJSON() async {
|
||||||
|
const defaultSettingsMigrationVersionKey =
|
||||||
|
'current_default_settings_migration_version';
|
||||||
|
|
||||||
final preferences = <String, Object>{
|
final preferences = <String, Object>{
|
||||||
PreferencesKey.currentWalletName:
|
PreferencesKey.currentWalletName:
|
||||||
_sharedPreferences.getString(PreferencesKey.currentWalletName),
|
_sharedPreferences.getString(PreferencesKey.currentWalletName),
|
||||||
|
@ -219,13 +267,22 @@ class BackupService {
|
||||||
_sharedPreferences.getString(PreferencesKey.currentLanguageCode),
|
_sharedPreferences.getString(PreferencesKey.currentLanguageCode),
|
||||||
PreferencesKey.displayActionListModeKey:
|
PreferencesKey.displayActionListModeKey:
|
||||||
_sharedPreferences.getInt(PreferencesKey.displayActionListModeKey),
|
_sharedPreferences.getInt(PreferencesKey.displayActionListModeKey),
|
||||||
PreferencesKey.currentTheme: _sharedPreferences.getInt(PreferencesKey.currentTheme)
|
PreferencesKey.currentTheme:
|
||||||
// FIX-ME: Unnamed constant.
|
_sharedPreferences.getInt(PreferencesKey.currentTheme),
|
||||||
|
defaultSettingsMigrationVersionKey:
|
||||||
|
_sharedPreferences.getInt(defaultSettingsMigrationVersionKey)
|
||||||
};
|
};
|
||||||
|
|
||||||
return json.encode(preferences);
|
return json.encode(preferences);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int getVersion(Uint8List data) => data.toList().first;
|
||||||
|
|
||||||
|
Uint8List setVersion(Uint8List data, int version) {
|
||||||
|
final bytes = data.toList()..insert(0, version);
|
||||||
|
return Uint8List.fromList(bytes);
|
||||||
|
}
|
||||||
|
|
||||||
Future<Uint8List> _encrypt(
|
Future<Uint8List> _encrypt(
|
||||||
Uint8List data, String secretKeySource, String nonceBase64) async {
|
Uint8List data, String secretKeySource, String nonceBase64) async {
|
||||||
final secretKeyHash = await sha256.hash(utf8.encode(secretKeySource));
|
final secretKeyHash = await sha256.hash(utf8.encode(secretKeySource));
|
75
lib/di.dart
75
lib/di.dart
|
@ -1,5 +1,5 @@
|
||||||
import 'package:cake_wallet/bitcoin/bitcoin_wallet_service.dart';
|
import 'package:cake_wallet/bitcoin/bitcoin_wallet_service.dart';
|
||||||
import 'package:cake_wallet/core/backup.dart';
|
import 'package:cake_wallet/core/backup_service.dart';
|
||||||
import 'package:cake_wallet/core/wallet_service.dart';
|
import 'package:cake_wallet/core/wallet_service.dart';
|
||||||
import 'package:cake_wallet/entities/biometric_auth.dart';
|
import 'package:cake_wallet/entities/biometric_auth.dart';
|
||||||
import 'package:cake_wallet/entities/contact_record.dart';
|
import 'package:cake_wallet/entities/contact_record.dart';
|
||||||
|
@ -105,6 +105,15 @@ import 'package:cake_wallet/exchange/exchange_template.dart';
|
||||||
|
|
||||||
final getIt = GetIt.instance;
|
final getIt = GetIt.instance;
|
||||||
|
|
||||||
|
var _isSetupFinished = false;
|
||||||
|
Box<WalletInfo> _walletInfoSource;
|
||||||
|
Box<Node> _nodeSource;
|
||||||
|
Box<Contact> _contactSource;
|
||||||
|
Box<Trade> _tradesSource;
|
||||||
|
Box<Template> _templates;
|
||||||
|
Box<ExchangeTemplate> _exchangeTemplates;
|
||||||
|
Box<TransactionDescription> _transactionDescriptionBox;
|
||||||
|
|
||||||
Future setup(
|
Future setup(
|
||||||
{Box<WalletInfo> walletInfoSource,
|
{Box<WalletInfo> walletInfoSource,
|
||||||
Box<Node> nodeSource,
|
Box<Node> nodeSource,
|
||||||
|
@ -113,12 +122,26 @@ Future setup(
|
||||||
Box<Template> templates,
|
Box<Template> templates,
|
||||||
Box<ExchangeTemplate> exchangeTemplates,
|
Box<ExchangeTemplate> exchangeTemplates,
|
||||||
Box<TransactionDescription> transactionDescriptionBox}) async {
|
Box<TransactionDescription> transactionDescriptionBox}) async {
|
||||||
|
_walletInfoSource = walletInfoSource;
|
||||||
|
_nodeSource = nodeSource;
|
||||||
|
_contactSource = contactSource;
|
||||||
|
_tradesSource = tradesSource;
|
||||||
|
_templates = templates;
|
||||||
|
_exchangeTemplates = exchangeTemplates;
|
||||||
|
_transactionDescriptionBox = transactionDescriptionBox;
|
||||||
|
|
||||||
|
if (!_isSetupFinished) {
|
||||||
getIt.registerSingletonAsync<SharedPreferences>(
|
getIt.registerSingletonAsync<SharedPreferences>(
|
||||||
() => SharedPreferences.getInstance());
|
() => SharedPreferences.getInstance());
|
||||||
|
}
|
||||||
|
|
||||||
final settingsStore = await SettingsStoreBase.load(nodeSource: nodeSource);
|
final settingsStore = await SettingsStoreBase.load(nodeSource: _nodeSource);
|
||||||
|
|
||||||
getIt.registerSingleton<Box<Node>>(nodeSource);
|
if (_isSetupFinished) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
getIt.registerFactory<Box<Node>>(() => _nodeSource);
|
||||||
|
|
||||||
getIt.registerSingleton<FlutterSecureStorage>(FlutterSecureStorage());
|
getIt.registerSingleton<FlutterSecureStorage>(FlutterSecureStorage());
|
||||||
getIt.registerSingleton(AuthenticationStore());
|
getIt.registerSingleton(AuthenticationStore());
|
||||||
|
@ -131,14 +154,14 @@ Future setup(
|
||||||
settingsStore: getIt.get<SettingsStore>(),
|
settingsStore: getIt.get<SettingsStore>(),
|
||||||
nodeListStore: getIt.get<NodeListStore>()));
|
nodeListStore: getIt.get<NodeListStore>()));
|
||||||
getIt.registerSingleton<TradesStore>(TradesStore(
|
getIt.registerSingleton<TradesStore>(TradesStore(
|
||||||
tradesSource: tradesSource, settingsStore: getIt.get<SettingsStore>()));
|
tradesSource: _tradesSource, settingsStore: getIt.get<SettingsStore>()));
|
||||||
getIt.registerSingleton<TradeFilterStore>(TradeFilterStore());
|
getIt.registerSingleton<TradeFilterStore>(TradeFilterStore());
|
||||||
getIt.registerSingleton<TransactionFilterStore>(TransactionFilterStore());
|
getIt.registerSingleton<TransactionFilterStore>(TransactionFilterStore());
|
||||||
getIt.registerSingleton<FiatConversionStore>(FiatConversionStore());
|
getIt.registerSingleton<FiatConversionStore>(FiatConversionStore());
|
||||||
getIt.registerSingleton<SendTemplateStore>(
|
getIt.registerSingleton<SendTemplateStore>(
|
||||||
SendTemplateStore(templateSource: templates));
|
SendTemplateStore(templateSource: _templates));
|
||||||
getIt.registerSingleton<ExchangeTemplateStore>(
|
getIt.registerSingleton<ExchangeTemplateStore>(
|
||||||
ExchangeTemplateStore(templateSource: exchangeTemplates));
|
ExchangeTemplateStore(templateSource: _exchangeTemplates));
|
||||||
|
|
||||||
final secretStore =
|
final secretStore =
|
||||||
await SecretStoreBase.load(getIt.get<FlutterSecureStorage>());
|
await SecretStoreBase.load(getIt.get<FlutterSecureStorage>());
|
||||||
|
@ -157,7 +180,7 @@ Future setup(
|
||||||
|
|
||||||
getIt.registerFactoryParam<WalletNewVM, WalletType, void>((type, _) =>
|
getIt.registerFactoryParam<WalletNewVM, WalletType, void>((type, _) =>
|
||||||
WalletNewVM(getIt.get<AppStore>(),
|
WalletNewVM(getIt.get<AppStore>(),
|
||||||
getIt.get<WalletCreationService>(param1: type), walletInfoSource,
|
getIt.get<WalletCreationService>(param1: type), _walletInfoSource,
|
||||||
type: type));
|
type: type));
|
||||||
|
|
||||||
getIt
|
getIt
|
||||||
|
@ -167,7 +190,7 @@ Future setup(
|
||||||
final mnemonic = args[2] as String;
|
final mnemonic = args[2] as String;
|
||||||
|
|
||||||
return WalletRestorationFromSeedVM(getIt.get<AppStore>(),
|
return WalletRestorationFromSeedVM(getIt.get<AppStore>(),
|
||||||
getIt.get<WalletCreationService>(param1: type), walletInfoSource,
|
getIt.get<WalletCreationService>(param1: type), _walletInfoSource,
|
||||||
type: type, language: language, seed: mnemonic);
|
type: type, language: language, seed: mnemonic);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -177,7 +200,7 @@ Future setup(
|
||||||
final language = args[1] as String;
|
final language = args[1] as String;
|
||||||
|
|
||||||
return WalletRestorationFromKeysVM(getIt.get<AppStore>(),
|
return WalletRestorationFromKeysVM(getIt.get<AppStore>(),
|
||||||
getIt.get<WalletCreationService>(param1: type), walletInfoSource,
|
getIt.get<WalletCreationService>(param1: type), _walletInfoSource,
|
||||||
type: type, language: language);
|
type: type, language: language);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -262,7 +285,7 @@ Future setup(
|
||||||
getIt.get<AppStore>().settingsStore,
|
getIt.get<AppStore>().settingsStore,
|
||||||
getIt.get<SendTemplateStore>(),
|
getIt.get<SendTemplateStore>(),
|
||||||
getIt.get<FiatConversionStore>(),
|
getIt.get<FiatConversionStore>(),
|
||||||
transactionDescriptionBox));
|
_transactionDescriptionBox));
|
||||||
|
|
||||||
getIt.registerFactory(
|
getIt.registerFactory(
|
||||||
() => SendPage(sendViewModel: getIt.get<SendViewModel>()));
|
() => SendPage(sendViewModel: getIt.get<SendViewModel>()));
|
||||||
|
@ -271,7 +294,7 @@ Future setup(
|
||||||
() => SendTemplatePage(sendViewModel: getIt.get<SendViewModel>()));
|
() => SendTemplatePage(sendViewModel: getIt.get<SendViewModel>()));
|
||||||
|
|
||||||
getIt.registerFactory(() => WalletListViewModel(
|
getIt.registerFactory(() => WalletListViewModel(
|
||||||
walletInfoSource,
|
_walletInfoSource,
|
||||||
getIt.get<AppStore>(),
|
getIt.get<AppStore>(),
|
||||||
getIt.get<KeyService>(),
|
getIt.get<KeyService>(),
|
||||||
getIt.get<WalletNewVM>(param1: WalletType.monero)));
|
getIt.get<WalletNewVM>(param1: WalletType.monero)));
|
||||||
|
@ -342,10 +365,10 @@ Future setup(
|
||||||
|
|
||||||
getIt.registerFactoryParam<ContactViewModel, ContactRecord, void>(
|
getIt.registerFactoryParam<ContactViewModel, ContactRecord, void>(
|
||||||
(ContactRecord contact, _) =>
|
(ContactRecord contact, _) =>
|
||||||
ContactViewModel(contactSource, contact: contact));
|
ContactViewModel(_contactSource, contact: contact));
|
||||||
|
|
||||||
getIt.registerFactory(
|
getIt.registerFactory(
|
||||||
() => ContactListViewModel(contactSource, walletInfoSource));
|
() => ContactListViewModel(_contactSource, _walletInfoSource));
|
||||||
|
|
||||||
getIt.registerFactoryParam<ContactListPage, bool, void>(
|
getIt.registerFactoryParam<ContactListPage, bool, void>(
|
||||||
(bool isEditable, _) => ContactListPage(getIt.get<ContactListViewModel>(),
|
(bool isEditable, _) => ContactListPage(getIt.get<ContactListViewModel>(),
|
||||||
|
@ -358,27 +381,27 @@ Future setup(
|
||||||
getIt.registerFactory(() {
|
getIt.registerFactory(() {
|
||||||
final appStore = getIt.get<AppStore>();
|
final appStore = getIt.get<AppStore>();
|
||||||
return NodeListViewModel(
|
return NodeListViewModel(
|
||||||
nodeSource, appStore.wallet, appStore.settingsStore);
|
_nodeSource, appStore.wallet, appStore.settingsStore);
|
||||||
});
|
});
|
||||||
|
|
||||||
getIt.registerFactory(() => NodeListPage(getIt.get<NodeListViewModel>()));
|
getIt.registerFactory(() => NodeListPage(getIt.get<NodeListViewModel>()));
|
||||||
|
|
||||||
getIt.registerFactory(() =>
|
getIt.registerFactory(() =>
|
||||||
NodeCreateOrEditViewModel(nodeSource, getIt.get<AppStore>().wallet));
|
NodeCreateOrEditViewModel(_nodeSource, getIt.get<AppStore>().wallet));
|
||||||
|
|
||||||
getIt.registerFactory(
|
getIt.registerFactory(
|
||||||
() => NodeCreateOrEditPage(getIt.get<NodeCreateOrEditViewModel>()));
|
() => NodeCreateOrEditPage(getIt.get<NodeCreateOrEditViewModel>()));
|
||||||
|
|
||||||
getIt.registerFactory(() => ExchangeViewModel(
|
getIt.registerFactory(() => ExchangeViewModel(
|
||||||
getIt.get<AppStore>().wallet,
|
getIt.get<AppStore>().wallet,
|
||||||
tradesSource,
|
_tradesSource,
|
||||||
getIt.get<ExchangeTemplateStore>(),
|
getIt.get<ExchangeTemplateStore>(),
|
||||||
getIt.get<TradesStore>(),
|
getIt.get<TradesStore>(),
|
||||||
getIt.get<AppStore>().settingsStore));
|
getIt.get<AppStore>().settingsStore));
|
||||||
|
|
||||||
getIt.registerFactory(() => ExchangeTradeViewModel(
|
getIt.registerFactory(() => ExchangeTradeViewModel(
|
||||||
wallet: getIt.get<AppStore>().wallet,
|
wallet: getIt.get<AppStore>().wallet,
|
||||||
trades: tradesSource,
|
trades: _tradesSource,
|
||||||
tradesStore: getIt.get<TradesStore>(),
|
tradesStore: getIt.get<TradesStore>(),
|
||||||
sendViewModel: getIt.get<SendViewModel>()));
|
sendViewModel: getIt.get<SendViewModel>()));
|
||||||
|
|
||||||
|
@ -393,9 +416,9 @@ Future setup(
|
||||||
getIt.registerFactory(
|
getIt.registerFactory(
|
||||||
() => ExchangeTemplatePage(getIt.get<ExchangeViewModel>()));
|
() => ExchangeTemplatePage(getIt.get<ExchangeViewModel>()));
|
||||||
|
|
||||||
getIt.registerFactory(() => MoneroWalletService(walletInfoSource));
|
getIt.registerFactory(() => MoneroWalletService(_walletInfoSource));
|
||||||
|
|
||||||
getIt.registerFactory(() => BitcoinWalletService(walletInfoSource));
|
getIt.registerFactory(() => BitcoinWalletService(_walletInfoSource));
|
||||||
|
|
||||||
getIt.registerFactoryParam<WalletService, WalletType, void>(
|
getIt.registerFactoryParam<WalletService, WalletType, void>(
|
||||||
(WalletType param1, __) {
|
(WalletType param1, __) {
|
||||||
|
@ -428,7 +451,7 @@ Future setup(
|
||||||
|
|
||||||
getIt.registerFactoryParam<WalletRestoreViewModel, WalletType, void>(
|
getIt.registerFactoryParam<WalletRestoreViewModel, WalletType, void>(
|
||||||
(type, _) => WalletRestoreViewModel(getIt.get<AppStore>(),
|
(type, _) => WalletRestoreViewModel(getIt.get<AppStore>(),
|
||||||
getIt.get<WalletCreationService>(param1: type), walletInfoSource,
|
getIt.get<WalletCreationService>(param1: type), _walletInfoSource,
|
||||||
type: type));
|
type: type));
|
||||||
|
|
||||||
getIt.registerFactoryParam<WalletRestorePage, WalletType, void>((type, _) =>
|
getIt.registerFactoryParam<WalletRestorePage, WalletType, void>((type, _) =>
|
||||||
|
@ -438,7 +461,7 @@ Future setup(
|
||||||
.registerFactoryParam<TransactionDetailsViewModel, TransactionInfo, void>(
|
.registerFactoryParam<TransactionDetailsViewModel, TransactionInfo, void>(
|
||||||
(TransactionInfo transactionInfo, _) => TransactionDetailsViewModel(
|
(TransactionInfo transactionInfo, _) => TransactionDetailsViewModel(
|
||||||
transactionInfo: transactionInfo,
|
transactionInfo: transactionInfo,
|
||||||
transactionDescriptionBox: transactionDescriptionBox,
|
transactionDescriptionBox: _transactionDescriptionBox,
|
||||||
settingsStore: getIt.get<SettingsStore>()));
|
settingsStore: getIt.get<SettingsStore>()));
|
||||||
|
|
||||||
getIt.registerFactoryParam<TransactionDetailsPage, TransactionInfo, void>(
|
getIt.registerFactoryParam<TransactionDetailsPage, TransactionInfo, void>(
|
||||||
|
@ -455,12 +478,11 @@ Future setup(
|
||||||
(WalletType type, _) => PreSeedPage(type));
|
(WalletType type, _) => PreSeedPage(type));
|
||||||
|
|
||||||
getIt.registerFactoryParam<TradeDetailsViewModel, Trade, void>((trade, _) =>
|
getIt.registerFactoryParam<TradeDetailsViewModel, Trade, void>((trade, _) =>
|
||||||
TradeDetailsViewModel(tradeForDetails: trade, trades: tradesSource));
|
TradeDetailsViewModel(tradeForDetails: trade, trades: _tradesSource));
|
||||||
|
|
||||||
getIt.registerFactory(() => BackupService(
|
getIt.registerFactory(() => BackupService(
|
||||||
getIt.get<FlutterSecureStorage>(),
|
getIt.get<FlutterSecureStorage>(),
|
||||||
getIt.get<AuthService>(),
|
_walletInfoSource,
|
||||||
walletInfoSource,
|
|
||||||
getIt.get<KeyService>(),
|
getIt.get<KeyService>(),
|
||||||
getIt.get<SharedPreferences>()));
|
getIt.get<SharedPreferences>()));
|
||||||
|
|
||||||
|
@ -476,8 +498,7 @@ Future setup(
|
||||||
getIt.registerFactory(
|
getIt.registerFactory(
|
||||||
() => EditBackupPasswordPage(getIt.get<EditBackupPasswordViewModel>()));
|
() => EditBackupPasswordPage(getIt.get<EditBackupPasswordViewModel>()));
|
||||||
|
|
||||||
getIt.registerFactoryParam<RestoreOptionsPage, WalletType, void>(
|
getIt.registerFactory(() => RestoreOptionsPage());
|
||||||
(WalletType type, _) => RestoreOptionsPage(type: type));
|
|
||||||
|
|
||||||
getIt.registerFactory(
|
getIt.registerFactory(
|
||||||
() => RestoreFromBackupViewModel(getIt.get<BackupService>()));
|
() => RestoreFromBackupViewModel(getIt.get<BackupService>()));
|
||||||
|
@ -487,4 +508,6 @@ Future setup(
|
||||||
|
|
||||||
getIt.registerFactoryParam<TradeDetailsPage, Trade, void>((Trade trade, _) =>
|
getIt.registerFactoryParam<TradeDetailsPage, Trade, void>((Trade trade, _) =>
|
||||||
TradeDetailsPage(getIt.get<TradeDetailsViewModel>(param1: trade)));
|
TradeDetailsPage(getIt.get<TradeDetailsViewModel>(param1: trade)));
|
||||||
|
|
||||||
|
_isSetupFinished = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,11 +5,12 @@ import 'package:cake_wallet/utils/mobx.dart';
|
||||||
|
|
||||||
part 'contact.g.dart';
|
part 'contact.g.dart';
|
||||||
|
|
||||||
@HiveType(typeId: 0)
|
@HiveType(typeId: Contact.typeId)
|
||||||
class Contact extends HiveObject with Keyable {
|
class Contact extends HiveObject with Keyable {
|
||||||
Contact({@required this.name, @required this.address, CryptoCurrency type})
|
Contact({@required this.name, @required this.address, CryptoCurrency type})
|
||||||
: raw = type?.raw;
|
: raw = type?.raw;
|
||||||
|
|
||||||
|
static const typeId = 0;
|
||||||
static const boxName = 'Contacts';
|
static const boxName = 'Contacts';
|
||||||
|
|
||||||
@HiveField(0)
|
@HiveField(0)
|
||||||
|
|
|
@ -1,9 +1,12 @@
|
||||||
import 'dart:io' show File, Platform;
|
import 'dart:io' show File, Platform;
|
||||||
|
import 'package:cake_wallet/core/generate_wallet_password.dart';
|
||||||
import 'package:cake_wallet/core/key_service.dart';
|
import 'package:cake_wallet/core/key_service.dart';
|
||||||
import 'package:cake_wallet/di.dart';
|
import 'package:cake_wallet/di.dart';
|
||||||
import 'package:cake_wallet/entities/pathForWallet.dart';
|
import 'package:cake_wallet/entities/pathForWallet.dart';
|
||||||
|
import 'package:cake_wallet/entities/secret_store_key.dart';
|
||||||
import 'package:cake_wallet/monero/monero_wallet_service.dart';
|
import 'package:cake_wallet/monero/monero_wallet_service.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
|
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
||||||
import 'package:hive/hive.dart';
|
import 'package:hive/hive.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
import 'package:cake_wallet/entities/preferences_key.dart';
|
import 'package:cake_wallet/entities/preferences_key.dart';
|
||||||
|
@ -17,10 +20,12 @@ import 'package:cake_wallet/entities/contact.dart';
|
||||||
import 'package:cake_wallet/entities/fs_migration.dart';
|
import 'package:cake_wallet/entities/fs_migration.dart';
|
||||||
import 'package:cake_wallet/entities/wallet_info.dart';
|
import 'package:cake_wallet/entities/wallet_info.dart';
|
||||||
import 'package:cake_wallet/exchange/trade.dart';
|
import 'package:cake_wallet/exchange/trade.dart';
|
||||||
|
import 'package:encrypt/encrypt.dart' as encrypt;
|
||||||
|
|
||||||
Future defaultSettingsMigration(
|
Future defaultSettingsMigration(
|
||||||
{@required int version,
|
{@required int version,
|
||||||
@required SharedPreferences sharedPreferences,
|
@required SharedPreferences sharedPreferences,
|
||||||
|
@required FlutterSecureStorage secureStorage,
|
||||||
@required Box<Node> nodes,
|
@required Box<Node> nodes,
|
||||||
@required Box<WalletInfo> walletInfoSource,
|
@required Box<WalletInfo> walletInfoSource,
|
||||||
@required Box<Trade> tradeSource,
|
@required Box<Trade> tradeSource,
|
||||||
|
@ -29,8 +34,8 @@ Future defaultSettingsMigration(
|
||||||
await ios_migrate_v1(walletInfoSource, tradeSource, contactSource);
|
await ios_migrate_v1(walletInfoSource, tradeSource, contactSource);
|
||||||
}
|
}
|
||||||
|
|
||||||
final currentVersion =
|
final currentVersion = sharedPreferences
|
||||||
sharedPreferences.getInt('current_default_settings_migration_version') ??
|
.getInt(PreferencesKey.currentDefaultSettingsMigrationVersion) ??
|
||||||
0;
|
0;
|
||||||
if (currentVersion >= version) {
|
if (currentVersion >= version) {
|
||||||
return;
|
return;
|
||||||
|
@ -85,6 +90,10 @@ Future defaultSettingsMigration(
|
||||||
await updateDisplayModes(sharedPreferences);
|
await updateDisplayModes(sharedPreferences);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 9:
|
||||||
|
await generateBackupPassword(secureStorage);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -230,5 +239,17 @@ Future<void> updateDisplayModes(SharedPreferences sharedPreferences) async {
|
||||||
final currentBalanceDisplayMode =
|
final currentBalanceDisplayMode =
|
||||||
sharedPreferences.getInt(PreferencesKey.currentBalanceDisplayModeKey);
|
sharedPreferences.getInt(PreferencesKey.currentBalanceDisplayModeKey);
|
||||||
final balanceDisplayMode = currentBalanceDisplayMode < 2 ? 3 : 2;
|
final balanceDisplayMode = currentBalanceDisplayMode < 2 ? 3 : 2;
|
||||||
await sharedPreferences.setInt(PreferencesKey.currentBalanceDisplayModeKey, balanceDisplayMode);
|
await sharedPreferences.setInt(
|
||||||
|
PreferencesKey.currentBalanceDisplayModeKey, balanceDisplayMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> generateBackupPassword(FlutterSecureStorage secureStorage) async {
|
||||||
|
final key = generateStoreKeyFor(key: SecretStoreKey.backupPassword);
|
||||||
|
|
||||||
|
if ((await secureStorage.read(key: key))?.isNotEmpty ?? false) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final password = encrypt.Key.fromSecureRandom(32).base16;
|
||||||
|
await secureStorage.write(key: key, value: password);
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ import 'package:cake_wallet/entities/digest_request.dart';
|
||||||
|
|
||||||
part 'node.g.dart';
|
part 'node.g.dart';
|
||||||
|
|
||||||
@HiveType(typeId: 1)
|
@HiveType(typeId: Node.typeId)
|
||||||
class Node extends HiveObject with Keyable {
|
class Node extends HiveObject with Keyable {
|
||||||
Node(
|
Node(
|
||||||
{@required this.uri,
|
{@required this.uri,
|
||||||
|
@ -26,6 +26,7 @@ class Node extends HiveObject with Keyable {
|
||||||
typeRaw = map['typeRaw'] as int,
|
typeRaw = map['typeRaw'] as int,
|
||||||
useSSL = map['useSSL'] as bool;
|
useSSL = map['useSSL'] as bool;
|
||||||
|
|
||||||
|
static const typeId = 1;
|
||||||
static const boxName = 'Nodes';
|
static const boxName = 'Nodes';
|
||||||
|
|
||||||
@HiveField(0)
|
@HiveField(0)
|
||||||
|
|
|
@ -14,4 +14,5 @@ class PreferencesKey {
|
||||||
static const displayActionListModeKey = 'display_list_mode';
|
static const displayActionListModeKey = 'display_list_mode';
|
||||||
static const currentPinLength = 'current_pin_length';
|
static const currentPinLength = 'current_pin_length';
|
||||||
static const currentLanguageCode = 'language_code';
|
static const currentLanguageCode = 'language_code';
|
||||||
|
static const currentDefaultSettingsMigrationVersion = 'current_default_settings_migration_version';
|
||||||
}
|
}
|
|
@ -2,10 +2,11 @@ import 'package:hive/hive.dart';
|
||||||
|
|
||||||
part 'template.g.dart';
|
part 'template.g.dart';
|
||||||
|
|
||||||
@HiveType(typeId: 6)
|
@HiveType(typeId: Template.typeId)
|
||||||
class Template extends HiveObject {
|
class Template extends HiveObject {
|
||||||
Template({this.name, this.address, this.cryptoCurrency, this.amount});
|
Template({this.name, this.address, this.cryptoCurrency, this.amount});
|
||||||
|
|
||||||
|
static const typeId = 6;
|
||||||
static const boxName = 'Template';
|
static const boxName = 'Template';
|
||||||
|
|
||||||
@HiveField(0)
|
@HiveField(0)
|
||||||
|
|
|
@ -2,10 +2,11 @@ import 'package:hive/hive.dart';
|
||||||
|
|
||||||
part 'transaction_description.g.dart';
|
part 'transaction_description.g.dart';
|
||||||
|
|
||||||
@HiveType(typeId: 2)
|
@HiveType(typeId: TransactionDescription.typeId)
|
||||||
class TransactionDescription extends HiveObject {
|
class TransactionDescription extends HiveObject {
|
||||||
TransactionDescription({this.id, this.recipientAddress, this.transactionNote});
|
TransactionDescription({this.id, this.recipientAddress, this.transactionNote});
|
||||||
|
|
||||||
|
static const typeId = 2;
|
||||||
static const boxName = 'TransactionDescriptions';
|
static const boxName = 'TransactionDescriptions';
|
||||||
static const boxKey = 'transactionDescriptionsBoxKey';
|
static const boxKey = 'transactionDescriptionsBoxKey';
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ import 'package:cake_wallet/entities/wallet_type.dart';
|
||||||
|
|
||||||
part 'wallet_info.g.dart';
|
part 'wallet_info.g.dart';
|
||||||
|
|
||||||
@HiveType(typeId: 4)
|
@HiveType(typeId: WalletInfo.typeId)
|
||||||
class WalletInfo extends HiveObject {
|
class WalletInfo extends HiveObject {
|
||||||
WalletInfo(this.id, this.name, this.type, this.isRecovery, this.restoreHeight,
|
WalletInfo(this.id, this.name, this.type, this.isRecovery, this.restoreHeight,
|
||||||
this.timestamp, this.dirPath, this.path, this.address);
|
this.timestamp, this.dirPath, this.path, this.address);
|
||||||
|
@ -23,6 +23,7 @@ class WalletInfo extends HiveObject {
|
||||||
date.millisecondsSinceEpoch ?? 0, dirPath, path, address);
|
date.millisecondsSinceEpoch ?? 0, dirPath, path, address);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const typeId = 4;
|
||||||
static const boxName = 'WalletInfo';
|
static const boxName = 'WalletInfo';
|
||||||
|
|
||||||
@HiveField(0)
|
@HiveField(0)
|
||||||
|
|
|
@ -4,8 +4,9 @@ import 'package:hive/hive.dart';
|
||||||
part 'wallet_type.g.dart';
|
part 'wallet_type.g.dart';
|
||||||
|
|
||||||
const walletTypes = [WalletType.monero, WalletType.bitcoin];
|
const walletTypes = [WalletType.monero, WalletType.bitcoin];
|
||||||
|
const walletTypeTypeId = 5;
|
||||||
|
|
||||||
@HiveType(typeId: 5)
|
@HiveType(typeId: walletTypeTypeId)
|
||||||
enum WalletType {
|
enum WalletType {
|
||||||
@HiveField(0)
|
@HiveField(0)
|
||||||
monero,
|
monero,
|
||||||
|
|
|
@ -2,7 +2,7 @@ import 'package:hive/hive.dart';
|
||||||
|
|
||||||
part 'exchange_template.g.dart';
|
part 'exchange_template.g.dart';
|
||||||
|
|
||||||
@HiveType(typeId: 7)
|
@HiveType(typeId: ExchangeTemplate.typeId)
|
||||||
class ExchangeTemplate extends HiveObject {
|
class ExchangeTemplate extends HiveObject {
|
||||||
ExchangeTemplate({
|
ExchangeTemplate({
|
||||||
this.amount,
|
this.amount,
|
||||||
|
@ -13,6 +13,7 @@ class ExchangeTemplate extends HiveObject {
|
||||||
this.receiveAddress
|
this.receiveAddress
|
||||||
});
|
});
|
||||||
|
|
||||||
|
static const typeId = 7;
|
||||||
static const boxName = 'ExchangeTemplate';
|
static const boxName = 'ExchangeTemplate';
|
||||||
|
|
||||||
@HiveField(0)
|
@HiveField(0)
|
||||||
|
|
|
@ -6,7 +6,7 @@ import 'package:cake_wallet/entities/format_amount.dart';
|
||||||
|
|
||||||
part 'trade.g.dart';
|
part 'trade.g.dart';
|
||||||
|
|
||||||
@HiveType(typeId: 3)
|
@HiveType(typeId: Trade.typeId)
|
||||||
class Trade extends HiveObject {
|
class Trade extends HiveObject {
|
||||||
Trade(
|
Trade(
|
||||||
{this.id,
|
{this.id,
|
||||||
|
@ -27,6 +27,7 @@ class Trade extends HiveObject {
|
||||||
toRaw = to?.raw,
|
toRaw = to?.raw,
|
||||||
stateRaw = state?.raw;
|
stateRaw = state?.raw;
|
||||||
|
|
||||||
|
static const typeId = 3;
|
||||||
static const boxName = 'Trades';
|
static const boxName = 'Trades';
|
||||||
static const boxKey = 'tradesBoxKey';
|
static const boxKey = 'tradesBoxKey';
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,3 @@
|
||||||
import 'package:cake_wallet/core/backup.dart';
|
|
||||||
import 'package:cake_wallet/src/screens/backup/backup_page.dart';
|
|
||||||
import 'package:cake_wallet/bitcoin/bitcoin_address_record.dart';
|
|
||||||
import 'package:cake_wallet/themes/theme_base.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:hive/hive.dart';
|
import 'package:hive/hive.dart';
|
||||||
|
@ -12,6 +8,7 @@ import 'package:flutter_localizations/flutter_localizations.dart';
|
||||||
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
||||||
import 'package:flutter_mobx/flutter_mobx.dart';
|
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||||
import 'package:cw_monero/wallet.dart' as monero_wallet;
|
import 'package:cw_monero/wallet.dart' as monero_wallet;
|
||||||
|
import 'package:cake_wallet/themes/theme_base.dart';
|
||||||
import 'package:cake_wallet/router.dart' as Router;
|
import 'package:cake_wallet/router.dart' as Router;
|
||||||
import 'package:cake_wallet/routes.dart';
|
import 'package:cake_wallet/routes.dart';
|
||||||
import 'package:cake_wallet/generated/i18n.dart';
|
import 'package:cake_wallet/generated/i18n.dart';
|
||||||
|
@ -32,20 +29,46 @@ import 'package:cake_wallet/src/screens/root/root.dart';
|
||||||
|
|
||||||
final navigatorKey = GlobalKey<NavigatorState>();
|
final navigatorKey = GlobalKey<NavigatorState>();
|
||||||
|
|
||||||
void main() async {
|
Future<void> main() async {
|
||||||
try {
|
try {
|
||||||
WidgetsFlutterBinding.ensureInitialized();
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
|
|
||||||
final appDir = await getApplicationDocumentsDirectory();
|
final appDir = await getApplicationDocumentsDirectory();
|
||||||
|
await Hive.close();
|
||||||
Hive.init(appDir.path);
|
Hive.init(appDir.path);
|
||||||
|
|
||||||
|
if (!Hive.isAdapterRegistered(Contact.typeId)) {
|
||||||
Hive.registerAdapter(ContactAdapter());
|
Hive.registerAdapter(ContactAdapter());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Hive.isAdapterRegistered(Node.typeId)) {
|
||||||
Hive.registerAdapter(NodeAdapter());
|
Hive.registerAdapter(NodeAdapter());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Hive.isAdapterRegistered(TransactionDescription.typeId)) {
|
||||||
Hive.registerAdapter(TransactionDescriptionAdapter());
|
Hive.registerAdapter(TransactionDescriptionAdapter());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Hive.isAdapterRegistered(Trade.typeId)) {
|
||||||
Hive.registerAdapter(TradeAdapter());
|
Hive.registerAdapter(TradeAdapter());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Hive.isAdapterRegistered(WalletInfo.typeId)) {
|
||||||
Hive.registerAdapter(WalletInfoAdapter());
|
Hive.registerAdapter(WalletInfoAdapter());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Hive.isAdapterRegistered(walletTypeTypeId)) {
|
||||||
Hive.registerAdapter(WalletTypeAdapter());
|
Hive.registerAdapter(WalletTypeAdapter());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Hive.isAdapterRegistered(Template.typeId)) {
|
||||||
Hive.registerAdapter(TemplateAdapter());
|
Hive.registerAdapter(TemplateAdapter());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Hive.isAdapterRegistered(ExchangeTemplate.typeId)) {
|
||||||
Hive.registerAdapter(ExchangeTemplateAdapter());
|
Hive.registerAdapter(ExchangeTemplateAdapter());
|
||||||
|
}
|
||||||
|
|
||||||
final secureStorage = FlutterSecureStorage();
|
final secureStorage = FlutterSecureStorage();
|
||||||
final transactionDescriptionsBoxKey = await getEncryptionKey(
|
final transactionDescriptionsBoxKey = await getEncryptionKey(
|
||||||
secureStorage: secureStorage, forKey: TransactionDescription.boxKey);
|
secureStorage: secureStorage, forKey: TransactionDescription.boxKey);
|
||||||
|
@ -72,7 +95,8 @@ void main() async {
|
||||||
templates: templates,
|
templates: templates,
|
||||||
exchangeTemplates: exchangeTemplates,
|
exchangeTemplates: exchangeTemplates,
|
||||||
transactionDescriptions: transactionDescriptions,
|
transactionDescriptions: transactionDescriptions,
|
||||||
initialMigrationVersion: 5);
|
secureStorage: secureStorage,
|
||||||
|
initialMigrationVersion: 9);
|
||||||
runApp(App());
|
runApp(App());
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
runApp(MaterialApp(
|
runApp(MaterialApp(
|
||||||
|
@ -88,7 +112,8 @@ void main() async {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> initialSetup({@required SharedPreferences sharedPreferences,
|
Future<void> initialSetup(
|
||||||
|
{@required SharedPreferences sharedPreferences,
|
||||||
@required Box<Node> nodes,
|
@required Box<Node> nodes,
|
||||||
@required Box<WalletInfo> walletInfoSource,
|
@required Box<WalletInfo> walletInfoSource,
|
||||||
@required Box<Contact> contactSource,
|
@required Box<Contact> contactSource,
|
||||||
|
@ -97,8 +122,10 @@ Future<void> initialSetup({@required SharedPreferences sharedPreferences,
|
||||||
@required Box<Template> templates,
|
@required Box<Template> templates,
|
||||||
@required Box<ExchangeTemplate> exchangeTemplates,
|
@required Box<ExchangeTemplate> exchangeTemplates,
|
||||||
@required Box<TransactionDescription> transactionDescriptions,
|
@required Box<TransactionDescription> transactionDescriptions,
|
||||||
int initialMigrationVersion = 6}) async {
|
FlutterSecureStorage secureStorage,
|
||||||
|
int initialMigrationVersion = 9}) async {
|
||||||
await defaultSettingsMigration(
|
await defaultSettingsMigration(
|
||||||
|
secureStorage: secureStorage,
|
||||||
version: initialMigrationVersion,
|
version: initialMigrationVersion,
|
||||||
sharedPreferences: sharedPreferences,
|
sharedPreferences: sharedPreferences,
|
||||||
walletInfoSource: walletInfoSource,
|
walletInfoSource: walletInfoSource,
|
||||||
|
@ -113,7 +140,7 @@ Future<void> initialSetup({@required SharedPreferences sharedPreferences,
|
||||||
templates: templates,
|
templates: templates,
|
||||||
exchangeTemplates: exchangeTemplates,
|
exchangeTemplates: exchangeTemplates,
|
||||||
transactionDescriptionBox: transactionDescriptions);
|
transactionDescriptionBox: transactionDescriptions);
|
||||||
bootstrap(navigatorKey);
|
await bootstrap(navigatorKey);
|
||||||
monero_wallet.onStartup();
|
monero_wallet.onStartup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,16 +152,14 @@ class App extends StatelessWidget {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final settingsStore = getIt
|
return Observer(builder: (BuildContext context) {
|
||||||
.get<AppStore>()
|
final settingsStore = getIt.get<AppStore>().settingsStore;
|
||||||
.settingsStore;
|
|
||||||
final statusBarColor = Colors.transparent;
|
final statusBarColor = Colors.transparent;
|
||||||
final authenticationStore = getIt.get<AuthenticationStore>();
|
final authenticationStore = getIt.get<AuthenticationStore>();
|
||||||
final initialRoute = authenticationStore.state == AuthenticationState.denied
|
final initialRoute =
|
||||||
|
authenticationStore.state == AuthenticationState.denied
|
||||||
? Routes.disclaimer
|
? Routes.disclaimer
|
||||||
: Routes.login;
|
: Routes.login;
|
||||||
|
|
||||||
return Observer(builder: (BuildContext context) {
|
|
||||||
final currentTheme = settingsStore.currentTheme;
|
final currentTheme = settingsStore.currentTheme;
|
||||||
final statusBarBrightness = currentTheme.type == ThemeType.dark
|
final statusBarBrightness = currentTheme.type == ThemeType.dark
|
||||||
? Brightness.light
|
? Brightness.light
|
||||||
|
|
|
@ -19,14 +19,12 @@ Future<void> bootstrap(GlobalKey<NavigatorState> navigatorKey) async {
|
||||||
final settingsStore = getIt.get<SettingsStore>();
|
final settingsStore = getIt.get<SettingsStore>();
|
||||||
final fiatConversionStore = getIt.get<FiatConversionStore>();
|
final fiatConversionStore = getIt.get<FiatConversionStore>();
|
||||||
|
|
||||||
if (authenticationStore.state == AuthenticationState.uninitialized) {
|
|
||||||
final currentWalletName = getIt
|
final currentWalletName = getIt
|
||||||
.get<SharedPreferences>()
|
.get<SharedPreferences>()
|
||||||
.getString(PreferencesKey.currentWalletName);
|
.getString(PreferencesKey.currentWalletName);
|
||||||
authenticationStore.state = currentWalletName == null
|
authenticationStore.state = currentWalletName == null
|
||||||
? AuthenticationState.denied
|
? AuthenticationState.denied
|
||||||
: AuthenticationState.installed;
|
: AuthenticationState.installed;
|
||||||
}
|
|
||||||
|
|
||||||
startAuthenticationStateChange(authenticationStore, navigatorKey);
|
startAuthenticationStateChange(authenticationStore, navigatorKey);
|
||||||
startCurrentWalletChangeReaction(
|
startCurrentWalletChangeReaction(
|
||||||
|
|
|
@ -106,9 +106,8 @@ Route<dynamic> createRoute(RouteSettings settings) {
|
||||||
param2: false));
|
param2: false));
|
||||||
|
|
||||||
case Routes.restoreOptions:
|
case Routes.restoreOptions:
|
||||||
final type = settings.arguments as WalletType;
|
|
||||||
return CupertinoPageRoute<void>(
|
return CupertinoPageRoute<void>(
|
||||||
builder: (_) => getIt.get<RestoreOptionsPage>(param1: type));
|
builder: (_) => getIt.get<RestoreOptionsPage>());
|
||||||
|
|
||||||
case Routes.restoreWalletOptions:
|
case Routes.restoreWalletOptions:
|
||||||
final type = WalletType.monero; //settings.arguments as WalletType;
|
final type = WalletType.monero; //settings.arguments as WalletType;
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_mobx/flutter_mobx.dart';
|
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||||
import 'package:esys_flutter_share/esys_flutter_share.dart';
|
import 'package:esys_flutter_share/esys_flutter_share.dart';
|
||||||
|
import 'package:cake_wallet/utils/show_bar.dart';
|
||||||
import 'package:cake_wallet/routes.dart';
|
import 'package:cake_wallet/routes.dart';
|
||||||
import 'package:cake_wallet/generated/i18n.dart';
|
import 'package:cake_wallet/generated/i18n.dart';
|
||||||
import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart';
|
import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart';
|
||||||
|
@ -34,7 +36,7 @@ class BackupPage extends BasePage {
|
||||||
Center(
|
Center(
|
||||||
child: Container(
|
child: Container(
|
||||||
padding: EdgeInsets.only(left: 20, right: 20),
|
padding: EdgeInsets.only(left: 20, right: 20),
|
||||||
height: 225,
|
height: 300,
|
||||||
child: Column(children: [
|
child: Column(children: [
|
||||||
Text(
|
Text(
|
||||||
'Backup password:',
|
'Backup password:',
|
||||||
|
@ -43,9 +45,21 @@ class BackupPage extends BasePage {
|
||||||
Padding(
|
Padding(
|
||||||
padding: EdgeInsets.only(top: 20, bottom: 10),
|
padding: EdgeInsets.only(top: 20, bottom: 10),
|
||||||
child: Observer(
|
child: Observer(
|
||||||
builder: (_) => Text(
|
builder: (_) => GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
Clipboard.setData(ClipboardData(
|
||||||
|
text:
|
||||||
|
backupViewModelBase.backupPassword));
|
||||||
|
showBar<void>(
|
||||||
|
context,
|
||||||
|
S.of(context).transaction_details_copied(
|
||||||
|
'Backup password'));
|
||||||
|
},
|
||||||
|
child: Text(
|
||||||
backupViewModelBase.backupPassword,
|
backupViewModelBase.backupPassword,
|
||||||
style: TextStyle(fontSize: 26),
|
style: TextStyle(fontSize: 26),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
),
|
||||||
))),
|
))),
|
||||||
Padding(
|
Padding(
|
||||||
padding: EdgeInsets.all(20),
|
padding: EdgeInsets.all(20),
|
||||||
|
|
|
@ -84,5 +84,6 @@ class RestoreFromBackupPage extends BasePage {
|
||||||
}
|
}
|
||||||
|
|
||||||
await restoreFromBackupViewModel.import(textEditingController.text);
|
await restoreFromBackupViewModel.import(textEditingController.text);
|
||||||
|
textEditingController.text = '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
import 'package:cake_wallet/entities/wallet_type.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:cake_wallet/routes.dart';
|
import 'package:cake_wallet/routes.dart';
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
|
@ -7,10 +6,9 @@ import 'package:cake_wallet/src/screens/base_page.dart';
|
||||||
import 'package:cake_wallet/generated/i18n.dart';
|
import 'package:cake_wallet/generated/i18n.dart';
|
||||||
|
|
||||||
class RestoreOptionsPage extends BasePage {
|
class RestoreOptionsPage extends BasePage {
|
||||||
RestoreOptionsPage({@required this.type});
|
RestoreOptionsPage();
|
||||||
|
|
||||||
static const _aspectRatioImage = 2.086;
|
static const _aspectRatioImage = 2.086;
|
||||||
final WalletType type;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get title => S.current.restore_restore_wallet;
|
String get title => S.current.restore_restore_wallet;
|
||||||
|
@ -29,25 +27,22 @@ class RestoreOptionsPage extends BasePage {
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
RestoreButton(
|
RestoreButton(
|
||||||
onPressed: () =>
|
onPressed: () =>
|
||||||
Navigator.pushNamed(
|
Navigator.pushNamed(context, Routes.restoreWalletOptionsFromWelcome),
|
||||||
context, Routes.restoreWalletOptionsFromWelcome),
|
|
||||||
image: imageSeedKeys,
|
image: imageSeedKeys,
|
||||||
title: S.of(context).restore_title_from_seed_keys,
|
title: S.of(context).restore_title_from_seed_keys,
|
||||||
description: S.of(context).restore_description_from_seed_keys
|
description:
|
||||||
),
|
S.of(context).restore_description_from_seed_keys),
|
||||||
Padding(
|
Padding(
|
||||||
padding: EdgeInsets.only(top: 24),
|
padding: EdgeInsets.only(top: 24),
|
||||||
child: RestoreButton(
|
child: RestoreButton(
|
||||||
onPressed: () => Navigator.pushNamed(
|
onPressed: () =>
|
||||||
context, Routes.restoreFromBackup),
|
Navigator.pushNamed(context, Routes.restoreFromBackup),
|
||||||
image: imageBackup,
|
image: imageBackup,
|
||||||
title: S.of(context).restore_title_from_backup,
|
title: S.of(context).restore_title_from_backup,
|
||||||
description: S.of(context).restore_description_from_backup
|
description: S.of(context).restore_description_from_backup),
|
||||||
),
|
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
)
|
));
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -160,7 +160,7 @@ class WelcomePage extends BasePage {
|
||||||
child: PrimaryImageButton(
|
child: PrimaryImageButton(
|
||||||
onPressed: () =>
|
onPressed: () =>
|
||||||
Navigator.pushNamed(context,
|
Navigator.pushNamed(context,
|
||||||
Routes.restoreWalletOptionsFromWelcome),
|
Routes.restoreOptions),
|
||||||
image: restoreWalletImage,
|
image: restoreWalletImage,
|
||||||
text: S
|
text: S
|
||||||
.of(context)
|
.of(context)
|
||||||
|
|
|
@ -18,7 +18,7 @@ class TrailButton extends StatelessWidget {
|
||||||
caption,
|
caption,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color:
|
color:
|
||||||
Theme.of(context).accentTextTheme.display4.decorationColor,
|
Theme.of(context).accentTextTheme.bodyText2.color,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
fontSize: 14),
|
fontSize: 14),
|
||||||
),
|
),
|
||||||
|
|
|
@ -85,10 +85,10 @@ abstract class SettingsStoreBase with Store {
|
||||||
(String languageCode) => sharedPreferences.setString(
|
(String languageCode) => sharedPreferences.setString(
|
||||||
PreferencesKey.currentLanguageCode, languageCode));
|
PreferencesKey.currentLanguageCode, languageCode));
|
||||||
|
|
||||||
reaction((_) => balanceDisplayMode,
|
reaction(
|
||||||
|
(_) => balanceDisplayMode,
|
||||||
(BalanceDisplayMode mode) => sharedPreferences.setInt(
|
(BalanceDisplayMode mode) => sharedPreferences.setInt(
|
||||||
PreferencesKey.currentBalanceDisplayModeKey,
|
PreferencesKey.currentBalanceDisplayModeKey, mode.serialize()));
|
||||||
mode.serialize()));
|
|
||||||
|
|
||||||
this
|
this
|
||||||
.nodes
|
.nodes
|
||||||
|
@ -203,6 +203,29 @@ abstract class SettingsStoreBase with Store {
|
||||||
initialLanguageCode: savedLanguageCode);
|
initialLanguageCode: savedLanguageCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> reload(
|
||||||
|
{@required Box<Node> nodeSource,
|
||||||
|
FiatCurrency initialFiatCurrency = FiatCurrency.usd,
|
||||||
|
TransactionPriority initialTransactionPriority = TransactionPriority.slow,
|
||||||
|
BalanceDisplayMode initialBalanceDisplayMode =
|
||||||
|
BalanceDisplayMode.availableBalance}) async {
|
||||||
|
final settings = await SettingsStoreBase.load(
|
||||||
|
nodeSource: nodeSource,
|
||||||
|
initialBalanceDisplayMode: initialBalanceDisplayMode,
|
||||||
|
initialFiatCurrency: initialFiatCurrency,
|
||||||
|
initialTransactionPriority: initialTransactionPriority);
|
||||||
|
fiatCurrency = settings.fiatCurrency;
|
||||||
|
actionlistDisplayMode = settings.actionlistDisplayMode;
|
||||||
|
transactionPriority = settings.transactionPriority;
|
||||||
|
balanceDisplayMode = settings.balanceDisplayMode;
|
||||||
|
shouldSaveRecipientAddress = settings.shouldSaveRecipientAddress;
|
||||||
|
allowBiometricalAuthentication = settings.allowBiometricalAuthentication;
|
||||||
|
currentTheme = settings.currentTheme;
|
||||||
|
pinCodeLength = settings.pinCodeLength;
|
||||||
|
languageCode = settings.languageCode;
|
||||||
|
appVersion = settings.appVersion;
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> _saveCurrentNode(Node node, WalletType walletType) async {
|
Future<void> _saveCurrentNode(Node node, WalletType walletType) async {
|
||||||
switch (walletType) {
|
switch (walletType) {
|
||||||
case WalletType.bitcoin:
|
case WalletType.bitcoin:
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import 'package:cake_wallet/core/backup.dart';
|
import 'package:cake_wallet/core/backup_service.dart';
|
||||||
import 'package:cake_wallet/core/execution_state.dart';
|
import 'package:cake_wallet/core/execution_state.dart';
|
||||||
import 'package:cake_wallet/entities/secret_store_key.dart';
|
import 'package:cake_wallet/entities/secret_store_key.dart';
|
||||||
import 'package:cake_wallet/store/secret_store.dart';
|
import 'package:cake_wallet/store/secret_store.dart';
|
||||||
|
@ -52,7 +52,7 @@ abstract class BackupViewModelBase with Store {
|
||||||
Future<BackupExportFile> exportBackup() async {
|
Future<BackupExportFile> exportBackup() async {
|
||||||
try {
|
try {
|
||||||
state = IsExecutingState();
|
state = IsExecutingState();
|
||||||
final backupContent = await backupService.exportBackup('', nonce: '');
|
final backupContent = await backupService.exportBackup(backupPassword);
|
||||||
state = ExecutedSuccessfullyState();
|
state = ExecutedSuccessfullyState();
|
||||||
|
|
||||||
return BackupExportFile(backupContent.toList(),
|
return BackupExportFile(backupContent.toList(),
|
||||||
|
@ -60,6 +60,7 @@ abstract class BackupViewModelBase with Store {
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print(e.toString());
|
print(e.toString());
|
||||||
state = FailureState(e.toString());
|
state = FailureState(e.toString());
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,17 @@
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
import 'package:hive/hive.dart';
|
||||||
import 'package:cake_wallet/core/backup.dart';
|
|
||||||
import 'package:mobx/mobx.dart';
|
import 'package:mobx/mobx.dart';
|
||||||
|
import 'package:cake_wallet/main.dart';
|
||||||
|
import 'package:cake_wallet/di.dart';
|
||||||
|
import 'package:cake_wallet/core/backup_service.dart';
|
||||||
|
import 'package:cake_wallet/entities/node.dart';
|
||||||
|
import 'package:cake_wallet/store/app_store.dart';
|
||||||
|
import 'package:cake_wallet/store/authentication_store.dart';
|
||||||
|
|
||||||
part 'restore_from_backup_view_model.g.dart';
|
part 'restore_from_backup_view_model.g.dart';
|
||||||
|
|
||||||
class RestoreFromBackupViewModel = RestoreFromBackupViewModelBase with _$RestoreFromBackupViewModel;
|
class RestoreFromBackupViewModel = RestoreFromBackupViewModelBase
|
||||||
|
with _$RestoreFromBackupViewModel;
|
||||||
|
|
||||||
abstract class RestoreFromBackupViewModelBase with Store {
|
abstract class RestoreFromBackupViewModelBase with Store {
|
||||||
RestoreFromBackupViewModelBase(this.backupService);
|
RestoreFromBackupViewModelBase(this.backupService);
|
||||||
|
@ -15,7 +21,11 @@ abstract class RestoreFromBackupViewModelBase with Store {
|
||||||
|
|
||||||
final BackupService backupService;
|
final BackupService backupService;
|
||||||
|
|
||||||
|
@action
|
||||||
|
void reset() => filePath = '';
|
||||||
|
|
||||||
Future<void> import(String password) async {
|
Future<void> import(String password) async {
|
||||||
|
try {
|
||||||
if (filePath?.isEmpty ?? true) {
|
if (filePath?.isEmpty ?? true) {
|
||||||
// FIXME: throw exception;
|
// FIXME: throw exception;
|
||||||
return;
|
return;
|
||||||
|
@ -24,6 +34,23 @@ abstract class RestoreFromBackupViewModelBase with Store {
|
||||||
final file = File(filePath);
|
final file = File(filePath);
|
||||||
final data = await file.readAsBytes();
|
final data = await file.readAsBytes();
|
||||||
|
|
||||||
await backupService.importBackup(data, password, nonce: null);
|
await backupService.importBackup(data, password);
|
||||||
|
await main();
|
||||||
|
|
||||||
|
final store = getIt.get<AppStore>();
|
||||||
|
ReactionDisposer reaction;
|
||||||
|
await store.settingsStore.reload(nodeSource: getIt.get<Box<Node>>());
|
||||||
|
|
||||||
|
reaction = autorun((_) {
|
||||||
|
final wallet = store.wallet;
|
||||||
|
|
||||||
|
if (wallet != null) {
|
||||||
|
store.authenticationStore.state = AuthenticationState.allowed;
|
||||||
|
reaction?.reaction?.dispose();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
print(e.toString());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -122,6 +122,19 @@ abstract class SettingsViewModelBase with Store {
|
||||||
onItemSelected: (ThemeBase theme) =>
|
onItemSelected: (ThemeBase theme) =>
|
||||||
_settingsStore.currentTheme = theme)
|
_settingsStore.currentTheme = theme)
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
RegularListItem(
|
||||||
|
title: 'Backup',
|
||||||
|
handler: (BuildContext context) {
|
||||||
|
Navigator.of(context).pushNamed(Routes.auth, arguments:
|
||||||
|
(bool isAuthenticatedSuccessfully, AuthPageState auth) {
|
||||||
|
auth.close();
|
||||||
|
if (isAuthenticatedSuccessfully) {
|
||||||
|
Navigator.of(context).pushNamed(Routes.backup);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}),
|
||||||
|
],
|
||||||
[
|
[
|
||||||
LinkListItem(
|
LinkListItem(
|
||||||
title: 'Email',
|
title: 'Email',
|
||||||
|
|
Loading…
Reference in a new issue