diff --git a/lib/main.dart b/lib/main.dart index ea12add..9ad437f 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -22,6 +22,7 @@ import 'package:gecko/globals.dart'; import 'package:gecko/models/cesium_plus.dart'; import 'package:gecko/models/change_pin.dart'; import 'package:gecko/models/chest_data.dart'; +import 'package:gecko/models/chest_provider.dart'; import 'package:gecko/models/generate_wallets.dart'; import 'package:gecko/models/history.dart'; import 'package:gecko/models/home.dart'; @@ -136,6 +137,7 @@ class Gecko extends StatelessWidget { ChangeNotifierProvider(create: (_) => HomeProvider()), ChangeNotifierProvider(create: (_) => HistoryProvider('')), ChangeNotifierProvider(create: (_) => MyWalletsProvider()), + ChangeNotifierProvider(create: (_) => ChestProvider()), ChangeNotifierProvider(create: (_) => GenerateWalletsProvider()), ChangeNotifierProvider(create: (_) => WalletOptionsProvider()), ChangeNotifierProvider(create: (_) => ChangePinProvider()), diff --git a/lib/models/chest_data.dart b/lib/models/chest_data.dart index 923a385..9e01d9a 100644 --- a/lib/models/chest_data.dart +++ b/lib/models/chest_data.dart @@ -1,3 +1,5 @@ +import 'dart:io'; + import 'package:hive_flutter/hive_flutter.dart'; part 'chest_data.g.dart'; @@ -17,6 +19,9 @@ class ChestData extends HiveObject { String imageName; @HiveField(5) + File imageFile; + + @HiveField(6) bool isCesium; ChestData({ @@ -24,6 +29,7 @@ class ChestData extends HiveObject { this.name, this.defaultWallet, this.imageName, + this.imageFile, this.isCesium, }); diff --git a/lib/models/chest_data.g.dart b/lib/models/chest_data.g.dart index ca25dff..1d0be58 100644 --- a/lib/models/chest_data.g.dart +++ b/lib/models/chest_data.g.dart @@ -21,14 +21,15 @@ class ChestDataAdapter extends TypeAdapter { name: fields[2] as String, defaultWallet: fields[3] as int, imageName: fields[4] as String, - isCesium: fields[5] as bool, + imageFile: fields[5] as File, + isCesium: fields[6] as bool, ); } @override void write(BinaryWriter writer, ChestData obj) { writer - ..writeByte(5) + ..writeByte(6) ..writeByte(0) ..write(obj.dewif) ..writeByte(2) @@ -38,6 +39,8 @@ class ChestDataAdapter extends TypeAdapter { ..writeByte(4) ..write(obj.imageName) ..writeByte(5) + ..write(obj.imageFile) + ..writeByte(6) ..write(obj.isCesium); } diff --git a/lib/models/chest_provider.dart b/lib/models/chest_provider.dart new file mode 100644 index 0000000..c466e50 --- /dev/null +++ b/lib/models/chest_provider.dart @@ -0,0 +1,53 @@ +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:gecko/globals.dart'; +import 'package:gecko/models/chest_data.dart'; + +class ChestProvider with ChangeNotifier { + void rebuildWidget() { + notifyListeners(); + } + + Future deleteChest(context, ChestData _chest) async { + final bool _answer = await _confirmDeletingChest(context, _chest.name); + + if (_answer) { + chestBox.delete(_chest.key); + int lastChest = chestBox.toMap().keys.first; + configBox.put('currentChest', lastChest); + notifyListeners(); + + Navigator.popUntil( + context, + ModalRoute.withName('/'), + ); + } + } + + Future _confirmDeletingChest(context, String _walletName) async { + return showDialog( + context: context, + barrierDismissible: true, // user must tap button! + builder: (BuildContext context) { + return AlertDialog( + title: Text( + 'Êtes-vous sûr de vouloir supprimer le coffre "$_walletName" ?'), + actions: [ + TextButton( + child: const Text("Non", key: Key('cancelDeleting')), + onPressed: () { + Navigator.pop(context, false); + }, + ), + TextButton( + child: const Text("Oui", key: Key('confirmDeleting')), + onPressed: () { + Navigator.pop(context, true); + }, + ), + ], + ); + }, + ); + } +} diff --git a/lib/models/generate_wallets.dart b/lib/models/generate_wallets.dart index 3b8cec8..1266dfc 100644 --- a/lib/models/generate_wallets.dart +++ b/lib/models/generate_wallets.dart @@ -39,15 +39,14 @@ class GenerateWalletsProvider with ChangeNotifier { bool canImport = false; bool isPinChanged = false; - void storeHDWChest( + Future storeHDWChest( NewWallet _wallet, String _name, BuildContext context) async { - int chestNumber = chestBox.length; - WalletData myWallet = WalletData( - chest: chestNumber, - number: 0, - name: _name, - derivation: 3, - imageName: '0.png'); + int chestNumber = 0; + chestBox.toMap().forEach((key, value) { + if (!value.isCesium) { + chestNumber++; + } + }); String chestName; if (chestNumber == 0) { @@ -55,7 +54,6 @@ class GenerateWalletsProvider with ChangeNotifier { } else { chestName = 'Coffre à Ğecko ${chestNumber + 1}'; } - walletBox.add(myWallet); ChestData thisChest = ChestData( dewif: _wallet.dewif, name: chestName, @@ -63,8 +61,19 @@ class GenerateWalletsProvider with ChangeNotifier { imageName: '${chestNumber % 8}.png', isCesium: false, ); - chestBox.add(thisChest); - configBox.put('currentChest', chestNumber); + await chestBox.add(thisChest); + int chestKey = chestBox.keys.last; + + WalletData myWallet = WalletData( + chest: chestKey, + number: 0, + name: _name, + derivation: 3, + imageName: '0.png'); + await walletBox.add(myWallet); + + await configBox.put('currentChest', chestKey); + notifyListeners(); } void checkAskedWord(String inputWord, String _mnemo) { @@ -240,16 +249,31 @@ class GenerateWalletsProvider with ChangeNotifier { isCesiumIDVisible = false; isCesiumPWDVisible = false; + int chestNumber = 0; + chestBox.toMap().forEach((key, value) { + if (value.isCesium) { + chestNumber++; + } + }); + + String chestName; + if (chestNumber == 0) { + chestName = 'Coffre à Césium'; + } else { + chestName = 'Coffre à Césium ${chestNumber + 1}'; + } + ChestData cesiumChest = ChestData( dewif: actualWallet.dewif, - name: 'Coffre à Cesium', + name: chestName, imageName: 'cesium.png', defaultWallet: 0, isCesium: true); - int chestNumber = chestBox.length; - chestBox.add(cesiumChest); - configBox.put('currentChest', chestNumber); + await chestBox.add(cesiumChest).then((value) => null); + int chestKey = await chestBox.toMap().keys.last; + // chestBox.toMap(). + await configBox.put('currentChest', chestKey); notifyListeners(); } diff --git a/lib/models/wallet_data.dart b/lib/models/wallet_data.dart index f4ce723..20ea9ef 100644 --- a/lib/models/wallet_data.dart +++ b/lib/models/wallet_data.dart @@ -1,3 +1,5 @@ +import 'dart:io'; + import 'package:hive_flutter/hive_flutter.dart'; part 'wallet_data.g.dart'; @@ -19,8 +21,16 @@ class WalletData extends HiveObject { @HiveField(4) String imageName; + @HiveField(5) + File imageFile; + WalletData( - {this.chest, this.number, this.name, this.derivation, this.imageName}); + {this.chest, + this.number, + this.name, + this.derivation, + this.imageName, + this.imageFile}); // representation of WalletData when debugging @override @@ -34,7 +44,7 @@ class WalletData extends HiveObject { } // returns only the id part of the ':'-separated string - List id() { + List id() { return [chest, number]; } } diff --git a/lib/models/wallet_data.g.dart b/lib/models/wallet_data.g.dart index 4ef937a..3f8ee52 100644 --- a/lib/models/wallet_data.g.dart +++ b/lib/models/wallet_data.g.dart @@ -22,13 +22,14 @@ class WalletDataAdapter extends TypeAdapter { name: fields[2] as String, derivation: fields[3] as int, imageName: fields[4] as String, + imageFile: fields[5] as File, ); } @override void write(BinaryWriter writer, WalletData obj) { writer - ..writeByte(5) + ..writeByte(6) ..writeByte(0) ..write(obj.chest) ..writeByte(1) @@ -38,7 +39,9 @@ class WalletDataAdapter extends TypeAdapter { ..writeByte(3) ..write(obj.derivation) ..writeByte(4) - ..write(obj.imageName); + ..write(obj.imageName) + ..writeByte(5) + ..write(obj.imageFile); } @override diff --git a/lib/models/wallet_options.dart b/lib/models/wallet_options.dart index fcabefa..68a55be 100644 --- a/lib/models/wallet_options.dart +++ b/lib/models/wallet_options.dart @@ -8,6 +8,7 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'dart:async'; import 'package:gecko/globals.dart'; +import 'package:gecko/models/chest_data.dart'; import 'package:gecko/models/my_wallets.dart'; import 'package:gecko/models/wallet_data.dart'; import 'package:image_picker/image_picker.dart'; @@ -24,7 +25,6 @@ class WalletOptionsProvider with ChangeNotifier { bool isBalanceBlur = true; FocusNode walletNameFocus = FocusNode(); TextEditingController nameController = TextEditingController(); - List walletID; bool isDefaultWallet; Future get badWallet => null; @@ -125,63 +125,28 @@ class WalletOptionsProvider with ChangeNotifier { return _pinLenght; } - void _renameWallet(List _walletID, _newName) async { - MyWalletsProvider myWalletClass = MyWalletsProvider(); + void _renameWallet(List _walletID, _newName, {bool isCesium}) async { + if (isCesium) { + ChestData _chestTarget = chestBox.get(_walletID[0]); + _chestTarget.name = _newName; + await chestBox.put(_chestTarget.key, _chestTarget); + } else { + MyWalletsProvider myWalletClass = MyWalletsProvider(); - WalletData _walletTarget = myWalletClass.getWalletData(_walletID); - _walletTarget.name = _newName; - await walletBox.put(_walletTarget.key, _walletTarget); + WalletData _walletTarget = myWalletClass.getWalletData(_walletID); + _walletTarget.name = _newName; + await walletBox.put(_walletTarget.key, _walletTarget); + } _newWalletName.text = ''; } - Future renameWalletAlerte( - context, _walletName, _walletNbr, _derivation) async { - return showDialog( - context: context, - barrierDismissible: true, - builder: (BuildContext context) { - return AlertDialog( - title: const Text('Choisissez un nouveau nom pour ce portefeuille'), - content: SingleChildScrollView( - child: ListBody( - children: [ - TextField( - controller: _newWalletName, - maxLines: 1, - textAlign: TextAlign.center, - decoration: const InputDecoration(), - style: const TextStyle( - fontSize: 14.0, - color: Colors.black, - fontWeight: FontWeight.bold)), - ], - ), - ), - actions: [ - TextButton( - child: const Text("Valider"), - onPressed: () { - WidgetsBinding.instance.addPostFrameCallback((_) async { - // await _renameWallet(_walletName, this._newWalletName.text, - // _walletNbr, _derivation); - }); - // notifyListeners(); - Navigator.pop(context, true); - }, - ), - ], - ); - }, - ); - } - - bool editWalletName(List _wID) { + bool editWalletName(List _wID, {bool isCesium}) { bool nameState; if (isEditing) { if (!nameController.text.contains(':') && nameController.text.length <= 39) { - _renameWallet(_wID, nameController.text); + _renameWallet(_wID, nameController.text, isCesium: isCesium); nameState = true; } else { nameState = false; @@ -281,10 +246,11 @@ class WalletOptionsProvider with ChangeNotifier { File _image; final picker = ImagePicker(); - final pickedFile = await picker.pickImage(source: ImageSource.gallery); + XFile pickedFile = await picker.pickImage(source: ImageSource.gallery); if (pickedFile != null) { _image = File(pickedFile.path); + log.i(pickedFile.path); return _image; } else { log.w('No image selected.'); diff --git a/lib/screens/home.dart b/lib/screens/home.dart index 2e4d392..7130569 100644 --- a/lib/screens/home.dart +++ b/lib/screens/home.dart @@ -1,5 +1,6 @@ import 'package:dubp/dubp.dart'; import 'package:gecko/globals.dart'; +import 'package:gecko/models/chest_provider.dart'; import 'package:gecko/models/history.dart'; import 'package:gecko/models/home.dart'; import 'package:flutter/material.dart'; @@ -23,10 +24,9 @@ class HomeScreen extends StatelessWidget { HistoryProvider _historyStatic = HistoryProvider(''); MyWalletsProvider _myWalletProvider = Provider.of(context); - final bool isWalletsExists = _myWalletProvider.checkIfWalletExist(); + Provider.of(context); - WalletData defaultWallet = - _myWalletProvider.getDefaultWallet(configBox.get('currentChest')); + final bool isWalletsExists = _myWalletProvider.checkIfWalletExist(); // walletBox.toMap().forEach((key, value) { // if (value.chest == 0) { @@ -281,6 +281,9 @@ class HomeScreen extends StatelessWidget { image: AssetImage('assets/lock.png'), height: 57)), onTap: () { + WalletData defaultWallet = + _myWalletProvider.getDefaultWallet( + configBox.get('currentChest')); isWalletsExists ? Navigator.push(context, MaterialPageRoute(builder: (context) { diff --git a/lib/screens/myWallets/cesium_wallet_options.dart b/lib/screens/myWallets/cesium_wallet_options.dart index 3a976a9..4e48b47 100644 --- a/lib/screens/myWallets/cesium_wallet_options.dart +++ b/lib/screens/myWallets/cesium_wallet_options.dart @@ -1,399 +1,310 @@ +import 'dart:io'; import 'dart:ui'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:gecko/globals.dart'; +import 'package:gecko/models/chest_data.dart'; +import 'package:gecko/models/chest_provider.dart'; import 'package:gecko/models/history.dart'; -import 'package:gecko/models/my_wallets.dart'; import 'package:gecko/models/queries.dart'; -import 'package:gecko/models/wallet_data.dart'; import 'package:gecko/models/wallet_options.dart'; import 'package:graphql_flutter/graphql_flutter.dart'; import 'package:provider/provider.dart'; import 'package:flutter/services.dart'; -// ignore: must_be_immutable -class CesiumWalletOptions extends StatelessWidget { - CesiumWalletOptions({Key keyMyWallets, @required this.cesiumWallet}) - : super(key: keyMyWallets); - WalletData cesiumWallet; - int _nbrLinesName = 1; - bool _isNewNameValid = false; +int _nbrLinesName = 1; +bool _isNewNameValid = false; - @override - Widget build(BuildContext context) { - SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]); - WalletOptionsProvider _walletOptions = - Provider.of(context); - MyWalletsProvider _myWalletProvider = - Provider.of(context); - HistoryProvider _historyProvider = Provider.of(context); +Widget cesiumWalletOptions(BuildContext context, ChestData cesiumWallet) { + SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]); + WalletOptionsProvider _walletOptions = + Provider.of(context); + ChestProvider _chestProvider = Provider.of(context); + HistoryProvider _historyProvider = Provider.of(context); - final int _currentChest = _myWalletProvider.getCurrentChest(); - final String shortPubkey = - _walletOptions.getShortPubkey(_walletOptions.pubkey.text); + final String shortPubkey = + _walletOptions.getShortPubkey(_walletOptions.pubkey.text); - if (_walletOptions.nameController.text == null || - _isNewNameValid == false) { - _walletOptions.nameController.text = cesiumWallet.name; - } else { - cesiumWallet.name = _walletOptions.nameController.text; - } + if (_walletOptions.nameController.text == null || _isNewNameValid == false) { + _walletOptions.nameController.text = cesiumWallet.name; + } else { + cesiumWallet.name = _walletOptions.nameController.text; + } - _walletOptions.nameController.text.length >= 15 - ? _nbrLinesName = 2 - : _nbrLinesName = 1; - if (_walletOptions.nameController.text.length >= 26 && isTall) { - _nbrLinesName = 3; - } + _walletOptions.nameController.text.length >= 15 + ? _nbrLinesName = 2 + : _nbrLinesName = 1; + if (_walletOptions.nameController.text.length >= 26 && isTall) { + _nbrLinesName = 3; + } - _walletOptions.walletID = [0, cesiumWallet.number]; - - WalletData defaultWallet = - _myWalletProvider.getDefaultWallet(_currentChest); - - _walletOptions.isDefaultWallet = - (defaultWallet.number == _walletOptions.walletID[1]); - - int currentChest = _myWalletProvider.getCurrentChest(); - - log.d("Wallet options: $currentChest:${cesiumWallet.number}"); - - return WillPopScope( - onWillPop: () { - _walletOptions.isEditing = false; - _walletOptions.isBalanceBlur = true; - Navigator.popUntil( - context, - ModalRoute.withName('/mywallets'), - ); - return Future.value(true); - }, - child: Scaffold( - resizeToAvoidBottomInset: false, - appBar: AppBar( - toolbarHeight: 60 * ratio, - leading: IconButton( - icon: const Icon(Icons.arrow_back, color: Colors.black), - onPressed: () { - _walletOptions.isEditing = false; - _walletOptions.isBalanceBlur = true; - Navigator.popUntil( - context, - ModalRoute.withName('/mywallets'), - ); - }), - title: SizedBox( - height: 22, - child: Text(_walletOptions.nameController.text), + return Scaffold( + resizeToAvoidBottomInset: false, + body: Builder( + builder: (ctx) => SafeArea( + child: Column(children: [ + Container( + height: isTall ? 30 : 15, + color: yellowC, + ), + Container( + decoration: BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [ + yellowC, + const Color(0xfffafafa), + ], )), - body: Builder( - builder: (ctx) => SafeArea( - child: Column(children: [ - Container( - height: isTall ? 15 : 0, - color: yellowC, + child: Row(children: [ + const SizedBox(width: 25), + InkWell( + onTap: () async { + File newAvatar = await _walletOptions.changeAvatar(); + if (newAvatar != null) { + cesiumWallet.imageFile = newAvatar; + } + _walletOptions.reloadBuild(); + }, + child: cesiumWallet.imageFile == null + ? Image.asset( + 'assets/chests/${cesiumWallet.imageName}', + width: 110, + ) + : Image.file(cesiumWallet.imageFile, width: 110), ), - Container( - decoration: BoxDecoration( - gradient: LinearGradient( - begin: Alignment.topCenter, - end: Alignment.bottomCenter, - colors: [ - yellowC, - const Color(0xfffafafa), - ], - )), - child: Row(children: [ - const SizedBox(width: 25), + InkWell( + onTap: () async { + File newAvatar = await _walletOptions.changeAvatar(); + if (newAvatar != null) { + cesiumWallet.imageFile = newAvatar; + } + _walletOptions.reloadBuild(); + }, + child: Column(children: [ + Image.asset( + 'assets/walletOptions/camera.png', + ), + const SizedBox(height: 100) + ])), + Column(children: [ + Row(children: [ + Column(children: [ + SizedBox( + width: 260, + child: TextField( + key: const Key('walletName'), + autofocus: false, + focusNode: _walletOptions.walletNameFocus, + enabled: _walletOptions.isEditing, + controller: _walletOptions.nameController, + maxLines: _nbrLinesName, + textAlign: TextAlign.center, + decoration: const InputDecoration( + border: InputBorder.none, + focusedBorder: InputBorder.none, + enabledBorder: InputBorder.none, + disabledBorder: InputBorder.none, + contentPadding: EdgeInsets.all(15.0), + ), + style: TextStyle( + fontSize: isTall ? 27 : 23, + color: Colors.black, + fontWeight: FontWeight.w400, + fontFamily: 'Monospace')), + ), + SizedBox(height: isTall ? 5 : 0), + Query( + options: QueryOptions( + document: gql(getBalance), + variables: { + 'pubkey': _walletOptions.pubkey.text, + }, + // pollInterval: Duration(seconds: 1), + ), + builder: (QueryResult result, + {VoidCallback refetch, FetchMore fetchMore}) { + if (result.hasException) { + return Text(result.exception.toString()); + } + + if (result.isLoading) { + return const Text('Loading'); + } + + // List repositories = result.data['viewer']['repositories']['nodes']; + String wBalanceUD; + if (result.data['balance'] == null) { + wBalanceUD = '0.0'; + } else { + int wBalanceG1 = result.data['balance']['amount']; + int currentUD = result.data['currentUd']['amount']; + double wBalanceUDBrut = + wBalanceG1 / currentUD; // .toString(); + wBalanceUD = double.parse( + (wBalanceUDBrut).toStringAsFixed(2)) + .toString(); + } + return Row(children: [ + ImageFiltered( + imageFilter: ImageFilter.blur( + sigmaX: _walletOptions.isBalanceBlur ? 6 : 0, + sigmaY: _walletOptions.isBalanceBlur ? 5 : 0), + child: Text(wBalanceUD, + style: TextStyle( + fontSize: isTall ? 20 : 18, + color: Colors.black)), + ), + Text(' DU', + style: TextStyle( + fontSize: isTall ? 20 : 18, + color: Colors.black)) + ]); + + // Text( + // '$wBalanceUD DU', + // style: TextStyle( + // fontSize: 20, color: Colors.black), + // ); + }, + ), + const SizedBox(height: 5), InkWell( - onTap: () async { - await _walletOptions.changeAvatar(); + key: const Key('displayBalance'), + onTap: () { + _walletOptions.bluringBalance(); }, child: Image.asset( - 'assets/avatars/${cesiumWallet.imageName}', - width: 110, + _walletOptions.isBalanceBlur + ? 'assets/walletOptions/icon_oeuil.png' + : 'assets/walletOptions/icon_oeuil_close.png', )), + ]), + const SizedBox(width: 0), + Column(children: [ InkWell( + key: const Key('renameWallet'), onTap: () async { - await _walletOptions.changeAvatar(); + _isNewNameValid = _walletOptions.editWalletName( + [cesiumWallet.key, 0], + isCesium: cesiumWallet.isCesium); + await Future.delayed( + const Duration(milliseconds: 30)); + _walletOptions.walletNameFocus.requestFocus(); }, - child: Column(children: [ - Image.asset( - 'assets/walletOptions/camera.png', - ), - const SizedBox(height: 100) - ])), - Column(children: [ - Row(children: [ - Column(children: [ - SizedBox( - width: 260, - child: TextField( - key: const Key('walletName'), - autofocus: false, - focusNode: _walletOptions.walletNameFocus, - enabled: _walletOptions.isEditing, - controller: _walletOptions.nameController, - maxLines: _nbrLinesName, - textAlign: TextAlign.center, - decoration: const InputDecoration( - border: InputBorder.none, - focusedBorder: InputBorder.none, - enabledBorder: InputBorder.none, - disabledBorder: InputBorder.none, - contentPadding: EdgeInsets.all(15.0), - ), - style: TextStyle( - fontSize: isTall ? 27 : 23, - color: Colors.black, - fontWeight: FontWeight.w400, - fontFamily: 'Monospace')), - ), - SizedBox(height: isTall ? 5 : 0), - Query( - options: QueryOptions( - document: gql(getBalance), - variables: { - 'pubkey': _walletOptions.pubkey.text, - }, - // pollInterval: Duration(seconds: 1), + child: ClipRRect( + child: Image.asset( + _walletOptions.isEditing + ? 'assets/walletOptions/android-checkmark.png' + : 'assets/walletOptions/edit.png', + width: 20, + height: 20), + )), + const SizedBox( + height: 60, + ) + ]) + ]), + ]), + ])), + SizedBox(height: 4 * ratio), + FutureBuilder( + future: _walletOptions.generateQRcode(_walletOptions.pubkey.text), + builder: (context, snapshot) { + return snapshot.data != null + ? Image.memory(snapshot.data, height: isTall ? 300 : 270) + : const Text('-', style: TextStyle(fontSize: 20)); + }), + SizedBox(height: 15 * ratio), + GestureDetector( + key: const Key('copyPubkey'), + onTap: () { + Clipboard.setData( + ClipboardData(text: _walletOptions.pubkey.text)); + _walletOptions.snackCopyKey(ctx); + }, + child: SizedBox( + height: 50, + child: Row(children: [ + const SizedBox(width: 30), + Image.asset( + 'assets/walletOptions/key.png', + ), + const SizedBox(width: 10), + Text("${shortPubkey.split(':')[0]}:", + style: const TextStyle( + fontSize: 22, + fontWeight: FontWeight.w800, + fontFamily: 'Monospace', + color: Colors.black)), + Text(shortPubkey.split(':')[1], + style: const TextStyle( + fontSize: 22, + fontWeight: FontWeight.w800, + fontFamily: 'Monospace')), + const SizedBox(width: 15), + SizedBox( + height: 40, + child: ElevatedButton( + style: ElevatedButton.styleFrom( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), ), - builder: (QueryResult result, - {VoidCallback refetch, FetchMore fetchMore}) { - if (result.hasException) { - return Text(result.exception.toString()); - } - - if (result.isLoading) { - return const Text('Loading'); - } - - // List repositories = result.data['viewer']['repositories']['nodes']; - String wBalanceUD; - if (result.data['balance'] == null) { - wBalanceUD = '0.0'; - } else { - int wBalanceG1 = - result.data['balance']['amount']; - int currentUD = - result.data['currentUd']['amount']; - double wBalanceUDBrut = - wBalanceG1 / currentUD; // .toString(); - wBalanceUD = double.parse( - (wBalanceUDBrut).toStringAsFixed(2)) - .toString(); - } - return Row(children: [ - ImageFiltered( - imageFilter: ImageFilter.blur( - sigmaX: _walletOptions.isBalanceBlur - ? 6 - : 0, - sigmaY: _walletOptions.isBalanceBlur - ? 5 - : 0), - child: Text(wBalanceUD, - style: TextStyle( - fontSize: isTall ? 20 : 18, - color: Colors.black)), - ), - Text(' DU', - style: TextStyle( - fontSize: isTall ? 20 : 18, - color: Colors.black)) - ]); - - // Text( - // '$wBalanceUD DU', - // style: TextStyle( - // fontSize: 20, color: Colors.black), - // ); - }, + elevation: 1, + primary: orangeC, // background + onPrimary: Colors.black, // foreground ), - const SizedBox(height: 5), - InkWell( - key: const Key('displayBalance'), - onTap: () { - _walletOptions.bluringBalance(); - }, - child: Image.asset( - _walletOptions.isBalanceBlur - ? 'assets/walletOptions/icon_oeuil.png' - : 'assets/walletOptions/icon_oeuil_close.png', - )), - ]), - const SizedBox(width: 0), - Column(children: [ - InkWell( - key: const Key('renameWallet'), - onTap: () async { - _isNewNameValid = _walletOptions - .editWalletName(_walletOptions.walletID); - await Future.delayed( - const Duration(milliseconds: 30)); - _walletOptions.walletNameFocus.requestFocus(); - }, - child: ClipRRect( - child: Image.asset( - _walletOptions.isEditing - ? 'assets/walletOptions/android-checkmark.png' - : 'assets/walletOptions/edit.png', - width: 20, - height: 20), - )), - const SizedBox( - height: 60, - ) - ]) - ]), - ]), - ])), - SizedBox(height: 4 * ratio), - FutureBuilder( - future: _walletOptions - .generateQRcode(_walletOptions.pubkey.text), - builder: (context, snapshot) { - return snapshot.data != null - ? Image.memory(snapshot.data, - height: isTall ? 300 : 270) - : const Text('-', style: TextStyle(fontSize: 20)); - }), - SizedBox(height: 15 * ratio), - GestureDetector( - key: const Key('copyPubkey'), - onTap: () { - Clipboard.setData( - ClipboardData(text: _walletOptions.pubkey.text)); - _walletOptions.snackCopyKey(ctx); - }, - child: SizedBox( - height: 50, - child: Row(children: [ - const SizedBox(width: 30), - Image.asset( - 'assets/walletOptions/key.png', - ), - const SizedBox(width: 10), - Text("${shortPubkey.split(':')[0]}:", - style: const TextStyle( - fontSize: 22, - fontWeight: FontWeight.w800, - fontFamily: 'Monospace', - color: Colors.black)), - Text(shortPubkey.split(':')[1], - style: const TextStyle( - fontSize: 22, - fontWeight: FontWeight.w800, - fontFamily: 'Monospace')), - const SizedBox(width: 15), - SizedBox( - height: 40, - child: ElevatedButton( - style: ElevatedButton.styleFrom( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8), - ), - elevation: 1, - primary: orangeC, // background - onPrimary: Colors.black, // foreground - ), - onPressed: () { - Clipboard.setData(ClipboardData( - text: _walletOptions.pubkey.text)); - _walletOptions.snackCopyKey(ctx); - }, - child: Row(children: [ - Image.asset( - 'assets/walletOptions/copy-white.png', - ), - const SizedBox(width: 7), - Text('Copier', - style: TextStyle( - fontSize: 15, - color: Colors.grey[50])) - ]))), - ]))), - SizedBox(height: 10 * ratio), - InkWell( - key: const Key('displayHistory'), - onTap: () { - _historyProvider.isPubkey(ctx, _walletOptions.pubkey.text, - goHistory: true); - }, - child: SizedBox( - height: 50, - child: Row(children: [ - const SizedBox(width: 30), - Image.asset( - 'assets/walletOptions/clock.png', - ), - const SizedBox(width: 12), - const Text('Historique des transactions', - style: - TextStyle(fontSize: 20, color: Colors.black)), - ]))), - SizedBox(height: 12 * ratio), - InkWell( - key: const Key('setDefaultWallet'), - onTap: !_walletOptions.isDefaultWallet - ? () { - defaultWallet = cesiumWallet; - chestBox.get(currentChest).defaultWallet = - cesiumWallet.number; - _myWalletProvider.readAllWallets(_currentChest); - _myWalletProvider.rebuildWidget(); - } - : null, - child: SizedBox( - height: 50, - child: Row(children: [ - const SizedBox(width: 31), - CircleAvatar( - backgroundColor: Colors.grey[ - _walletOptions.isDefaultWallet ? 300 : 500], - child: Image.asset( - 'assets/walletOptions/android-checkmark.png', - )), - const SizedBox(width: 12), - Text( - _walletOptions.isDefaultWallet - ? 'Ce portefeuille est celui par defaut' - : 'Définir comme portefeuille par défaut', - style: TextStyle( - fontSize: 20, - color: _walletOptions.isDefaultWallet - ? Colors.grey[500] - : Colors.black)), - ]))), - SizedBox(height: 17 * ratio), - if (!_walletOptions.isDefaultWallet) - InkWell( - key: const Key('deleteWallet'), - onTap: !_walletOptions.isDefaultWallet - ? () async { - await _walletOptions.deleteWallet( - context, cesiumWallet); - WidgetsBinding.instance.addPostFrameCallback((_) { - _myWalletProvider.listWallets = - _myWalletProvider - .readAllWallets(_currentChest); - _myWalletProvider.rebuildWidget(); - }); - } - : null, - child: Row(children: [ - const SizedBox(width: 33), - Image.asset( - 'assets/walletOptions/trash.png', - ), - const SizedBox(width: 14), - const Text('Supprimer ce portefeuille', - style: TextStyle( - fontSize: 20, color: Color(0xffD80000))), - ])), - ]), - ), - ), - )); - } + onPressed: () { + Clipboard.setData(ClipboardData( + text: _walletOptions.pubkey.text)); + _walletOptions.snackCopyKey(ctx); + }, + child: Row(children: [ + Image.asset( + 'assets/walletOptions/copy-white.png', + ), + const SizedBox(width: 7), + Text('Copier', + style: TextStyle( + fontSize: 15, color: Colors.grey[50])) + ]))), + ]))), + SizedBox(height: 10 * ratio), + InkWell( + key: const Key('displayHistory'), + onTap: () { + _historyProvider.isPubkey(ctx, _walletOptions.pubkey.text, + goHistory: true); + }, + child: SizedBox( + height: 50, + child: Row(children: [ + const SizedBox(width: 30), + Image.asset( + 'assets/walletOptions/clock.png', + ), + const SizedBox(width: 12), + const Text('Historique des transactions', + style: TextStyle(fontSize: 20, color: Colors.black)), + ]))), + SizedBox(height: 12 * ratio), + InkWell( + key: const Key('deleteWallet'), + onTap: () async { + await _chestProvider.deleteChest(context, cesiumWallet); + }, + child: Row(children: [ + const SizedBox(width: 33), + Image.asset( + 'assets/walletOptions/trash.png', + ), + const SizedBox(width: 14), + const Text('Supprimer ce coffre', + style: TextStyle(fontSize: 20, color: Color(0xffD80000))), + ])), + ]), + ), + ), + ); } diff --git a/lib/screens/myWallets/choose_chest.dart b/lib/screens/myWallets/choose_chest.dart index c6d78a7..d24e37e 100644 --- a/lib/screens/myWallets/choose_chest.dart +++ b/lib/screens/myWallets/choose_chest.dart @@ -45,7 +45,7 @@ class _ChooseChestState extends State { options: CarouselOptions( height: 210, onPageChanged: (index, reason) { - currentChest = index; + currentChest = chestBox.toMap().keys.toList()[index]; setState(() {}); }, enableInfiniteScroll: false, @@ -57,10 +57,15 @@ class _ChooseChestState extends State { return Builder( builder: (BuildContext context) { return Column(children: [ - Image.asset( - 'assets/chests/${i.value.imageName}', - height: 150, - ), + i.value.imageFile == null + ? Image.asset( + 'assets/chests/${i.value.imageName}', + height: 150, + ) + : Image.file( + i.value.imageFile, + height: 150, + ), const SizedBox(height: 30), Text( i.value.name, @@ -71,28 +76,30 @@ class _ChooseChestState extends State { ); }).toList(), ), - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: chestBox.toMap().entries.map((entry) { - return GestureDetector( - onTap: () => - buttonCarouselController.animateToPage(entry.key), - child: Container( - width: 12.0, - height: 12.0, - margin: const EdgeInsets.symmetric( - vertical: 8.0, horizontal: 4.0), - decoration: BoxDecoration( - shape: BoxShape.circle, - color: (Theme.of(context).brightness == Brightness.dark - ? Colors.white - : Colors.black) - .withOpacity( - currentChest == entry.key ? 0.9 : 0.4)), - ), - ); - }).toList(), - ), + if (chestBox.values.toList().length > 1) + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: chestBox.toMap().entries.map((entry) { + return GestureDetector( + onTap: () => + buttonCarouselController.animateToPage(entry.key), + child: Container( + width: 12.0, + height: 12.0, + margin: const EdgeInsets.symmetric( + vertical: 8.0, horizontal: 4.0), + decoration: BoxDecoration( + shape: BoxShape.circle, + color: + (Theme.of(context).brightness == Brightness.dark + ? Colors.white + : Colors.black) + .withOpacity( + currentChest == entry.key ? 0.9 : 0.4)), + ), + ); + }).toList(), + ), SizedBox(height: 80 * ratio), SizedBox( width: 400, diff --git a/lib/screens/myWallets/unlocking_wallet.dart b/lib/screens/myWallets/unlocking_wallet.dart index 0db74a0..65c1b5f 100644 --- a/lib/screens/myWallets/unlocking_wallet.dart +++ b/lib/screens/myWallets/unlocking_wallet.dart @@ -23,7 +23,6 @@ class UnlockingWallet extends StatelessWidget { // ignore: close_sinks StreamController errorController; final formKey = GlobalKey(); - bool hasError = false; var pinColor = const Color(0xffF9F9F1); var walletPin = ''; String resultPay; @@ -56,10 +55,15 @@ class UnlockingWallet extends StatelessWidget { child: Column(children: [ SizedBox(height: isTall ? 80 : 20), Row(mainAxisAlignment: MainAxisAlignment.center, children: [ - Image.asset( - 'assets/chests/${currentChest.imageName}', - height: isTall ? 130 : 100, - ), + currentChest.imageFile == null + ? Image.asset( + 'assets/chests/${currentChest.imageName}', + width: isTall ? 130 : 100, + ) + : Image.file( + currentChest.imageFile, + width: isTall ? 130 : 100, + ), const SizedBox(width: 5), SizedBox( width: 250, @@ -123,11 +127,14 @@ class UnlockingWallet extends StatelessWidget { Provider.of(context); HistoryProvider _historyProvider = Provider.of(context); + FocusNode pinFocus = FocusNode(); + return Form( key: formKey, child: Padding( padding: EdgeInsets.symmetric(vertical: 5 * ratio, horizontal: 30), child: PinCodeTextField( + focusNode: pinFocus, autoFocus: true, appContext: context, pastedTextStyle: TextStyle( @@ -152,7 +159,7 @@ class UnlockingWallet extends StatelessWidget { borderRadius: BorderRadius.circular(5), fieldHeight: 50 * ratio, fieldWidth: 50, - activeFillColor: hasError ? Colors.blueAccent : Colors.black, + activeFillColor: Colors.black, ), cursorColor: Colors.black, animationDuration: const Duration(milliseconds: 300), @@ -180,9 +187,9 @@ class UnlockingWallet extends StatelessWidget { if (resultWallet == 'bad') { errorController.add(ErrorAnimationType .shake); // Triggering error shake animation - hasError = true; pinColor = Colors.red[600]; _walletOptions.reloadBuild(); + pinFocus.requestFocus(); } else { pinColor = Colors.green[400]; // await Future.delayed(Duration(milliseconds: 50)); diff --git a/lib/screens/myWallets/wallet_options.dart b/lib/screens/myWallets/wallet_options.dart index 0097057..fc1dc99 100644 --- a/lib/screens/myWallets/wallet_options.dart +++ b/lib/screens/myWallets/wallet_options.dart @@ -1,3 +1,4 @@ +import 'dart:io'; import 'dart:ui'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; @@ -46,13 +47,10 @@ class WalletOptions extends StatelessWidget { _nbrLinesName = 3; } - _walletOptions.walletID = [0, wallet.number]; - WalletData defaultWallet = _myWalletProvider.getDefaultWallet(_currentChest); - _walletOptions.isDefaultWallet = - (defaultWallet.number == _walletOptions.walletID[1]); + _walletOptions.isDefaultWallet = (defaultWallet.number == wallet.id()[1]); int currentChest = _myWalletProvider.getCurrentChest(); @@ -107,15 +105,30 @@ class WalletOptions extends StatelessWidget { const SizedBox(width: 25), InkWell( onTap: () async { - await _walletOptions.changeAvatar(); + File newAvatar = + await _walletOptions.changeAvatar(); + if (newAvatar != null) { + wallet.imageFile = newAvatar; + } + _walletOptions.reloadBuild(); }, - child: Image.asset( - 'assets/avatars/${wallet.imageName}', - width: 110, - )), + child: wallet.imageFile == null + ? Image.asset( + 'assets/avatars/${wallet.imageName}', + width: 110, + ) + : Image.file( + wallet.imageFile, + width: 110, + )), InkWell( onTap: () async { - await _walletOptions.changeAvatar(); + File newAvatar = + await _walletOptions.changeAvatar(); + if (newAvatar != null) { + wallet.imageFile = newAvatar; + } + _walletOptions.reloadBuild(); }, child: Column(children: [ Image.asset( @@ -227,8 +240,9 @@ class WalletOptions extends StatelessWidget { InkWell( key: const Key('renameWallet'), onTap: () async { - _isNewNameValid = _walletOptions - .editWalletName(_walletOptions.walletID); + _isNewNameValid = + _walletOptions.editWalletName(wallet.id(), + isCesium: false); await Future.delayed( const Duration(milliseconds: 30)); _walletOptions.walletNameFocus.requestFocus(); diff --git a/lib/screens/myWallets/wallets_home.dart b/lib/screens/myWallets/wallets_home.dart index 91a0768..453382e 100644 --- a/lib/screens/myWallets/wallets_home.dart +++ b/lib/screens/myWallets/wallets_home.dart @@ -7,6 +7,7 @@ import 'package:gecko/models/wallet_data.dart'; import 'package:gecko/models/wallet_options.dart'; import 'package:flutter/material.dart'; import 'package:gecko/screens/common_elements.dart'; +import 'package:gecko/screens/myWallets/cesium_wallet_options.dart'; import 'package:gecko/screens/myWallets/choose_chest.dart'; import 'package:gecko/screens/myWallets/wallet_options.dart'; import 'package:gecko/screens/onBoarding/0_no_keychain_found.dart'; @@ -62,18 +63,18 @@ class WalletsHome extends StatelessWidget { child: !isWalletsExists ? const NoKeyChainScreen() : _currentChest.isCesium - ? cesiumWalletOptions(context) + ? cesiumWalletOptions(context, _currentChest) : myWalletsTiles(context), ), ), ); } - Widget cesiumWalletOptions(BuildContext context) { - return Column(children: const [ - Center(child: Text('This is a Cesium wallet')), - ]); - } + // Widget cesiumWalletOptions(BuildContext context) { + // return Column(children: const [ + // Center(child: Text('This is a Cesium wallet')), + // ]); + // } Widget chestOptions(BuildContext context) { return Column(children: [ @@ -214,11 +215,17 @@ class WalletsHome extends StatelessWidget { child: // SvgPicture.asset('assets/chopp-gecko2.png', // semanticsLabel: 'Gecko', height: 48), - Image.asset( - 'assets/avatars/${_repository.imageName}', - alignment: Alignment.bottomCenter, - scale: 0.5, - ), + _repository.imageFile == null + ? Image.asset( + 'assets/avatars/${_repository.imageName}', + alignment: Alignment.bottomCenter, + scale: 0.5, + ) + : Image.file( + _repository.imageFile, + alignment: Alignment.bottomCenter, + scale: 0.5, + ), )), // balanceBuilder(context, _walletOptions.pubkey.text), ListTile( diff --git a/pubspec.lock b/pubspec.lock index 97d22f2..49c04fe 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -176,6 +176,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.15.0" + confirm_dialog: + dependency: "direct main" + description: + name: confirm_dialog + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.0" connectivity_plus: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 02d1c66..df55520 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -56,6 +56,7 @@ dependencies: assorted_layout_widgets: ^5.2.1 carousel_slider: ^4.0.0 flutter_lints: ^1.0.4 + confirm_dialog: ^1.0.0 flutter_icons: android: "ic_launcher" @@ -79,6 +80,7 @@ flutter: - images/ - config/gva_endpoints.json - assets/ + - assets/customs/ - assets/avatars/ - assets/chests/ - assets/icon/ diff --git a/test_driver/app_test.dart b/test_driver/app_test.dart index 72a15f9..09de003 100644 --- a/test_driver/app_test.dart +++ b/test_driver/app_test.dart @@ -1,8 +1,8 @@ -// Imports the Flutter Driver API. +// ignore_for_file: avoid_print + import 'dart:async'; import 'dart:io'; import 'package:flutter_driver/flutter_driver.dart'; -import 'package:gecko/globals.dart'; import 'package:test/test.dart'; // import 'package:flutter/services.dart'; @@ -71,13 +71,8 @@ void main() { } // Create a derivation - Future createDerivation(String _name) async { + Future createDerivation() async { await tapOn('addDerivation'); - await sleep(100); - - await driver.enterText(_name); - - await tapOn('validDerivation'); await sleep(300); } @@ -109,7 +104,7 @@ void main() { await sleep(300); await tapOn('generateKeychain'); while (await getText('generatedPin') == '') { - log.i('Waiting for pin code generation...'); + print('Waiting for pin code generation...'); await sleep(100); } pinCode = await getText('generatedPin'); @@ -172,7 +167,7 @@ void main() { await tapOn('goStep7'); while (await getText('word1') == '...') { - log.i('Waiting for Mnemonic generation...'); + print('Waiting for Mnemonic generation...'); await sleep(100); } @@ -226,7 +221,7 @@ void main() { await tapOn('goStep11'); while (await getText('generatedPin') == '') { - log.i('Waiting for pin code generation...'); + print('Waiting for pin code generation...'); await sleep(100); } @@ -258,7 +253,7 @@ void main() { {timeout = const Duration(seconds: 2)}) async { await tapOn('goWalletHome'); - expect(await getText('myWallets'), "Mes portefeuilles"); + expect(await getText('myWallets'), "Coffre à Ğecko"); await sleep(300); // Go to first derivation and rename it @@ -281,10 +276,10 @@ void main() { {timeout = const Duration(seconds: 2)}) async { await driver.waitFor(find.text('Renommage wallet 1'), timeout: timeout); // Add a second derivation - await createDerivation('Derivation 2'); + await createDerivation(); // Go to second derivation options - await driver.tap(find.text('Derivation 2')); + await driver.tap(find.text('Portefeuille 2')); await sleep(100); // Test options @@ -305,14 +300,14 @@ void main() { await goBack(); // Add a third derivation - await createDerivation('Derivation 3'); + await createDerivation(); // Add a fourth derivation - await createDerivation('Derivation 4'); + await createDerivation(); await sleep(50); // Go to third derivation options - await driver.tap(find.text('Derivation 3')); + await driver.tap(find.text('Portefeuille 3')); await sleep(100); await tapOn('displayBalance'); @@ -323,10 +318,10 @@ void main() { test('My wallets - Extra tests', ( {timeout = const Duration(seconds: 2)}) async { // Add derivation 5,6 and 7 - await driver.waitFor(find.text('Derivation 4'), timeout: timeout); - await createDerivation('Derivation 5'); - await createDerivation('Derivation 6'); - await createDerivation('Derivation 7'); + await driver.waitFor(find.text('Portefeuille 4'), timeout: timeout); + await createDerivation(); + await createDerivation(); + await createDerivation(); // Go home and come back to my wallets view await goBack(); @@ -338,12 +333,12 @@ void main() { await sleep(200); // Go to derivation 6 and delete it - await driver.tap(find.text('Derivation 6')); + await driver.tap(find.text('Portefeuille 6')); await sleep(100); await deleteWallet(true); // Go to 2nd derivation and check if it's de default - await driver.tap(find.text('Derivation 2')); + await driver.tap(find.text('Portefeuille 2')); await driver.waitFor(find.text('Ce portefeuille est celui par defaut')); await tapOn('setDefaultWallet'); await sleep(100); @@ -369,43 +364,44 @@ void main() { await sleep(400); await goBack(); await driver.waitFor(find.text('Renommage wallet 2')); - await createDerivation('Derivation 8'); await driver.scrollIntoView(find.text('+')); - await createDerivation('Derivation 9'); - await createDerivation('Derivation 10'); + await createDerivation(); + await createDerivation(); await driver.scrollIntoView(find.text('+')); - await createDerivation('Derivation 11'); - await createDerivation('Derivation 12'); + await createDerivation(); + await createDerivation(); await driver.scrollIntoView(find.text('+')); - await createDerivation('Derivation 13'); - await createDerivation('Derivation 14'); + await createDerivation(); + await createDerivation(); await driver.scrollIntoView(find.text('+')); - await createDerivation('Derivation 15'); - await createDerivation('Derivation 16'); + await createDerivation(); + await createDerivation(); await driver.scrollIntoView(find.text('+')); - await createDerivation('Derivation 17'); - await createDerivation('Derivation 18'); + await createDerivation(); + await createDerivation(); await driver.scrollIntoView(find.text('+')); - await createDerivation('Derivation 19'); - await createDerivation('Derivation 20'); + await createDerivation(); + await createDerivation(); + await driver.scrollIntoView(find.text('+')); + await createDerivation(); await sleep(400); // Scroll the wallet screen until Derivation 20 and open it await driver.scrollUntilVisible( find.byValueKey('listWallets'), - find.text('Derivation 20'), + find.text('Portefeuille 20'), dyScroll: -300.0, ); - await driver.waitFor(find.text('Derivation 20')); + await driver.waitFor(find.text('Portefeuille 20')); await sleep(400); - await driver.tap(find.text('Derivation 20')); + await driver.tap(find.text('Portefeuille 20')); await tapOn('copyPubkey'); }); test('Search - Search Pi profile, navigate in history transactions', ( {timeout = const Duration(seconds: 2)}) async { - await driver.waitFor(find.text('Derivation 20'), timeout: timeout); + await driver.waitFor(find.text('Portefeuille 20'), timeout: timeout); await goBack(); await goBack(); await sleep(200); @@ -448,7 +444,7 @@ void main() { await sleep(200); await driver.enterText(pincode); await sleep(100); - await createDerivation('Derivation 2'); + await createDerivation(); await sleep(100); await driver.tap(find.text('Fast wallet')); await driver.waitFor(find.text('Fast wallet'));