fix: chest change not consistent; feat: Can create custom derivation number, and root wallet

This commit is contained in:
poka 2022-06-01 15:17:07 +02:00
parent 51182efe97
commit 8e49ac73ff
8 changed files with 292 additions and 32 deletions

View File

@ -74,6 +74,9 @@ Future<void> main() async {
await _homeProvider.getValidEndpoints();
// await configBox.delete('isCacheChecked');
if (configBox.get('isCacheChecked') == null) {
configBox.put('isCacheChecked', false);
}
// log.d(await configBox.get('endpoint'));
HttpOverrides.global = MyHttpOverrides();

View File

@ -57,12 +57,7 @@ class GenerateWalletsProvider with ChangeNotifier {
Future storeHDWChest(
String address, String _name, BuildContext context) async {
int chestNumber = 0;
chestBox.toMap().forEach((key, value) {
if (!value.isCesium!) {
chestNumber++;
}
});
int chestNumber = chestBox.isEmpty ? 0 : chestBox.keys.last + 1;
String chestName;
if (chestNumber == 0) {

View File

@ -30,7 +30,8 @@ class MyWalletsProvider with ChangeNotifier {
}
}
List<WalletData> readAllWallets(int? _chest) {
List<WalletData> readAllWallets([int? _chest]) {
_chest = _chest ?? configBox.get('currentChest') ?? 0;
listWallets.clear();
walletBox.toMap().forEach((key, value) {
if (value.chest == _chest) {
@ -108,28 +109,20 @@ class MyWalletsProvider with ChangeNotifier {
}
}
Future<void> generateNewDerivation(context, String _name) async {
MyWalletsProvider _myWalletProvider =
Provider.of<MyWalletsProvider>(context, listen: false);
Future<void> generateNewDerivation(context, String _name,
[int? number]) async {
isNewDerivationLoading = true;
notifyListeners();
int _newDerivationNbr;
int _newWalletNbr;
final List idList = getNextWalletNumberAndDerivation();
int _newWalletNbr = idList[0];
int _newDerivationNbr = number ?? idList[1];
int? _chest = getCurrentChest();
List<WalletData> _walletConfig = readAllWallets(_chest);
if (_walletConfig.isEmpty) {
_newDerivationNbr = 2;
_newWalletNbr = 0;
} else {
_newDerivationNbr = _walletConfig.last.derivation! + 2;
_newWalletNbr = _walletConfig.last.number! + 1;
}
SubstrateSdk _sub = Provider.of<SubstrateSdk>(context, listen: false);
WalletData defaultWallet = _myWalletProvider.getDefaultWallet()!;
WalletData defaultWallet = getDefaultWallet()!;
final address = await _sub.derive(
context, defaultWallet.address!, _newDerivationNbr, pinCode);
@ -149,6 +142,71 @@ class MyWalletsProvider with ChangeNotifier {
notifyListeners();
}
Future<void> generateRootWallet(context, String _name) async {
MyWalletsProvider _myWalletProvider =
Provider.of<MyWalletsProvider>(context, listen: false);
isNewDerivationLoading = true;
notifyListeners();
int _newWalletNbr;
int? _chest = getCurrentChest();
List<WalletData> _walletConfig = readAllWallets(_chest);
if (_walletConfig.isEmpty) {
_newWalletNbr = 0;
} else {
_newWalletNbr = _walletConfig.last.number! + 1;
}
SubstrateSdk _sub = Provider.of<SubstrateSdk>(context, listen: false);
WalletData defaultWallet = _myWalletProvider.getDefaultWallet()!;
final address =
await _sub.generateRootKeypair(defaultWallet.address!, pinCode);
WalletData newWallet = WalletData(
version: dataVersion,
chest: _chest,
address: address,
number: _newWalletNbr,
name: _name,
derivation: -1,
imageDefaultPath: '${_newWalletNbr % 4}.png');
await walletBox.add(newWallet);
isNewDerivationLoading = false;
notifyListeners();
}
List<int> getNextWalletNumberAndDerivation(
{int? chestNumber, bool isOneshoot = false}) {
int _newDerivationNbr = 0;
int _newWalletNbr = 0;
chestNumber ??= getCurrentChest();
List<WalletData> _walletConfig = readAllWallets(chestNumber);
if (_walletConfig.isEmpty) {
_newDerivationNbr = 2;
} else {
WalletData _lastWallet = _walletConfig.reduce(
(curr, next) => curr.derivation! > next.derivation! ? curr : next);
if (_lastWallet.derivation == -1) {
_newDerivationNbr = 2;
} else {
_newDerivationNbr = _lastWallet.derivation! + (isOneshoot ? 1 : 2);
}
_newWalletNbr = _walletConfig.last.number! + 1;
}
return [_newWalletNbr, _newDerivationNbr];
}
int lockPin = 0;
Future resetPinCode([int minutes = 15]) async {
lockPin++;

View File

@ -230,6 +230,8 @@ class SubstrateSdk with ChangeNotifier {
Future<bool> checkPassword(String address, String pass) async {
final account = getKeypair(address);
// log.d(account.address);
return await sdk.api.keyring.checkPassword(account, pass);
}
@ -510,7 +512,23 @@ class SubstrateSdk with ChangeNotifier {
generatedMnemonic = seedList[0];
return await importAccount(
fromMnemonic: true, derivePath: '//$number', password: password);
mnemonic: generatedMnemonic,
fromMnemonic: true,
derivePath: '//$number',
password: password);
}
Future<String> generateRootKeypair(String address, String password) async {
final keypair = getKeypair(address);
final seedMap =
await keyring.store.getDecryptedSeed(keypair.pubKey, password);
if (seedMap?['type'] != 'mnemonic') return '';
final List seedList = seedMap!['seed'].split('//');
generatedMnemonic = seedList[0];
return await importAccount(fromMnemonic: true, password: password);
}
Future<bool> isMnemonicValid(String mnemonic) async {

View File

@ -7,6 +7,7 @@ import 'package:gecko/providers/chest_provider.dart';
import 'package:gecko/providers/home.dart';
import 'package:gecko/providers/my_wallets.dart';
import 'package:gecko/screens/myWallets/change_pin.dart';
import 'package:gecko/screens/myWallets/custom_derivations.dart';
import 'package:gecko/screens/myWallets/show_seed.dart';
import 'package:gecko/screens/myWallets/unlocking_wallet.dart';
import 'package:provider/provider.dart';
@ -123,7 +124,7 @@ class ChestOptions extends StatelessWidget {
child: SizedBox(
height: 50,
child: Row(children: <Widget>[
const SizedBox(width: 28),
const SizedBox(width: 26),
Image.asset(
'assets/chests/secret_code.png',
height: 25,
@ -137,6 +138,35 @@ class ChestOptions extends StatelessWidget {
),
SizedBox(height: 10 * ratio),
InkWell(
key: const Key('createRootDerivation'),
onTap: () async {
await Navigator.push(
context,
MaterialPageRoute(
builder: (context) {
return const CustomDerivation();
},
),
);
},
child: SizedBox(
height: 50,
child: Row(children: const <Widget>[
SizedBox(width: 35),
Icon(
Icons.manage_accounts,
size: 33,
),
SizedBox(width: 25),
Text(
'Créer une autre dérivation',
style: TextStyle(fontSize: 20, color: Colors.black),
),
]),
),
),
SizedBox(height: 10 * ratio),
InkWell(
key: const Key('deleteChest'),
onTap: () async {
await _chestProvider.deleteChest(context, currentChest);
@ -144,7 +174,7 @@ class ChestOptions extends StatelessWidget {
child: SizedBox(
height: 50,
child: Row(children: <Widget>[
const SizedBox(width: 30),
const SizedBox(width: 28),
Image.asset(
'assets/walletOptions/trash.png',
height: 45,

View File

@ -0,0 +1,161 @@
import 'package:flutter/services.dart';
import 'package:gecko/globals.dart';
import 'package:flutter/material.dart';
import 'package:gecko/models/wallet_data.dart';
import 'package:gecko/providers/my_wallets.dart';
import 'package:gecko/screens/myWallets/unlocking_wallet.dart';
import 'package:provider/provider.dart';
class CustomDerivation extends StatefulWidget {
const CustomDerivation({Key? key}) : super(key: key);
@override
State<CustomDerivation> createState() => _CustomDerivationState();
}
class _CustomDerivationState extends State<CustomDerivation> {
String? dropdownValue;
@override
void initState() {
dropdownValue = 'root';
super.initState();
}
@override
Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
MyWalletsProvider _myWalletProvider =
Provider.of<MyWalletsProvider>(context, listen: false);
final derivationList = <String>[
'root',
for (var i = 0; i < 50; i += 1) i.toString()
];
final listWallets = _myWalletProvider.readAllWallets();
for (WalletData _wallet in listWallets) {
derivationList.remove(_wallet.derivation.toString());
if (_wallet.derivation == -1) {
derivationList.remove('root');
}
}
if (!derivationList.contains(dropdownValue)) {
dropdownValue = derivationList.first;
}
return Scaffold(
backgroundColor: backgroundColor,
appBar: AppBar(
toolbarHeight: 60 * ratio,
title: const SizedBox(
height: 22,
child: Text('Créer une dérivation personnalisé'),
)),
body: Center(
child: SafeArea(
child: Column(children: <Widget>[
const Spacer(),
const Text(
'Choisissez une dérivation:',
),
const SizedBox(height: 20),
SizedBox(
width: 100,
child: DropdownButton<String>(
value: dropdownValue,
menuMaxHeight: 300,
icon: const Icon(Icons.arrow_downward),
elevation: 16,
style: TextStyle(color: orangeC),
underline: Container(
height: 2,
color: orangeC,
),
onChanged: (String? newValue) {
setState(() {
dropdownValue = newValue!;
});
},
items: derivationList
.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: SizedBox(
width: 75,
child: Row(children: [
const Spacer(),
Text(
value,
style: const TextStyle(
fontSize: 20, color: Colors.black),
),
const Spacer(),
]),
));
}).toList(),
),
),
const Spacer(flex: 1),
SizedBox(
width: 410,
height: 70,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
elevation: 4,
primary: orangeC, // background
onPrimary: Colors.white, // foreground
),
onPressed: () async {
WalletData? defaultWallet =
_myWalletProvider.getDefaultWallet();
String? _pin;
if (_myWalletProvider.pinCode == '') {
_pin = await Navigator.push(
context,
MaterialPageRoute(
builder: (homeContext) {
return UnlockingWallet(wallet: defaultWallet);
},
),
);
}
if (_pin != null || _myWalletProvider.pinCode != '') {
String _newDerivationName =
'Portefeuille ${_myWalletProvider.listWallets.last.number! + 2}';
if (dropdownValue == 'root') {
await _myWalletProvider.generateRootWallet(
context, 'Portefeuille racine');
} else {
await _myWalletProvider.generateNewDerivation(
context,
_newDerivationName,
int.parse(dropdownValue!),
);
}
Navigator.pop(context);
Navigator.pop(context);
// Navigator.push(
// context,
// MaterialPageRoute(builder: (context) {
// return const WalletsHome();
// }),
// );
}
},
child: const Text(
'Valider',
style: TextStyle(fontSize: 24, fontWeight: FontWeight.w600),
),
),
),
const Spacer(),
]),
),
),
);
}
}

View File

@ -37,10 +37,6 @@ class UnlockingWallet extends StatelessWidget {
currentChestNumber = configBox.get('currentChest');
currentChest = chestBox.get(currentChestNumber)!;
if (configBox.get('isCacheChecked') == null) {
configBox.put('isCacheChecked', false);
}
int _pinLenght = _walletOptions.getPinLenght(wallet!.number);
errorController = StreamController<ErrorAnimationType>();
@ -222,7 +218,6 @@ class UnlockingWallet extends StatelessWidget {
],
onCompleted: (_pin) async {
_myWalletProvider.pinCode = _pin.toUpperCase();
final isValid = await _sub.checkPassword(
defaultWallet!.address!, _pin.toUpperCase());

View File

@ -5,7 +5,7 @@ description: Pay with G1.
# pub.dev using `pub publish`. This is preferred for private packages.
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
version: 0.0.7+9
version: 0.0.7+10
environment:
sdk: '>=2.12.0 <3.0.0'