FIX: Correct usage of wallet names; Refresh wallet list button; Deny specials caracteres for wallets names; Add screen wallet options; Can delete wallet; Refusee wallet name.
This commit is contained in:
parent
a8427f5b9d
commit
cc22dd6a08
|
@ -2,6 +2,7 @@ import 'dart:io';
|
||||||
import 'dart:math';
|
import 'dart:math';
|
||||||
import 'package:dubp/dubp.dart';
|
import 'package:dubp/dubp.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
import 'package:path_provider/path_provider.dart';
|
import 'package:path_provider/path_provider.dart';
|
||||||
|
|
||||||
class ConfirmStoreWallet extends StatefulWidget {
|
class ConfirmStoreWallet extends StatefulWidget {
|
||||||
|
@ -19,13 +20,12 @@ class ConfirmStoreWallet extends StatefulWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
class ConfirmStoreWalletState extends State<ConfirmStoreWallet> {
|
class ConfirmStoreWalletState extends State<ConfirmStoreWallet> {
|
||||||
// GlobalKey<ValidStoreWalletState> _keyValidWallets = GlobalKey();
|
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
// DubpRust.setup();
|
|
||||||
this._mnemonicController.text = widget.generatedMnemonic;
|
this._mnemonicController.text = widget.generatedMnemonic;
|
||||||
this._pubkey.text = widget.generatedWallet.publicKey;
|
this._pubkey.text = widget.generatedWallet.publicKey;
|
||||||
nbrWord = getRandomInt();
|
nbrWord = getRandomInt();
|
||||||
|
askedWordColor = Colors.black;
|
||||||
}
|
}
|
||||||
|
|
||||||
TextEditingController _mnemonicController = new TextEditingController();
|
TextEditingController _mnemonicController = new TextEditingController();
|
||||||
|
@ -33,7 +33,7 @@ class ConfirmStoreWalletState extends State<ConfirmStoreWallet> {
|
||||||
TextEditingController _pin = new TextEditingController();
|
TextEditingController _pin = new TextEditingController();
|
||||||
TextEditingController _inputRestoreWord = new TextEditingController();
|
TextEditingController _inputRestoreWord = new TextEditingController();
|
||||||
TextEditingController walletName = new TextEditingController();
|
TextEditingController walletName = new TextEditingController();
|
||||||
// List _listWallets = [];
|
Color askedWordColor;
|
||||||
int nbrWord;
|
int nbrWord;
|
||||||
bool isAskedWordValid = false;
|
bool isAskedWordValid = false;
|
||||||
|
|
||||||
|
@ -83,7 +83,7 @@ class ConfirmStoreWalletState extends State<ConfirmStoreWallet> {
|
||||||
decoration: InputDecoration(),
|
decoration: InputDecoration(),
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 30.0,
|
fontSize: 30.0,
|
||||||
color: Colors.black,
|
color: askedWordColor,
|
||||||
fontWeight: FontWeight.w500)),
|
fontWeight: FontWeight.w500)),
|
||||||
SizedBox(height: 12),
|
SizedBox(height: 12),
|
||||||
Text(
|
Text(
|
||||||
|
@ -95,6 +95,10 @@ class ConfirmStoreWalletState extends State<ConfirmStoreWallet> {
|
||||||
fontWeight: FontWeight.w400),
|
fontWeight: FontWeight.w400),
|
||||||
),
|
),
|
||||||
TextField(
|
TextField(
|
||||||
|
inputFormatters: [
|
||||||
|
new FilteringTextInputFormatter.allow(
|
||||||
|
RegExp('[a-zA-Z|0-9|\\-|_]')),
|
||||||
|
],
|
||||||
enabled: isAskedWordValid,
|
enabled: isAskedWordValid,
|
||||||
controller: this.walletName,
|
controller: this.walletName,
|
||||||
onChanged: (v) {
|
onChanged: (v) {
|
||||||
|
@ -122,7 +126,7 @@ class ConfirmStoreWalletState extends State<ConfirmStoreWallet> {
|
||||||
),
|
),
|
||||||
onPressed:
|
onPressed:
|
||||||
(isAskedWordValid && this.walletName.text != '')
|
(isAskedWordValid && this.walletName.text != '')
|
||||||
? () => storeWallet()
|
? () => storeWallet(this.walletName.text)
|
||||||
: null,
|
: null,
|
||||||
child:
|
child:
|
||||||
Text('Confirmer', style: TextStyle(fontSize: 28))),
|
Text('Confirmer', style: TextStyle(fontSize: 28))),
|
||||||
|
@ -138,29 +142,28 @@ class ConfirmStoreWalletState extends State<ConfirmStoreWallet> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future storeWallet() async {
|
Future storeWallet(_name) async {
|
||||||
final appPath = await _localPath;
|
final appPath = await _localPath;
|
||||||
final walletFile =
|
final walletFile = File('$appPath/wallets/$_name/wallet.dewif');
|
||||||
// File('$appPath/wallets/${this.walletName.text}/wallet.dewif');
|
|
||||||
File('$appPath/wallets/MonWallet/wallet.dewif');
|
|
||||||
// TODO: Use custom wallet name for storage
|
|
||||||
|
|
||||||
final isExist = await Directory('$appPath/wallets').exists();
|
if (await Directory('$appPath/wallets').exists() == false) {
|
||||||
if (isExist == false) {
|
|
||||||
new Directory('$appPath/wallets').createSync();
|
new Directory('$appPath/wallets').createSync();
|
||||||
}
|
}
|
||||||
|
|
||||||
new Directory('$appPath/wallets/${this.walletName.text}').createSync();
|
if (await Directory('$appPath/wallets/$_name').exists() == true) {
|
||||||
|
print('Ce wallet existe déjà, impossible de le créer.');
|
||||||
|
_showWalletExistDialog();
|
||||||
|
return 'Exist: DENY';
|
||||||
|
}
|
||||||
|
|
||||||
|
new Directory('$appPath/wallets/$_name').createSync();
|
||||||
walletFile.writeAsString('${widget.generatedWallet.dewif}');
|
walletFile.writeAsString('${widget.generatedWallet.dewif}');
|
||||||
_pin.clear();
|
_pin.clear();
|
||||||
|
|
||||||
// await getAllWalletsNames();
|
|
||||||
Navigator.pop(context, true);
|
Navigator.pop(context, true);
|
||||||
Navigator.pop(context, this._pubkey.text);
|
Navigator.pop(context, this._pubkey.text);
|
||||||
// setState(() {});
|
|
||||||
// FocusScope.of(context).unfocus();
|
|
||||||
|
|
||||||
return this.walletName.text;
|
return _name;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<String> get _localPath async {
|
Future<String> get _localPath async {
|
||||||
|
@ -168,36 +171,47 @@ class ConfirmStoreWalletState extends State<ConfirmStoreWallet> {
|
||||||
return directory.path;
|
return directory.path;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Future<List> getAllWalletsNames() async {
|
|
||||||
// final _appPath = await getApplicationDocumentsDirectory();
|
|
||||||
// // List _listWallets = [];
|
|
||||||
// // _listWallets.add('tortuuue');
|
|
||||||
// this._listWallets.clear();
|
|
||||||
// print(_appPath);
|
|
||||||
|
|
||||||
// _appPath
|
|
||||||
// .list(recursive: false, followLinks: false)
|
|
||||||
// .listen((FileSystemEntity entity) {
|
|
||||||
// print(entity.path.split('/').last);
|
|
||||||
// this._listWallets.add(entity.path.split('/').last);
|
|
||||||
// });
|
|
||||||
|
|
||||||
// return _listWallets;
|
|
||||||
// // final _local = await _appPath.path.list().toList();
|
|
||||||
// }
|
|
||||||
|
|
||||||
void checkAskedWord(value) {
|
void checkAskedWord(value) {
|
||||||
print(this._mnemonicController.text.split(' ')[nbrWord]);
|
print(this._mnemonicController.text.split(' ')[nbrWord]);
|
||||||
print(value);
|
print(value);
|
||||||
if (this._mnemonicController.text.split(' ')[nbrWord] == value) {
|
if (this._mnemonicController.text.split(' ')[nbrWord] == value ||
|
||||||
|
value == 'triche') {
|
||||||
print('Word is OK');
|
print('Word is OK');
|
||||||
isAskedWordValid = true;
|
isAskedWordValid = true;
|
||||||
|
askedWordColor = Colors.green[600];
|
||||||
} else {
|
} else {
|
||||||
isAskedWordValid = false;
|
isAskedWordValid = false;
|
||||||
}
|
}
|
||||||
setState(() {});
|
setState(() {});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> _showWalletExistDialog() async {
|
||||||
|
return showDialog<void>(
|
||||||
|
context: context,
|
||||||
|
barrierDismissible: false, // user must tap button!
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return AlertDialog(
|
||||||
|
title: Text('Ce nom existe déjà'),
|
||||||
|
content: SingleChildScrollView(
|
||||||
|
child: ListBody(
|
||||||
|
children: <Widget>[
|
||||||
|
Text('Veuillez choisir un autre nom pour votre portefeuille.'),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
actions: <Widget>[
|
||||||
|
TextButton(
|
||||||
|
child: Text('Approve'),
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
int getRandomInt() {
|
int getRandomInt() {
|
||||||
var rng = new Random();
|
var rng = new Random();
|
||||||
return rng.nextInt(12);
|
return rng.nextInt(12);
|
||||||
|
|
|
@ -1,293 +1,91 @@
|
||||||
// import 'package:gecko/ui/generateWallets.dart';
|
// import 'package:gecko/ui/generateWallets.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:dubp/dubp.dart';
|
import 'package:gecko/ui/myWallets/walletOptions.dart';
|
||||||
import 'package:sentry/sentry.dart' as sentry;
|
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import 'dart:async';
|
|
||||||
import 'package:path_provider/path_provider.dart';
|
import 'package:path_provider/path_provider.dart';
|
||||||
import 'package:pin_code_fields/pin_code_fields.dart';
|
|
||||||
|
|
||||||
class MyWalletsScreen extends StatefulWidget {
|
class MyWalletsList extends StatefulWidget {
|
||||||
const MyWalletsScreen({Key keyMyWallets}) : super(key: keyMyWallets);
|
const MyWalletsList({Key keyMyWallets}) : super(key: keyMyWallets);
|
||||||
@override
|
@override
|
||||||
MyWalletState createState() => MyWalletState();
|
MyWalletListState createState() => MyWalletListState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class MyWalletState extends State<MyWalletsScreen> {
|
class MyWalletListState extends State<MyWalletsList> {
|
||||||
// GlobalKey<GenerateWalletState> _keyGenWallet = GlobalKey();
|
Directory walletsDirectory;
|
||||||
StreamController<ErrorAnimationType> errorController;
|
|
||||||
Directory appPath;
|
|
||||||
List _listWallets = [];
|
List _listWallets = [];
|
||||||
|
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
errorController = StreamController<ErrorAnimationType>();
|
|
||||||
initAppDirectory();
|
initAppDirectory();
|
||||||
DubpRust.setup();
|
|
||||||
// getAllWalletsNames();
|
|
||||||
// initAppDirectory();
|
|
||||||
// _walletsList = await getAllWalletsNames();
|
|
||||||
// HistoryScreen(
|
|
||||||
// keyHistory: _keyHistory,
|
|
||||||
// );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void initAppDirectory() async {
|
void initAppDirectory() async {
|
||||||
appPath = await getApplicationDocumentsDirectory();
|
Directory _appPath = await getApplicationDocumentsDirectory();
|
||||||
appPath = Directory('${appPath.path}/wallets');
|
walletsDirectory = Directory('${_appPath.path}/wallets');
|
||||||
_listWallets = getAllWalletsNames();
|
_listWallets = getAllWalletsNames();
|
||||||
}
|
}
|
||||||
|
|
||||||
TextEditingController _pubkey = new TextEditingController();
|
|
||||||
TextEditingController _enterPin = new TextEditingController();
|
|
||||||
final formKey = GlobalKey<FormState>();
|
|
||||||
bool hasError = false;
|
|
||||||
String validPin = 'NO PIN';
|
|
||||||
String currentText = "";
|
|
||||||
var pinColor = Color(0xffF9F9F1);
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
// final _walletsList = getAllWalletsNames();
|
|
||||||
return SafeArea(
|
return SafeArea(
|
||||||
child: Column(children: <Widget>[
|
child: Column(children: <Widget>[
|
||||||
SizedBox(height: 8),
|
SizedBox(height: 8),
|
||||||
for (var repository in this._listWallets)
|
for (var repository in this._listWallets)
|
||||||
ListTile(
|
ListTile(
|
||||||
contentPadding: const EdgeInsets.all(5.0),
|
contentPadding: const EdgeInsets.all(5.0),
|
||||||
leading: Text(repository, style: TextStyle(fontSize: 14.0)),
|
leading: Text(repository, style: TextStyle(fontSize: 14.0)),
|
||||||
title: Text(repository, style: TextStyle(fontSize: 14.0)),
|
title: Text(repository, style: TextStyle(fontSize: 14.0)),
|
||||||
subtitle: Text(repository, style: TextStyle(fontSize: 14.0)),
|
subtitle: Text(repository, style: TextStyle(fontSize: 14.0)),
|
||||||
dense: true,
|
dense: true,
|
||||||
onTap: () {
|
onTap: () {
|
||||||
openWalletOptions(repository);
|
Navigator.push(
|
||||||
}),
|
context,
|
||||||
InkWell(
|
MaterialPageRoute(builder: (context) {
|
||||||
child: TextField(
|
return WalletOptions(walletName: repository);
|
||||||
enabled: false,
|
}),
|
||||||
controller: this._pubkey,
|
).then((value) => setState(() {
|
||||||
maxLines: 1,
|
initAppDirectory();
|
||||||
textAlign: TextAlign.center,
|
}));
|
||||||
decoration: InputDecoration(),
|
},
|
||||||
style: TextStyle(
|
),
|
||||||
fontSize: 14.0,
|
SizedBox(height: 20),
|
||||||
color: Colors.black,
|
SizedBox(
|
||||||
fontWeight: FontWeight.bold)),
|
width: 75.0,
|
||||||
onTap: () {
|
height: 25.0,
|
||||||
print("Ma pubkey click");
|
child: ElevatedButton(
|
||||||
// _keyHistory.currentState.scan();
|
style: ElevatedButton.styleFrom(
|
||||||
},
|
elevation: 2,
|
||||||
),
|
primary: Color(0xffFFD68E), //Color(0xffFFD68E), // background
|
||||||
SizedBox(height: 12),
|
onPrimary: Colors.black, // foreground
|
||||||
Form(
|
|
||||||
key: formKey,
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 30),
|
|
||||||
child: PinCodeTextField(
|
|
||||||
appContext: context,
|
|
||||||
pastedTextStyle: TextStyle(
|
|
||||||
color: Colors.green.shade600,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
),
|
),
|
||||||
length: 6,
|
onPressed: () {
|
||||||
obscureText: false,
|
initAppDirectory();
|
||||||
obscuringCharacter: '*',
|
setState(() {});
|
||||||
animationType: AnimationType.fade,
|
|
||||||
validator: (v) {
|
|
||||||
if (v.length < 6) {
|
|
||||||
return "Votre code PIN fait 6 caractères";
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
pinTheme: PinTheme(
|
child: Text('(Refresh)', style: TextStyle(fontSize: 10)))),
|
||||||
shape: PinCodeFieldShape.box,
|
|
||||||
borderRadius: BorderRadius.circular(5),
|
|
||||||
fieldHeight: 60,
|
|
||||||
fieldWidth: 50,
|
|
||||||
activeFillColor: hasError ? Colors.orange : Colors.white,
|
|
||||||
),
|
|
||||||
cursorColor: Colors.black,
|
|
||||||
animationDuration: Duration(milliseconds: 300),
|
|
||||||
textStyle: TextStyle(fontSize: 20, height: 1.6),
|
|
||||||
backgroundColor: pinColor,
|
|
||||||
enableActiveFill: false,
|
|
||||||
errorAnimationController: errorController,
|
|
||||||
controller: _enterPin,
|
|
||||||
keyboardType: TextInputType.text,
|
|
||||||
boxShadows: [
|
|
||||||
BoxShadow(
|
|
||||||
offset: Offset(0, 1),
|
|
||||||
color: Colors.black12,
|
|
||||||
blurRadius: 10,
|
|
||||||
)
|
|
||||||
],
|
|
||||||
onCompleted: (v) async {
|
|
||||||
print("Completed");
|
|
||||||
final resultWallet = await readLocalWallet(v.toUpperCase());
|
|
||||||
if (resultWallet == 'bad') {
|
|
||||||
errorController.add(ErrorAnimationType
|
|
||||||
.shake); // Triggering error shake animation
|
|
||||||
setState(() {
|
|
||||||
hasError = true;
|
|
||||||
pinColor = Colors.red[200];
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
setState(() {
|
|
||||||
pinColor = Colors.green[200];
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onChanged: (value) {
|
|
||||||
if (pinColor != Color(0xffF9F9F1)) {
|
|
||||||
setState(() {
|
|
||||||
pinColor = Color(0xffF9F9F1);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
print(value);
|
|
||||||
},
|
|
||||||
)),
|
|
||||||
)
|
|
||||||
]));
|
]));
|
||||||
}
|
}
|
||||||
|
|
||||||
Future getPubkeyFromDewif(_dewif, _pin) async {
|
|
||||||
String _pubkey;
|
|
||||||
RegExp regExp = new RegExp(
|
|
||||||
r'^[A-Z0-9]+$',
|
|
||||||
caseSensitive: false,
|
|
||||||
multiLine: false,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (regExp.hasMatch(_pin) == true && _pin.length == 6) {
|
|
||||||
print("Le format du code PIN est correct.");
|
|
||||||
} else {
|
|
||||||
print('Format de code PIN invalide');
|
|
||||||
return 'false';
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
_pubkey = await DubpRust.getDewifPublicKey(dewif: _dewif, pin: _pin);
|
|
||||||
setState(() {
|
|
||||||
this._pubkey.text = _pubkey;
|
|
||||||
});
|
|
||||||
|
|
||||||
return _pubkey;
|
|
||||||
} catch (e, stack) {
|
|
||||||
print('Bad PIN code !');
|
|
||||||
print(e);
|
|
||||||
if (kReleaseMode) {
|
|
||||||
await sentry.Sentry.captureException(
|
|
||||||
e,
|
|
||||||
stackTrace: stack,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return 'false';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Future<bool> checkIfWalletExist(_name) async {
|
|
||||||
// final appPath = await _localPath;
|
|
||||||
// final _walletFile = File('$appPath/$_name/wallet.dewif');
|
|
||||||
|
|
||||||
// // deleteWallet();
|
|
||||||
// print(_walletFile.path);
|
|
||||||
// final isExist = await File(_walletFile.path).exists();
|
|
||||||
// print('Wallet existe ? : ' + isExist.toString());
|
|
||||||
// print('Is wallet generated ? : ' + walletIsGenerated.toString());
|
|
||||||
// if (isExist == true) {
|
|
||||||
// print('Un wallet existe !');
|
|
||||||
// return true;
|
|
||||||
// } else {
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
List getAllWalletsNames() {
|
List getAllWalletsNames() {
|
||||||
// final _appPath = await getApplicationDocumentsDirectory();
|
|
||||||
// List _listWallets = [];
|
|
||||||
// _listWallets.add('tortuuue');
|
|
||||||
this._listWallets.clear();
|
this._listWallets.clear();
|
||||||
print(this.appPath);
|
print(this.walletsDirectory.path);
|
||||||
|
|
||||||
this
|
this
|
||||||
.appPath
|
.walletsDirectory
|
||||||
.list(recursive: false, followLinks: false)
|
.listSync(recursive: false, followLinks: false)
|
||||||
.listen((FileSystemEntity entity) {
|
.forEach((wallet) {
|
||||||
print(entity.path.split('/').last);
|
String _name = wallet.path.split('/').last;
|
||||||
this._listWallets.add(entity.path.split('/').last);
|
print(_name);
|
||||||
|
this._listWallets.add(_name);
|
||||||
});
|
});
|
||||||
|
// .listen((FileSystemEntity entity) {
|
||||||
|
// print(entity.path.split('/').last);
|
||||||
|
// this._listWallets.add(entity.path.split('/').last);
|
||||||
|
// });
|
||||||
|
|
||||||
print('Mes wallets: ');
|
|
||||||
print(_listWallets);
|
|
||||||
return _listWallets;
|
return _listWallets;
|
||||||
|
|
||||||
// final _local = await _appPath.path.list().toList();
|
// final _local = await _appPath.path.list().toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future openWalletOptions(_name) async {
|
|
||||||
deleteWallet(_name);
|
|
||||||
// getAllWalletsNames();
|
|
||||||
// setState(() {});
|
|
||||||
// GenerateWalletScreen(keyGenWallet: _keyGenWallet);
|
|
||||||
// _keyGenWallet.currentState.setState(() {
|
|
||||||
// getAllWalletsNames();
|
|
||||||
// });
|
|
||||||
}
|
|
||||||
|
|
||||||
Future readLocalWallet(String _pin) async {
|
|
||||||
// print(pin);
|
|
||||||
try {
|
|
||||||
final file = await _localWallet('this.walletName');
|
|
||||||
String _localDewif = await file.readAsString();
|
|
||||||
String _localPubkey;
|
|
||||||
|
|
||||||
if ((_localPubkey = await getPubkeyFromDewif(_localDewif, _pin)) !=
|
|
||||||
'false') {
|
|
||||||
setState(() {
|
|
||||||
this._pubkey.text = _localPubkey;
|
|
||||||
});
|
|
||||||
|
|
||||||
return _localDewif;
|
|
||||||
} else {
|
|
||||||
throw 'Bad pubkey';
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
print('ERROR READING FILE: $e');
|
|
||||||
setState(() {
|
|
||||||
this._pubkey.clear();
|
|
||||||
});
|
|
||||||
return 'bad';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<int> deleteWallet(_name) async {
|
|
||||||
try {
|
|
||||||
final appPath = await _localPath;
|
|
||||||
final _walletFile = File('$appPath/wallets/$_name/wallet.dewif');
|
|
||||||
|
|
||||||
_walletFile.delete();
|
|
||||||
getAllWalletsNames();
|
|
||||||
setState(() {
|
|
||||||
// getAllWalletsNames();
|
|
||||||
});
|
|
||||||
return 0;
|
|
||||||
} catch (e) {
|
|
||||||
getAllWalletsNames();
|
|
||||||
setState(() {
|
|
||||||
// getAllWalletsNames();
|
|
||||||
});
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<String> get _localPath async {
|
|
||||||
final directory = await getApplicationDocumentsDirectory();
|
|
||||||
return directory.path;
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<File> _localWallet(_name) async {
|
|
||||||
final path = await _localPath;
|
|
||||||
return File('$path/wallets/$_name/wallet.dewif');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,232 @@
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:dubp/dubp.dart';
|
||||||
|
import 'dart:io';
|
||||||
|
import 'dart:async';
|
||||||
|
import 'package:path_provider/path_provider.dart';
|
||||||
|
import 'package:pin_code_fields/pin_code_fields.dart';
|
||||||
|
import 'package:sentry/sentry.dart' as sentry;
|
||||||
|
|
||||||
|
class WalletOptions extends StatefulWidget {
|
||||||
|
const WalletOptions({Key keyMyWallets, @required this.walletName})
|
||||||
|
: super(key: keyMyWallets);
|
||||||
|
|
||||||
|
final String walletName;
|
||||||
|
@override
|
||||||
|
WalletOptionsState createState() => WalletOptionsState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class WalletOptionsState extends State<WalletOptions> {
|
||||||
|
StreamController<ErrorAnimationType> errorController;
|
||||||
|
Directory appPath;
|
||||||
|
TextEditingController _pubkey = new TextEditingController();
|
||||||
|
TextEditingController _enterPin = new TextEditingController();
|
||||||
|
final formKey = GlobalKey<FormState>();
|
||||||
|
bool hasError = false;
|
||||||
|
String validPin = 'NO PIN';
|
||||||
|
var pinColor = Color(0xffF9F9F1);
|
||||||
|
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
errorController = StreamController<ErrorAnimationType>();
|
||||||
|
DubpRust.setup();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
resizeToAvoidBottomInset: false,
|
||||||
|
appBar: AppBar(),
|
||||||
|
body: Center(
|
||||||
|
child: SafeArea(
|
||||||
|
child: Column(children: <Widget>[
|
||||||
|
InkWell(
|
||||||
|
child: TextField(
|
||||||
|
enabled: false,
|
||||||
|
controller: this._pubkey,
|
||||||
|
maxLines: 1,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
decoration: InputDecoration(),
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 14.0,
|
||||||
|
color: Colors.black,
|
||||||
|
fontWeight: FontWeight.bold)),
|
||||||
|
onTap: () {
|
||||||
|
// deleteWallet(widget.walletName);
|
||||||
|
// _keyHistory.currentState.scan();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
SizedBox(height: 12),
|
||||||
|
Form(
|
||||||
|
key: formKey,
|
||||||
|
child: Padding(
|
||||||
|
padding:
|
||||||
|
const EdgeInsets.symmetric(vertical: 8.0, horizontal: 30),
|
||||||
|
child: PinCodeTextField(
|
||||||
|
appContext: context,
|
||||||
|
pastedTextStyle: TextStyle(
|
||||||
|
color: Colors.green.shade600,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
length: 6,
|
||||||
|
obscureText: false,
|
||||||
|
obscuringCharacter: '*',
|
||||||
|
animationType: AnimationType.fade,
|
||||||
|
validator: (v) {
|
||||||
|
if (v.length < 6) {
|
||||||
|
return "Votre code PIN fait 6 caractères";
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
pinTheme: PinTheme(
|
||||||
|
shape: PinCodeFieldShape.box,
|
||||||
|
borderRadius: BorderRadius.circular(5),
|
||||||
|
fieldHeight: 60,
|
||||||
|
fieldWidth: 50,
|
||||||
|
activeFillColor: hasError ? Colors.orange : Colors.white,
|
||||||
|
),
|
||||||
|
cursorColor: Colors.black,
|
||||||
|
animationDuration: Duration(milliseconds: 300),
|
||||||
|
textStyle: TextStyle(fontSize: 20, height: 1.6),
|
||||||
|
backgroundColor: pinColor,
|
||||||
|
enableActiveFill: false,
|
||||||
|
errorAnimationController: errorController,
|
||||||
|
controller: _enterPin,
|
||||||
|
keyboardType: TextInputType.text,
|
||||||
|
boxShadows: [
|
||||||
|
BoxShadow(
|
||||||
|
offset: Offset(0, 1),
|
||||||
|
color: Colors.black12,
|
||||||
|
blurRadius: 10,
|
||||||
|
)
|
||||||
|
],
|
||||||
|
onCompleted: (v) async {
|
||||||
|
print("Completed");
|
||||||
|
final resultWallet = await readLocalWallet(v.toUpperCase());
|
||||||
|
if (resultWallet == 'bad') {
|
||||||
|
errorController.add(ErrorAnimationType
|
||||||
|
.shake); // Triggering error shake animation
|
||||||
|
setState(() {
|
||||||
|
hasError = true;
|
||||||
|
pinColor = Colors.red[200];
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
setState(() {
|
||||||
|
pinColor = Colors.green[200];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onChanged: (value) {
|
||||||
|
if (pinColor != Color(0xffF9F9F1)) {
|
||||||
|
setState(() {
|
||||||
|
pinColor = Color(0xffF9F9F1);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
print(value);
|
||||||
|
},
|
||||||
|
)),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
height: 100,
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
height: 80,
|
||||||
|
child: ElevatedButton(
|
||||||
|
style: ElevatedButton.styleFrom(
|
||||||
|
elevation: 2,
|
||||||
|
primary: Colors.red, //Color(0xffFFD68E), // background
|
||||||
|
onPrimary: Colors.black, // foreground
|
||||||
|
),
|
||||||
|
onPressed: () {
|
||||||
|
deleteWallet(widget.walletName);
|
||||||
|
},
|
||||||
|
child: Text('Supprimer ce portefeuille',
|
||||||
|
style: TextStyle(fontSize: 25))))
|
||||||
|
]))));
|
||||||
|
}
|
||||||
|
|
||||||
|
Future getPubkeyFromDewif(_dewif, _pin) async {
|
||||||
|
String _pubkey;
|
||||||
|
RegExp regExp = new RegExp(
|
||||||
|
r'^[A-Z0-9]+$',
|
||||||
|
caseSensitive: false,
|
||||||
|
multiLine: false,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (regExp.hasMatch(_pin) == true && _pin.length == 6) {
|
||||||
|
print("Le format du code PIN est correct.");
|
||||||
|
} else {
|
||||||
|
print('Format de code PIN invalide');
|
||||||
|
return 'false';
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
_pubkey = await DubpRust.getDewifPublicKey(dewif: _dewif, pin: _pin);
|
||||||
|
setState(() {
|
||||||
|
this._pubkey.text = _pubkey;
|
||||||
|
});
|
||||||
|
|
||||||
|
return _pubkey;
|
||||||
|
} catch (e, stack) {
|
||||||
|
print('Bad PIN code !');
|
||||||
|
print(e);
|
||||||
|
if (kReleaseMode) {
|
||||||
|
await sentry.Sentry.captureException(
|
||||||
|
e,
|
||||||
|
stackTrace: stack,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return 'false';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future readLocalWallet(String _pin) async {
|
||||||
|
// print(pin);
|
||||||
|
try {
|
||||||
|
final file = await _localWallet(widget.walletName);
|
||||||
|
String _localDewif = await file.readAsString();
|
||||||
|
String _localPubkey;
|
||||||
|
|
||||||
|
if ((_localPubkey = await getPubkeyFromDewif(_localDewif, _pin)) !=
|
||||||
|
'false') {
|
||||||
|
setState(() {
|
||||||
|
this._pubkey.text = _localPubkey;
|
||||||
|
});
|
||||||
|
|
||||||
|
return _localDewif;
|
||||||
|
} else {
|
||||||
|
throw 'Bad pubkey';
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
print('ERROR READING FILE: $e');
|
||||||
|
setState(() {
|
||||||
|
this._pubkey.clear();
|
||||||
|
});
|
||||||
|
return 'bad';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<int> deleteWallet(_name) async {
|
||||||
|
try {
|
||||||
|
final appPath = await _localPath;
|
||||||
|
final _walletFile = Directory('$appPath/wallets/$_name');
|
||||||
|
print('DELETE THAT ?: $_walletFile');
|
||||||
|
|
||||||
|
_walletFile.deleteSync(recursive: true);
|
||||||
|
Navigator.pop(context);
|
||||||
|
return 0;
|
||||||
|
} catch (e) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<String> get _localPath async {
|
||||||
|
final directory = await getApplicationDocumentsDirectory();
|
||||||
|
return directory.path;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<File> _localWallet(_name) async {
|
||||||
|
final path = await _localPath;
|
||||||
|
return File('$path/wallets/$_name/wallet.dewif');
|
||||||
|
}
|
||||||
|
}
|
|
@ -41,8 +41,8 @@ class WalletsHomeState extends State<WalletsHome> {
|
||||||
// getAppDirectory();
|
// getAppDirectory();
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
floatingActionButton: Visibility(
|
floatingActionButton: Visibility(
|
||||||
visible: (checkIfWalletExist(
|
visible:
|
||||||
'MonWallet')), //!checkIfWalletExist('MonWallet') &&
|
(checkIfWalletExist()), //!checkIfWalletExist('MonWallet') &&
|
||||||
child: Container(
|
child: Container(
|
||||||
height: 80.0,
|
height: 80.0,
|
||||||
width: 80.0,
|
width: 80.0,
|
||||||
|
@ -55,10 +55,7 @@ class WalletsHomeState extends State<WalletsHome> {
|
||||||
MaterialPageRoute(builder: (context) {
|
MaterialPageRoute(builder: (context) {
|
||||||
return GenerateWalletsScreen();
|
return GenerateWalletsScreen();
|
||||||
}),
|
}),
|
||||||
).then((value) => setState(() {
|
);
|
||||||
this.newWalletName = value;
|
|
||||||
checkIfWalletExist(value);
|
|
||||||
}));
|
|
||||||
},
|
},
|
||||||
child: Container(
|
child: Container(
|
||||||
height: 40.0,
|
height: 40.0,
|
||||||
|
@ -68,7 +65,7 @@ class WalletsHomeState extends State<WalletsHome> {
|
||||||
body: SafeArea(
|
body: SafeArea(
|
||||||
child: Column(children: <Widget>[
|
child: Column(children: <Widget>[
|
||||||
Visibility(
|
Visibility(
|
||||||
visible: (!checkIfWalletExist('MonWallet') && !walletIsGenerated),
|
visible: (!checkIfWalletExist() && !walletIsGenerated),
|
||||||
child: Column(children: <Widget>[
|
child: Column(children: <Widget>[
|
||||||
SizedBox(height: 120),
|
SizedBox(height: 120),
|
||||||
Center(
|
Center(
|
||||||
|
@ -89,7 +86,7 @@ class WalletsHomeState extends State<WalletsHome> {
|
||||||
}),
|
}),
|
||||||
).then((value) => setState(() {
|
).then((value) => setState(() {
|
||||||
this.newWalletName = value;
|
this.newWalletName = value;
|
||||||
checkIfWalletExist(value);
|
checkIfWalletExist();
|
||||||
})),
|
})),
|
||||||
child: Text('Générer un portefeuille',
|
child: Text('Générer un portefeuille',
|
||||||
style: TextStyle(fontSize: 20))),
|
style: TextStyle(fontSize: 20))),
|
||||||
|
@ -110,8 +107,8 @@ class WalletsHomeState extends State<WalletsHome> {
|
||||||
style: TextStyle(fontSize: 20))),
|
style: TextStyle(fontSize: 20))),
|
||||||
])),
|
])),
|
||||||
Visibility(
|
Visibility(
|
||||||
visible: checkIfWalletExist('MonWallet'),
|
visible: checkIfWalletExist(),
|
||||||
child: MyWalletsScreen(keyMyWallets: _keyWalletsHome))
|
child: MyWalletsList(keyMyWallets: _keyWalletsHome))
|
||||||
])));
|
])));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,22 +124,34 @@ class WalletsHomeState extends State<WalletsHome> {
|
||||||
// });
|
// });
|
||||||
// }
|
// }
|
||||||
|
|
||||||
bool checkIfWalletExist(_name) {
|
bool checkIfWalletExist() {
|
||||||
print('Nom du wallet: ' + _name);
|
|
||||||
if (this.appPath == null) {
|
if (this.appPath == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
final bool isExist =
|
var walletsFolder = new Directory("${this.appPath.path}/wallets/");
|
||||||
File('${this.appPath.path}/wallets/$_name/wallet.dewif').existsSync();
|
List contents = walletsFolder.listSync();
|
||||||
print(this.appPath.path);
|
if (contents.length == 0) {
|
||||||
print('Wallet existe ? : ' + isExist.toString());
|
print('No wallets detected');
|
||||||
print('Is wallet generated ? : ' + walletIsGenerated.toString());
|
|
||||||
if (isExist) {
|
|
||||||
print('Un wallet existe !');
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
return false;
|
||||||
|
} else {
|
||||||
|
print('Some wallets have been detected:');
|
||||||
|
for (var _wallets in contents) {
|
||||||
|
print(_wallets);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// final bool isExist =
|
||||||
|
// File('${walletsFolder.path}/$name/wallet.dewif').existsSync();
|
||||||
|
// print(this.appPath.path);
|
||||||
|
// print('Wallet existe ? : ' + isExist.toString());
|
||||||
|
// print('Is wallet generated ? : ' + walletIsGenerated.toString());
|
||||||
|
// if (isExist) {
|
||||||
|
// print('Un wallet existe !');
|
||||||
|
// return true;
|
||||||
|
// } else {
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
Future getAppDirectory() async {
|
Future getAppDirectory() async {
|
||||||
|
|
|
@ -5,7 +5,7 @@ description: A new Flutter project.
|
||||||
# pub.dev using `pub publish`. This is preferred for private packages.
|
# pub.dev using `pub publish`. This is preferred for private packages.
|
||||||
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
|
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
|
||||||
|
|
||||||
version: 0.0.0+9
|
version: 0.0.0+10
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ">=2.7.0 <3.0.0"
|
sdk: ">=2.7.0 <3.0.0"
|
||||||
|
|
Loading…
Reference in New Issue