From 1f1f7a3e8530ed5a1e1302daa36138bb8e46fc7b Mon Sep 17 00:00:00 2001
From: poka <poka@p2p.legal>
Date: Fri, 18 Feb 2022 02:19:08 +0100
Subject: [PATCH] WIP: Manage keystore

---
 lib/globals.dart                      |  2 +
 lib/main.dart                         |  7 +++-
 lib/models/g1_wallets_list.g.dart     |  6 ---
 lib/models/keystore_data.dart         | 28 +++++++++++++
 lib/models/keystore_data.g.dart       | 41 +++++++++++++++++++
 lib/models/stateful_wrapper.dart      | 23 +++++++++++
 lib/models/wallet_data.dart           |  2 -
 lib/providers/substrate_sdk.dart      | 30 ++++++++++++++
 lib/screens/home.dart                 | 22 +---------
 lib/screens/myWallets/change_pin.dart | 23 +----------
 lib/screens/substrate_sandbox.dart    | 59 +++++++++++++++++----------
 11 files changed, 169 insertions(+), 74 deletions(-)
 create mode 100644 lib/models/keystore_data.dart
 create mode 100644 lib/models/keystore_data.g.dart
 create mode 100644 lib/models/stateful_wrapper.dart

diff --git a/lib/globals.dart b/lib/globals.dart
index abbaf476..c408d33f 100644
--- a/lib/globals.dart
+++ b/lib/globals.dart
@@ -2,6 +2,7 @@ import 'dart:io';
 import 'package:flutter/material.dart';
 import 'package:gecko/models/chest_data.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:hive/hive.dart';
 import 'package:logger/logger.dart';
@@ -20,6 +21,7 @@ late Box<WalletData> walletBox;
 late Box<ChestData> chestBox;
 late Box configBox;
 late Box<G1WalletsList> g1WalletsBox;
+late Box<KeyStoreData> keystoreBox;
 
 String cesiumPod = "https://g1.data.le-sou.org";
 // String cesiumPod = "https://g1.data.e-is.pro";
diff --git a/lib/main.dart b/lib/main.dart
index 75e0142f..f4ccde60 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -1,4 +1,4 @@
-//  Copyright (C) 2020 Axiom-Team.
+//  Copyright (C) 2022 Axiom-Team.
 //
 // This program is free software: you can redistribute it and/or modify
 // it under the terms of the GNU Affero General Public License as
@@ -19,6 +19,7 @@ import 'dart:async';
 import 'dart:io';
 import 'package:flutter/services.dart';
 import 'package:gecko/globals.dart';
+import 'package:gecko/models/keystore_data.dart';
 import 'package:gecko/providers/cesium_plus.dart';
 import 'package:gecko/providers/change_pin.dart';
 import 'package:gecko/models/chest_data.dart';
@@ -39,6 +40,7 @@ import 'package:gecko/screens/search.dart';
 import 'package:gecko/screens/search_result.dart';
 import 'package:graphql_flutter/graphql_flutter.dart';
 import 'package:hive_flutter/hive_flutter.dart';
+import 'package:polkawallet_sdk/storage/types/keyPairData.dart';
 import 'package:provider/provider.dart';
 import 'package:flutter/foundation.dart';
 import 'package:responsive_framework/responsive_framework.dart';
@@ -66,10 +68,13 @@ Future<void> main() async {
   Hive.registerAdapter(ChestDataAdapter());
   Hive.registerAdapter(G1WalletsListAdapter());
   Hive.registerAdapter(IdAdapter());
+  Hive.registerAdapter(KeyStoreDataAdapter());
+  Hive.registerAdapter(KeyPairData());
   walletBox = await Hive.openBox<WalletData>("walletBox");
   chestBox = await Hive.openBox<ChestData>("chestBox");
   configBox = await Hive.openBox("configBox");
   g1WalletsBox = await Hive.openBox<G1WalletsList>("g1WalletsBox");
+  keystoreBox = await Hive.openBox<KeyStoreData>("keystoreBox");
 
   g1WalletsBox.clear();
 
diff --git a/lib/models/g1_wallets_list.g.dart b/lib/models/g1_wallets_list.g.dart
index bb7c15d7..b81cf401 100644
--- a/lib/models/g1_wallets_list.g.dart
+++ b/lib/models/g1_wallets_list.g.dart
@@ -1,7 +1,5 @@
 // GENERATED CODE - DO NOT MODIFY BY HAND
 
-// ignore_for_file: unused_local_variable
-
 part of 'g1_wallets_list.dart';
 
 // **************************************************************************
@@ -66,10 +64,6 @@ class IdAdapter extends TypeAdapter<Id> {
 
   @override
   Id read(BinaryReader reader) {
-    final numOfFields = reader.readByte();
-    final fields = <int, dynamic>{
-      for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
-    };
     return Id();
   }
 
diff --git a/lib/models/keystore_data.dart b/lib/models/keystore_data.dart
new file mode 100644
index 00000000..90819699
--- /dev/null
+++ b/lib/models/keystore_data.dart
@@ -0,0 +1,28 @@
+import 'package:hive_flutter/hive_flutter.dart';
+import 'package:polkawallet_sdk/storage/types/keyPairData.dart';
+part 'keystore_data.g.dart';
+
+@HiveType(typeId: 4)
+class KeyStoreData extends HiveObject {
+  @HiveField(0)
+  KeyPairData? keystore;
+
+  KeyStoreData({this.keystore});
+
+  @override
+  String toString() {
+    return keystore!.address!;
+  }
+
+  String name() {
+    return keystore!.name!;
+  }
+
+  String pubkey() {
+    return keystore!.pubKey!;
+  }
+
+  Map indexInfo() {
+    return keystore!.indexInfo!;
+  }
+}
diff --git a/lib/models/keystore_data.g.dart b/lib/models/keystore_data.g.dart
new file mode 100644
index 00000000..8c8e0114
--- /dev/null
+++ b/lib/models/keystore_data.g.dart
@@ -0,0 +1,41 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+part of 'keystore_data.dart';
+
+// **************************************************************************
+// TypeAdapterGenerator
+// **************************************************************************
+
+class KeyStoreDataAdapter extends TypeAdapter<KeyStoreData> {
+  @override
+  final int typeId = 4;
+
+  @override
+  KeyStoreData read(BinaryReader reader) {
+    final numOfFields = reader.readByte();
+    final fields = <int, dynamic>{
+      for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
+    };
+    return KeyStoreData(
+      keystore: fields[0] as KeyPairData?,
+    );
+  }
+
+  @override
+  void write(BinaryWriter writer, KeyStoreData obj) {
+    writer
+      ..writeByte(1)
+      ..writeByte(0)
+      ..write(obj.keystore);
+  }
+
+  @override
+  int get hashCode => typeId.hashCode;
+
+  @override
+  bool operator ==(Object other) =>
+      identical(this, other) ||
+      other is KeyStoreDataAdapter &&
+          runtimeType == other.runtimeType &&
+          typeId == other.typeId;
+}
diff --git a/lib/models/stateful_wrapper.dart b/lib/models/stateful_wrapper.dart
new file mode 100644
index 00000000..5706812a
--- /dev/null
+++ b/lib/models/stateful_wrapper.dart
@@ -0,0 +1,23 @@
+import 'package:flutter/material.dart';
+
+class StatefulWrapper extends StatefulWidget {
+  final Function onInit;
+  final Widget child;
+  const StatefulWrapper({Key? key, required this.onInit, required this.child})
+      : super(key: key);
+  @override
+  _StatefulWrapperState createState() => _StatefulWrapperState();
+}
+
+class _StatefulWrapperState extends State<StatefulWrapper> {
+  @override
+  void initState() {
+    widget.onInit();
+    super.initState();
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return widget.child;
+  }
+}
diff --git a/lib/models/wallet_data.dart b/lib/models/wallet_data.dart
index fc7cf515..4e7cfefb 100644
--- a/lib/models/wallet_data.dart
+++ b/lib/models/wallet_data.dart
@@ -1,7 +1,5 @@
 import 'dart:io';
-
 import 'package:hive_flutter/hive_flutter.dart';
-
 part 'wallet_data.g.dart';
 
 @HiveType(typeId: 0)
diff --git a/lib/providers/substrate_sdk.dart b/lib/providers/substrate_sdk.dart
index 6fa3ca1d..774a3a52 100644
--- a/lib/providers/substrate_sdk.dart
+++ b/lib/providers/substrate_sdk.dart
@@ -1,4 +1,7 @@
 import 'package:flutter/material.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/types/networkParams.dart';
 import 'package:polkawallet_sdk/polkawallet_sdk.dart';
 import 'package:polkawallet_sdk/storage/keyring.dart';
@@ -13,6 +16,9 @@ class SubstrateSdk with ChangeNotifier {
   bool nodeConnected = false;
   int blocNumber = 0;
 
+  TextEditingController jsonKeystore = TextEditingController();
+  TextEditingController keystorePassword = TextEditingController();
+
   Future<void> initApi() async {
     await keyring.init([0, 2]);
 
@@ -42,4 +48,28 @@ class SubstrateSdk with ChangeNotifier {
       notifyListeners();
     });
   }
+
+  Future<void> importFromKeystore() async {
+    final json = await sdk.api.keyring.importAccount(
+      keyring,
+      keyType: KeyType.keystore,
+      key: jsonKeystore.text,
+      name: 'testKey',
+      password: keystorePassword.text,
+    );
+    final acc = await sdk.api.keyring.addAccount(
+      keyring,
+      keyType: KeyType.mnemonic,
+      acc: json!,
+      password: keystorePassword.text,
+    );
+
+    KeyStoreData _keystore = KeyStoreData(keystore: acc);
+    await keystoreBox.add(_keystore);
+    notifyListeners();
+  }
+
+  void reload() {
+    notifyListeners();
+  }
 }
diff --git a/lib/screens/home.dart b/lib/screens/home.dart
index 7be0ce5c..fe80eee5 100644
--- a/lib/screens/home.dart
+++ b/lib/screens/home.dart
@@ -1,5 +1,6 @@
 import 'package:bubble/bubble.dart';
 import 'package:gecko/globals.dart';
+import 'package:gecko/models/stateful_wrapper.dart';
 import 'package:gecko/providers/chest_provider.dart';
 import 'package:gecko/providers/wallets_profiles.dart';
 import 'package:flutter/material.dart';
@@ -532,27 +533,6 @@ Widget welcomeHome(context) {
   );
 }
 
-class StatefulWrapper extends StatefulWidget {
-  final Function onInit;
-  final Widget child;
-  const StatefulWrapper({Key? key, required this.onInit, required this.child})
-      : super(key: key);
-  @override
-  _StatefulWrapperState createState() => _StatefulWrapperState();
-}
-
-class _StatefulWrapperState extends State<StatefulWrapper> {
-  @override
-  void initState() {
-    widget.onInit();
-    super.initState();
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    return widget.child;
-  }
-}
 
 Widget bubbleSpeak(String text, {double? long, Key? textKey}) {
   return Bubble(
diff --git a/lib/screens/myWallets/change_pin.dart b/lib/screens/myWallets/change_pin.dart
index 1366e67b..94108656 100644
--- a/lib/screens/myWallets/change_pin.dart
+++ b/lib/screens/myWallets/change_pin.dart
@@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
 import 'package:durt/durt.dart';
 import 'package:flutter/services.dart';
 import 'package:gecko/globals.dart';
+import 'package:gecko/models/stateful_wrapper.dart';
 import 'package:gecko/providers/change_pin.dart';
 import 'package:gecko/providers/my_wallets.dart';
 import 'dart:io';
@@ -116,25 +117,3 @@ class ChangePinScreen extends StatelessWidget with ChangeNotifier {
     );
   }
 }
-
-class StatefulWrapper extends StatefulWidget {
-  final Function onInit;
-  final Widget child;
-  const StatefulWrapper({Key? key, required this.onInit, required this.child})
-      : super(key: key);
-  @override
-  _StatefulWrapperState createState() => _StatefulWrapperState();
-}
-
-class _StatefulWrapperState extends State<StatefulWrapper> {
-  @override
-  void initState() {
-    widget.onInit();
-    super.initState();
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    return widget.child;
-  }
-}
diff --git a/lib/screens/substrate_sandbox.dart b/lib/screens/substrate_sandbox.dart
index 89b4997b..0f91dd7e 100644
--- a/lib/screens/substrate_sandbox.dart
+++ b/lib/screens/substrate_sandbox.dart
@@ -1,5 +1,6 @@
 import 'package:flutter/material.dart';
 import 'package:gecko/globals.dart';
+import 'package:gecko/models/stateful_wrapper.dart';
 import 'package:gecko/providers/substrate_sdk.dart';
 import 'package:provider/provider.dart';
 
@@ -33,6 +34,42 @@ class SubstrateSandBox extends StatelessWidget {
                       'Noeud connecté ?: ${_sub.nodeConnected} (${_sub.subNode})'),
                   if (_sub.nodeConnected)
                     Text('Numéro de bloc: ${_sub.blocNumber}'),
+                  const SizedBox(height: 20),
+                  const Text('List des trousseaux:'),
+                  Text(keystoreBox.isEmpty
+                      ? '-'
+                      : keystoreBox.toMap().entries.toString()),
+                  const SizedBox(height: 20),
+                  const Text('Trousseau:'),
+                  TextField(
+                    controller: _sub.jsonKeystore,
+                    onChanged: (_) => _sub.reload(),
+                    minLines: 5,
+                    maxLines: 5,
+                  ),
+                  const SizedBox(height: 20),
+                  const Text('Mot de passe:'),
+                  TextField(
+                    controller: _sub.keystorePassword,
+                    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),
+                      ),
+                    ),
+                  ]),
                 ]);
           }),
         ),
@@ -40,25 +77,3 @@ class SubstrateSandBox extends StatelessWidget {
     );
   }
 }
-
-class StatefulWrapper extends StatefulWidget {
-  final Function onInit;
-  final Widget child;
-  const StatefulWrapper({Key? key, required this.onInit, required this.child})
-      : super(key: key);
-  @override
-  _StatefulWrapperState createState() => _StatefulWrapperState();
-}
-
-class _StatefulWrapperState extends State<StatefulWrapper> {
-  @override
-  void initState() {
-    widget.onInit();
-    super.initState();
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    return widget.child;
-  }
-}
-- 
GitLab