From 533f19dabc23990820fd30cc3a10ee9d578c641b Mon Sep 17 00:00:00 2001 From: poka Date: Mon, 15 Feb 2021 23:57:38 +0100 Subject: [PATCH] Can import and use Cesium wallet (salut/password) --- lib/models/generateWallets.dart | 78 ++++++++- lib/models/myWallets.dart | 2 - lib/models/walletOptions.dart | 80 +++++---- lib/screens/myWallets/importWallet.dart | 221 ++++++++++++++++++++++++ lib/screens/myWallets/walletsHome.dart | 8 +- 5 files changed, 348 insertions(+), 41 deletions(-) create mode 100644 lib/screens/myWallets/importWallet.dart diff --git a/lib/models/generateWallets.dart b/lib/models/generateWallets.dart index 05e27e1..842fd5f 100644 --- a/lib/models/generateWallets.dart +++ b/lib/models/generateWallets.dart @@ -11,6 +11,7 @@ import 'package:sentry_flutter/sentry_flutter.dart' as sentry; import 'package:pdf/pdf.dart'; import 'package:pdf/widgets.dart' as pw; import 'package:printing/printing.dart'; +import 'package:truncate/truncate.dart'; class GenerateWalletsProvider with ChangeNotifier { GenerateWalletsProvider(); @@ -20,6 +21,7 @@ class GenerateWalletsProvider with ChangeNotifier { FocusNode walletNameFocus = FocusNode(); Color askedWordColor = Colors.black; bool isAskedWordValid = false; + int nbrWord; String generatedMnemonic; @@ -28,6 +30,15 @@ class GenerateWalletsProvider with ChangeNotifier { TextEditingController mnemonicController = TextEditingController(); TextEditingController pin = TextEditingController(); + // Import wallet + TextEditingController cesiumID = TextEditingController(); + TextEditingController cesiumPWD = TextEditingController(); + TextEditingController cesiumPubkey = TextEditingController(); + bool isCesiumIDVisible = false; + bool isCesiumPWDVisible = false; + bool canImport = false; + bool isPinChanged = false; + Future storeWallet(NewWallet wallet, String _name, BuildContext context, {bool isHD = false}) async { int nbrWallet = 0; @@ -55,11 +66,19 @@ class GenerateWalletsProvider with ChangeNotifier { await configFile .writeAsString('$nbrWallet:$_name:$_derivationNbr:$_pubkey'); } else { - await configFile.writeAsString('$nbrWallet:$_name'); + final int _derivationNbr = -1; + String _pubkey = await DubpRust.getDewifPublicKey( + dewif: wallet.dewif, + pin: wallet.pin, + ); + await configFile + .writeAsString('$nbrWallet:$_name:$_derivationNbr:$_pubkey'); } Navigator.pop(context, true); - Navigator.pop(context, true); + if (isHD) { + Navigator.pop(context, true); + } // notifyListeners(); return _name; @@ -164,13 +183,13 @@ class GenerateWalletsProvider with ChangeNotifier { } Future changePinCode() async { - this.actualWallet = await DubpRust.changeDewifPin( - dewif: this.actualWallet.dewif, - oldPin: this.actualWallet.pin, + actualWallet = await DubpRust.changeDewifPin( + dewif: actualWallet.dewif, + oldPin: actualWallet.pin, ); - pin.text = this.actualWallet.pin; - // notifyListeners(); + pin.text = actualWallet.pin; + notifyListeners(); } Future printWallet(String _title) async { @@ -210,4 +229,49 @@ class GenerateWalletsProvider with ChangeNotifier { return pdf.save(); } + + Future generateCesiumWalletPubkey( + String _cesiumID, String _cesiumPWD) async { + actualWallet = await DubpRust.genWalletFromDeprecatedSaltPassword( + salt: _cesiumID, password: _cesiumPWD); + String _walletPubkey = await DubpRust.getLegacyPublicKey( + salt: _cesiumID, password: _cesiumPWD); + + cesiumPubkey.text = _walletPubkey; + // changePinCode(); + // notifyListeners(); + print(_walletPubkey); + } + + Future importWallet(context, _cesiumID, _cesiumPWD) async { + String _walletPubkey = await DubpRust.getLegacyPublicKey( + salt: _cesiumID, password: _cesiumPWD); + String shortPubkey = truncate(_walletPubkey, 9, + omission: "...", position: TruncatePosition.end); + await storeWallet( + actualWallet, 'Portefeuille Cesium - $shortPubkey', context); + print('taaaaaaaaaaaaaaaaa'); + print(actualWallet.pin); + cesiumID.text = ''; + cesiumPWD.text = ''; + cesiumPubkey.text = ''; + canImport = false; + isPinChanged = false; + pin.text = ''; + notifyListeners(); + } + + void cesiumIDisVisible() { + isCesiumIDVisible = !isCesiumIDVisible; + notifyListeners(); + } + + void cesiumPWDisVisible() { + isCesiumPWDVisible = !isCesiumPWDVisible; + notifyListeners(); + } + + void reloadBuild() { + notifyListeners(); + } } diff --git a/lib/models/myWallets.dart b/lib/models/myWallets.dart index 03d0072..f1b96fb 100644 --- a/lib/models/myWallets.dart +++ b/lib/models/myWallets.dart @@ -23,8 +23,6 @@ class MyWalletsProvider with ChangeNotifier { } } - Future importWallet() async {} - String getAllWalletsNames() { final bool _isWalletsExists = checkIfWalletExist(); if (!_isWalletsExists) { diff --git a/lib/models/walletOptions.dart b/lib/models/walletOptions.dart index 3fd5257..0b708c0 100644 --- a/lib/models/walletOptions.dart +++ b/lib/models/walletOptions.dart @@ -3,7 +3,6 @@ import 'package:dubp/dubp.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'dart:async'; -import 'package:sentry/sentry.dart' as sentry; import 'package:gecko/globals.dart'; class WalletOptionsProvider with ChangeNotifier { @@ -30,26 +29,35 @@ class WalletOptionsProvider with ChangeNotifier { print('Format de code PIN invalide'); return 'false'; } - try { - List _pubkeysTmp = await DubpRust.getBip32DewifAccountsPublicKeys( - dewif: _dewif, secretCode: _pin, accountsIndex: [derivation]); - _pubkey = _pubkeysTmp[0]; - this.pubkey.text = _pubkey; - notifyListeners(); + if (derivation != -1) { + try { + List _pubkeysTmp = await DubpRust.getBip32DewifAccountsPublicKeys( + dewif: _dewif, secretCode: _pin, accountsIndex: [derivation]); + _pubkey = _pubkeysTmp[0]; + this.pubkey.text = _pubkey; + notifyListeners(); - return _pubkey; - } catch (e, stack) { - print('Bad PIN code !'); - print(e); - if (kReleaseMode) { - await sentry.Sentry.captureException( - e, - stackTrace: stack, - ); + return _pubkey; + } catch (e) { + print('Bad PIN code !'); + print(e); + notifyListeners(); + + return 'false'; } - notifyListeners(); + } else { + try { + _pubkey = await DubpRust.getDewifPublicKey(dewif: _dewif, pin: _pin); + this.pubkey.text = _pubkey; + notifyListeners(); + return _pubkey; + } catch (e) { + print('Bad PIN code !'); + print(e); + notifyListeners(); - return 'false'; + return 'false'; + } } } @@ -97,12 +105,17 @@ class WalletOptionsProvider with ChangeNotifier { String newConfig = await _walletConfig.readAsLines().then((List lines) { + int nbrLines = lines.length; int _index = lines.indexOf('$_walletNbr:$_walletName:$_derivation'); - lines.removeWhere( - (element) => element == '$_walletNbr:$_walletName:$_derivation'); - lines.insert(_index, '$_walletNbr:$_newName:$_derivation'); - - return lines.join('\n'); + print(nbrLines); + if (nbrLines != 1) { + lines.removeWhere((element) => + element.contains('$_walletNbr:$_walletName:$_derivation')); + lines.insert(_index, '$_walletNbr:$_newName:$_derivation'); + return lines.join('\n'); + } else { + return '$_walletNbr:$_newName:$_derivation'; + } }); await _walletConfig.delete(); @@ -158,16 +171,21 @@ class WalletOptionsProvider with ChangeNotifier { final _walletConfig = File('${walletsDirectory.path}/$_walletNbr/config.txt'); - String newConfig = - await _walletConfig.readAsLines().then((List lines) { - lines.removeWhere( - (element) => element.contains('$_walletNbr:$_name:$_derivation')); + if (_derivation != -1) { + String newConfig = + await _walletConfig.readAsLines().then((List lines) { + lines.removeWhere( + (element) => element.contains('$_walletNbr:$_name:$_derivation')); - return lines.join('\n'); - }); + return lines.join('\n'); + }); - await _walletConfig.delete(); - await _walletConfig.writeAsString(newConfig); + await _walletConfig.delete(); + await _walletConfig.writeAsString(newConfig); + } else { + final _walletFile = Directory('${walletsDirectory.path}/$_walletNbr'); + await _walletFile.delete(recursive: true); + } Navigator.pop(context); } return 0; diff --git a/lib/screens/myWallets/importWallet.dart b/lib/screens/myWallets/importWallet.dart new file mode 100644 index 0000000..cd0216b --- /dev/null +++ b/lib/screens/myWallets/importWallet.dart @@ -0,0 +1,221 @@ +import 'dart:async'; +import 'package:gecko/models/generateWallets.dart'; +import 'package:flutter/material.dart'; +import 'package:gecko/models/myWallets.dart'; +import 'package:provider/provider.dart'; + +class ImportWalletScreen extends StatelessWidget { + @override + Widget build(BuildContext context) { + GlobalKey _toolTipSecret = GlobalKey(); + Timer _debounce; + GenerateWalletsProvider _generateWalletProvider = + Provider.of(context); + MyWalletsProvider _myWalletProvider = + Provider.of(context); + + return WillPopScope( + onWillPop: () { + _generateWalletProvider.cesiumID.text = ''; + _generateWalletProvider.cesiumPWD.text = ''; + _generateWalletProvider.cesiumPubkey.text = ''; + _generateWalletProvider.pin.text = ''; + _generateWalletProvider.canImport = false; + _generateWalletProvider.isPinChanged = false; + return Future.value(true); + }, + child: Scaffold( + appBar: AppBar( + leading: IconButton( + icon: Icon(Icons.arrow_back, color: Colors.black), + onPressed: () { + _generateWalletProvider.cesiumID.text = ''; + _generateWalletProvider.cesiumPWD.text = ''; + _generateWalletProvider.cesiumPubkey.text = ''; + _generateWalletProvider.pin.text = ''; + _generateWalletProvider.canImport = false; + _generateWalletProvider.isPinChanged = false; + Navigator.of(context).pop(); + }), + title: SizedBox( + height: 22, + child: Text('Importer un portefeuille'), + )), + body: Builder( + builder: (ctx) => SafeArea( + child: Column(children: [ + SizedBox(height: 20), + TextFormField( + onChanged: (text) { + if (_debounce?.isActive ?? false) + // _generateWalletProvider.canImport = false; + // _generateWalletProvider.reloadBuild(); + _debounce.cancel(); + _debounce = + Timer(const Duration(milliseconds: 200), () { + print("ID Cesium tappé: $text"); + _generateWalletProvider + .generateCesiumWalletPubkey(text, + _generateWalletProvider.cesiumPWD.text) + .then((value) { + _generateWalletProvider.canImport = true; + _generateWalletProvider.reloadBuild(); + }); + }); + }, + keyboardType: TextInputType.text, + controller: _generateWalletProvider.cesiumID, + obscureText: !_generateWalletProvider + .isCesiumIDVisible, //This will obscure text dynamically + decoration: InputDecoration( + hintText: 'Entrez votre identifiant Cesium', + suffixIcon: IconButton( + icon: Icon( + _generateWalletProvider.isCesiumIDVisible + ? Icons.visibility + : Icons.visibility_off, + color: Colors.black, + ), + onPressed: () { + _generateWalletProvider.cesiumIDisVisible(); + }, + ), + ), + ), + SizedBox(height: 15), + TextFormField( + onChanged: (text) { + if (_debounce?.isActive ?? false) + // _generateWalletProvider.canImport = false; + // _generateWalletProvider.reloadBuild(); + _debounce.cancel(); + _debounce = + Timer(const Duration(milliseconds: 200), () { + print("ID Cesium tappé: $text"); + _generateWalletProvider + .generateCesiumWalletPubkey( + _generateWalletProvider.cesiumID.text, + text) + .then((value) { + _generateWalletProvider.canImport = true; + _generateWalletProvider.reloadBuild(); + }); + }); + }, + keyboardType: TextInputType.text, + controller: _generateWalletProvider.cesiumPWD, + obscureText: !_generateWalletProvider + .isCesiumPWDVisible, //This will obscure text dynamically + decoration: InputDecoration( + hintText: 'Entrez votre mot de passe Cesium', + suffixIcon: IconButton( + icon: Icon( + _generateWalletProvider.isCesiumPWDVisible + ? Icons.visibility + : Icons.visibility_off, + color: Colors.black, + ), + onPressed: () { + _generateWalletProvider.cesiumPWDisVisible(); + }, + ), + ), + ), + SizedBox(height: 15), + Text( + _generateWalletProvider.cesiumPubkey.text, + style: TextStyle( + fontSize: 14.0, + color: Colors.black, + fontWeight: FontWeight.bold, + fontFamily: 'Monospace'), + ), + SizedBox(height: 20), + toolTips(_toolTipSecret, 'Code secret:', + "Retenez bien votre code secret, il vous sera demandé à chaque paiement, ainsi que pour configurer votre portefeuille"), + Container( + child: Stack( + alignment: Alignment.centerRight, + children: [ + TextField( + enabled: false, + controller: _generateWalletProvider.pin, + maxLines: 1, + textAlign: TextAlign.center, + decoration: InputDecoration(), + style: TextStyle( + fontSize: 30.0, + color: Colors.black, + fontWeight: FontWeight.bold)), + IconButton( + icon: Icon(Icons.replay), + color: Color(0xffD28928), + onPressed: () { + _generateWalletProvider.changePinCode(); + _generateWalletProvider.isPinChanged = true; + }, + ), + ], + ), + ), + SizedBox(height: 30), + ElevatedButton( + style: ElevatedButton.styleFrom( + primary: Color(0xffFFD68E), // background + onPrimary: Colors.black, // foreground + ), + onPressed: _generateWalletProvider.canImport && + _generateWalletProvider.isPinChanged + ? () { + _generateWalletProvider + .importWallet( + context, + _generateWalletProvider + .cesiumID.text, + _generateWalletProvider + .cesiumPWD.text) + .then((value) { + _myWalletProvider.rebuildWidget(); + }); + } + : null, + child: Text('Importer ce portefeuille Cesium', + style: TextStyle(fontSize: 20))), + ]), + )))); + } + + Widget toolTips(_key, _text, _message) { + return GestureDetector( + onTap: () { + final dynamic _toolTip = _key.currentState; + _toolTip.ensureTooltipVisible(); + }, + child: Tooltip( + padding: EdgeInsets.all(10), + key: _key, + showDuration: Duration(seconds: 5), + message: _message, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SizedBox(width: 20), + Column(children: [ + SizedBox( + width: 30, + height: 25, + child: Icon(Icons.info_outline, + size: 22, color: Color(0xffD28928))), + SizedBox(height: 1) + ]), + Text( + _text, + style: TextStyle( + fontSize: 15.0, + color: Colors.grey[600], + fontWeight: FontWeight.w400), + ), + SizedBox(width: 45) + ]))); + } +} diff --git a/lib/screens/myWallets/walletsHome.dart b/lib/screens/myWallets/walletsHome.dart index c593dd1..e66b0d3 100644 --- a/lib/screens/myWallets/walletsHome.dart +++ b/lib/screens/myWallets/walletsHome.dart @@ -2,6 +2,7 @@ import 'package:gecko/models/myWallets.dart'; import 'package:gecko/models/walletOptions.dart'; import 'package:gecko/screens/myWallets/generateWallets.dart'; import 'package:flutter/material.dart'; +import 'package:gecko/screens/myWallets/importWallet.dart'; import 'package:gecko/screens/myWallets/walletOptions.dart'; import 'package:provider/provider.dart'; @@ -78,7 +79,12 @@ class WalletsHome extends StatelessWidget { primary: Color(0xffFFD68E), // background onPrimary: Colors.black, // foreground ), - onPressed: () => myWalletProvider.importWallet(), + onPressed: () => Navigator.push( + context, + MaterialPageRoute(builder: (context) { + return ImportWalletScreen(); + }), + ), child: Text('Importer un portefeuille existant', style: TextStyle(fontSize: 20))), ])),