From d7fcf0636f40e6ba50a05ff829689146533ad78b Mon Sep 17 00:00:00 2001 From: poka Date: Tue, 7 Jun 2022 01:10:40 +0200 Subject: [PATCH 1/5] wip: try to import existing wallets --- lib/providers/generate_wallets.dart | 23 +++++++++++++++++++++++ lib/screens/myWallets/restore_chest.dart | 4 ++-- lib/screens/onBoarding/10.dart | 13 +++++++------ lib/screens/onBoarding/7.dart | 5 +++-- lib/screens/onBoarding/8.dart | 6 ++++-- lib/screens/onBoarding/9.dart | 6 ++++-- 6 files changed, 43 insertions(+), 14 deletions(-) diff --git a/lib/providers/generate_wallets.dart b/lib/providers/generate_wallets.dart index d4560d0..47150f9 100644 --- a/lib/providers/generate_wallets.dart +++ b/lib/providers/generate_wallets.dart @@ -10,6 +10,7 @@ import 'package:gecko/models/wallet_data.dart'; import 'package:gecko/providers/substrate_sdk.dart'; import 'package:pdf/pdf.dart'; import 'package:pdf/widgets.dart' as pw; +import 'package:polkawallet_sdk/api/apiKeyring.dart'; import 'package:provider/provider.dart'; import "package:unorm_dart/unorm_dart.dart" as unorm; @@ -361,4 +362,26 @@ class GenerateWalletsProvider with ChangeNotifier { void reloadBuild() { notifyListeners(); } + + Future scanDerivations(BuildContext context, {int number = 10}) async { + SubstrateSdk _sub = Provider.of(context, listen: false); + final ss58 = _sub.ss58; + + // for () + // final addressData = await _sub.sdk.api.keyring.addressFromMnemonic(ss58, + // cryptoType: CryptoType.sr25519, + // mnemonic: generatedMnemonic!, + // derivePath: '//4'); + + // final balance = await _sub.getBalance(addressData.address!); + + // log.d(balance); + // if (balance != 0) { + // await _sub.importAccount( + // mnemonic: '', + // fromMnemonic: true, + // derivePath: '//4', + // password: pin.text); + // } + } } diff --git a/lib/screens/myWallets/restore_chest.dart b/lib/screens/myWallets/restore_chest.dart index 212e7b3..60a49e8 100644 --- a/lib/screens/myWallets/restore_chest.dart +++ b/lib/screens/myWallets/restore_chest.dart @@ -102,8 +102,8 @@ class RestoreChest extends StatelessWidget { context, FaderTransition( page: skipIntro - ? const OnboardingStepNine() - : const OnboardingStepSeven(), + ? const OnboardingStepNine(scanDerivation: true) + : const OnboardingStepSeven(scanDerivation: true), isFast: true), ); } else { diff --git a/lib/screens/onBoarding/10.dart b/lib/screens/onBoarding/10.dart index a00e5d0..f736e7f 100644 --- a/lib/screens/onBoarding/10.dart +++ b/lib/screens/onBoarding/10.dart @@ -15,10 +15,10 @@ import 'package:provider/provider.dart'; // ignore: must_be_immutable class OnboardingStepTen extends StatelessWidget { - OnboardingStepTen({ - Key? validationKey, - }) : super(key: validationKey); + OnboardingStepTen({Key? validationKey, this.scanDerivation = false}) + : super(key: validationKey); + final bool scanDerivation; final formKey = GlobalKey(); Color? pinColor = const Color(0xFFA4B600); bool hasError = false; @@ -161,10 +161,11 @@ class OnboardingStepTen extends StatelessWidget { await _generateWalletProvider.storeHDWChest( address, 'Mon portefeuille courant', context); _myWalletProvider.readAllWallets(_currentChest); - // scheduleMicrotask(() { - // _walletOptions.reloadBuild(); _myWalletProvider.rebuildWidget(); - // }); + + await _generateWalletProvider.scanDerivations(context, + number: 20); + _generateWalletProvider.generatedMnemonic = ''; _myWalletProvider.resetPinCode(); Navigator.push( diff --git a/lib/screens/onBoarding/7.dart b/lib/screens/onBoarding/7.dart index b430bf0..676331a 100644 --- a/lib/screens/onBoarding/7.dart +++ b/lib/screens/onBoarding/7.dart @@ -6,7 +6,8 @@ import 'package:gecko/screens/common_elements.dart'; import 'package:gecko/screens/onBoarding/8.dart'; class OnboardingStepSeven extends StatelessWidget { - const OnboardingStepSeven({Key? key}) : super(key: key); + const OnboardingStepSeven({Key? key, this.scanDerivation = false}) : super(key: key); + final bool scanDerivation; @override Widget build(BuildContext context) { @@ -35,7 +36,7 @@ class OnboardingStepSeven extends StatelessWidget { ], 'coffre-fort-code-secret-dans-telephone.png', '>', - const OnboardingStepEight(), + OnboardingStepEight(scanDerivation: scanDerivation), 6, boxHeight: 400), ), diff --git a/lib/screens/onBoarding/8.dart b/lib/screens/onBoarding/8.dart index 4bcb744..0b6555f 100644 --- a/lib/screens/onBoarding/8.dart +++ b/lib/screens/onBoarding/8.dart @@ -6,7 +6,9 @@ import 'package:gecko/screens/common_elements.dart'; import 'package:gecko/screens/onBoarding/9.dart'; class OnboardingStepEight extends StatelessWidget { - const OnboardingStepEight({Key? key}) : super(key: key); + const OnboardingStepEight({Key? key, this.scanDerivation = false}) + : super(key: key); + final bool scanDerivation; @override Widget build(BuildContext context) { @@ -41,7 +43,7 @@ class OnboardingStepEight extends StatelessWidget { ], 'coffre-fort-protege-les-portefeuilles.png', '>', - const OnboardingStepNine(), + OnboardingStepNine(scanDerivation: scanDerivation), 7), ), ); diff --git a/lib/screens/onBoarding/9.dart b/lib/screens/onBoarding/9.dart index 5dda878..16dbda0 100644 --- a/lib/screens/onBoarding/9.dart +++ b/lib/screens/onBoarding/9.dart @@ -9,7 +9,9 @@ import 'package:provider/provider.dart'; // ignore: must_be_immutable class OnboardingStepNine extends StatelessWidget { - const OnboardingStepNine({Key? key}) : super(key: key); + const OnboardingStepNine({Key? key, this.scanDerivation = false}) + : super(key: key); + final bool scanDerivation; @override Widget build(BuildContext context) { @@ -103,7 +105,7 @@ class OnboardingStepNine extends StatelessWidget { ))), SizedBox(height: 22 * ratio), common.nextButton(context, "J'ai noté mon code secret", - OnboardingStepTen(), false), + OnboardingStepTen(scanDerivation: scanDerivation), false), SizedBox(height: 35 * ratio), ]), )); From 3f75fa5c204a342e79f5a7fd067c93ce54e7c05e Mon Sep 17 00:00:00 2001 From: poka Date: Tue, 7 Jun 2022 19:06:46 +0200 Subject: [PATCH 2/5] fix: do not valid mnemonic word if others exist in import --- lib/providers/generate_wallets.dart | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/lib/providers/generate_wallets.dart b/lib/providers/generate_wallets.dart index 47150f9..9e4ec10 100644 --- a/lib/providers/generate_wallets.dart +++ b/lib/providers/generate_wallets.dart @@ -273,12 +273,25 @@ class GenerateWalletsProvider with ChangeNotifier { } bool isBipWord(String word) { + bool isValid = false; notifyListeners(); // Needed for bad encoding of UTF-8 word = word.replaceAll('é', 'é'); word = word.replaceAll('è', 'è'); - return bip39Words(appLang).contains(word.toLowerCase()); + + int nbrMatch = 0; + if (bip39Words(appLang).contains(word.toLowerCase())) { + for (var bipWord in bip39Words(appLang)) { + if (bipWord.startsWith(word)) { + log.d('ploppp : ' + nbrMatch.toString()); + isValid = nbrMatch == 0 ? true : false; + nbrMatch = nbrMatch + 1; + } + } + } + + return isValid; } bool isBipWordsList(List words) { From 4625fa1d70f213c38bac438719c8c1bd757dabf9 Mon Sep 17 00:00:00 2001 From: poka Date: Tue, 7 Jun 2022 19:15:11 +0200 Subject: [PATCH 3/5] fix the fix --- lib/providers/generate_wallets.dart | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/lib/providers/generate_wallets.dart b/lib/providers/generate_wallets.dart index 9e4ec10..2a0f57f 100644 --- a/lib/providers/generate_wallets.dart +++ b/lib/providers/generate_wallets.dart @@ -272,7 +272,7 @@ class GenerateWalletsProvider with ChangeNotifier { return _wordsList; } - bool isBipWord(String word) { + bool isBipWord(String word, [bool checkRedondance = true]) { bool isValid = false; notifyListeners(); @@ -284,9 +284,8 @@ class GenerateWalletsProvider with ChangeNotifier { if (bip39Words(appLang).contains(word.toLowerCase())) { for (var bipWord in bip39Words(appLang)) { if (bipWord.startsWith(word)) { - log.d('ploppp : ' + nbrMatch.toString()); isValid = nbrMatch == 0 ? true : false; - nbrMatch = nbrMatch + 1; + if (checkRedondance) nbrMatch = nbrMatch + 1; } } } @@ -363,7 +362,7 @@ class GenerateWalletsProvider with ChangeNotifier { cellController11 ]; for (var word in sentence!.text!.split(' ')) { - bool isValid = isBipWord(word); + bool isValid = isBipWord(word, false); if (isValid) { cells[nbr].text = word; From 263b99fb95e98348c9342818c38dd9b7a4a8e1e4 Mon Sep 17 00:00:00 2001 From: poka Date: Tue, 7 Jun 2022 21:36:57 +0200 Subject: [PATCH 4/5] Scan derivation on import is OK --- lib/providers/generate_wallets.dart | 102 ++++++++++++++++++++-------- lib/screens/onBoarding/10.dart | 48 ++++++++++--- 2 files changed, 113 insertions(+), 37 deletions(-) diff --git a/lib/providers/generate_wallets.dart b/lib/providers/generate_wallets.dart index 2a0f57f..ede8a80 100644 --- a/lib/providers/generate_wallets.dart +++ b/lib/providers/generate_wallets.dart @@ -22,6 +22,7 @@ class GenerateWalletsProvider with ChangeNotifier { FocusNode walletNameFocus = FocusNode(); Color? askedWordColor = Colors.black; bool isAskedWordValid = false; + int scanedWalletNumber = -1; late int nbrWord; String? nbrWordAlpha; @@ -56,8 +57,7 @@ class GenerateWalletsProvider with ChangeNotifier { TextEditingController cellController11 = TextEditingController(); bool isFirstTimeSentenceComplete = true; - Future storeHDWChest( - String address, String _name, BuildContext context) async { + Future storeHDWChest(BuildContext context) async { int chestNumber = chestBox.isEmpty ? 0 : chestBox.keys.last + 1; String chestName; @@ -76,16 +76,6 @@ class GenerateWalletsProvider with ChangeNotifier { await chestBox.add(thisChest); int? chestKey = chestBox.keys.last; - WalletData myWallet = WalletData( - version: dataVersion, - chest: chestKey, - address: address, - number: 0, - name: _name, - derivation: 2, - imageDefaultPath: '0.png'); - await walletBox.add(myWallet); - await configBox.put('currentChest', chestKey); notifyListeners(); } @@ -375,25 +365,83 @@ class GenerateWalletsProvider with ChangeNotifier { notifyListeners(); } - Future scanDerivations(BuildContext context, {int number = 10}) async { + Future scanDerivations(BuildContext context, + {int numberScan = 10}) async { SubstrateSdk _sub = Provider.of(context, listen: false); final ss58 = _sub.ss58; + final currentChestNumber = configBox.get('currentChest'); + bool isAlive = false; + scanedWalletNumber = 0; + notifyListeners(); - // for () - // final addressData = await _sub.sdk.api.keyring.addressFromMnemonic(ss58, - // cryptoType: CryptoType.sr25519, - // mnemonic: generatedMnemonic!, - // derivePath: '//4'); + final hasRoot = await scanRootBalance(_sub, currentChestNumber); + if (hasRoot) { + scanedWalletNumber = 1; + isAlive = true; + } - // final balance = await _sub.getBalance(addressData.address!); + for (var derivationNbr in [for (var i = 0; i < numberScan; i += 1) i]) { + final addressData = await _sub.sdk.api.keyring.addressFromMnemonic(ss58, + cryptoType: CryptoType.sr25519, + mnemonic: generatedMnemonic!, + derivePath: '//$derivationNbr'); - // log.d(balance); - // if (balance != 0) { - // await _sub.importAccount( - // mnemonic: '', - // fromMnemonic: true, - // derivePath: '//4', - // password: pin.text); - // } + final balance = await _sub.getBalance(addressData.address!); + + log.d(balance); + if (balance != 0) { + isAlive = true; + String walletName = scanedWalletNumber == 0 + ? 'Mon portefeuille courant' + : 'Portefeuille ${scanedWalletNumber + 1}'; + await _sub.importAccount( + mnemonic: '', + fromMnemonic: true, + derivePath: '//$derivationNbr', + password: pin.text); + + WalletData myWallet = WalletData( + version: dataVersion, + chest: currentChestNumber, + address: addressData.address!, + number: scanedWalletNumber, + name: walletName, + derivation: derivationNbr, + imageDefaultPath: '${scanedWalletNumber % 4}.png'); + await walletBox.add(myWallet); + scanedWalletNumber = scanedWalletNumber + 1; + } + } + scanedWalletNumber = -1; + notifyListeners(); + return isAlive; + } + + Future scanRootBalance( + SubstrateSdk _sub, int currentChestNumber) async { + final addressData = await _sub.sdk.api.keyring.addressFromMnemonic(ss58, + cryptoType: CryptoType.sr25519, mnemonic: generatedMnemonic!); + + final balance = await _sub.getBalance(addressData.address!); + + log.d(balance); + if (balance != 0) { + String walletName = 'Mon portefeuille racine'; + await _sub.importAccount( + mnemonic: '', fromMnemonic: true, password: pin.text); + + WalletData myWallet = WalletData( + version: dataVersion, + chest: currentChestNumber, + address: addressData.address!, + number: 0, + name: walletName, + derivation: -1, + imageDefaultPath: '0.png'); + await walletBox.add(myWallet); + return true; + } else { + return false; + } } } diff --git a/lib/screens/onBoarding/10.dart b/lib/screens/onBoarding/10.dart index f736e7f..f73f45a 100644 --- a/lib/screens/onBoarding/10.dart +++ b/lib/screens/onBoarding/10.dart @@ -4,6 +4,7 @@ import 'dart:async'; import 'package:flutter/services.dart'; import 'package:flutter/material.dart'; import 'package:gecko/globals.dart'; +import 'package:gecko/models/wallet_data.dart'; import 'package:gecko/providers/generate_wallets.dart'; import 'package:gecko/providers/my_wallets.dart'; import 'package:gecko/providers/substrate_sdk.dart'; @@ -58,6 +59,20 @@ class OnboardingStepTen extends StatelessWidget { style: TextStyle(fontSize: 16 * ratio)) ]), SizedBox(height: isTall ? 80 : 20), + Visibility( + visible: _generateWalletProvider.scanedWalletNumber != -1, + child: Padding( + padding: const EdgeInsets.only(bottom: 15), + child: SizedBox( + height: 22, + width: 22, + child: CircularProgressIndicator( + color: orangeC, + strokeWidth: 3, + ), + ), + ), + ), pinForm(context, _walletOptions, _pinLenght, 1, 2), InkWell( onTap: () { @@ -153,19 +168,32 @@ class OnboardingStepTen extends StatelessWidget { log.d(_pin + ' || ' + _generateWalletProvider.pin.text); if (_pin.toUpperCase() == _generateWalletProvider.pin.text) { pinColor = Colors.green[500]; - final address = await _sub.importAccount( - fromMnemonic: true, - mnemonic: _generateWalletProvider.generatedMnemonic!, - derivePath: '//2', - password: _generateWalletProvider.pin.text); - await _generateWalletProvider.storeHDWChest( - address, 'Mon portefeuille courant', context); + + await _generateWalletProvider.storeHDWChest(context); + bool isAlive = false; + if (scanDerivation) { + isAlive = await _generateWalletProvider + .scanDerivations(context, numberScan: 30); + } + if (!isAlive) { + final address = await _sub.importAccount( + fromMnemonic: true, + mnemonic: _generateWalletProvider.generatedMnemonic!, + derivePath: '//2', + password: _generateWalletProvider.pin.text); + WalletData myWallet = WalletData( + version: dataVersion, + chest: configBox.get('currentChest'), + address: address, + number: 0, + name: 'Mon portefeuille courant', + derivation: 2, + imageDefaultPath: '0.png'); + await walletBox.add(myWallet); + } _myWalletProvider.readAllWallets(_currentChest); _myWalletProvider.rebuildWidget(); - await _generateWalletProvider.scanDerivations(context, - number: 20); - _generateWalletProvider.generatedMnemonic = ''; _myWalletProvider.resetPinCode(); Navigator.push( From b7817a329907f6559e715ab5aac43fe298909d62 Mon Sep 17 00:00:00 2001 From: poka Date: Tue, 7 Jun 2022 22:16:56 +0200 Subject: [PATCH 5/5] improve paste mnemonic button; set numberScan to 20 --- lib/providers/generate_wallets.dart | 2 +- lib/screens/myWallets/restore_chest.dart | 48 ++++++++++++++---------- lib/screens/onBoarding/10.dart | 2 +- 3 files changed, 31 insertions(+), 21 deletions(-) diff --git a/lib/providers/generate_wallets.dart b/lib/providers/generate_wallets.dart index ede8a80..5b9c5f7 100644 --- a/lib/providers/generate_wallets.dart +++ b/lib/providers/generate_wallets.dart @@ -366,7 +366,7 @@ class GenerateWalletsProvider with ChangeNotifier { } Future scanDerivations(BuildContext context, - {int numberScan = 10}) async { + {int numberScan = 20}) async { SubstrateSdk _sub = Provider.of(context, listen: false); final ss58 = _sub.ss58; final currentChestNumber = configBox.get('currentChest'); diff --git a/lib/screens/myWallets/restore_chest.dart b/lib/screens/myWallets/restore_chest.dart index 60a49e8..2dc935d 100644 --- a/lib/screens/myWallets/restore_chest.dart +++ b/lib/screens/myWallets/restore_chest.dart @@ -102,8 +102,10 @@ class RestoreChest extends StatelessWidget { context, FaderTransition( page: skipIntro - ? const OnboardingStepNine(scanDerivation: true) - : const OnboardingStepSeven(scanDerivation: true), + ? const OnboardingStepNine( + scanDerivation: true) + : const OnboardingStepSeven( + scanDerivation: true), isFast: true), ); } else { @@ -123,24 +125,32 @@ class RestoreChest extends StatelessWidget { Column(children: [ const SizedBox(height: 20), SizedBox( - width: 150, - height: 50, + width: 190, + height: 60, child: ElevatedButton( - style: ElevatedButton.styleFrom( - elevation: 4, - primary: yellowC, // background - onPrimary: Colors.black, // foreground - ), - onPressed: () { - genW.pasteMnemonic(context); - }, - child: const Text( - 'Coller depuis le\npresse-papier', - textAlign: TextAlign.center, - style: - TextStyle(fontSize: 16, fontWeight: FontWeight.w400), - ), - ), + style: ElevatedButton.styleFrom( + elevation: 4, + primary: yellowC, // background + onPrimary: Colors.black, // foreground + ), + onPressed: () { + genW.pasteMnemonic(context); + }, + child: Row( + children: const [ + Icon( + Icons.content_paste_go, + size: 25, + ), + SizedBox(width: 10), + Text( + 'Coller depuis le\npresse-papier', + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 17, fontWeight: FontWeight.w400), + ), + ], + )), ) ]) ]), diff --git a/lib/screens/onBoarding/10.dart b/lib/screens/onBoarding/10.dart index f73f45a..d2e756d 100644 --- a/lib/screens/onBoarding/10.dart +++ b/lib/screens/onBoarding/10.dart @@ -173,7 +173,7 @@ class OnboardingStepTen extends StatelessWidget { bool isAlive = false; if (scanDerivation) { isAlive = await _generateWalletProvider - .scanDerivations(context, numberScan: 30); + .scanDerivations(context, numberScan: 20); } if (!isAlive) { final address = await _sub.importAccount(