From 6ccda07152e0496d58c1300cab8dc80b75287c46 Mon Sep 17 00:00:00 2001
From: Hugo Trentesaux <hugo@trentesaux.fr>
Date: Wed, 7 Jun 2023 11:12:10 +0200
Subject: [PATCH] WIP refac to track tx progress

---
 src/commands/collective.rs |  6 ++---
 src/commands/identity.rs   |  7 +++--
 src/commands/oneshot.rs    | 21 +++++----------
 src/commands/smith.rs      | 31 +++++++++--------------
 src/commands/sudo.rs       | 11 ++++----
 src/commands/transfer.rs   | 15 ++++-------
 src/main.rs                | 52 +++++++++++++++++++++++---------------
 7 files changed, 67 insertions(+), 76 deletions(-)

diff --git a/src/commands/collective.rs b/src/commands/collective.rs
index d95d9df..ea4b0f4 100644
--- a/src/commands/collective.rs
+++ b/src/commands/collective.rs
@@ -85,7 +85,7 @@ pub async fn technical_committee_vote(
 	proposal_hash: H256,
 	proposal_index: u32,
 	vote: bool,
-) -> Result<()> {
+) -> Result<TxProgress, subxt::Error> {
 	client
 		.tx()
 		.sign_and_submit_then_watch(
@@ -95,7 +95,5 @@ pub async fn technical_committee_vote(
 			&PairSigner::new(pair),
 			BaseExtrinsicParamsBuilder::new(),
 		)
-		.await?;
-
-	Ok(())
+		.await
 }
diff --git a/src/commands/identity.rs b/src/commands/identity.rs
index b1e9d11..7b9ea24 100644
--- a/src/commands/identity.rs
+++ b/src/commands/identity.rs
@@ -5,7 +5,6 @@ use crate::runtime::runtime_types::common_runtime::entities::IdtyData;
 use crate::runtime::runtime_types::pallet_identity::types::*;
 use crate::runtime::runtime_types::sp_core::sr25519::Signature;
 use crate::runtime::runtime_types::sp_runtime::MultiSignature;
-use anyhow::{anyhow, Result};
 use sp_core::{crypto::AccountId32, sr25519::Pair};
 use std::str::FromStr;
 use subxt::tx::{BaseExtrinsicParamsBuilder, PairSigner};
@@ -15,7 +14,7 @@ pub async fn get_identity(
 	mut account_id: Option<AccountId32>,
 	mut identity_id: Option<u32>,
 	mut username: Option<String>,
-) -> Result<()> {
+) -> Result<(), anyhow::Error> {
 	let client = data.client();
 	let indexer = data.indexer.clone();
 
@@ -73,7 +72,7 @@ pub async fn get_identity(
 pub async fn get_idty_index_by_account_id(
 	client: &Client,
 	account_id: &AccountId32,
-) -> Result<Option<u32>> {
+) -> Result<Option<u32>, anyhow::Error> {
 	Ok(client
 		.storage()
 		.fetch(
@@ -86,7 +85,7 @@ pub async fn get_idty_index_by_account_id(
 pub async fn get_identity_by_index(
 	client: &Client,
 	idty_index: u32,
-) -> Result<Option<IdtyValue<u32, AccountId32, IdtyData>>> {
+) -> Result<Option<IdtyValue<u32, AccountId32, IdtyData>>, anyhow::Error> {
 	Ok(client
 		.storage()
 		.fetch(&runtime::storage().identity().identities(idty_index), None)
diff --git a/src/commands/oneshot.rs b/src/commands/oneshot.rs
index 15c53c3..70f5796 100644
--- a/src/commands/oneshot.rs
+++ b/src/commands/oneshot.rs
@@ -1,6 +1,5 @@
 use crate::*;
 
-use anyhow::Result;
 use sp_core::{crypto::AccountId32, sr25519::Pair};
 use subxt::tx::{BaseExtrinsicParamsBuilder, PairSigner};
 
@@ -9,7 +8,7 @@ pub async fn create_oneshot_account(
 	client: &Client,
 	balance: u64,
 	dest: AccountId32,
-) -> Result<()> {
+) -> Result<TxProgress, subxt::Error> {
 	client
 		.tx()
 		.sign_and_submit_then_watch(
@@ -19,9 +18,7 @@ pub async fn create_oneshot_account(
 			&PairSigner::new(pair),
 			BaseExtrinsicParamsBuilder::new(),
 		)
-		.await?;
-
-	Ok(())
+		.await
 }
 
 pub async fn consume_oneshot_account(
@@ -29,7 +26,7 @@ pub async fn consume_oneshot_account(
 	client: &Client,
 	dest: AccountId32,
 	dest_oneshot: bool,
-) -> Result<()> {
+) -> Result<TxProgress, subxt::Error> {
 	let number = client
 		.storage()
 		.fetch(&runtime::storage().system().number(), None)
@@ -53,9 +50,7 @@ pub async fn consume_oneshot_account(
 			&PairSigner::new(pair),
 			BaseExtrinsicParamsBuilder::new(),
 		)
-		.await?;
-
-	Ok(())
+		.await
 }
 
 pub async fn consume_oneshot_account_with_remaining(
@@ -66,7 +61,7 @@ pub async fn consume_oneshot_account_with_remaining(
 	dest_oneshot: bool,
 	remaining_to: AccountId32,
 	remaining_to_oneshot: bool,
-) -> Result<()> {
+) -> Result<TxProgress, subxt::Error> {
 	let number = client
 		.storage()
 		.fetch(&runtime::storage().system().number(), None)
@@ -102,12 +97,10 @@ pub async fn consume_oneshot_account_with_remaining(
 			&PairSigner::new(pair),
 			BaseExtrinsicParamsBuilder::new(),
 		)
-		.await?;
-
-	Ok(())
+		.await
 }
 
-pub async fn oneshot_account_balance(client: &Client, account: AccountId32) -> Result<()> {
+pub async fn oneshot_account_balance(client: &Client, account: AccountId32) -> Result<(), anyhow::Error> {
 	log::info!(
 		"{}",
 		client
diff --git a/src/commands/smith.rs b/src/commands/smith.rs
index 3c31171..e9d89b7 100644
--- a/src/commands/smith.rs
+++ b/src/commands/smith.rs
@@ -1,13 +1,12 @@
 use crate::*;
 
-use anyhow::{anyhow, Result};
 use sp_core::{crypto::AccountId32, sr25519::Pair, Pair as _};
 use std::ops::Deref;
 use subxt::tx::{BaseExtrinsicParamsBuilder, PairSigner, TxStatus};
 
 type SessionKeys = [u8; 128];
 
-pub async fn rotate_keys(client: &Client) -> Result<SessionKeys> {
+pub async fn rotate_keys(client: &Client) -> Result<SessionKeys, anyhow::Error> {
 	client
 		.rpc()
 		.rotate_keys()
@@ -21,7 +20,7 @@ pub async fn set_session_keys(
 	pair: Pair,
 	client: &Client,
 	session_keys: SessionKeys,
-) -> Result<()> {
+) -> Result<TxProgress, subxt::Error> {
 	client
 		.tx()
 		.sign_and_submit_then_watch(
@@ -31,17 +30,15 @@ pub async fn set_session_keys(
 			&PairSigner::new(pair),
 			BaseExtrinsicParamsBuilder::new(),
 		)
-		.await?;
-
-	Ok(())
+		.await
 }
 
-pub async fn update_session_keys(pair: Pair, client: &Client) -> Result<()> {
+pub async fn update_session_keys(pair: Pair, client: &Client) -> Result<TxProgress, GcliError> {
 	let session_keys = rotate_keys(client).await?;
-	set_session_keys(pair, client, session_keys).await
+	set_session_keys(pair, client, session_keys).await.map_err(|e| e.into())
 }
 
-pub async fn go_online(pair: Pair, client: &Client) -> Result<()> {
+pub async fn go_online(pair: Pair, client: &Client) -> Result<TxProgress, GcliError> {
 	if client
 		.storage()
 		.fetch(
@@ -53,7 +50,7 @@ pub async fn go_online(pair: Pair, client: &Client) -> Result<()> {
 		.await?
 		.is_none()
 	{
-		return Err(anyhow!("This account has not set session keys!"));
+		return Err(GcliError::Logic("This account has not set session keys!".to_string()));
 	}
 
 	client
@@ -63,12 +60,10 @@ pub async fn go_online(pair: Pair, client: &Client) -> Result<()> {
 			&PairSigner::new(pair),
 			BaseExtrinsicParamsBuilder::new(),
 		)
-		.await?;
-
-	Ok(())
+		.await.map_err(|e| e.into())
 }
 
-pub async fn go_offline(pair: Pair, client: &Client) -> Result<()> {
+pub async fn go_offline(pair: Pair, client: &Client) -> Result<TxProgress, subxt::Error> {
 	client
 		.tx()
 		.sign_and_submit_then_watch(
@@ -76,12 +71,10 @@ pub async fn go_offline(pair: Pair, client: &Client) -> Result<()> {
 			&PairSigner::new(pair),
 			BaseExtrinsicParamsBuilder::new(),
 		)
-		.await?;
-
-	Ok(())
+		.await
 }
 
-pub async fn online(data: &Data) -> Result<()> {
+pub async fn online(data: &Data) -> Result<(), anyhow::Error> {
 	let client = data.client();
 	let indexer = data.indexer.clone();
 
@@ -162,7 +155,7 @@ pub async fn online(data: &Data) -> Result<()> {
 }
 
 /// submit a certification and track progress
-pub 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<(), anyhow::Error> {
 	let mut progress = client
 		.tx()
 		.sign_and_submit_then_watch(
diff --git a/src/commands/sudo.rs b/src/commands/sudo.rs
index 89bc43f..0a9b9a2 100644
--- a/src/commands/sudo.rs
+++ b/src/commands/sudo.rs
@@ -1,10 +1,13 @@
 use crate::*;
 
-use anyhow::Result;
 use sp_core::{crypto::AccountId32, sr25519::Pair};
 use subxt::tx::{BaseExtrinsicParamsBuilder, PairSigner};
 
-pub async fn set_key(pair: Pair, client: &Client, new_key: AccountId32) -> Result<()> {
+pub async fn set_key(
+	pair: Pair,
+	client: &Client,
+	new_key: AccountId32,
+) -> Result<TxProgress, subxt::Error> {
 	client
 		.tx()
 		.sign_and_submit_then_watch(
@@ -12,7 +15,5 @@ pub async fn set_key(pair: Pair, client: &Client, new_key: AccountId32) -> Resul
 			&PairSigner::new(pair),
 			BaseExtrinsicParamsBuilder::new(),
 		)
-		.await?;
-
-	Ok(())
+		.await
 }
diff --git a/src/commands/transfer.rs b/src/commands/transfer.rs
index f9f7820..6656175 100644
--- a/src/commands/transfer.rs
+++ b/src/commands/transfer.rs
@@ -1,6 +1,5 @@
 use crate::*;
 
-use anyhow::Result;
 use sp_core::{crypto::AccountId32, sr25519::Pair};
 use subxt::tx::{BaseExtrinsicParamsBuilder, PairSigner};
 
@@ -14,7 +13,7 @@ pub async fn transfer(
 	balance: u64,
 	dest: AccountId32,
 	keep_alive: bool,
-) -> Result<()> {
+) -> Result<TxProgress, subxt::Error> {
 	if keep_alive {
 		client
 			.tx()
@@ -23,7 +22,7 @@ pub async fn transfer(
 				&PairSigner::new(pair),
 				BaseExtrinsicParamsBuilder::new(),
 			)
-			.await?;
+			.await
 	} else {
 		client
 			.tx()
@@ -34,10 +33,8 @@ pub async fn transfer(
 				&PairSigner::new(pair),
 				BaseExtrinsicParamsBuilder::new(),
 			)
-			.await?;
+			.await
 	}
-
-	Ok(())
 }
 
 pub async fn transfer_multiple(
@@ -45,7 +42,7 @@ pub async fn transfer_multiple(
 	client: &Client,
 	amount: u64,
 	dests: Vec<AccountId32>,
-) -> Result<()> {
+) -> Result<TxProgress, subxt::Error> {
 	// build the list of transactions from the destination accounts
 	let transactions: Vec<Call> = dests
 		.into_iter()
@@ -65,7 +62,5 @@ pub async fn transfer_multiple(
 			&PairSigner::new(pair.clone()),
 			BaseExtrinsicParamsBuilder::new(),
 		)
-		.await?;
-
-	Ok(())
+		.await
 }
diff --git a/src/main.rs b/src/main.rs
index 09c643a..ede8ed5 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -5,6 +5,7 @@ mod data;
 mod indexer;
 mod keys;
 
+use anyhow::anyhow;
 use clap::Parser;
 use codec::Encode;
 use data::*;
@@ -119,6 +120,8 @@ pub enum GcliError {
 	Duniter(String),
 	/// error coming from indexer
 	Indexer(String),
+	/// logic error (illegal operation or security)
+	Logic(String),
 	/// error coming from anyhow
 	Anyhow(anyhow::Error),
 }
@@ -315,7 +318,7 @@ async fn main() -> Result<(), GcliError> {
 		}
 		Subcommand::CreateOneshot { balance, dest } => {
 			data = data.build_client().await?;
-			commands::oneshot::create_oneshot_account(
+			let progress = commands::oneshot::create_oneshot_account(
 				get_keys(
 					args.secret_format,
 					&args.address,
@@ -328,11 +331,12 @@ async fn main() -> Result<(), GcliError> {
 				balance,
 				dest,
 			)
-			.await?
+			.await?;
+			track_progress(progress).await?;
 		}
 		Subcommand::ConsumeOneshot { dest, dest_oneshot } => {
 			data = data.build_client().await?;
-			commands::oneshot::consume_oneshot_account(
+			let progress = commands::oneshot::consume_oneshot_account(
 				get_keys(
 					args.secret_format,
 					&args.address,
@@ -345,7 +349,8 @@ async fn main() -> Result<(), GcliError> {
 				dest,
 				dest_oneshot,
 			)
-			.await?
+			.await?;
+			track_progress(progress).await?;
 		}
 		Subcommand::ConsumeOneshotWithRemaining {
 			balance,
@@ -355,7 +360,7 @@ async fn main() -> Result<(), GcliError> {
 			remaining_to_oneshot,
 		} => {
 			data = data.build_client().await?;
-			commands::oneshot::consume_oneshot_account_with_remaining(
+			let progress = commands::oneshot::consume_oneshot_account_with_remaining(
 				get_keys(
 					args.secret_format,
 					&args.address,
@@ -371,7 +376,8 @@ async fn main() -> Result<(), GcliError> {
 				remaining_to,
 				remaining_to_oneshot,
 			)
-			.await?
+			.await?;
+			track_progress(progress).await?;
 		}
 		Subcommand::Expire { blocks, sessions } => {
 			data = data.build_client().await?;
@@ -402,7 +408,7 @@ async fn main() -> Result<(), GcliError> {
 		}
 		Subcommand::GoOffline => {
 			data = data.build_client().await?;
-			commands::smith::go_offline(
+			let progress = commands::smith::go_offline(
 				get_keys(
 					args.secret_format,
 					&args.address,
@@ -413,11 +419,12 @@ async fn main() -> Result<(), GcliError> {
 				.unwrap(),
 				data.client(),
 			)
-			.await?
+			.await?;
+			track_progress(progress).await?;
 		}
 		Subcommand::GoOnline => {
 			data = data.build_client().await?;
-			commands::smith::go_online(
+			let progress = commands::smith::go_online(
 				get_keys(
 					args.secret_format,
 					&args.address,
@@ -428,7 +435,8 @@ async fn main() -> Result<(), GcliError> {
 				.unwrap(),
 				data.client(),
 			)
-			.await?
+			.await?;
+			track_progress(progress).await?;
 		}
 		Subcommand::OneshotBalance { account } => {
 			data = data.build_client().await?;
@@ -476,7 +484,8 @@ async fn main() -> Result<(), GcliError> {
 		}
 		Subcommand::SudoSetKey { new_key } => {
 			data = data.build_keypair().build_client().await?;
-			commands::sudo::set_key(data.keypair(), data.client(), new_key).await?
+			let progress = commands::sudo::set_key(data.keypair(), data.client(), new_key).await?;
+			track_progress(progress).await?;
 		}
 		Subcommand::SmithCert { to } => {
 			data = data
@@ -502,7 +511,7 @@ async fn main() -> Result<(), GcliError> {
 				1 => true,
 				_ => panic!("Vote must be written 0 if you disagree, or 1 if you agree."),
 			};
-			commands::collective::technical_committee_vote(
+			let progress = commands::collective::technical_committee_vote(
 				get_keys(
 					args.secret_format,
 					&args.address,
@@ -516,7 +525,8 @@ async fn main() -> Result<(), GcliError> {
 				index,
 				vote,
 			)
-			.await?
+			.await?;
+			track_progress(progress).await?;
 		}
 		Subcommand::Transfer {
 			amount,
@@ -524,7 +534,7 @@ async fn main() -> Result<(), GcliError> {
 			keep_alive,
 		} => {
 			data = data.build_client().await?;
-			commands::transfer::transfer(
+			let progress = commands::transfer::transfer(
 				get_keys(
 					args.secret_format,
 					&args.address,
@@ -538,11 +548,12 @@ async fn main() -> Result<(), GcliError> {
 				dest,
 				keep_alive,
 			)
-			.await?
+			.await?;
+			track_progress(progress).await?;
 		}
 		Subcommand::TransferMultiple { amount, dests } => {
 			data = data.build_client().await?;
-			commands::transfer::transfer_multiple(
+			let progress = commands::transfer::transfer_multiple(
 				get_keys(
 					args.secret_format,
 					&args.address,
@@ -555,11 +566,12 @@ async fn main() -> Result<(), GcliError> {
 				amount,
 				dests,
 			)
-			.await?
+			.await?;
+			track_progress(progress).await?;
 		}
 		Subcommand::UpdateKeys => {
 			data = data.build_client().await?;
-			commands::smith::update_session_keys(
+			let progress = commands::smith::update_session_keys(
 				get_keys(
 					args.secret_format,
 					&args.address,
@@ -570,8 +582,8 @@ async fn main() -> Result<(), GcliError> {
 				.unwrap(),
 				data.client(),
 			)
-			.await
-			.unwrap()
+			.await?;
+			track_progress(progress).await?;
 		}
 		Subcommand::RuntimeInfo => {
 			data = data.build_client().await?.fetch_system_properties().await?;
-- 
GitLab