gecko/lib/providers/generate_wallets.dart

459 lines
14 KiB
Dart
Raw Normal View History

2021-01-26 21:00:26 +01:00
import 'dart:math';
import 'dart:typed_data';
2022-05-04 19:00:09 +02:00
import 'package:durt/durt.dart' as durt;
2022-06-17 01:13:14 +02:00
import 'package:easy_localization/easy_localization.dart';
2021-01-26 21:00:26 +01:00
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:gecko/globals.dart';
2021-11-21 06:36:12 +01:00
import 'package:gecko/models/bip39_words.dart';
2021-11-14 19:21:20 +01:00
import 'package:gecko/models/chest_data.dart';
import 'package:gecko/models/wallet_data.dart';
2022-05-04 19:00:09 +02:00
import 'package:gecko/providers/substrate_sdk.dart';
import 'package:pdf/pdf.dart';
import 'package:pdf/widgets.dart' as pw;
2022-06-07 01:10:40 +02:00
import 'package:polkawallet_sdk/api/apiKeyring.dart';
2022-05-04 19:00:09 +02:00
import 'package:provider/provider.dart';
import "package:unorm_dart/unorm_dart.dart" as unorm;
2021-01-26 21:00:26 +01:00
class GenerateWalletsProvider with ChangeNotifier {
GenerateWalletsProvider();
// NewWallet generatedWallet;
2022-05-04 19:00:09 +02:00
durt.NewWallet? actualWallet;
2021-01-26 21:00:26 +01:00
FocusNode walletNameFocus = FocusNode();
2021-12-23 12:36:09 +01:00
Color? askedWordColor = Colors.black;
2021-01-26 21:00:26 +01:00
bool isAskedWordValid = false;
2022-06-07 21:36:57 +02:00
int scanedWalletNumber = -1;
2021-12-23 12:36:09 +01:00
late int nbrWord;
String? nbrWordAlpha;
2021-01-26 21:00:26 +01:00
2021-12-23 12:36:09 +01:00
String? generatedMnemonic;
bool walletIsGenerated = true;
2021-01-26 21:00:26 +01:00
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;
2022-05-04 19:00:09 +02:00
late durt.CesiumWallet cesiumWallet;
2021-11-21 06:36:12 +01:00
// Import Chest
TextEditingController cellController0 = TextEditingController();
TextEditingController cellController1 = TextEditingController();
TextEditingController cellController2 = TextEditingController();
TextEditingController cellController3 = TextEditingController();
TextEditingController cellController4 = TextEditingController();
TextEditingController cellController5 = TextEditingController();
TextEditingController cellController6 = TextEditingController();
TextEditingController cellController7 = TextEditingController();
TextEditingController cellController8 = TextEditingController();
TextEditingController cellController9 = TextEditingController();
TextEditingController cellController10 = TextEditingController();
TextEditingController cellController11 = TextEditingController();
bool isFirstTimeSentenceComplete = true;
2022-06-07 21:36:57 +02:00
Future storeHDWChest(BuildContext context) async {
int chestNumber = chestBox.isEmpty ? 0 : chestBox.keys.last + 1;
2021-11-09 04:22:04 +01:00
String chestName;
if (chestNumber == 0) {
2022-06-17 01:13:14 +02:00
chestName = 'geckoChest'.tr();
2021-11-09 04:22:04 +01:00
} else {
2022-06-17 01:13:14 +02:00
chestName = 'geckoChest'.tr() + '${chestNumber + 1}';
2021-11-09 04:22:04 +01:00
}
await configBox.put('currentChest', chestNumber);
2021-11-09 04:22:04 +01:00
ChestData thisChest = ChestData(
2021-11-14 04:33:59 +01:00
name: chestName,
defaultWallet: 0,
imageName: '${chestNumber % 8}.png',
);
2021-11-17 06:20:23 +01:00
await chestBox.add(thisChest);
2021-12-23 12:36:09 +01:00
int? chestKey = chestBox.keys.last;
2021-11-17 06:20:23 +01:00
await configBox.put('currentChest', chestKey);
notifyListeners();
2021-01-26 21:00:26 +01:00
}
void checkAskedWord(String inputWord, String _mnemo) {
final expectedWord = _mnemo.split(' ')[nbrWord];
final normInputWord = unorm.nfkd(inputWord);
log.i("Is $expectedWord equal to input $normInputWord ?");
if (expectedWord == normInputWord ||
inputWord == 'triche' ||
inputWord == '3.14') {
2021-04-02 12:05:37 +02:00
log.d('Word is OK');
2021-01-26 21:00:26 +01:00
isAskedWordValid = true;
askedWordColor = Colors.green[600];
// walletNameFocus.nextFocus();
notifyListeners();
2021-01-26 21:00:26 +01:00
} else {
isAskedWordValid = false;
}
// notifyListeners();
2021-01-26 21:00:26 +01:00
}
String removeDiacritics(String str) {
var withDia =
'ÀÁÂÃÄÅàáâãäåÒÓÔÕÕÖØòóôõöøÈÉÊËèéêëðÇçÐÌÍÎÏìíîïÙÚÛÜùúûüÑñŠšŸÿýŽž';
var withoutDia =
'AAAAAAaaaaaaOOOOOOOooooooEEEEeeeeeCcDIIIIiiiiUUUUuuuuNnSsYyyZz';
for (int i = 0; i < withDia.length; i++) {
str = str.replaceAll(withDia[i], withoutDia[i]);
}
return str;
}
int getRandomInt() {
2021-11-14 19:21:20 +01:00
var rng = Random();
2021-01-26 21:00:26 +01:00
return rng.nextInt(12);
}
2021-12-23 12:36:09 +01:00
String? intToString(int _nbr) {
Map nbrToString = {};
2022-06-18 00:48:07 +02:00
nbrToString[1] = '1th'.tr();
nbrToString[2] = '2th'.tr();
nbrToString[3] = '3th'.tr();
nbrToString[4] = '4th'.tr();
nbrToString[5] = '5th'.tr();
nbrToString[6] = '6th'.tr();
nbrToString[7] = '7th'.tr();
nbrToString[8] = '8th'.tr();
nbrToString[9] = '9th'.tr();
nbrToString[10] = '10th'.tr();
nbrToString[11] = '11th'.tr();
nbrToString[12] = '12th'.tr();
nbrWordAlpha = nbrToString[_nbr];
return nbrWordAlpha;
}
2021-01-26 21:00:26 +01:00
void nameChanged() {
notifyListeners();
}
2021-12-23 12:36:09 +01:00
String changePinCode({required bool reload}) {
2022-05-04 19:00:09 +02:00
pin.text = durt.randomSecretCode(pinLength);
if (reload) {
notifyListeners();
}
return pin.text;
2021-01-26 21:00:26 +01:00
}
2022-05-23 10:53:44 +02:00
Future<Uint8List> printWallet(AsyncSnapshot<List>? mnemoList) async {
final ByteData fontData =
await rootBundle.load("assets/OpenSans-Regular.ttf");
final pw.Font ttf = pw.Font.ttf(fontData.buffer.asByteData());
final pdf = pw.Document();
2022-05-23 10:53:44 +02:00
// const imageProvider = AssetImage('assets/icon/gecko_final.png');
// final geckoLogo = await flutterImageProvider(imageProvider);
pw.Widget arrayCell(dataWord) {
return pw.SizedBox(
width: 120,
child: pw.Column(children: <pw.Widget>[
pw.Text(
dataWord.split(':')[0],
style: pw.TextStyle(
fontSize: 15, color: const PdfColor(0.5, 0, 0), font: ttf),
),
pw.Text(
dataWord.split(':')[1],
style: pw.TextStyle(
fontSize: 20, color: const PdfColor(0, 0, 0), font: ttf),
),
pw.SizedBox(height: 10)
]),
);
}
pdf.addPage(
pw.Page(
pageFormat: PdfPageFormat.a4,
build: (context) {
2022-05-23 10:53:44 +02:00
return pw.Column(
// mainAxisAlignment: pw.MainAxisAlignment.center,
// mainAxisSize: pw.MainAxisSize.max,
// crossAxisAlignment: pw.CrossAxisAlignment.center,
children: <pw.Widget>[
pw.Row(children: <pw.Widget>[
arrayCell(mnemoList!.data![0]),
arrayCell(mnemoList.data![1]),
arrayCell(mnemoList.data![2]),
arrayCell(mnemoList.data![3]),
]),
pw.Row(children: <pw.Widget>[
arrayCell(mnemoList.data![4]),
arrayCell(mnemoList.data![5]),
arrayCell(mnemoList.data![6]),
arrayCell(mnemoList.data![7]),
]),
pw.Row(children: <pw.Widget>[
arrayCell(mnemoList.data![8]),
arrayCell(mnemoList.data![9]),
arrayCell(mnemoList.data![10]),
arrayCell(mnemoList.data![11])
]),
pw.Expanded(
child: pw.Align(
alignment: pw.Alignment.bottomCenter,
child: pw.Text(
"Gardez cette feuille préciseusement, à labri des lézards indiscrets.",
style: pw.TextStyle(fontSize: 15, font: ttf),
)))
],
);
},
),
);
return pdf.save();
}
Future<void> generateCesiumWalletPubkey(
String _cesiumID, String _cesiumPWD) async {
2022-05-04 19:00:09 +02:00
cesiumWallet = durt.CesiumWallet(_cesiumID, _cesiumPWD);
String _walletPubkey = cesiumWallet.pubkey;
cesiumPubkey.text = _walletPubkey;
2021-04-02 12:05:37 +02:00
log.d(_walletPubkey);
}
void cesiumIDisVisible() {
isCesiumIDVisible = !isCesiumIDVisible;
notifyListeners();
}
void cesiumPWDisVisible() {
isCesiumPWDVisible = !isCesiumPWDVisible;
notifyListeners();
}
2021-11-21 06:36:12 +01:00
void resetCesiumImportView() {
cesiumID.text = cesiumPWD.text = cesiumPubkey.text = pin.text = '';
canImport = isCesiumIDVisible = isCesiumPWDVisible = false;
actualWallet = null;
notifyListeners();
}
2022-05-04 19:00:09 +02:00
Future<List<String>> generateWordList(BuildContext context) async {
SubstrateSdk _sub = Provider.of<SubstrateSdk>(context, listen: false);
2022-05-04 19:00:09 +02:00
generatedMnemonic = await _sub.generateMnemonic(lang: appLang);
2021-02-28 06:04:22 +01:00
List<String> _wordsList = [];
String word;
int _nbr = 1;
2021-12-23 12:36:09 +01:00
for (word in generatedMnemonic!.split(' ')) {
2021-02-28 06:04:22 +01:00
_wordsList.add("$_nbr:$word");
_nbr++;
}
return _wordsList;
}
2022-06-07 19:15:11 +02:00
bool isBipWord(String word, [bool checkRedondance = true]) {
bool isValid = false;
2021-11-21 06:36:12 +01:00
notifyListeners();
2021-11-22 03:54:22 +01:00
// Needed for bad encoding of UTF-8
word = word.replaceAll('é', '');
word = word.replaceAll('è', '');
int nbrMatch = 0;
if (bip39Words(appLang).contains(word.toLowerCase())) {
for (var bipWord in bip39Words(appLang)) {
if (bipWord.startsWith(word)) {
isValid = nbrMatch == 0 ? true : false;
2022-06-07 19:15:11 +02:00
if (checkRedondance) nbrMatch = nbrMatch + 1;
}
}
}
return isValid;
2021-11-21 06:36:12 +01:00
}
2021-12-23 21:44:24 +01:00
bool isBipWordsList(List<String> words) {
2021-11-21 06:36:12 +01:00
bool isValid = true;
2021-12-23 21:44:24 +01:00
for (String word in words) {
2021-11-22 03:54:22 +01:00
// Needed for bad encoding of UTF-8
word = word.replaceAll('é', '');
word = word.replaceAll('è', '');
if (!bip39Words(appLang).contains(word.toLowerCase())) {
2021-11-21 06:36:12 +01:00
isValid = false;
}
}
return isValid;
}
void resetImportView() {
cellController0.text = cellController1.text = cellController2.text =
cellController3.text = cellController4.text = cellController5.text =
cellController6.text = cellController7.text = cellController8.text =
2022-05-04 19:00:09 +02:00
cellController9.text =
cellController10.text = cellController11.text = '';
2021-11-21 06:36:12 +01:00
isFirstTimeSentenceComplete = true;
notifyListeners();
}
bool isSentenceComplete(BuildContext context) {
if (isBipWordsList(
[
cellController0.text,
cellController1.text,
cellController2.text,
cellController3.text,
cellController4.text,
cellController5.text,
cellController6.text,
cellController7.text,
cellController8.text,
cellController9.text,
cellController10.text,
cellController11.text
],
)) {
if (isFirstTimeSentenceComplete) {
FocusScope.of(context).unfocus();
}
isFirstTimeSentenceComplete = false;
return true;
} else {
return false;
}
}
2022-05-19 09:07:26 +02:00
Future pasteMnemonic(BuildContext context) async {
final sentence = await Clipboard.getData('text/plain');
int nbr = 0;
List cells = [
cellController0,
cellController1,
cellController2,
cellController3,
cellController4,
cellController5,
cellController6,
cellController7,
cellController8,
cellController9,
cellController10,
cellController11
];
for (var word in sentence!.text!.split(' ')) {
2022-06-07 19:15:11 +02:00
bool isValid = isBipWord(word, false);
2022-05-19 09:07:26 +02:00
if (isValid) {
cells[nbr].text = word;
}
nbr++;
}
}
void reloadBuild() {
notifyListeners();
}
2022-06-07 01:10:40 +02:00
2022-06-07 21:36:57 +02:00
Future<bool> scanDerivations(BuildContext context,
{int numberScan = 20}) async {
2022-06-07 01:10:40 +02:00
SubstrateSdk _sub = Provider.of<SubstrateSdk>(context, listen: false);
2022-06-07 21:36:57 +02:00
final currentChestNumber = configBox.get('currentChest');
bool isAlive = false;
scanedWalletNumber = 0;
notifyListeners();
if (!_sub.nodeConnected) {
return false;
}
2022-06-07 21:36:57 +02:00
final hasRoot = await scanRootBalance(_sub, currentChestNumber);
if (hasRoot) {
scanedWalletNumber = 1;
isAlive = true;
}
2022-06-07 01:10:40 +02:00
2022-06-07 21:36:57 +02:00
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');
2022-06-09 01:28:02 +02:00
final balance = await _sub.getBalance(addressData.address!).timeout(
const Duration(seconds: 1),
onTimeout: () => 0,
);
// const balance = 0;
2022-06-07 21:36:57 +02:00
log.d(balance);
if (balance != 0) {
isAlive = true;
String walletName = scanedWalletNumber == 0
2022-06-17 01:13:14 +02:00
? 'currentWallet'.tr()
: 'wallet'.tr() + ' ${scanedWalletNumber + 1}';
2022-06-07 21:36:57 +02:00
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!);
2022-06-09 01:28:02 +02:00
final balance = await _sub.getBalance(addressData.address!).timeout(
const Duration(seconds: 1),
onTimeout: () => 0,
);
2022-06-07 21:36:57 +02:00
log.d(balance);
if (balance != 0) {
2022-06-17 01:13:14 +02:00
String walletName = 'myRootWallet'.tr();
2022-06-07 21:36:57 +02:00
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;
}
2022-06-07 01:10:40 +02:00
}
2021-01-26 21:00:26 +01:00
}