2021-01-26 21:00:26 +01:00
|
|
|
|
import 'dart:math';
|
2021-01-29 02:20:15 +01:00
|
|
|
|
import 'dart:typed_data';
|
2022-05-04 19:00:09 +02:00
|
|
|
|
import 'package:durt/durt.dart' as durt;
|
2021-01-26 21:00:26 +01:00
|
|
|
|
import 'package:flutter/material.dart';
|
2021-01-29 02:20:15 +01:00
|
|
|
|
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';
|
2021-01-29 02:20:15 +01:00
|
|
|
|
import 'package:pdf/pdf.dart';
|
|
|
|
|
import 'package:pdf/widgets.dart' as pw;
|
2022-05-04 19:00:09 +02:00
|
|
|
|
import 'package:provider/provider.dart';
|
2021-04-27 04:09:20 +02:00
|
|
|
|
import "package:unorm_dart/unorm_dart.dart" as unorm;
|
2021-01-26 21:00:26 +01:00
|
|
|
|
|
|
|
|
|
class GenerateWalletsProvider with ChangeNotifier {
|
2021-01-28 15:10:09 +01:00
|
|
|
|
GenerateWalletsProvider();
|
|
|
|
|
// NewWallet generatedWallet;
|
2022-05-04 19:00:09 +02:00
|
|
|
|
durt.NewWallet? actualWallet;
|
2021-01-28 15:10:09 +01:00
|
|
|
|
|
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;
|
2021-02-15 23:57:38 +01:00
|
|
|
|
|
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;
|
2021-01-28 15:10:09 +01:00
|
|
|
|
bool walletIsGenerated = true;
|
2021-01-26 21:00:26 +01:00
|
|
|
|
|
|
|
|
|
TextEditingController mnemonicController = TextEditingController();
|
|
|
|
|
TextEditingController pin = TextEditingController();
|
|
|
|
|
|
2021-02-15 23:57:38 +01:00
|
|
|
|
// 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-02-15 23:57:38 +01:00
|
|
|
|
|
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;
|
|
|
|
|
|
2021-11-17 06:20:23 +01:00
|
|
|
|
Future storeHDWChest(
|
2022-05-04 19:00:09 +02:00
|
|
|
|
String address, String _name, BuildContext context) async {
|
2021-11-17 06:20:23 +01:00
|
|
|
|
int chestNumber = 0;
|
|
|
|
|
chestBox.toMap().forEach((key, value) {
|
2021-12-23 12:36:09 +01:00
|
|
|
|
if (!value.isCesium!) {
|
2021-11-17 06:20:23 +01:00
|
|
|
|
chestNumber++;
|
|
|
|
|
}
|
|
|
|
|
});
|
2021-11-09 04:22:04 +01:00
|
|
|
|
|
|
|
|
|
String chestName;
|
|
|
|
|
if (chestNumber == 0) {
|
2021-11-12 01:32:05 +01:00
|
|
|
|
chestName = 'Coffre à Ğecko';
|
2021-11-09 04:22:04 +01:00
|
|
|
|
} else {
|
2021-11-12 01:32:05 +01:00
|
|
|
|
chestName = 'Coffre à Ğecko ${chestNumber + 1}';
|
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',
|
|
|
|
|
isCesium: false,
|
|
|
|
|
);
|
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
|
|
|
|
|
|
|
|
|
WalletData myWallet = WalletData(
|
2022-05-24 16:51:40 +02:00
|
|
|
|
version: dataVersion,
|
2021-11-17 06:20:23 +01:00
|
|
|
|
chest: chestKey,
|
2022-05-19 07:00:25 +02:00
|
|
|
|
address: address,
|
2021-11-17 06:20:23 +01:00
|
|
|
|
number: 0,
|
|
|
|
|
name: _name,
|
2022-05-20 15:15:29 +02:00
|
|
|
|
derivation: 2,
|
2022-05-28 19:13:30 +02:00
|
|
|
|
imageDefaultPath: '0.png');
|
2021-11-17 06:20:23 +01:00
|
|
|
|
await walletBox.add(myWallet);
|
|
|
|
|
|
|
|
|
|
await configBox.put('currentChest', chestKey);
|
|
|
|
|
notifyListeners();
|
2021-01-26 21:00:26 +01:00
|
|
|
|
}
|
|
|
|
|
|
2021-04-27 04:09:20 +02: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];
|
2021-03-02 07:05:47 +01:00
|
|
|
|
// walletNameFocus.nextFocus();
|
2021-01-28 15:10:09 +01:00
|
|
|
|
notifyListeners();
|
2021-01-26 21:00:26 +01:00
|
|
|
|
} else {
|
|
|
|
|
isAskedWordValid = false;
|
|
|
|
|
}
|
2021-01-28 15:10:09 +01:00
|
|
|
|
// 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) {
|
2021-03-02 07:05:47 +01:00
|
|
|
|
Map nbrToString = {};
|
|
|
|
|
nbrToString[1] = 'Premier';
|
|
|
|
|
nbrToString[2] = 'Deuxième';
|
|
|
|
|
nbrToString[3] = 'Troisième';
|
|
|
|
|
nbrToString[4] = 'Quatrième';
|
|
|
|
|
nbrToString[5] = 'Cinquième';
|
|
|
|
|
nbrToString[6] = 'Sixième';
|
|
|
|
|
nbrToString[7] = 'Septième';
|
|
|
|
|
nbrToString[8] = 'Huitième';
|
|
|
|
|
nbrToString[9] = 'Neuvième';
|
|
|
|
|
nbrToString[10] = 'Dixième';
|
|
|
|
|
nbrToString[11] = 'Onzième';
|
|
|
|
|
nbrToString[12] = 'Douzième';
|
|
|
|
|
|
|
|
|
|
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);
|
2021-02-16 03:04:33 +01:00
|
|
|
|
if (reload) {
|
|
|
|
|
notifyListeners();
|
|
|
|
|
}
|
2021-12-19 21:05:04 +01:00
|
|
|
|
return pin.text;
|
2021-01-26 21:00:26 +01:00
|
|
|
|
}
|
2021-01-29 02:20:15 +01:00
|
|
|
|
|
2022-05-23 10:53:44 +02:00
|
|
|
|
Future<Uint8List> printWallet(AsyncSnapshot<List>? mnemoList) async {
|
2021-01-29 02:20:15 +01:00
|
|
|
|
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)
|
|
|
|
|
]),
|
|
|
|
|
);
|
|
|
|
|
}
|
2021-01-29 02:20:15 +01:00
|
|
|
|
|
|
|
|
|
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, à l’abri des lézards indiscrets.",
|
|
|
|
|
style: pw.TextStyle(fontSize: 15, font: ttf),
|
|
|
|
|
)))
|
|
|
|
|
],
|
|
|
|
|
);
|
2021-01-29 02:20:15 +01:00
|
|
|
|
},
|
|
|
|
|
),
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
return pdf.save();
|
|
|
|
|
}
|
2021-02-15 23:57:38 +01:00
|
|
|
|
|
|
|
|
|
Future<void> generateCesiumWalletPubkey(
|
|
|
|
|
String _cesiumID, String _cesiumPWD) async {
|
2022-05-04 19:00:09 +02:00
|
|
|
|
cesiumWallet = durt.CesiumWallet(_cesiumID, _cesiumPWD);
|
2021-12-19 14:55:47 +01:00
|
|
|
|
String _walletPubkey = cesiumWallet.pubkey;
|
2021-02-15 23:57:38 +01:00
|
|
|
|
|
|
|
|
|
cesiumPubkey.text = _walletPubkey;
|
2021-04-02 12:05:37 +02:00
|
|
|
|
log.d(_walletPubkey);
|
2021-02-15 23:57:38 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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 = '';
|
2021-12-19 21:05:04 +01:00
|
|
|
|
canImport = isCesiumIDVisible = isCesiumPWDVisible = false;
|
2021-02-18 04:42:57 +01:00
|
|
|
|
actualWallet = null;
|
|
|
|
|
notifyListeners();
|
2021-02-16 03:04:33 +01:00
|
|
|
|
}
|
|
|
|
|
|
2022-05-04 19:00:09 +02:00
|
|
|
|
Future<List<String>> generateWordList(BuildContext context) async {
|
2022-05-20 15:15:29 +02:00
|
|
|
|
SubstrateSdk _sub = Provider.of<SubstrateSdk>(context, listen: false);
|
2022-05-04 19:00:09 +02:00
|
|
|
|
|
2022-05-20 15:15:29 +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;
|
|
|
|
|
}
|
|
|
|
|
|
2021-11-21 06:36:12 +01:00
|
|
|
|
bool isBipWord(String word) {
|
|
|
|
|
notifyListeners();
|
2021-11-22 03:54:22 +01:00
|
|
|
|
|
|
|
|
|
// Needed for bad encoding of UTF-8
|
|
|
|
|
word = word.replaceAll('é', 'é');
|
|
|
|
|
word = word.replaceAll('è', 'è');
|
2022-05-19 07:00:25 +02:00
|
|
|
|
return bip39Words(appLang).contains(word);
|
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('è', 'è');
|
2022-05-19 07:00:25 +02:00
|
|
|
|
if (!bip39Words(appLang).contains(word)) {
|
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(' ')) {
|
|
|
|
|
bool isValid = isBipWord(word);
|
|
|
|
|
|
|
|
|
|
if (isValid) {
|
|
|
|
|
cells[nbr].text = word;
|
|
|
|
|
}
|
|
|
|
|
nbr++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-02-15 23:57:38 +01:00
|
|
|
|
void reloadBuild() {
|
|
|
|
|
notifyListeners();
|
|
|
|
|
}
|
2021-01-26 21:00:26 +01:00
|
|
|
|
}
|