From 8eda68de3c8b574a0140eb99b35da47a9c454b3c Mon Sep 17 00:00:00 2001
From: Hugo Trentesaux <hugo@trentesaux.fr>
Date: Wed, 31 May 2023 19:52:31 +0200
Subject: [PATCH] wip refac smith cert

---
 src/cache.rs               |  2 +-
 src/commands/collective.rs |  2 +-
 src/commands/expire.rs     | 10 ++++--
 src/commands/identity.rs   | 14 ++++++--
 src/commands/net_test.rs   |  3 +-
 src/commands/oneshot.rs    |  8 +++--
 src/commands/smith.rs      | 39 ++++------------------
 src/keys.rs                |  3 +-
 src/main.rs                | 68 +++++++++++++++++++++++++++-----------
 9 files changed, 85 insertions(+), 64 deletions(-)

diff --git a/src/cache.rs b/src/cache.rs
index c7720ee..643f7a4 100644
--- a/src/cache.rs
+++ b/src/cache.rs
@@ -1,5 +1,5 @@
-use crate::*;
 use crate::indexer::*;
+use crate::*;
 
 use anyhow::{anyhow, Result};
 use std::collections::{hash_map, HashMap};
diff --git a/src/commands/collective.rs b/src/commands/collective.rs
index f2e3951..a63b55b 100644
--- a/src/commands/collective.rs
+++ b/src/commands/collective.rs
@@ -1,5 +1,5 @@
-use crate::*;
 use crate::indexer::*;
+use crate::*;
 
 use anyhow::Result;
 use sp_core::{sr25519::Pair, H256};
diff --git a/src/commands/expire.rs b/src/commands/expire.rs
index 7322028..f749f89 100644
--- a/src/commands/expire.rs
+++ b/src/commands/expire.rs
@@ -1,5 +1,5 @@
-use crate::*;
 use crate::indexer::*;
+use crate::*;
 
 use anyhow::Result;
 use futures::join;
@@ -102,7 +102,9 @@ pub async fn monitor_expirations(
 	let mut smith_certs_iter = client
 		.storage()
 		.iter(
-			runtime::storage().smith_cert().storage_certs_removable_on(0),
+			runtime::storage()
+				.smith_cert()
+				.storage_certs_removable_on(0),
 			10,
 			Some(parent_hash),
 		)
@@ -163,7 +165,9 @@ pub async fn monitor_expirations(
 	let mut smith_membership_iter = client
 		.storage()
 		.iter(
-			runtime::storage().smith_membership().memberships_expire_on(0),
+			runtime::storage()
+				.smith_membership()
+				.memberships_expire_on(0),
 			10,
 			Some(parent_hash),
 		)
diff --git a/src/commands/identity.rs b/src/commands/identity.rs
index f18f42b..71562d9 100644
--- a/src/commands/identity.rs
+++ b/src/commands/identity.rs
@@ -1,5 +1,5 @@
-use crate::*;
 use crate::indexer::*;
+use crate::*;
 
 use crate::runtime::runtime_types::common_runtime::entities::IdtyData;
 use crate::runtime::runtime_types::pallet_identity::types::*;
@@ -101,7 +101,11 @@ pub async fn get_identity_by_index(
 		.await?)
 }
 
-pub async fn create_identity(pair: Pair, client: Client, target: AccountId32) -> Result<TxProgress, subxt::Error> {
+pub async fn create_identity(
+	pair: Pair,
+	client: Client,
+	target: AccountId32,
+) -> Result<TxProgress, subxt::Error> {
 	Ok(client
 		.tx()
 		.sign_and_submit_then_watch(
@@ -112,7 +116,11 @@ pub async fn create_identity(pair: Pair, client: Client, target: AccountId32) ->
 		.await?)
 }
 
-pub async fn confirm_identity(pair: Pair, client: Client, name: String) -> Result<TxProgress, subxt::Error> {
+pub async fn confirm_identity(
+	pair: Pair,
+	client: Client,
+	name: String,
+) -> Result<TxProgress, subxt::Error> {
 	Ok(client
 		.tx()
 		.sign_and_submit_then_watch(
diff --git a/src/commands/net_test.rs b/src/commands/net_test.rs
index 3d22d04..9a2c73b 100644
--- a/src/commands/net_test.rs
+++ b/src/commands/net_test.rs
@@ -50,8 +50,7 @@ pub async fn repart(
 
 pub async fn spam_roll(pair: Pair, client: Client, actual_repart: usize) -> Result<()> {
 	let mut nonce = 0;
-	let mut pairs =
-		Vec::<(PairSigner<Runtime, Pair>, AccountId32)>::with_capacity(actual_repart);
+	let mut pairs = Vec::<(PairSigner<Runtime, Pair>, AccountId32)>::with_capacity(actual_repart);
 	for i in 0..actual_repart {
 		let pair_i = pair
 			.derive(std::iter::once(DeriveJunction::hard::<u32>(i as u32)), None)
diff --git a/src/commands/oneshot.rs b/src/commands/oneshot.rs
index d2bf50c..c6d4fb9 100644
--- a/src/commands/oneshot.rs
+++ b/src/commands/oneshot.rs
@@ -45,7 +45,9 @@ pub async fn consume_oneshot_account(
 						dest.into(),
 					)
 				} else {
-					runtime::runtime_types::pallet_oneshot_account::types::Account::Normal(dest.into())
+					runtime::runtime_types::pallet_oneshot_account::types::Account::Normal(
+						dest.into(),
+					)
 				},
 			),
 			&PairSigner::new(pair),
@@ -111,7 +113,9 @@ pub async fn oneshot_account_balance(client: Client, account: AccountId32) -> Re
 		client
 			.storage()
 			.fetch(
-				&runtime::storage().oneshot_account().oneshot_accounts(&account),
+				&runtime::storage()
+					.oneshot_account()
+					.oneshot_accounts(&account),
 				None
 			)
 			.await?
diff --git a/src/commands/smith.rs b/src/commands/smith.rs
index 2643317..3bc83d3 100644
--- a/src/commands/smith.rs
+++ b/src/commands/smith.rs
@@ -124,7 +124,9 @@ pub async fn online(client: Client, args: &Args) -> Result<()> {
 	let incoming_authorities = client
 		.storage()
 		.fetch(
-			&runtime::storage().authority_members().incoming_authorities(),
+			&runtime::storage()
+				.authority_members()
+				.incoming_authorities(),
 			Some(parent_hash),
 		)
 		.await?
@@ -144,7 +146,9 @@ pub async fn online(client: Client, args: &Args) -> Result<()> {
 	let outgoing_authorities = client
 		.storage()
 		.fetch(
-			&runtime::storage().authority_members().outgoing_authorities(),
+			&runtime::storage()
+				.authority_members()
+				.outgoing_authorities(),
 			Some(parent_hash),
 		)
 		.await?
@@ -164,37 +168,8 @@ pub async fn online(client: Client, args: &Args) -> Result<()> {
 	Ok(())
 }
 
-/// emit a new smith cert from signer's identity to target identity
-pub async fn emit_cert(args: Args, receiver: u32) -> Result<()> {
-	// issuer key
-	let pair = get_keys(
-		args.secret_format,
-		&args.address,
-		&args.secret,
-		NeededKeys::Secret,
-	)?
-	.1
-	.unwrap();
-
-	// connect to client
-	let client = Client::from_url(&args.url).await.unwrap();
-
-	// get issuer index
-	let issuer = commands::identity::get_idty_index_by_account_id(
-		client.clone(),
-		&AccountId32::from(pair.public()),
-	)
-	.await?
-	.ok_or(anyhow!("can not certify if not member"))?;
-
-	// submit and track certification
-	cert(client, pair, issuer, receiver).await?;
-
-	Ok(())
-}
-
 /// submit a certification and track progress
-async fn cert(client: Client, pair: Pair, issuer: u32, receiver: u32) -> Result<()> {
+pub async fn cert(client: Client, pair: Pair, issuer: u32, receiver: u32) -> Result<()> {
 	let mut progress = client
 		.tx()
 		.sign_and_submit_then_watch(
diff --git a/src/keys.rs b/src/keys.rs
index 5940d29..fa75289 100644
--- a/src/keys.rs
+++ b/src/keys.rs
@@ -14,11 +14,12 @@ pub enum NeededKeys {
 	Secret,
 }
 
-#[derive(Clone, Copy, Debug, Eq, PartialEq)]
+#[derive(Clone, Copy, Debug, Eq, PartialEq, Default)]
 pub enum SecretFormat {
 	/// Raw 32B seed
 	Seed,
 	/// Substrate secret key or BIP39 mnemonic (optionally followed by derivation path)
+	#[default]
 	Substrate,
 }
 
diff --git a/src/main.rs b/src/main.rs
index f65c40b..00dfb47 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -52,7 +52,7 @@ impl From<u64> for Tip {
 	}
 }
 
-#[derive(Clone, Parser, Debug)]
+#[derive(Clone, Parser, Debug, Default)]
 #[clap(author, version, about, long_about = None)]
 pub struct Args {
 	#[clap(subcommand)]
@@ -81,11 +81,13 @@ pub struct Args {
 
 /// Data of current command
 /// can also include fetched information
+#[derive(Default)]
 pub struct Data {
 	pub args: Args,
 	pub client: Option<Client>,
 	pub address: Option<AccountId>,
 	pub keypair: Option<Pair>,
+	pub idty_index: Option<u32>,
 }
 
 // implement helper functions for Data
@@ -94,12 +96,11 @@ impl Data {
 	pub fn new(args: Args) -> Self {
 		Self {
 			args,
-			client: None,
-			address: None,
-			keypair: None,
+			..Default::default()
 		}
 	}
 	// --- getters ---
+	// the "unwrap" should not fail if data is well prepared
 	pub fn client(&self) -> Client {
 		self.client.clone().unwrap()
 	}
@@ -109,7 +110,11 @@ impl Data {
 	pub fn keypair(&self) -> Pair {
 		self.keypair.clone().unwrap()
 	}
+	pub fn idty_index(&self) -> u32 {
+		self.idty_index.clone().unwrap()
+	}
 	// --- mutators ---
+	/// force an address if needed
 	pub fn build_address(mut self) -> Self {
 		self.address = Some(
 			get_keys(
@@ -124,24 +129,38 @@ impl Data {
 		);
 		self
 	}
+	/// force a keypair if needed
 	pub fn build_keypair(mut self) -> Self {
-		self.keypair = Some(
-			get_keys(
-				self.args.secret_format,
-				&self.args.address,
-				&self.args.secret,
-				NeededKeys::Secret,
-			)
-			.expect("needed")
-			.1
-			.expect("needed"),
-		);
+		let (address, keypair) = get_keys(
+			self.args.secret_format,
+			&self.args.address,
+			&self.args.secret,
+			NeededKeys::Secret,
+		)
+		.expect("needed");
+		self.address = address;
+		self.keypair = keypair;
 		self
 	}
+	/// build a client from url
+	// TODO get client from a pre-defined list
 	pub async fn build_client(mut self) -> Self {
 		self.client = Some(Client::from_url(&self.args.url).await.expect("needed"));
 		self
 	}
+	/// get issuer index
+	/// needs address and client first
+	pub async fn fetch_idty_index(mut self) -> Result<Self, anyhow::Error> {
+		self.idty_index = Some(
+			commands::identity::get_idty_index_by_account_id(
+				self.client().clone(),
+				&self.address(),
+			)
+			.await?
+			.ok_or(anyhow::anyhow!("needs to be member to use this command"))?,
+		);
+		Ok(self)
+	}
 }
 
 /// track progress of transaction on the network
@@ -181,8 +200,11 @@ impl From<anyhow::Error> for GcliError {
 	}
 }
 
-#[derive(Clone, Debug, clap::Subcommand)]
+#[derive(Clone, Debug, clap::Subcommand, Default)]
 pub enum Subcommand {
+	// TODO flodef
+	#[default]
+	GetBalance,
 	/// Create and certify an identity
 	///
 	/// Caller must be member, and the target account must exist.
@@ -301,11 +323,11 @@ async fn main() -> Result<(), GcliError> {
 	let mut data = Data::new(args.clone());
 
 	match args.subcommand {
+		Subcommand::GetBalance => {}
 		Subcommand::CreateIdentity { target } => {
 			data = data.build_client().await.build_keypair();
 			let progress =
-				commands::identity::create_identity(data.keypair(), data.client(), target)
-					.await?;
+				commands::identity::create_identity(data.keypair(), data.client(), target).await?;
 			track_progress(progress).await?
 		}
 		Subcommand::ConfirmIdentity { name } => {
@@ -495,7 +517,15 @@ async fn main() -> Result<(), GcliError> {
 			)
 			.await?
 		}
-		Subcommand::SmithCert { to } => commands::smith::emit_cert(args, to).await?,
+		Subcommand::SmithCert { to } => {
+			data = data
+				.build_client()
+				.await
+				.build_keypair()
+				.fetch_idty_index()
+				.await?;
+			commands::smith::cert(data.client(), data.keypair(), data.idty_index(), to).await?
+		}
 		Subcommand::TechMembers => {
 			commands::collective::technical_committee_members(
 				Client::from_url(&args.url).await.unwrap(),
-- 
GitLab