Merge branch 'derivationsDetection'

This commit is contained in:
poka 2022-06-07 22:17:48 +02:00
commit 86467c06f3
6 changed files with 180 additions and 53 deletions

View File

@ -10,6 +10,7 @@ import 'package:gecko/models/wallet_data.dart';
import 'package:gecko/providers/substrate_sdk.dart'; import 'package:gecko/providers/substrate_sdk.dart';
import 'package:pdf/pdf.dart'; import 'package:pdf/pdf.dart';
import 'package:pdf/widgets.dart' as pw; import 'package:pdf/widgets.dart' as pw;
import 'package:polkawallet_sdk/api/apiKeyring.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import "package:unorm_dart/unorm_dart.dart" as unorm; import "package:unorm_dart/unorm_dart.dart" as unorm;
@ -21,6 +22,7 @@ class GenerateWalletsProvider with ChangeNotifier {
FocusNode walletNameFocus = FocusNode(); FocusNode walletNameFocus = FocusNode();
Color? askedWordColor = Colors.black; Color? askedWordColor = Colors.black;
bool isAskedWordValid = false; bool isAskedWordValid = false;
int scanedWalletNumber = -1;
late int nbrWord; late int nbrWord;
String? nbrWordAlpha; String? nbrWordAlpha;
@ -55,8 +57,7 @@ class GenerateWalletsProvider with ChangeNotifier {
TextEditingController cellController11 = TextEditingController(); TextEditingController cellController11 = TextEditingController();
bool isFirstTimeSentenceComplete = true; bool isFirstTimeSentenceComplete = true;
Future storeHDWChest( Future storeHDWChest(BuildContext context) async {
String address, String _name, BuildContext context) async {
int chestNumber = chestBox.isEmpty ? 0 : chestBox.keys.last + 1; int chestNumber = chestBox.isEmpty ? 0 : chestBox.keys.last + 1;
String chestName; String chestName;
@ -75,16 +76,6 @@ class GenerateWalletsProvider with ChangeNotifier {
await chestBox.add(thisChest); await chestBox.add(thisChest);
int? chestKey = chestBox.keys.last; 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); await configBox.put('currentChest', chestKey);
notifyListeners(); notifyListeners();
} }
@ -271,13 +262,25 @@ class GenerateWalletsProvider with ChangeNotifier {
return _wordsList; return _wordsList;
} }
bool isBipWord(String word) { bool isBipWord(String word, [bool checkRedondance = true]) {
bool isValid = false;
notifyListeners(); notifyListeners();
// Needed for bad encoding of UTF-8 // Needed for bad encoding of UTF-8
word = word.replaceAll('é', ''); word = word.replaceAll('é', '');
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)) {
isValid = nbrMatch == 0 ? true : false;
if (checkRedondance) nbrMatch = nbrMatch + 1;
}
}
}
return isValid;
} }
bool isBipWordsList(List<String> words) { bool isBipWordsList(List<String> words) {
@ -349,7 +352,7 @@ class GenerateWalletsProvider with ChangeNotifier {
cellController11 cellController11
]; ];
for (var word in sentence!.text!.split(' ')) { for (var word in sentence!.text!.split(' ')) {
bool isValid = isBipWord(word); bool isValid = isBipWord(word, false);
if (isValid) { if (isValid) {
cells[nbr].text = word; cells[nbr].text = word;
@ -361,4 +364,84 @@ class GenerateWalletsProvider with ChangeNotifier {
void reloadBuild() { void reloadBuild() {
notifyListeners(); notifyListeners();
} }
Future<bool> scanDerivations(BuildContext context,
{int numberScan = 20}) async {
SubstrateSdk _sub = Provider.of<SubstrateSdk>(context, listen: false);
final ss58 = _sub.ss58;
final currentChestNumber = configBox.get('currentChest');
bool isAlive = false;
scanedWalletNumber = 0;
notifyListeners();
final hasRoot = await scanRootBalance(_sub, currentChestNumber);
if (hasRoot) {
scanedWalletNumber = 1;
isAlive = true;
}
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');
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<bool> 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;
}
}
} }

View File

@ -102,8 +102,10 @@ class RestoreChest extends StatelessWidget {
context, context,
FaderTransition( FaderTransition(
page: skipIntro page: skipIntro
? const OnboardingStepNine() ? const OnboardingStepNine(
: const OnboardingStepSeven(), scanDerivation: true)
: const OnboardingStepSeven(
scanDerivation: true),
isFast: true), isFast: true),
); );
} else { } else {
@ -123,24 +125,32 @@ class RestoreChest extends StatelessWidget {
Column(children: [ Column(children: [
const SizedBox(height: 20), const SizedBox(height: 20),
SizedBox( SizedBox(
width: 150, width: 190,
height: 50, height: 60,
child: ElevatedButton( child: ElevatedButton(
style: ElevatedButton.styleFrom( style: ElevatedButton.styleFrom(
elevation: 4, elevation: 4,
primary: yellowC, // background primary: yellowC, // background
onPrimary: Colors.black, // foreground onPrimary: Colors.black, // foreground
), ),
onPressed: () { onPressed: () {
genW.pasteMnemonic(context); genW.pasteMnemonic(context);
}, },
child: const Text( child: Row(
'Coller depuis le\npresse-papier', children: const [
textAlign: TextAlign.center, Icon(
style: Icons.content_paste_go,
TextStyle(fontSize: 16, fontWeight: FontWeight.w400), size: 25,
), ),
), SizedBox(width: 10),
Text(
'Coller depuis le\npresse-papier',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 17, fontWeight: FontWeight.w400),
),
],
)),
) )
]) ])
]), ]),

View File

@ -4,6 +4,7 @@ import 'dart:async';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:gecko/globals.dart'; import 'package:gecko/globals.dart';
import 'package:gecko/models/wallet_data.dart';
import 'package:gecko/providers/generate_wallets.dart'; import 'package:gecko/providers/generate_wallets.dart';
import 'package:gecko/providers/my_wallets.dart'; import 'package:gecko/providers/my_wallets.dart';
import 'package:gecko/providers/substrate_sdk.dart'; import 'package:gecko/providers/substrate_sdk.dart';
@ -15,10 +16,10 @@ import 'package:provider/provider.dart';
// ignore: must_be_immutable // ignore: must_be_immutable
class OnboardingStepTen extends StatelessWidget { class OnboardingStepTen extends StatelessWidget {
OnboardingStepTen({ OnboardingStepTen({Key? validationKey, this.scanDerivation = false})
Key? validationKey, : super(key: validationKey);
}) : super(key: validationKey);
final bool scanDerivation;
final formKey = GlobalKey<FormState>(); final formKey = GlobalKey<FormState>();
Color? pinColor = const Color(0xFFA4B600); Color? pinColor = const Color(0xFFA4B600);
bool hasError = false; bool hasError = false;
@ -58,6 +59,20 @@ class OnboardingStepTen extends StatelessWidget {
style: TextStyle(fontSize: 16 * ratio)) style: TextStyle(fontSize: 16 * ratio))
]), ]),
SizedBox(height: isTall ? 80 : 20), 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), pinForm(context, _walletOptions, _pinLenght, 1, 2),
InkWell( InkWell(
onTap: () { onTap: () {
@ -153,18 +168,32 @@ class OnboardingStepTen extends StatelessWidget {
log.d(_pin + ' || ' + _generateWalletProvider.pin.text); log.d(_pin + ' || ' + _generateWalletProvider.pin.text);
if (_pin.toUpperCase() == _generateWalletProvider.pin.text) { if (_pin.toUpperCase() == _generateWalletProvider.pin.text) {
pinColor = Colors.green[500]; pinColor = Colors.green[500];
final address = await _sub.importAccount(
fromMnemonic: true, await _generateWalletProvider.storeHDWChest(context);
mnemonic: _generateWalletProvider.generatedMnemonic!, bool isAlive = false;
derivePath: '//2', if (scanDerivation) {
password: _generateWalletProvider.pin.text); isAlive = await _generateWalletProvider
await _generateWalletProvider.storeHDWChest( .scanDerivations(context, numberScan: 20);
address, 'Mon portefeuille courant', context); }
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.readAllWallets(_currentChest);
// scheduleMicrotask(() {
// _walletOptions.reloadBuild();
_myWalletProvider.rebuildWidget(); _myWalletProvider.rebuildWidget();
// });
_generateWalletProvider.generatedMnemonic = ''; _generateWalletProvider.generatedMnemonic = '';
_myWalletProvider.resetPinCode(); _myWalletProvider.resetPinCode();
Navigator.push( Navigator.push(

View File

@ -6,7 +6,8 @@ import 'package:gecko/screens/common_elements.dart';
import 'package:gecko/screens/onBoarding/8.dart'; import 'package:gecko/screens/onBoarding/8.dart';
class OnboardingStepSeven extends StatelessWidget { 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 @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -35,7 +36,7 @@ class OnboardingStepSeven extends StatelessWidget {
], ],
'coffre-fort-code-secret-dans-telephone.png', 'coffre-fort-code-secret-dans-telephone.png',
'>', '>',
const OnboardingStepEight(), OnboardingStepEight(scanDerivation: scanDerivation),
6, 6,
boxHeight: 400), boxHeight: 400),
), ),

View File

@ -6,7 +6,9 @@ import 'package:gecko/screens/common_elements.dart';
import 'package:gecko/screens/onBoarding/9.dart'; import 'package:gecko/screens/onBoarding/9.dart';
class OnboardingStepEight extends StatelessWidget { 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 @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -41,7 +43,7 @@ class OnboardingStepEight extends StatelessWidget {
], ],
'coffre-fort-protege-les-portefeuilles.png', 'coffre-fort-protege-les-portefeuilles.png',
'>', '>',
const OnboardingStepNine(), OnboardingStepNine(scanDerivation: scanDerivation),
7), 7),
), ),
); );

View File

@ -9,7 +9,9 @@ import 'package:provider/provider.dart';
// ignore: must_be_immutable // ignore: must_be_immutable
class OnboardingStepNine extends StatelessWidget { 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 @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -103,7 +105,7 @@ class OnboardingStepNine extends StatelessWidget {
))), ))),
SizedBox(height: 22 * ratio), SizedBox(height: 22 * ratio),
common.nextButton(context, "J'ai noté mon code secret", common.nextButton(context, "J'ai noté mon code secret",
OnboardingStepTen(), false), OnboardingStepTen(scanDerivation: scanDerivation), false),
SizedBox(height: 35 * ratio), SizedBox(height: 35 * ratio),
]), ]),
)); ));