Begin to manage keystores

This commit is contained in:
poka 2022-02-18 18:57:03 +01:00
parent 1f1f7a3e85
commit 900c4d2418
5 changed files with 107 additions and 60 deletions

View File

@ -2,7 +2,6 @@ import 'dart:io';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:gecko/models/chest_data.dart'; import 'package:gecko/models/chest_data.dart';
import 'package:gecko/models/g1_wallets_list.dart'; import 'package:gecko/models/g1_wallets_list.dart';
import 'package:gecko/models/keystore_data.dart';
import 'package:gecko/models/wallet_data.dart'; import 'package:gecko/models/wallet_data.dart';
import 'package:hive/hive.dart'; import 'package:hive/hive.dart';
import 'package:logger/logger.dart'; import 'package:logger/logger.dart';
@ -21,7 +20,7 @@ late Box<WalletData> walletBox;
late Box<ChestData> chestBox; late Box<ChestData> chestBox;
late Box configBox; late Box configBox;
late Box<G1WalletsList> g1WalletsBox; late Box<G1WalletsList> g1WalletsBox;
late Box<KeyStoreData> keystoreBox; late Box keystoreBox;
String cesiumPod = "https://g1.data.le-sou.org"; String cesiumPod = "https://g1.data.le-sou.org";
// String cesiumPod = "https://g1.data.e-is.pro"; // String cesiumPod = "https://g1.data.e-is.pro";

View File

@ -19,7 +19,6 @@ import 'dart:async';
import 'dart:io'; import 'dart:io';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:gecko/globals.dart'; import 'package:gecko/globals.dart';
import 'package:gecko/models/keystore_data.dart';
import 'package:gecko/providers/cesium_plus.dart'; import 'package:gecko/providers/cesium_plus.dart';
import 'package:gecko/providers/change_pin.dart'; import 'package:gecko/providers/change_pin.dart';
import 'package:gecko/models/chest_data.dart'; import 'package:gecko/models/chest_data.dart';
@ -40,7 +39,6 @@ import 'package:gecko/screens/search.dart';
import 'package:gecko/screens/search_result.dart'; import 'package:gecko/screens/search_result.dart';
import 'package:graphql_flutter/graphql_flutter.dart'; import 'package:graphql_flutter/graphql_flutter.dart';
import 'package:hive_flutter/hive_flutter.dart'; import 'package:hive_flutter/hive_flutter.dart';
import 'package:polkawallet_sdk/storage/types/keyPairData.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:responsive_framework/responsive_framework.dart'; import 'package:responsive_framework/responsive_framework.dart';
@ -68,13 +66,13 @@ Future<void> main() async {
Hive.registerAdapter(ChestDataAdapter()); Hive.registerAdapter(ChestDataAdapter());
Hive.registerAdapter(G1WalletsListAdapter()); Hive.registerAdapter(G1WalletsListAdapter());
Hive.registerAdapter(IdAdapter()); Hive.registerAdapter(IdAdapter());
Hive.registerAdapter(KeyStoreDataAdapter()); // Hive.registerAdapter(KeyStoreDataAdapter());
Hive.registerAdapter(KeyPairData());
walletBox = await Hive.openBox<WalletData>("walletBox"); walletBox = await Hive.openBox<WalletData>("walletBox");
chestBox = await Hive.openBox<ChestData>("chestBox"); chestBox = await Hive.openBox<ChestData>("chestBox");
configBox = await Hive.openBox("configBox"); configBox = await Hive.openBox("configBox");
g1WalletsBox = await Hive.openBox<G1WalletsList>("g1WalletsBox"); g1WalletsBox = await Hive.openBox<G1WalletsList>("g1WalletsBox");
keystoreBox = await Hive.openBox<KeyStoreData>("keystoreBox"); keystoreBox = await Hive.openBox("keystoreBox");
g1WalletsBox.clear(); g1WalletsBox.clear();
@ -185,7 +183,7 @@ class Gecko extends StatelessWidget {
), ),
primaryColor: const Color(0xffFFD58D), primaryColor: const Color(0xffFFD58D),
textTheme: const TextTheme( textTheme: const TextTheme(
bodyText1: TextStyle(fontSize: 20), bodyText1: TextStyle(fontSize: 16),
bodyText2: TextStyle(fontSize: 18), bodyText2: TextStyle(fontSize: 18),
).apply( ).apply(
bodyColor: const Color(0xFF000000), bodyColor: const Color(0xFF000000),

View File

@ -1,6 +1,8 @@
import 'dart:convert';
import 'dart:math';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:gecko/globals.dart'; import 'package:gecko/globals.dart';
import 'package:gecko/models/keystore_data.dart';
import 'package:polkawallet_sdk/api/apiKeyring.dart'; import 'package:polkawallet_sdk/api/apiKeyring.dart';
import 'package:polkawallet_sdk/api/types/networkParams.dart'; import 'package:polkawallet_sdk/api/types/networkParams.dart';
import 'package:polkawallet_sdk/polkawallet_sdk.dart'; import 'package:polkawallet_sdk/polkawallet_sdk.dart';
@ -13,6 +15,7 @@ class SubstrateSdk with ChangeNotifier {
final WalletSDK sdk = WalletSDK(); final WalletSDK sdk = WalletSDK();
final Keyring keyring = Keyring(); final Keyring keyring = Keyring();
bool sdkReady = false; bool sdkReady = false;
bool sdkLoading = false;
bool nodeConnected = false; bool nodeConnected = false;
int blocNumber = 0; int blocNumber = 0;
@ -20,10 +23,12 @@ class SubstrateSdk with ChangeNotifier {
TextEditingController keystorePassword = TextEditingController(); TextEditingController keystorePassword = TextEditingController();
Future<void> initApi() async { Future<void> initApi() async {
sdkLoading = true;
await keyring.init([0, 2]); await keyring.init([0, 2]);
await sdk.init(keyring); await sdk.init(keyring);
sdkReady = true; sdkReady = true;
sdkLoading = false;
notifyListeners(); notifyListeners();
} }
@ -39,6 +44,7 @@ class SubstrateSdk with ChangeNotifier {
); );
if (res != null) { if (res != null) {
nodeConnected = true; nodeConnected = true;
print("Connecté au noeud ${sdk.api.connectedNode!.name}");
notifyListeners(); notifyListeners();
} }
@ -53,7 +59,7 @@ class SubstrateSdk with ChangeNotifier {
final json = await sdk.api.keyring.importAccount( final json = await sdk.api.keyring.importAccount(
keyring, keyring,
keyType: KeyType.keystore, keyType: KeyType.keystore,
key: jsonKeystore.text, key: jsonKeystore.text.replaceAll("'", "\\'"),
name: 'testKey', name: 'testKey',
password: keystorePassword.text, password: keystorePassword.text,
); );
@ -64,12 +70,29 @@ class SubstrateSdk with ChangeNotifier {
password: keystorePassword.text, password: keystorePassword.text,
); );
KeyStoreData _keystore = KeyStoreData(keystore: acc); // await keystoreBox.clear();
await keystoreBox.add(_keystore); await keystoreBox.add(acc.toJson());
Clipboard.setData(ClipboardData(text: jsonEncode(acc.toJson())));
notifyListeners(); notifyListeners();
} }
void reload() { void reload() {
notifyListeners(); notifyListeners();
} }
List getKeyStoreAddress() {
List result = [];
for (var element in keystoreBox.values) {
// Clipboard.setData(ClipboardData(text: jsonEncode(element)));
result.add(element['address']);
}
return result;
}
Future<String> generateMnemonic() async {
final gen = await sdk.api.keyring.generateMnemonic(42);
return gen.mnemonic!;
}
} }

View File

@ -2,6 +2,7 @@ import 'package:bubble/bubble.dart';
import 'package:gecko/globals.dart'; import 'package:gecko/globals.dart';
import 'package:gecko/models/stateful_wrapper.dart'; import 'package:gecko/models/stateful_wrapper.dart';
import 'package:gecko/providers/chest_provider.dart'; import 'package:gecko/providers/chest_provider.dart';
import 'package:gecko/providers/substrate_sdk.dart';
import 'package:gecko/providers/wallets_profiles.dart'; import 'package:gecko/providers/wallets_profiles.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:gecko/providers/home.dart'; import 'package:gecko/providers/home.dart';
@ -27,6 +28,7 @@ class HomeScreen extends StatelessWidget {
Provider.of<MyWalletsProvider>(context); Provider.of<MyWalletsProvider>(context);
Provider.of<ChestProvider>(context); Provider.of<ChestProvider>(context);
HomeProvider homeClass = HomeProvider(); HomeProvider homeClass = HomeProvider();
SubstrateSdk _sub = Provider.of<SubstrateSdk>(context, listen: false);
final bool isWalletsExists = _myWalletProvider.checkIfWalletExist(); final bool isWalletsExists = _myWalletProvider.checkIfWalletExist();
@ -84,7 +86,9 @@ class HomeScreen extends StatelessWidget {
body: Builder( body: Builder(
builder: (ctx) => StatefulWrapper( builder: (ctx) => StatefulWrapper(
onInit: () { onInit: () {
WidgetsBinding.instance!.addPostFrameCallback((_) { WidgetsBinding.instance!.addPostFrameCallback((_) async {
if (!_sub.sdkReady && !_sub.sdkLoading) await _sub.initApi();
if (_sub.sdkReady && !_sub.nodeConnected) await _sub.connectNode();
if (isWalletsExists) homeClass.snackNode(ctx); if (isWalletsExists) homeClass.snackNode(ctx);
}); });
}, },
@ -533,7 +537,6 @@ Widget welcomeHome(context) {
); );
} }
Widget bubbleSpeak(String text, {double? long, Key? textKey}) { Widget bubbleSpeak(String text, {double? long, Key? textKey}) {
return Bubble( return Bubble(
padding: long == null padding: long == null

View File

@ -9,12 +9,12 @@ class SubstrateSandBox extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
SubstrateSdk _sub = Provider.of<SubstrateSdk>(context, listen: false); // SubstrateSdk _sub = Provider.of<SubstrateSdk>(context, listen: false);
return StatefulWrapper( return StatefulWrapper(
onInit: () async { onInit: () async {
await _sub.initApi(); // if (!_sub.sdkReady && !_sub.sdkLoading) await _sub.initApi();
await _sub.connectNode(); // if (_sub.sdkReady && !_sub.nodeConnected) await _sub.connectNode();
}, },
child: Scaffold( child: Scaffold(
appBar: AppBar( appBar: AppBar(
@ -26,51 +26,75 @@ class SubstrateSandBox extends StatelessWidget {
), ),
body: SafeArea( body: SafeArea(
child: Consumer<SubstrateSdk>(builder: (context, _sub, _) { child: Consumer<SubstrateSdk>(builder: (context, _sub, _) {
return Column( return SingleChildScrollView(
crossAxisAlignment: CrossAxisAlignment.start, child: Column(
children: <Widget>[ crossAxisAlignment: CrossAxisAlignment.start,
Text('js-api chargé ?: ${_sub.sdkReady}'), children: <Widget>[
Text( Text('js-api chargé ?: ${_sub.sdkReady}'),
'Noeud connecté ?: ${_sub.nodeConnected} (${_sub.subNode})'), InkWell(
if (_sub.nodeConnected) onTap: !_sub.nodeConnected
Text('Numéro de bloc: ${_sub.blocNumber}'), ? () async {
const SizedBox(height: 20), await _sub.connectNode();
const Text('List des trousseaux:'), }
Text(keystoreBox.isEmpty : null,
? '-' child: Text(
: keystoreBox.toMap().entries.toString()), 'Noeud connecté ?: ${_sub.nodeConnected} (${_sub.subNode})')),
const SizedBox(height: 20), if (_sub.nodeConnected)
const Text('Trousseau:'), Text(
TextField( 'Noeud "${_sub.sdk.api.connectedNode!.name}", bloc N°${_sub.blocNumber}'),
controller: _sub.jsonKeystore, const SizedBox(height: 20),
onChanged: (_) => _sub.reload(), const Text('Liste des trousseaux:'),
minLines: 5, Text(keystoreBox.isEmpty
maxLines: 5, ? '-'
), : _sub.getKeyStoreAddress().toString()),
const SizedBox(height: 20), const SizedBox(height: 40),
const Text('Mot de passe:'), const Text('Trousseau:'),
TextField( TextField(
controller: _sub.keystorePassword, controller: _sub.jsonKeystore,
onChanged: (_) => _sub.reload(), onChanged: (_) => _sub.reload(),
), minLines: 5,
const SizedBox(height: 20), maxLines: 5,
Row(mainAxisAlignment: MainAxisAlignment.center, children: [
ElevatedButton(
style: ElevatedButton.styleFrom(
primary: yellowC, // background
onPrimary: Colors.black, // foreground
),
onPressed: _sub.jsonKeystore.text.isNotEmpty &&
_sub.keystorePassword.text.isNotEmpty
? () async => await _sub.importFromKeystore()
: null,
child: const Text(
'Importer la trousseau',
style: TextStyle(fontSize: 20),
),
), ),
const SizedBox(height: 20),
const Text('Mot de passe:'),
TextField(
controller: _sub.keystorePassword,
obscureText: true,
obscuringCharacter: '',
onChanged: (_) => _sub.reload(),
),
const SizedBox(height: 20),
Row(mainAxisAlignment: MainAxisAlignment.center, children: [
ElevatedButton(
style: ElevatedButton.styleFrom(
primary: yellowC, // background
onPrimary: Colors.black, // foreground
),
onPressed: _sub.jsonKeystore.text.isNotEmpty &&
_sub.keystorePassword.text.isNotEmpty
? () async => await _sub.importFromKeystore()
: null,
child: const Text(
'Importer la trousseau',
style: TextStyle(fontSize: 20),
),
),
const SizedBox(height: 40),
ElevatedButton(
style: ElevatedButton.styleFrom(
primary: yellowC, // background
onPrimary: Colors.black, // foreground
),
onPressed: () async =>
print(await _sub.generateMnemonic()),
child: const Text(
'Générer un mnemonic',
style: TextStyle(fontSize: 20),
),
),
]),
]), ]),
]); );
}), }),
), ),
), ),