diff --git a/res/metadata.scale b/res/metadata.scale
index 5ca3e2273e371e7e0f42789281bf44892e42e55b..ff2e4c744170ba9f541fe08fb699d41f1a28eb0a 100644
Binary files a/res/metadata.scale and b/res/metadata.scale differ
diff --git a/src/cache.rs b/src/cache.rs
index bec5baeae59b1fb23c25a7b48cdef09bb110a101..5662335068d0c53b8492a0fdd30d5cd32bbb9556 100644
--- a/src/cache.rs
+++ b/src/cache.rs
@@ -1,5 +1,4 @@
-use crate::indexer::*;
-use crate::*;
+use crate::{indexer::*, *};
 
 use std::collections::{hash_map, HashMap};
 
diff --git a/src/commands/account.rs b/src/commands/account.rs
index 59856a4cb2fbfd8901454ae90340578270ba057a..dc86d706acaceeaa13d5121f537e6e4c2485ca5b 100644
--- a/src/commands/account.rs
+++ b/src/commands/account.rs
@@ -18,7 +18,6 @@ pub enum Subcommand {
 		/// Use universal dividends instead of units
 		#[clap(short = 'u', long = "ud")]
 		is_ud: bool,
-		
 	},
 	/// Transfer the same amount for each space-separated address.
 	/// If an address appears mutiple times, it will get multiple times the same amount
@@ -42,7 +41,7 @@ pub async fn handle_command(data: Data, command: Subcommand) -> anyhow::Result<(
 			amount,
 			dest,
 			keep_alive,
-			is_ud
+			is_ud,
 		} => {
 			commands::transfer::transfer(&data, amount, dest, keep_alive, is_ud).await?;
 		}
diff --git a/src/commands/expire.rs b/src/commands/expire.rs
index 7fe25187a0c087789e1c1964c860f42f1ef29ded..43d7d98379b6cc63dca208451e1cb1fe96a6be90 100644
--- a/src/commands/expire.rs
+++ b/src/commands/expire.rs
@@ -3,7 +3,7 @@ use crate::*;
 use futures::join;
 use std::collections::BTreeMap;
 
-pub async fn monitor_expirations(data: &Data, blocks: u32, sessions: u32) -> anyhow::Result<()> {
+pub async fn monitor_expirations(data: &Data, blocks: u32, _sessions: u32) -> anyhow::Result<()> {
 	let client = data.client();
 	let indexer = data.indexer.clone();
 
@@ -14,7 +14,7 @@ pub async fn monitor_expirations(data: &Data, blocks: u32, sessions: u32) -> any
 		.unwrap();
 	let addr_current_block = runtime::storage().system().number();
 	let addr_current_session = runtime::storage().session().current_index();
-	let (current_block, current_session) = join!(
+	let (current_block, _current_session) = join!(
 		client
 			.storage()
 			.fetch(&addr_current_block, Some(parent_hash)),
@@ -23,47 +23,11 @@ pub async fn monitor_expirations(data: &Data, blocks: u32, sessions: u32) -> any
 			.fetch(&addr_current_session, Some(parent_hash),)
 	);
 	let current_block = current_block?.unwrap_or_default();
-	let current_session = current_session?.unwrap_or_default();
 
 	let end_block = current_block + blocks;
-	let end_session = current_session + sessions;
 
 	let mut identity_cache = cache::IdentityCache::new(client.clone(), indexer);
 
-	// Rotate keys
-	let mut must_rotate_keys_before_iter = client
-		.storage()
-		.iter(
-			runtime::storage()
-				.authority_members()
-				.must_rotate_keys_before(0),
-			10,
-			Some(parent_hash),
-		)
-		.await?;
-	let mut must_rotate_keys_before = BTreeMap::new();
-	while let Some((k, v)) = must_rotate_keys_before_iter.next().await? {
-		let session_index = u32::from_le_bytes(k.as_ref()[40..44].try_into().unwrap());
-		if session_index < end_session {
-			must_rotate_keys_before.insert(session_index - current_session, v);
-		}
-	}
-
-	println!("\nAuthority members:");
-	for (sessions_left, identity_ids) in must_rotate_keys_before {
-		println!("Must rotate keys before {sessions_left} sessions:");
-		for identity_id in identity_ids {
-			println!(
-				"  {} ({})",
-				identity_cache
-					.fetch_identity(identity_id, parent_hash)
-					.await
-					.unwrap_or_else(|_| "?".into()),
-				identity_id
-			);
-		}
-	}
-
 	// Certifications
 	let mut basic_certs_iter = client
 		.storage()
diff --git a/src/commands/smith.rs b/src/commands/smith.rs
index 865a9ed70012f9c5a3bb9310e56b2955168600a1..8a69b7a727f52228d6749889473d12372091e85e 100644
--- a/src/commands/smith.rs
+++ b/src/commands/smith.rs
@@ -86,7 +86,9 @@ pub async fn handle_command(data: Data, command: Subcommand) -> anyhow::Result<(
 				data.client()
 					.storage()
 					.fetch(
-						&runtime::storage().smith_membership().counter_for_membership(),
+						&runtime::storage()
+							.smith_membership()
+							.counter_for_membership(),
 						None,
 					)
 					.await?
@@ -103,7 +105,13 @@ pub async fn rotate_keys(client: &Client) -> Result<SessionKeys, anyhow::Error>
 	client
 		.rpc()
 		.rotate_keys()
-		.await.map_err(|e| anyhow!("Please make sure you are connected to your validator node with the unsafe RPC API enabled {e}"))?
+		.await
+		.map_err(|e| {
+			anyhow!(
+				"Please make sure you are connected to your validator node with the unsafe RPC \
+				 API enabled {e}"
+			)
+		})?
 		.deref()
 		.try_into()
 		.map_err(|e| anyhow!("Session keys have wrong length: {:?}", e))
@@ -190,7 +198,8 @@ pub async fn go_online(data: &Data) -> Result<(), GcliError> {
 		runtime::authority_members::events::MemberGoOnline,
 		StaticTxPayload<runtime::authority_members::calls::GoOnline>,
 	>(data, &runtime::tx().authority_members().go_online())
-	.await.map_err(|e| e.into())
+	.await
+	.map_err(|e| e.into())
 }
 
 /// claim smith membership
diff --git a/src/commands/transfer.rs b/src/commands/transfer.rs
index aca2273a9bd9fbf87d391adb3e5b77d61b030f73..c49512b89dc80b8acab25c1fa10a649fb7e57b87 100644
--- a/src/commands/transfer.rs
+++ b/src/commands/transfer.rs
@@ -12,49 +12,54 @@ pub async fn transfer(
 	keep_alive: bool,
 	is_ud: bool,
 ) -> Result<(), subxt::Error> {
-	let progress = if keep_alive {
-		if is_ud {data.client()
-			.tx()
-			.sign_and_submit_then_watch(
-				&runtime::tx().universal_dividend().transfer_ud(dest.into(), balance),
-				&PairSigner::new(data.keypair()),
-				BaseExtrinsicParamsBuilder::new(),
+	match (keep_alive, is_ud) {
+		(true, false) => {
+			submit_call_and_look_event::<
+				runtime::balances::events::Transfer,
+				StaticTxPayload<runtime::balances::calls::TransferKeepAlive>,
+			>(
+				data,
+				&runtime::tx()
+					.balances()
+					.transfer_keep_alive(dest.into(), balance),
 			)
-			.await?} else {data.client()
-			.tx()
-			.sign_and_submit_then_watch(
+			.await
+		}
+		(false, false) => {
+			submit_call_and_look_event::<
+				runtime::balances::events::Transfer,
+				StaticTxPayload<runtime::balances::calls::Transfer>,
+			>(
+				data,
 				&runtime::tx().balances().transfer(dest.into(), balance),
-				&PairSigner::new(data.keypair()),
-				BaseExtrinsicParamsBuilder::new(),
 			)
-			.await?}
-	} else {
-		if is_ud {data.client()
-			.tx()
-			.sign_and_submit_then_watch(
-				&runtime::tx().universal_dividend().transfer_ud_keep_alive(dest.into(), balance),
-				&PairSigner::new(data.keypair()),
-				BaseExtrinsicParamsBuilder::new(),
+			.await
+		}
+		(true, true) => {
+			submit_call_and_look_event::<
+				runtime::balances::events::Transfer,
+				StaticTxPayload<runtime::universal_dividend::calls::TransferUdKeepAlive>,
+			>(
+				data,
+				&runtime::tx()
+					.universal_dividend()
+					.transfer_ud_keep_alive(dest.into(), balance),
 			)
-			.await?} else {data.client()
-			.tx()
-			.sign_and_submit_then_watch(
-				&runtime::tx().balances().transfer_keep_alive(dest.into(), balance),
-				&PairSigner::new(data.keypair()),
-				BaseExtrinsicParamsBuilder::new(),
+			.await
+		}
+		(false, true) => {
+			submit_call_and_look_event::<
+				runtime::balances::events::Transfer,
+				StaticTxPayload<runtime::universal_dividend::calls::TransferUd>,
+			>(
+				data,
+				&runtime::tx()
+					.universal_dividend()
+					.transfer_ud(dest.into(), balance),
 			)
-			.await?}
-	};
-
-	if data.args.no_wait {
-		return Ok(());
+			.await
+		}
 	}
-	let events = track_progress(progress).await?;
-
-	if let Some(e) = events.find_first::<runtime::balances::events::Transfer>()? {
-		println!("{e:?}");
-	}
-	Ok(())
 }
 
 /// transfer balance to multiple target
diff --git a/src/indexer.rs b/src/indexer.rs
index 25473cbc76a79f2854252270b8739cb805eb9c98..51677d664cf82429ad9c3325bac9044a8c2ddb40 100644
--- a/src/indexer.rs
+++ b/src/indexer.rs
@@ -1,5 +1,4 @@
-use graphql_client::reqwest::post_graphql;
-use graphql_client::GraphQLQuery;
+use graphql_client::{reqwest::post_graphql, GraphQLQuery};
 
 use crate::*;
 
diff --git a/src/main.rs b/src/main.rs
index b976245d4cd83c916145e98da74b9883ee1433dc..e4c0b008508f7c00651d44bf841772ccc9bd8b9b 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -15,9 +15,11 @@ use keys::*;
 use runtime_config::*;
 use serde::Deserialize;
 use sp_core::{sr25519::Pair, Pair as _};
-use subxt::blocks::ExtrinsicEvents;
-use subxt::events::StaticEvent;
-use subxt::tx::{BaseExtrinsicParamsBuilder, PairSigner, TxPayload, TxStatus, StaticTxPayload};
+use subxt::{
+	blocks::ExtrinsicEvents,
+	events::StaticEvent,
+	tx::{BaseExtrinsicParamsBuilder, PairSigner, StaticTxPayload, TxPayload, TxStatus},
+};
 use utils::*;
 
 /// define command line arguments
diff --git a/src/runtime_config.rs b/src/runtime_config.rs
index e1c2a19dfe8a0a396a350a0cafac0d2b03861d1b..d62c5e1172f96d69ab3eed69296462a8a4d0ff31 100644
--- a/src/runtime_config.rs
+++ b/src/runtime_config.rs
@@ -14,7 +14,8 @@ pub type Client = subxt::OnlineClient<Runtime>;
 pub type AccountId = subxt::ext::sp_runtime::AccountId32;
 pub type TxProgress = subxt::tx::TxProgress<Runtime, Client>;
 pub type Balance = u64;
-pub type AccountData = runtime::runtime_types::pallet_duniter_account::types::AccountData<Balance>;
+pub type AccountData =
+	runtime::runtime_types::pallet_duniter_account::types::AccountData<Balance, u32>;
 pub type AccountInfo = runtime::runtime_types::frame_system::AccountInfo<u32, AccountData>;
 pub type Hash = sp_core::H256;