Db encryption
This commit is contained in:
parent
d26a045863
commit
bbbfabb5af
|
@ -203,4 +203,4 @@ SPEC CHECKSUMS:
|
|||
|
||||
PODFILE CHECKSUM: e1af8a78652670a5b7b8de8c5f3641ce5c737641
|
||||
|
||||
COCOAPODS: 1.11.3
|
||||
COCOAPODS: 1.12.0
|
||||
|
|
|
@ -190,8 +190,16 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||
MessageLookupByLibrary.simpleMessage("Tap + to add a new contact"),
|
||||
"crypto": MessageLookupByLibrary.simpleMessage("Crypto"),
|
||||
"currency": MessageLookupByLibrary.simpleMessage("Currency"),
|
||||
"currentPassword":
|
||||
MessageLookupByLibrary.simpleMessage("Current Password"),
|
||||
"currentPasswordIncorrect":
|
||||
MessageLookupByLibrary.simpleMessage("Current password incorrect"),
|
||||
"custom": MessageLookupByLibrary.simpleMessage("Custom"),
|
||||
"dark": MessageLookupByLibrary.simpleMessage("Dark"),
|
||||
"databaseEncrypted": MessageLookupByLibrary.simpleMessage(
|
||||
"Database Encrypted. Please Restart the App."),
|
||||
"databasePassword":
|
||||
MessageLookupByLibrary.simpleMessage("Database Password"),
|
||||
"databaseUpdatedPleaseRestartTheApp":
|
||||
MessageLookupByLibrary.simpleMessage(
|
||||
"Database updated. Please restart the app."),
|
||||
|
@ -219,6 +227,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||
"duplicateContact": MessageLookupByLibrary.simpleMessage(
|
||||
"Another contact has this address"),
|
||||
"editContact": MessageLookupByLibrary.simpleMessage("Edit Contact"),
|
||||
"encryptDatabase":
|
||||
MessageLookupByLibrary.simpleMessage("Encrypt Database"),
|
||||
"encryptedBackup": m6,
|
||||
"encryptionKey": MessageLookupByLibrary.simpleMessage("Encryption Key"),
|
||||
"enterSecretShareIfAccountIsMultisignature":
|
||||
|
@ -255,6 +265,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||
"invalidAddress":
|
||||
MessageLookupByLibrary.simpleMessage("Invalid Address"),
|
||||
"invalidKey": MessageLookupByLibrary.simpleMessage("Invalid Key"),
|
||||
"invalidPassword":
|
||||
MessageLookupByLibrary.simpleMessage("Invalid Password"),
|
||||
"invalidQrCode": m8,
|
||||
"key": MessageLookupByLibrary.simpleMessage(
|
||||
"Seed, Secret Key or View Key (optional)"),
|
||||
|
@ -295,6 +307,9 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||
"nameIsEmpty": MessageLookupByLibrary.simpleMessage("Name is empty"),
|
||||
"newAccount": MessageLookupByLibrary.simpleMessage("New Account"),
|
||||
"newLabel": MessageLookupByLibrary.simpleMessage("New"),
|
||||
"newPassword": MessageLookupByLibrary.simpleMessage("New Password"),
|
||||
"newPasswordsDoNotMatch":
|
||||
MessageLookupByLibrary.simpleMessage("New passwords do not match"),
|
||||
"newSnapAddress":
|
||||
MessageLookupByLibrary.simpleMessage("New Snap Address"),
|
||||
"newSubAccount":
|
||||
|
@ -360,6 +375,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||
MessageLookupByLibrary.simpleMessage("Receive Payment"),
|
||||
"received": m13,
|
||||
"recipient": MessageLookupByLibrary.simpleMessage("Recipient"),
|
||||
"repeatNewPassword":
|
||||
MessageLookupByLibrary.simpleMessage("Repeat New Password"),
|
||||
"reply": MessageLookupByLibrary.simpleMessage("Reply"),
|
||||
"rescan": MessageLookupByLibrary.simpleMessage("Rescan"),
|
||||
"rescanFrom": MessageLookupByLibrary.simpleMessage("Rescan from..."),
|
||||
|
|
|
@ -193,8 +193,16 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||
"Crea un contacto y aparecerá aquí."),
|
||||
"crypto": MessageLookupByLibrary.simpleMessage("Crypto"),
|
||||
"currency": MessageLookupByLibrary.simpleMessage("Moneda"),
|
||||
"currentPassword":
|
||||
MessageLookupByLibrary.simpleMessage("Current password"),
|
||||
"currentPasswordIncorrect":
|
||||
MessageLookupByLibrary.simpleMessage("Current password incorrect"),
|
||||
"custom": MessageLookupByLibrary.simpleMessage("Personalizado"),
|
||||
"dark": MessageLookupByLibrary.simpleMessage("Noche"),
|
||||
"databaseEncrypted": MessageLookupByLibrary.simpleMessage(
|
||||
"Database Encrypted. Please Restart the App."),
|
||||
"databasePassword":
|
||||
MessageLookupByLibrary.simpleMessage("Database Password"),
|
||||
"databaseUpdatedPleaseRestartTheApp":
|
||||
MessageLookupByLibrary.simpleMessage(
|
||||
"Por favor reinicie la aplicación"),
|
||||
|
@ -221,6 +229,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||
"duplicateAccount":
|
||||
MessageLookupByLibrary.simpleMessage("Cuenta duplicada"),
|
||||
"editContact": MessageLookupByLibrary.simpleMessage("Editar contacto"),
|
||||
"encryptDatabase":
|
||||
MessageLookupByLibrary.simpleMessage("Encrypt Database"),
|
||||
"encryptedBackup": m6,
|
||||
"encryptionKey":
|
||||
MessageLookupByLibrary.simpleMessage("Clave de encriptación"),
|
||||
|
@ -260,6 +270,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||
"invalidAddress":
|
||||
MessageLookupByLibrary.simpleMessage("La Dirección no es válida"),
|
||||
"invalidKey": MessageLookupByLibrary.simpleMessage("Tecla inválida"),
|
||||
"invalidPassword":
|
||||
MessageLookupByLibrary.simpleMessage("Invalid Password"),
|
||||
"invalidQrCode": m8,
|
||||
"key": MessageLookupByLibrary.simpleMessage("Clave"),
|
||||
"keyTool": MessageLookupByLibrary.simpleMessage("Clave Utilidad"),
|
||||
|
@ -300,6 +312,9 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||
"nameIsEmpty": MessageLookupByLibrary.simpleMessage("Nombre vacío"),
|
||||
"newAccount": MessageLookupByLibrary.simpleMessage("Nueva cuenta"),
|
||||
"newLabel": MessageLookupByLibrary.simpleMessage("Nueva"),
|
||||
"newPassword": MessageLookupByLibrary.simpleMessage("New Password"),
|
||||
"newPasswordsDoNotMatch":
|
||||
MessageLookupByLibrary.simpleMessage("New passwords do not match"),
|
||||
"newSnapAddress":
|
||||
MessageLookupByLibrary.simpleMessage("Nueva Dirección instantánea"),
|
||||
"newSubAccount":
|
||||
|
@ -364,6 +379,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||
MessageLookupByLibrary.simpleMessage("Recibir un pago"),
|
||||
"received": m13,
|
||||
"recipient": MessageLookupByLibrary.simpleMessage("Destinatario"),
|
||||
"repeatNewPassword":
|
||||
MessageLookupByLibrary.simpleMessage("Repeat New Password"),
|
||||
"reply": MessageLookupByLibrary.simpleMessage("Responder"),
|
||||
"rescan": MessageLookupByLibrary.simpleMessage("Escanear"),
|
||||
"rescanFrom":
|
||||
|
|
|
@ -192,8 +192,16 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||
"Créez un nouveau contact et il apparaîtra ici"),
|
||||
"crypto": MessageLookupByLibrary.simpleMessage("Crypto"),
|
||||
"currency": MessageLookupByLibrary.simpleMessage("Devise"),
|
||||
"currentPassword":
|
||||
MessageLookupByLibrary.simpleMessage("Current password"),
|
||||
"currentPasswordIncorrect":
|
||||
MessageLookupByLibrary.simpleMessage("Current password incorrect"),
|
||||
"custom": MessageLookupByLibrary.simpleMessage("Personnaliser"),
|
||||
"dark": MessageLookupByLibrary.simpleMessage("Sombre"),
|
||||
"databaseEncrypted": MessageLookupByLibrary.simpleMessage(
|
||||
"Database Encrypted. Please Restart the App."),
|
||||
"databasePassword":
|
||||
MessageLookupByLibrary.simpleMessage("Database Password"),
|
||||
"databaseUpdatedPleaseRestartTheApp":
|
||||
MessageLookupByLibrary.simpleMessage("Redémarrer l\'appli SVP"),
|
||||
"date": MessageLookupByLibrary.simpleMessage("Date"),
|
||||
|
@ -221,6 +229,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||
MessageLookupByLibrary.simpleMessage("Compte en double"),
|
||||
"editContact":
|
||||
MessageLookupByLibrary.simpleMessage("Changer le Contact"),
|
||||
"encryptDatabase":
|
||||
MessageLookupByLibrary.simpleMessage("Encrypt Database"),
|
||||
"encryptedBackup": m6,
|
||||
"encryptionKey": MessageLookupByLibrary.simpleMessage("Clé Publique"),
|
||||
"enterSecretShareIfAccountIsMultisignature":
|
||||
|
@ -259,6 +269,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||
"invalidAddress":
|
||||
MessageLookupByLibrary.simpleMessage("Adresse invalide"),
|
||||
"invalidKey": MessageLookupByLibrary.simpleMessage("Clé invalide"),
|
||||
"invalidPassword":
|
||||
MessageLookupByLibrary.simpleMessage("Invalid Password"),
|
||||
"invalidQrCode": m8,
|
||||
"key": MessageLookupByLibrary.simpleMessage("Clé"),
|
||||
"keyTool": MessageLookupByLibrary.simpleMessage("Clés Utilitaires"),
|
||||
|
@ -300,6 +312,9 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||
"nameIsEmpty": MessageLookupByLibrary.simpleMessage("Le nom est vide"),
|
||||
"newAccount": MessageLookupByLibrary.simpleMessage("Nouveau Compte"),
|
||||
"newLabel": MessageLookupByLibrary.simpleMessage("Nouveau"),
|
||||
"newPassword": MessageLookupByLibrary.simpleMessage("New Password"),
|
||||
"newPasswordsDoNotMatch":
|
||||
MessageLookupByLibrary.simpleMessage("New passwords do not match"),
|
||||
"newSnapAddress": MessageLookupByLibrary.simpleMessage(
|
||||
"Nouvelle adresse instantanée"),
|
||||
"newSubAccount":
|
||||
|
@ -365,6 +380,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||
MessageLookupByLibrary.simpleMessage("Recevoir un payment"),
|
||||
"received": m13,
|
||||
"recipient": MessageLookupByLibrary.simpleMessage("Destinataire"),
|
||||
"repeatNewPassword":
|
||||
MessageLookupByLibrary.simpleMessage("Repeat New Password"),
|
||||
"reply": MessageLookupByLibrary.simpleMessage("Répondre"),
|
||||
"rescan": MessageLookupByLibrary.simpleMessage("Parcourir à nouveau"),
|
||||
"rescanFrom":
|
||||
|
|
|
@ -3031,6 +3031,96 @@ class S {
|
|||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Encrypt Database`
|
||||
String get encryptDatabase {
|
||||
return Intl.message(
|
||||
'Encrypt Database',
|
||||
name: 'encryptDatabase',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Current Password`
|
||||
String get currentPassword {
|
||||
return Intl.message(
|
||||
'Current Password',
|
||||
name: 'currentPassword',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `New Password`
|
||||
String get newPassword {
|
||||
return Intl.message(
|
||||
'New Password',
|
||||
name: 'newPassword',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Repeat New Password`
|
||||
String get repeatNewPassword {
|
||||
return Intl.message(
|
||||
'Repeat New Password',
|
||||
name: 'repeatNewPassword',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Database Password`
|
||||
String get databasePassword {
|
||||
return Intl.message(
|
||||
'Database Password',
|
||||
name: 'databasePassword',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Current password incorrect`
|
||||
String get currentPasswordIncorrect {
|
||||
return Intl.message(
|
||||
'Current password incorrect',
|
||||
name: 'currentPasswordIncorrect',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `New passwords do not match`
|
||||
String get newPasswordsDoNotMatch {
|
||||
return Intl.message(
|
||||
'New passwords do not match',
|
||||
name: 'newPasswordsDoNotMatch',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Database Encrypted. Please Restart the App.`
|
||||
String get databaseEncrypted {
|
||||
return Intl.message(
|
||||
'Database Encrypted. Please Restart the App.',
|
||||
name: 'databaseEncrypted',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Invalid Password`
|
||||
String get invalidPassword {
|
||||
return Intl.message(
|
||||
'Invalid Password',
|
||||
name: 'invalidPassword',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class AppLocalizationDelegate extends LocalizationsDelegate<S> {
|
||||
|
|
|
@ -6,16 +6,19 @@ import 'package:flutter/material.dart';
|
|||
import 'package:flutter_foreground_task/flutter_foreground_task.dart';
|
||||
import 'package:flutter_form_builder/flutter_form_builder.dart';
|
||||
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
import 'package:warp_api/data_fb_generated.dart';
|
||||
import 'package:warp_api/types.dart';
|
||||
import 'package:warp_api/warp_api.dart';
|
||||
import 'package:badges/badges.dart' as Badges;
|
||||
import 'package:path/path.dart' as p;
|
||||
|
||||
import 'about.dart';
|
||||
import 'account.dart';
|
||||
import 'animated_qr.dart';
|
||||
import 'budget.dart';
|
||||
import 'coin/coins.dart';
|
||||
import 'contact.dart';
|
||||
import 'db.dart';
|
||||
import 'history.dart';
|
||||
|
@ -194,6 +197,7 @@ class HomeInnerState extends State<HomeInnerPage> with SingleTickerProviderState
|
|||
PopupMenuButton(
|
||||
child: Text(s.advanced),
|
||||
itemBuilder: (_) => [
|
||||
if (!isMobile()) PopupMenuItem(child: Text(s.encryptDatabase), value: "Encrypt"),
|
||||
PopupMenuItem(child: Text(s.rewindToCheckpoint), value: "Rewind"),
|
||||
PopupMenuItem(child: Text(s.convertToWatchonly), enabled: active.canPay, value: "Cold"),
|
||||
PopupMenuItem(child: Text(s.signOffline), enabled: active.canPay, value: "Sign"),
|
||||
|
@ -297,6 +301,9 @@ class HomeInnerState extends State<HomeInnerPage> with SingleTickerProviderState
|
|||
case "Expert":
|
||||
Navigator.of(context).pushNamed('/dev');
|
||||
break;
|
||||
case "Encrypt":
|
||||
_encryptDb();
|
||||
break;
|
||||
case "Ledger":
|
||||
_ledger();
|
||||
break;
|
||||
|
@ -474,6 +481,56 @@ class HomeInnerState extends State<HomeInnerPage> with SingleTickerProviderState
|
|||
// }
|
||||
}
|
||||
|
||||
_encryptDb() async {
|
||||
final s = S.of(context);
|
||||
final hasPasswd = settings.dbPasswd.isNotEmpty;
|
||||
final oldPasswdController = TextEditingController();
|
||||
final newPasswdController = TextEditingController();
|
||||
final repeatPasswdController = TextEditingController();
|
||||
final confirmed = await showDialog<bool>(
|
||||
context: context,
|
||||
barrierDismissible: false,
|
||||
builder: (context) =>
|
||||
AlertDialog(
|
||||
title: Text(s.encryptDatabase),
|
||||
contentPadding: EdgeInsets.all(16),
|
||||
content: Form(child: SingleChildScrollView(child: Column(children: [
|
||||
if (hasPasswd) TextFormField(
|
||||
decoration: InputDecoration(labelText: s.currentPassword),
|
||||
obscureText: true,
|
||||
controller: oldPasswdController),
|
||||
TextFormField(
|
||||
decoration: InputDecoration(labelText: s.newPassword),
|
||||
obscureText: true,
|
||||
controller: newPasswdController),
|
||||
TextFormField(
|
||||
decoration: InputDecoration(labelText: s.repeatNewPassword),
|
||||
obscureText: true,
|
||||
controller: repeatPasswdController),
|
||||
]))),
|
||||
actions: confirmButtons(
|
||||
context, () => Navigator.of(context).pop(true),
|
||||
cancelValue: false))) ??
|
||||
false;
|
||||
if (confirmed) {
|
||||
if (oldPasswdController.text != settings.dbPasswd)
|
||||
showSnackBar(s.currentPasswordIncorrect);
|
||||
else if (newPasswdController.text != repeatPasswdController.text) {
|
||||
showSnackBar(s.newPasswordsDoNotMatch);
|
||||
}
|
||||
else {
|
||||
final passwd = newPasswdController.text;
|
||||
for (var c in coins) {
|
||||
final tempPath = p.join(settings.tempDir, c.dbName);
|
||||
WarpApi.cloneDbWithPasswd(c.coin, tempPath, passwd);
|
||||
}
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
prefs.setBool('recover', true);
|
||||
showSnackBar(s.databaseEncrypted);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_convertToWatchOnly() {
|
||||
WarpApi.convertToWatchOnly(active.coin, active.id);
|
||||
active.canPay = false;
|
||||
|
|
|
@ -296,5 +296,14 @@
|
|||
"signingPleaseWait": "Signing, please wait...",
|
||||
"sweep": "Sweep",
|
||||
"transparentKey": "Transparent Key",
|
||||
"unifiedViewingKey": "Unified Viewing Key"
|
||||
"unifiedViewingKey": "Unified Viewing Key",
|
||||
"encryptDatabase": "Encrypt Database",
|
||||
"currentPassword": "Current Password",
|
||||
"newPassword": "New Password",
|
||||
"repeatNewPassword": "Repeat New Password",
|
||||
"databasePassword": "Database Password",
|
||||
"currentPasswordIncorrect": "Current password incorrect",
|
||||
"newPasswordsDoNotMatch": "New passwords do not match",
|
||||
"databaseEncrypted": "Database Encrypted. Please Restart the App.",
|
||||
"invalidPassword": "Invalid Password"
|
||||
}
|
||||
|
|
|
@ -294,5 +294,14 @@
|
|||
"signingPleaseWait": "Firmando",
|
||||
"sweep": "Barrer",
|
||||
"transparentKey": "Transparente Clavo",
|
||||
"unifiedViewingKey": "Clave de visualización Unidad"
|
||||
"unifiedViewingKey": "Clave de visualización Unidad",
|
||||
"encryptDatabase": "Encrypt Database",
|
||||
"currentPassword": "Current password",
|
||||
"newPassword": "New Password",
|
||||
"repeatNewPassword": "Repeat New Password",
|
||||
"databasePassword": "Database Password",
|
||||
"currentPasswordIncorrect": "Current password incorrect",
|
||||
"newPasswordsDoNotMatch": "New passwords do not match",
|
||||
"databaseEncrypted": "Database Encrypted. Please Restart the App.",
|
||||
"invalidPassword": "Invalid Password"
|
||||
}
|
||||
|
|
|
@ -294,5 +294,14 @@
|
|||
"signingPleaseWait": "Signature en cours...",
|
||||
"sweep": "Balayer",
|
||||
"transparentKey": "Clé Transparente",
|
||||
"unifiedViewingKey": "Clé publique unifiée"
|
||||
"unifiedViewingKey": "Clé publique unifiée",
|
||||
"encryptDatabase": "Encrypt Database",
|
||||
"currentPassword": "Current password",
|
||||
"newPassword": "New Password",
|
||||
"repeatNewPassword": "Repeat New Password",
|
||||
"databasePassword": "Database Password",
|
||||
"currentPasswordIncorrect": "Current password incorrect",
|
||||
"newPasswordsDoNotMatch": "New passwords do not match",
|
||||
"databaseEncrypted": "Database Encrypted. Please Restart the App.",
|
||||
"invalidPassword": "Invalid Password"
|
||||
}
|
||||
|
|
|
@ -8,7 +8,6 @@ import 'dart:ui';
|
|||
import 'package:app_links/app_links.dart';
|
||||
import 'package:camera/camera.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
||||
import 'package:path/path.dart' as p;
|
||||
import 'package:csv/csv.dart';
|
||||
import 'package:currency_text_input_formatter/currency_text_input_formatter.dart';
|
||||
|
@ -212,11 +211,6 @@ void main() async {
|
|||
if (!isMobile()) {
|
||||
await windowManager.ensureInitialized();
|
||||
|
||||
final secureStorage = FlutterSecureStorage();
|
||||
await secureStorage.write(key: 'TEST_KEY', value: '1000');
|
||||
final v = await secureStorage.read(key: 'TEST_KEY');
|
||||
print(v);
|
||||
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
final width = prefs.getDouble('width');
|
||||
final height = prefs.getDouble('height');
|
||||
|
@ -391,9 +385,20 @@ class ZWalletAppState extends State<ZWalletApp> {
|
|||
_setProgress(0, 'Mempool');
|
||||
print("db path $dbPath");
|
||||
WarpApi.mempoolRun(unconfirmedBalancePort.sendPort.nativePort);
|
||||
|
||||
final c = coins.first;
|
||||
if (!isMobile()) {
|
||||
if (!WarpApi.decryptDb(c.dbFullPath, '')) {
|
||||
final passwd = await getDbPasswd(context, c.dbFullPath);
|
||||
if (passwd != null) {
|
||||
settings.dbPasswd = passwd;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (var c in coins) {
|
||||
_setProgress(0.2 * (c.coin+1), 'Initializing ${c.ticker}');
|
||||
await compute(_initWallet, c);
|
||||
await compute(_initWallet, { 'coin': c, 'passwd': settings.dbPasswd });
|
||||
}
|
||||
|
||||
_setProgress(0.7, 'Restoring Active Account');
|
||||
|
@ -451,7 +456,10 @@ class ZWalletAppState extends State<ZWalletApp> {
|
|||
return false;
|
||||
}
|
||||
|
||||
static void _initWallet(CoinBase c) {
|
||||
static void _initWallet(Map<String, dynamic> args) {
|
||||
CoinBase c = args['coin'];
|
||||
String passwd = args['passwd'];
|
||||
WarpApi.setDbPasswd(c.coin, passwd);
|
||||
WarpApi.migrateWallet(c.coin, c.dbFullPath);
|
||||
WarpApi.initWallet(c.coin, c.dbFullPath);
|
||||
try {
|
||||
|
@ -915,7 +923,7 @@ Future<String> getDataPath() async {
|
|||
String? home;
|
||||
if (Platform.isAndroid) home = (await getApplicationDocumentsDirectory()).parent.path;
|
||||
if (Platform.isWindows) home = Platform.environment['LOCALAPPDATA'];
|
||||
if (Platform.isLinux) home = Platform.environment['XDG_DATA_HOME'];
|
||||
if (Platform.isLinux) home = Platform.environment['XDG_DATA_HOME'] ?? Platform.environment['HOME'];
|
||||
if (Platform.isMacOS) home = Platform.environment['HOME'];
|
||||
final h = home ?? "";
|
||||
return h;
|
||||
|
@ -967,3 +975,37 @@ class NotificationController {
|
|||
void resetApp() {
|
||||
WarpApi.truncateData();
|
||||
}
|
||||
|
||||
Future<String?> getDbPasswd(BuildContext context, String dbPath) async {
|
||||
final s = S.of(context);
|
||||
final passwdController = TextEditingController();
|
||||
final checkPasswd = (String? v) {
|
||||
final valid = WarpApi.decryptDb(dbPath, passwdController.text);
|
||||
if (!valid) return s.invalidPassword;
|
||||
return null;
|
||||
};
|
||||
final formKey = GlobalKey<FormState>();
|
||||
|
||||
final confirmed = await showDialog<bool>(
|
||||
context: context,
|
||||
barrierColor: Colors.black,
|
||||
builder: (context) {
|
||||
return AlertDialog(
|
||||
content: Container(
|
||||
width: double.maxFinite,
|
||||
child: SingleChildScrollView(child: Form(key: formKey, child: Column(children: [
|
||||
TextFormField(
|
||||
decoration: InputDecoration(labelText: s.databasePassword),
|
||||
controller: passwdController,
|
||||
validator: checkPasswd,
|
||||
obscureText: true,
|
||||
),
|
||||
])))),
|
||||
actions: confirmButtons(context, () {
|
||||
if (formKey.currentState!.validate())
|
||||
Navigator.of(context).pop(true);
|
||||
}, okLabel: s.ok),
|
||||
);
|
||||
}) ?? false;
|
||||
return confirmed ? passwdController.text : null;
|
||||
}
|
||||
|
|
|
@ -152,13 +152,6 @@ class SettingsState extends State<SettingsPage>
|
|||
_needAuth = true;
|
||||
},
|
||||
onSaved: _onProtectOpen)),
|
||||
// if (coin.supportsUA)
|
||||
// Expanded(
|
||||
// child: FormBuilderCheckbox(
|
||||
// name: 'use_ua',
|
||||
// title: Text(s.useUa),
|
||||
// initialValue: settings.useUA,
|
||||
// onSaved: _onUseUA)),
|
||||
]),
|
||||
|
||||
if (!simpleMode)
|
||||
|
@ -304,6 +297,7 @@ class SettingsState extends State<SettingsPage>
|
|||
keyboardType: TextInputType.number,
|
||||
controller: _gapLimitController,
|
||||
onSaved: _onGapLimit),
|
||||
Padding(padding: EdgeInsets.symmetric(vertical: 8)),
|
||||
ButtonBar(children: confirmButtons(context, _onSave))
|
||||
]))))));
|
||||
}
|
||||
|
|
|
@ -221,6 +221,8 @@ abstract class _Settings with Store {
|
|||
@observable
|
||||
int minPrivacyLevel = 0;
|
||||
|
||||
String dbPasswd = "";
|
||||
|
||||
@action
|
||||
Future<bool> restore() async {
|
||||
if (Platform.isIOS) SharedPreferencesIOS.registerWith();
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
|
||||
#include <audioplayers_linux/audioplayers_linux_plugin.h>
|
||||
#include <awesome_notifications/awesome_notifications_plugin.h>
|
||||
#include <flutter_secure_storage_linux/flutter_secure_storage_linux_plugin.h>
|
||||
#include <screen_retriever/screen_retriever_plugin.h>
|
||||
#include <url_launcher_linux/url_launcher_plugin.h>
|
||||
#include <window_manager/window_manager_plugin.h>
|
||||
|
@ -20,9 +19,6 @@ void fl_register_plugins(FlPluginRegistry* registry) {
|
|||
g_autoptr(FlPluginRegistrar) awesome_notifications_registrar =
|
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "AwesomeNotificationsPlugin");
|
||||
awesome_notifications_plugin_register_with_registrar(awesome_notifications_registrar);
|
||||
g_autoptr(FlPluginRegistrar) flutter_secure_storage_linux_registrar =
|
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "FlutterSecureStorageLinuxPlugin");
|
||||
flutter_secure_storage_linux_plugin_register_with_registrar(flutter_secure_storage_linux_registrar);
|
||||
g_autoptr(FlPluginRegistrar) screen_retriever_registrar =
|
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "ScreenRetrieverPlugin");
|
||||
screen_retriever_plugin_register_with_registrar(screen_retriever_registrar);
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
list(APPEND FLUTTER_PLUGIN_LIST
|
||||
audioplayers_linux
|
||||
awesome_notifications
|
||||
flutter_secure_storage_linux
|
||||
screen_retriever
|
||||
url_launcher_linux
|
||||
window_manager
|
||||
|
|
|
@ -9,7 +9,6 @@ import app_links
|
|||
import audioplayers_darwin
|
||||
import awesome_notifications
|
||||
import connectivity_plus_macos
|
||||
import flutter_secure_storage_macos
|
||||
import network_info_plus_macos
|
||||
import path_provider_foundation
|
||||
import screen_retriever
|
||||
|
@ -23,7 +22,6 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
|||
AudioplayersDarwinPlugin.register(with: registry.registrar(forPlugin: "AudioplayersDarwinPlugin"))
|
||||
AwesomeNotificationsPlugin.register(with: registry.registrar(forPlugin: "AwesomeNotificationsPlugin"))
|
||||
ConnectivityPlugin.register(with: registry.registrar(forPlugin: "ConnectivityPlugin"))
|
||||
FlutterSecureStoragePlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStoragePlugin"))
|
||||
NetworkInfoPlusPlugin.register(with: registry.registrar(forPlugin: "NetworkInfoPlusPlugin"))
|
||||
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
|
||||
ScreenRetrieverPlugin.register(with: registry.registrar(forPlugin: "ScreenRetrieverPlugin"))
|
||||
|
|
|
@ -8,8 +8,6 @@ PODS:
|
|||
- connectivity_plus_macos (0.0.1):
|
||||
- FlutterMacOS
|
||||
- ReachabilitySwift
|
||||
- flutter_secure_storage_macos (6.1.1):
|
||||
- FlutterMacOS
|
||||
- FlutterMacOS (1.0.0)
|
||||
- network_info_plus_macos (0.0.1):
|
||||
- FlutterMacOS
|
||||
|
@ -34,7 +32,6 @@ DEPENDENCIES:
|
|||
- audioplayers_darwin (from `Flutter/ephemeral/.symlinks/plugins/audioplayers_darwin/macos`)
|
||||
- awesome_notifications (from `Flutter/ephemeral/.symlinks/plugins/awesome_notifications/macos`)
|
||||
- connectivity_plus_macos (from `Flutter/ephemeral/.symlinks/plugins/connectivity_plus_macos/macos`)
|
||||
- flutter_secure_storage_macos (from `Flutter/ephemeral/.symlinks/plugins/flutter_secure_storage_macos/macos`)
|
||||
- FlutterMacOS (from `Flutter/ephemeral`)
|
||||
- network_info_plus_macos (from `Flutter/ephemeral/.symlinks/plugins/network_info_plus_macos/macos`)
|
||||
- path_provider_foundation (from `Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/macos`)
|
||||
|
@ -57,8 +54,6 @@ EXTERNAL SOURCES:
|
|||
:path: Flutter/ephemeral/.symlinks/plugins/awesome_notifications/macos
|
||||
connectivity_plus_macos:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/connectivity_plus_macos/macos
|
||||
flutter_secure_storage_macos:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/flutter_secure_storage_macos/macos
|
||||
FlutterMacOS:
|
||||
:path: Flutter/ephemeral
|
||||
network_info_plus_macos:
|
||||
|
@ -81,7 +76,6 @@ SPEC CHECKSUMS:
|
|||
audioplayers_darwin: dcad41de4fbd0099cb3749f7ab3b0cb8f70b810c
|
||||
awesome_notifications: 428f5c15a700b117418aed09e29c21c5806fcf69
|
||||
connectivity_plus_macos: f6e86fd000e971d361e54b5afcadc8c8fa773308
|
||||
flutter_secure_storage_macos: d56e2d218c1130b262bef8b4a7d64f88d7f9c9ea
|
||||
FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24
|
||||
network_info_plus_macos: d2b9e6c01c291449b91a584217aa53b113847dbd
|
||||
path_provider_foundation: 37748e03f12783f9de2cb2c4eadfaa25fe6d4852
|
||||
|
@ -94,4 +88,4 @@ SPEC CHECKSUMS:
|
|||
|
||||
PODFILE CHECKSUM: 353c8bcc5d5b0994e508d035b5431cfe18c1dea7
|
||||
|
||||
COCOAPODS: 1.11.3
|
||||
COCOAPODS: 1.12.0
|
||||
|
|
|
@ -582,12 +582,13 @@
|
|||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NAME)";
|
||||
DEVELOPMENT_TEAM = 26RX6RJ8ED;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = me.hanh.ywallet;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = me.hanh.ywallet.ios;
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
STRIP_STYLE = "non-global";
|
||||
SWIFT_VERSION = 5.0;
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 1a2dbc991fe877783aa7ef3c38ab323a0d220aa5
|
||||
Subproject commit 17301a6900fdc0a274c9631b2ffb59394829ce3e
|
|
@ -38,6 +38,11 @@ Pointer<Uint8> toNativeBytes(Uint8List bytes) {
|
|||
return ptr;
|
||||
}
|
||||
|
||||
bool unwrapResultBool(CResult_bool r) {
|
||||
if (r.error != nullptr) throw convertCString(r.error);
|
||||
return r.value != 0;
|
||||
}
|
||||
|
||||
int unwrapResultU8(CResult_u8 r) {
|
||||
if (r.error != nullptr) throw convertCString(r.error);
|
||||
return r.value;
|
||||
|
@ -313,7 +318,11 @@ class WarpApi {
|
|||
syncHistoricalPricesIsolateFn, SyncHistoricalPricesParams(currency));
|
||||
}
|
||||
|
||||
static updateLWD(int coin, String url) {
|
||||
static void setDbPasswd(int coin, String passwd) {
|
||||
warp_api_lib.set_coin_passwd(coin, toNative(passwd));
|
||||
}
|
||||
|
||||
static void updateLWD(int coin, String url) {
|
||||
warp_api_lib.set_coin_lwd_url(coin, url.toNativeUtf8().cast<Int8>());
|
||||
}
|
||||
|
||||
|
@ -569,6 +578,14 @@ class WarpApi {
|
|||
static void clearTxDetails(int coin, int account) {
|
||||
warp_api_lib.clear_tx_details(coin, account);
|
||||
}
|
||||
|
||||
static void cloneDbWithPasswd(int coin, String tempPath, String passwd) {
|
||||
warp_api_lib.clone_db_with_passwd(coin, toNative(tempPath), toNative(passwd));
|
||||
}
|
||||
|
||||
static bool decryptDb(String dbPath, String passwd) {
|
||||
return unwrapResultBool(warp_api_lib.decrypt_db(toNative(dbPath), toNative(passwd)));
|
||||
}
|
||||
}
|
||||
|
||||
String signOnlyIsolateFn(SignOnlyParams params) {
|
||||
|
|
|
@ -152,6 +152,21 @@ class NativeLibrary {
|
|||
late final _dart_get_lwd_url _get_lwd_url =
|
||||
_get_lwd_url_ptr.asFunction<_dart_get_lwd_url>();
|
||||
|
||||
void set_coin_passwd(
|
||||
int coin,
|
||||
ffi.Pointer<ffi.Int8> passwd,
|
||||
) {
|
||||
return _set_coin_passwd(
|
||||
coin,
|
||||
passwd,
|
||||
);
|
||||
}
|
||||
|
||||
late final _set_coin_passwd_ptr =
|
||||
_lookup<ffi.NativeFunction<_c_set_coin_passwd>>('set_coin_passwd');
|
||||
late final _dart_set_coin_passwd _set_coin_passwd =
|
||||
_set_coin_passwd_ptr.asFunction<_dart_set_coin_passwd>();
|
||||
|
||||
void reset_app() {
|
||||
return _reset_app();
|
||||
}
|
||||
|
@ -1279,6 +1294,39 @@ class NativeLibrary {
|
|||
late final _dart_get_checkpoints _get_checkpoints =
|
||||
_get_checkpoints_ptr.asFunction<_dart_get_checkpoints>();
|
||||
|
||||
CResult_bool decrypt_db(
|
||||
ffi.Pointer<ffi.Int8> db_path,
|
||||
ffi.Pointer<ffi.Int8> passwd,
|
||||
) {
|
||||
return _decrypt_db(
|
||||
db_path,
|
||||
passwd,
|
||||
);
|
||||
}
|
||||
|
||||
late final _decrypt_db_ptr =
|
||||
_lookup<ffi.NativeFunction<_c_decrypt_db>>('decrypt_db');
|
||||
late final _dart_decrypt_db _decrypt_db =
|
||||
_decrypt_db_ptr.asFunction<_dart_decrypt_db>();
|
||||
|
||||
CResult_u8 clone_db_with_passwd(
|
||||
int coin,
|
||||
ffi.Pointer<ffi.Int8> temp_path,
|
||||
ffi.Pointer<ffi.Int8> passwd,
|
||||
) {
|
||||
return _clone_db_with_passwd(
|
||||
coin,
|
||||
temp_path,
|
||||
passwd,
|
||||
);
|
||||
}
|
||||
|
||||
late final _clone_db_with_passwd_ptr =
|
||||
_lookup<ffi.NativeFunction<_c_clone_db_with_passwd>>(
|
||||
'clone_db_with_passwd');
|
||||
late final _dart_clone_db_with_passwd _clone_db_with_passwd =
|
||||
_clone_db_with_passwd_ptr.asFunction<_dart_clone_db_with_passwd>();
|
||||
|
||||
int has_cuda() {
|
||||
return _has_cuda();
|
||||
}
|
||||
|
@ -1364,6 +1412,16 @@ class CResult_u64 extends ffi.Struct {
|
|||
external int len;
|
||||
}
|
||||
|
||||
class CResult_bool extends ffi.Struct {
|
||||
@ffi.Int8()
|
||||
external int value;
|
||||
|
||||
external ffi.Pointer<ffi.Int8> error;
|
||||
|
||||
@ffi.Uint32()
|
||||
external int len;
|
||||
}
|
||||
|
||||
const int EXPIRY_HEIGHT_OFFSET = 50;
|
||||
|
||||
const int QR_DATA_SIZE = 256;
|
||||
|
@ -1550,6 +1608,16 @@ typedef _dart_get_lwd_url = ffi.Pointer<ffi.Int8> Function(
|
|||
int coin,
|
||||
);
|
||||
|
||||
typedef _c_set_coin_passwd = ffi.Void Function(
|
||||
ffi.Uint8 coin,
|
||||
ffi.Pointer<ffi.Int8> passwd,
|
||||
);
|
||||
|
||||
typedef _dart_set_coin_passwd = void Function(
|
||||
int coin,
|
||||
ffi.Pointer<ffi.Int8> passwd,
|
||||
);
|
||||
|
||||
typedef _c_reset_app = ffi.Void Function();
|
||||
|
||||
typedef _dart_reset_app = void Function();
|
||||
|
@ -2298,6 +2366,28 @@ typedef _dart_get_checkpoints = CResult______u8 Function(
|
|||
int coin,
|
||||
);
|
||||
|
||||
typedef _c_decrypt_db = CResult_bool Function(
|
||||
ffi.Pointer<ffi.Int8> db_path,
|
||||
ffi.Pointer<ffi.Int8> passwd,
|
||||
);
|
||||
|
||||
typedef _dart_decrypt_db = CResult_bool Function(
|
||||
ffi.Pointer<ffi.Int8> db_path,
|
||||
ffi.Pointer<ffi.Int8> passwd,
|
||||
);
|
||||
|
||||
typedef _c_clone_db_with_passwd = CResult_u8 Function(
|
||||
ffi.Uint8 coin,
|
||||
ffi.Pointer<ffi.Int8> temp_path,
|
||||
ffi.Pointer<ffi.Int8> passwd,
|
||||
);
|
||||
|
||||
typedef _dart_clone_db_with_passwd = CResult_u8 Function(
|
||||
int coin,
|
||||
ffi.Pointer<ffi.Int8> temp_path,
|
||||
ffi.Pointer<ffi.Int8> passwd,
|
||||
);
|
||||
|
||||
typedef _c_has_cuda = ffi.Int8 Function();
|
||||
|
||||
typedef _dart_has_cuda = int Function();
|
||||
|
|
|
@ -30,7 +30,7 @@ ffigen:
|
|||
- '../../native/zcash-sync/binding.h'
|
||||
# On MacOS
|
||||
llvm-path:
|
||||
- '/opt/homebrew/Cellar/llvm/15.0.6'
|
||||
- '/opt/homebrew/Cellar/llvm/15.0.7_1'
|
||||
|
||||
# For information on the generic Dart part of this file, see the
|
||||
# following page: https://dart.dev/tools/pub/pubspec
|
||||
|
|
48
pubspec.lock
48
pubspec.lock
|
@ -685,54 +685,6 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.2.0"
|
||||
flutter_secure_storage:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: flutter_secure_storage
|
||||
sha256: "98352186ee7ad3639ccc77ad7924b773ff6883076ab952437d20f18a61f0a7c5"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "8.0.0"
|
||||
flutter_secure_storage_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_secure_storage_linux
|
||||
sha256: "0912ae29a572230ad52d8a4697e5518d7f0f429052fd51df7e5a7952c7efe2a3"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.3"
|
||||
flutter_secure_storage_macos:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_secure_storage_macos
|
||||
sha256: "083add01847fc1c80a07a08e1ed6927e9acd9618a35e330239d4422cd2a58c50"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.0"
|
||||
flutter_secure_storage_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_secure_storage_platform_interface
|
||||
sha256: b3773190e385a3c8a382007893d678ae95462b3c2279e987b55d140d3b0cb81b
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.1"
|
||||
flutter_secure_storage_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_secure_storage_web
|
||||
sha256: "42938e70d4b872e856e678c423cc0e9065d7d294f45bc41fc1981a4eb4beaffe"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.1"
|
||||
flutter_secure_storage_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_secure_storage_windows
|
||||
sha256: fc2910ec9b28d60598216c29ea763b3a96c401f0ce1d13cdf69ccb0e5c93c3ee
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.0"
|
||||
flutter_speed_dial:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
|
|
@ -15,7 +15,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
|
|||
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
|
||||
# Read more about iOS versioning at
|
||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||
version: 1.3.5+390
|
||||
version: 1.3.5+392
|
||||
|
||||
environment:
|
||||
sdk: ">=2.12.0 <3.0.0"
|
||||
|
@ -39,7 +39,6 @@ dependencies:
|
|||
rflutter_alert: ^2.0.4
|
||||
sprintf: ^6.0.0
|
||||
local_auth: ^2.1.2
|
||||
flutter_secure_storage: ^8.0.0
|
||||
key_guardmanager: ^1.0.0
|
||||
shared_preferences: ^2.0.7
|
||||
shared_preferences_android:
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
#include <audioplayers_windows/audioplayers_windows_plugin.h>
|
||||
#include <awesome_notifications/awesome_notifications_plugin_c_api.h>
|
||||
#include <connectivity_plus_windows/connectivity_plus_windows_plugin.h>
|
||||
#include <flutter_secure_storage_windows/flutter_secure_storage_windows_plugin.h>
|
||||
#include <local_auth_windows/local_auth_plugin.h>
|
||||
#include <network_info_plus_windows/network_info_plus_windows_plugin.h>
|
||||
#include <screen_retriever/screen_retriever_plugin.h>
|
||||
|
@ -26,8 +25,6 @@ void RegisterPlugins(flutter::PluginRegistry* registry) {
|
|||
registry->GetRegistrarForPlugin("AwesomeNotificationsPluginCApi"));
|
||||
ConnectivityPlusWindowsPluginRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("ConnectivityPlusWindowsPlugin"));
|
||||
FlutterSecureStorageWindowsPluginRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("FlutterSecureStorageWindowsPlugin"));
|
||||
LocalAuthPluginRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("LocalAuthPlugin"));
|
||||
NetworkInfoPlusWindowsPluginRegisterWithRegistrar(
|
||||
|
|
|
@ -7,7 +7,6 @@ list(APPEND FLUTTER_PLUGIN_LIST
|
|||
audioplayers_windows
|
||||
awesome_notifications
|
||||
connectivity_plus_windows
|
||||
flutter_secure_storage_windows
|
||||
local_auth_windows
|
||||
network_info_plus_windows
|
||||
screen_retriever
|
||||
|
|
Loading…
Reference in New Issue