fix: chest change not consistent; feat: Can create custom derivation number, and root wallet
This commit is contained in:
parent
51182efe97
commit
8e49ac73ff
|
@ -74,6 +74,9 @@ Future<void> main() async {
|
||||||
|
|
||||||
await _homeProvider.getValidEndpoints();
|
await _homeProvider.getValidEndpoints();
|
||||||
// await configBox.delete('isCacheChecked');
|
// await configBox.delete('isCacheChecked');
|
||||||
|
if (configBox.get('isCacheChecked') == null) {
|
||||||
|
configBox.put('isCacheChecked', false);
|
||||||
|
}
|
||||||
// log.d(await configBox.get('endpoint'));
|
// log.d(await configBox.get('endpoint'));
|
||||||
|
|
||||||
HttpOverrides.global = MyHttpOverrides();
|
HttpOverrides.global = MyHttpOverrides();
|
||||||
|
|
|
@ -57,12 +57,7 @@ class GenerateWalletsProvider with ChangeNotifier {
|
||||||
|
|
||||||
Future storeHDWChest(
|
Future storeHDWChest(
|
||||||
String address, String _name, BuildContext context) async {
|
String address, String _name, BuildContext context) async {
|
||||||
int chestNumber = 0;
|
int chestNumber = chestBox.isEmpty ? 0 : chestBox.keys.last + 1;
|
||||||
chestBox.toMap().forEach((key, value) {
|
|
||||||
if (!value.isCesium!) {
|
|
||||||
chestNumber++;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
String chestName;
|
String chestName;
|
||||||
if (chestNumber == 0) {
|
if (chestNumber == 0) {
|
||||||
|
|
|
@ -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();
|
listWallets.clear();
|
||||||
walletBox.toMap().forEach((key, value) {
|
walletBox.toMap().forEach((key, value) {
|
||||||
if (value.chest == _chest) {
|
if (value.chest == _chest) {
|
||||||
|
@ -108,28 +109,20 @@ class MyWalletsProvider with ChangeNotifier {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> generateNewDerivation(context, String _name) async {
|
Future<void> generateNewDerivation(context, String _name,
|
||||||
MyWalletsProvider _myWalletProvider =
|
[int? number]) async {
|
||||||
Provider.of<MyWalletsProvider>(context, listen: false);
|
|
||||||
|
|
||||||
isNewDerivationLoading = true;
|
isNewDerivationLoading = true;
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
int _newDerivationNbr;
|
|
||||||
int _newWalletNbr;
|
final List idList = getNextWalletNumberAndDerivation();
|
||||||
|
int _newWalletNbr = idList[0];
|
||||||
|
int _newDerivationNbr = number ?? idList[1];
|
||||||
|
|
||||||
int? _chest = getCurrentChest();
|
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);
|
SubstrateSdk _sub = Provider.of<SubstrateSdk>(context, listen: false);
|
||||||
|
|
||||||
WalletData defaultWallet = _myWalletProvider.getDefaultWallet()!;
|
WalletData defaultWallet = getDefaultWallet()!;
|
||||||
|
|
||||||
final address = await _sub.derive(
|
final address = await _sub.derive(
|
||||||
context, defaultWallet.address!, _newDerivationNbr, pinCode);
|
context, defaultWallet.address!, _newDerivationNbr, pinCode);
|
||||||
|
@ -149,6 +142,71 @@ class MyWalletsProvider with ChangeNotifier {
|
||||||
notifyListeners();
|
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;
|
int lockPin = 0;
|
||||||
Future resetPinCode([int minutes = 15]) async {
|
Future resetPinCode([int minutes = 15]) async {
|
||||||
lockPin++;
|
lockPin++;
|
||||||
|
|
|
@ -230,6 +230,8 @@ class SubstrateSdk with ChangeNotifier {
|
||||||
|
|
||||||
Future<bool> checkPassword(String address, String pass) async {
|
Future<bool> checkPassword(String address, String pass) async {
|
||||||
final account = getKeypair(address);
|
final account = getKeypair(address);
|
||||||
|
// log.d(account.address);
|
||||||
|
|
||||||
return await sdk.api.keyring.checkPassword(account, pass);
|
return await sdk.api.keyring.checkPassword(account, pass);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -510,7 +512,23 @@ class SubstrateSdk with ChangeNotifier {
|
||||||
generatedMnemonic = seedList[0];
|
generatedMnemonic = seedList[0];
|
||||||
|
|
||||||
return await importAccount(
|
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 {
|
Future<bool> isMnemonicValid(String mnemonic) async {
|
||||||
|
|
|
@ -7,6 +7,7 @@ import 'package:gecko/providers/chest_provider.dart';
|
||||||
import 'package:gecko/providers/home.dart';
|
import 'package:gecko/providers/home.dart';
|
||||||
import 'package:gecko/providers/my_wallets.dart';
|
import 'package:gecko/providers/my_wallets.dart';
|
||||||
import 'package:gecko/screens/myWallets/change_pin.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/show_seed.dart';
|
||||||
import 'package:gecko/screens/myWallets/unlocking_wallet.dart';
|
import 'package:gecko/screens/myWallets/unlocking_wallet.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
@ -123,7 +124,7 @@ class ChestOptions extends StatelessWidget {
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 50,
|
height: 50,
|
||||||
child: Row(children: <Widget>[
|
child: Row(children: <Widget>[
|
||||||
const SizedBox(width: 28),
|
const SizedBox(width: 26),
|
||||||
Image.asset(
|
Image.asset(
|
||||||
'assets/chests/secret_code.png',
|
'assets/chests/secret_code.png',
|
||||||
height: 25,
|
height: 25,
|
||||||
|
@ -136,6 +137,35 @@ class ChestOptions extends StatelessWidget {
|
||||||
])),
|
])),
|
||||||
),
|
),
|
||||||
SizedBox(height: 10 * ratio),
|
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(
|
InkWell(
|
||||||
key: const Key('deleteChest'),
|
key: const Key('deleteChest'),
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
|
@ -144,7 +174,7 @@ class ChestOptions extends StatelessWidget {
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 50,
|
height: 50,
|
||||||
child: Row(children: <Widget>[
|
child: Row(children: <Widget>[
|
||||||
const SizedBox(width: 30),
|
const SizedBox(width: 28),
|
||||||
Image.asset(
|
Image.asset(
|
||||||
'assets/walletOptions/trash.png',
|
'assets/walletOptions/trash.png',
|
||||||
height: 45,
|
height: 45,
|
||||||
|
|
|
@ -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(),
|
||||||
|
]),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -37,10 +37,6 @@ class UnlockingWallet extends StatelessWidget {
|
||||||
currentChestNumber = configBox.get('currentChest');
|
currentChestNumber = configBox.get('currentChest');
|
||||||
currentChest = chestBox.get(currentChestNumber)!;
|
currentChest = chestBox.get(currentChestNumber)!;
|
||||||
|
|
||||||
if (configBox.get('isCacheChecked') == null) {
|
|
||||||
configBox.put('isCacheChecked', false);
|
|
||||||
}
|
|
||||||
|
|
||||||
int _pinLenght = _walletOptions.getPinLenght(wallet!.number);
|
int _pinLenght = _walletOptions.getPinLenght(wallet!.number);
|
||||||
errorController = StreamController<ErrorAnimationType>();
|
errorController = StreamController<ErrorAnimationType>();
|
||||||
|
|
||||||
|
@ -222,7 +218,6 @@ class UnlockingWallet extends StatelessWidget {
|
||||||
],
|
],
|
||||||
onCompleted: (_pin) async {
|
onCompleted: (_pin) async {
|
||||||
_myWalletProvider.pinCode = _pin.toUpperCase();
|
_myWalletProvider.pinCode = _pin.toUpperCase();
|
||||||
|
|
||||||
final isValid = await _sub.checkPassword(
|
final isValid = await _sub.checkPassword(
|
||||||
defaultWallet!.address!, _pin.toUpperCase());
|
defaultWallet!.address!, _pin.toUpperCase());
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ description: Pay with G1.
|
||||||
# pub.dev using `pub publish`. This is preferred for private packages.
|
# 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
|
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:
|
environment:
|
||||||
sdk: '>=2.12.0 <3.0.0'
|
sdk: '>=2.12.0 <3.0.0'
|
||||||
|
|
Loading…
Reference in New Issue