diff --git a/README.md b/README.md
index d888442cb76701bc9db547eb19796d583b2d9e76..8b082058984c748a53d2f7ba913d003697475f1a 100644
--- a/README.md
+++ b/README.md
@@ -16,11 +16,11 @@ If using a different runtime, update the metadata for the client to compile:
 
 Send 10 ÄžD from Alice to Ferdie:
 
-	cargo run -- --url ws://localhost:9944 --secret //Alice transfer 1000 5CiPPseXPECbkjWCa6MnjNokrgYjMqmKndv2rSnekmSK2DjL
+	cargo run -- --url ws://localhost:9944 --secret //Alice account transfer 1000 5CiPPseXPECbkjWCa6MnjNokrgYjMqmKndv2rSnekmSK2DjL
 
 List certifications and session keys that will expire within one month:
 
-	cargo run -- --url wss://gdev.p2p.legal:443/ws expire --blocks 432000
+	cargo run -- --url wss://gdev.p2p.legal:443/ws smith expire --blocks 432000
 
 For more examples see [in the example file](./doc/example.md).
 
@@ -55,8 +55,8 @@ Now the command `duniter-rpc` will open an SSH session and a bridge to your RPC
 When your node is ready to forge blocks, rotate keys and go online:
 
 ```bash
-gcli --secret "my secret phrase" update-keys
-gcli --secret "my secret phrase" go-online
+gcli --secret "my secret phrase" smith update-keys
+gcli --secret "my secret phrase" smith go-online
 ```
 
 ### Keys
diff --git a/doc/example.md b/doc/example.md
index d66db7671b8f1121e6813403626763a780c90331..5a1816a7e0d81756c8012f1b6fa7d4c8a4a0f342 100644
--- a/doc/example.md
+++ b/doc/example.md
@@ -42,11 +42,9 @@ gcli --network gdev config save
 # get duniter current block
 gcli current-block
 # get balance of test1 account
-gcli --address 5FeggKqw2AbnGZF9Y9WPM2QTgzENS3Hit94Ewgmzdg5a3LNa balance
+gcli --address 5FeggKqw2AbnGZF9Y9WPM2QTgzENS3Hit94Ewgmzdg5a3LNa account balance
 # get information about test1 identity (needs indexer)
 gcli identity get --username test1
-# show address of given secret
-gcli --secret "pipe paddle ketchup filter life ice feel embody glide quantum ride usage"//2 show-address
 ```
 
 ## Indexer commands
diff --git a/src/cache.rs b/src/cache.rs
index 36d8c724a9c9eed3651055fc1f233bfa2832abb8..bec5baeae59b1fb23c25a7b48cdef09bb110a101 100644
--- a/src/cache.rs
+++ b/src/cache.rs
@@ -1,7 +1,6 @@
 use crate::indexer::*;
 use crate::*;
 
-use anyhow::{anyhow, Result};
 use std::collections::{hash_map, HashMap};
 
 pub struct IdentityCache {
@@ -23,7 +22,7 @@ impl IdentityCache {
 		&mut self,
 		identity_id: u32,
 		parent_hash: sp_core::H256,
-	) -> Result<String> {
+	) -> anyhow::Result<String> {
 		Ok(match self.identities.entry(identity_id) {
 			hash_map::Entry::Occupied(entry) => entry.get().clone(),
 			hash_map::Entry::Vacant(entry) => entry
diff --git a/src/commands/account.rs b/src/commands/account.rs
index 101e088a91d2c05e68d2fee63217f20ce00cc986..0d5add6c2d0ea9993a1db3f7888acaa94bad4f40 100644
--- a/src/commands/account.rs
+++ b/src/commands/account.rs
@@ -1,5 +1,69 @@
 use crate::*;
 
+/// define account subcommands
+#[derive(Clone, Default, Debug, clap::Parser)]
+pub enum Subcommand {
+	/// Fetch account balance
+	#[default]
+	Balance,
+	/// Transfer some currency to an account
+	Transfer {
+		/// Amount to transfer
+		amount: u64,
+		/// Destination address
+		dest: AccountId,
+		/// Prevent from going below account existential deposit
+		#[clap(short = 'k', long = "keep-alive")]
+		keep_alive: bool,
+	},
+	/// Transfer the same amount for each space-separated address.
+	/// If an address appears mutiple times, it will get multiple times the same amount
+	TransferMultiple {
+		/// Amount given to each destination address
+		amount: u64,
+		/// List of target addresses
+		dests: Vec<AccountId>,
+	},
+}
+
+/// handle account commands
+pub async fn handle_command(data: Data, command: Subcommand) -> anyhow::Result<()> {
+	let mut data = data.build_client().await?.build_indexer().await?;
+	match command {
+		Subcommand::Balance => {
+			data = data
+				.build_address()
+				.fetch_system_properties()
+				.await?;
+			commands::account::get_balance(data).await?
+		}
+		Subcommand::Transfer {
+			amount,
+			dest,
+			keep_alive,
+		} => {
+			data = data.build_client().await?;
+			commands::transfer::transfer(
+				&data,
+				amount,
+				dest,
+				keep_alive,
+			)
+			.await?;
+		}
+		Subcommand::TransferMultiple { amount, dests } => {
+			data = data.build_client().await?;
+			commands::transfer::transfer_multiple(&data,
+				amount,
+				dests,
+			)
+			.await?;
+		}
+	};
+
+	Ok(())
+}
+
 /// get balance
 pub async fn get_balance(data: Data) -> Result<(), anyhow::Error> {
 	let account_id = data.address();
diff --git a/src/commands/collective.rs b/src/commands/collective.rs
index 698be58e8a84f85c45e9c2457204b22a50474df1..92c8da45bc325ed598201bf1865ceb1f3a79b5b2 100644
--- a/src/commands/collective.rs
+++ b/src/commands/collective.rs
@@ -1,7 +1,6 @@
 use crate::*;
 
 use anyhow::Result;
-use subxt::tx::{BaseExtrinsicParamsBuilder, PairSigner};
 
 /// define technical committee subcommands
 #[derive(Clone, Default, Debug, clap::Parser)]
diff --git a/src/commands/expire.rs b/src/commands/expire.rs
index 96004ed629963911ff5fc1f802c45a1d6ad3d71c..7fe25187a0c087789e1c1964c860f42f1ef29ded 100644
--- a/src/commands/expire.rs
+++ b/src/commands/expire.rs
@@ -1,10 +1,9 @@
 use crate::*;
 
-use anyhow::Result;
 use futures::join;
 use std::collections::BTreeMap;
 
-pub async fn monitor_expirations(data: &Data, blocks: u32, sessions: u32) -> Result<()> {
+pub async fn monitor_expirations(data: &Data, blocks: u32, sessions: u32) -> anyhow::Result<()> {
 	let client = data.client();
 	let indexer = data.indexer.clone();
 
diff --git a/src/commands/identity.rs b/src/commands/identity.rs
index 32b5fc8744396db03c1a712c3482ccf9ed263005..81a08baf28f7242f8c869535173e53f537cc32f9 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 sp_core::{crypto::AccountId32, sr25519::Pair};
 use std::str::FromStr;
 
 /// define identity subcommands
@@ -84,7 +83,7 @@ pub async fn handle_command(data: Data, command: Subcommand) -> anyhow::Result<(
 /// get identity
 pub async fn get_identity(
 	data: &Data,
-	mut account_id: Option<AccountId32>,
+	mut account_id: Option<AccountId>,
 	mut identity_id: Option<u32>,
 	mut username: Option<String>,
 ) -> Result<(), anyhow::Error> {
@@ -107,7 +106,7 @@ pub async fn get_identity(
 			))?;
 			if let Some(pubkey) = indexer.pubkey_by_username(username).await? {
 				// convert string to accountid
-				let fetched_account_id = AccountId32::from_str(&pubkey).map_err(|e| anyhow!(e))?;
+				let fetched_account_id = AccountId::from_str(&pubkey).map_err(|e| anyhow!(e))?;
 				// in the future, also ask indexer the identity index
 				identity_id = get_idty_index_by_account_id(client, &fetched_account_id).await?;
 				account_id = Some(fetched_account_id);
@@ -127,7 +126,7 @@ pub async fn get_identity(
 		"Account id:  {}",
 		account_id
 			.as_ref()
-			.map_or(String::new(), AccountId32::to_string)
+			.map_or(String::new(), AccountId::to_string)
 	);
 	println!(
 		"Identity id: {}",
@@ -145,7 +144,7 @@ pub async fn get_identity(
 /// get identity index by account id
 pub async fn get_idty_index_by_account_id(
 	client: &Client,
-	account_id: &AccountId32,
+	account_id: &AccountId,
 ) -> Result<Option<u32>, anyhow::Error> {
 	Ok(client
 		.storage()
@@ -160,7 +159,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>>, anyhow::Error> {
+) -> Result<Option<IdtyValue<u32, AccountId, IdtyData>>, anyhow::Error> {
 	Ok(client
 		.storage()
 		.fetch(&runtime::storage().identity().identities(idty_index), None)
@@ -171,7 +170,7 @@ pub async fn get_identity_by_index(
 pub async fn create_identity(
 	pair: Pair,
 	client: &Client,
-	target: AccountId32,
+	target: AccountId,
 ) -> Result<(), subxt::Error> {
 	let progress = client
 		.tx()
diff --git a/src/commands/net_test.rs b/src/commands/net_test.rs
index 228469c5b2388e1a3725a061207cd2df5c01bfa6..e1c3c38ad4eafb2996e6a207a5e7c971cb94d5bf 100644
--- a/src/commands/net_test.rs
+++ b/src/commands/net_test.rs
@@ -1,18 +1,14 @@
 use crate::*;
 
-use anyhow::{anyhow, Result};
-use sp_core::{crypto::AccountId32, sr25519::Pair, DeriveJunction, Pair as _};
-use subxt::{
-	ext::sp_runtime::MultiAddress,
-	tx::{BaseExtrinsicParamsBuilder, PairSigner},
-};
+use sp_core::DeriveJunction;
+use subxt::ext::sp_runtime::MultiAddress;
 
 pub async fn repart(
 	pair: Pair,
 	client: &Client,
 	target: u32,
 	actual_repart: Option<u32>,
-) -> Result<()> {
+) -> anyhow::Result<()> {
 	let mut pairs = Vec::new();
 	for i in actual_repart.unwrap_or_default()..target {
 		let pair_i = pair
@@ -48,9 +44,9 @@ pub async fn repart(
 	Ok(())
 }
 
-pub async fn spam_roll(pair: Pair, client: &Client, actual_repart: usize) -> Result<()> {
+pub async fn spam_roll(pair: Pair, client: &Client, actual_repart: usize) -> anyhow::Result<()> {
 	let mut nonce = 0;
-	let mut pairs = Vec::<(PairSigner<Runtime, Pair>, AccountId32)>::with_capacity(actual_repart);
+	let mut pairs = Vec::<(PairSigner<Runtime, Pair>, AccountId)>::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)
@@ -63,7 +59,7 @@ pub async fn spam_roll(pair: Pair, client: &Client, actual_repart: usize) -> Res
 	loop {
 		let mut watchers = Vec::with_capacity(actual_repart);
 		for i in 0..(actual_repart - 1) {
-			let dest: AccountId32 = pairs[i + 1].1.clone();
+			let dest: AccountId = pairs[i + 1].1.clone();
 			let watcher = client
 				.tx()
 				.create_signed_with_nonce(
@@ -78,7 +74,7 @@ pub async fn spam_roll(pair: Pair, client: &Client, actual_repart: usize) -> Res
 			log::info!("send 1 cent from //{} to //{}", i, i + 1);
 			watchers.push(watcher);
 		}
-		let dest: AccountId32 = pairs[0].1.clone();
+		let dest: AccountId = pairs[0].1.clone();
 		let watcher = client
 			.tx()
 			.sign_and_submit_then_watch(
diff --git a/src/commands/smith.rs b/src/commands/smith.rs
index a05f677e28035432e722d211d2a51d0bb97021e7..49670f1a339cd8961c6637ff68a54051c3ceafa0 100644
--- a/src/commands/smith.rs
+++ b/src/commands/smith.rs
@@ -1,7 +1,6 @@
 use crate::*;
 
 use std::ops::Deref;
-use subxt::tx::{BaseExtrinsicParamsBuilder, PairSigner};
 
 type SessionKeys = [u8; 128];
 
diff --git a/src/commands/sudo.rs b/src/commands/sudo.rs
index 301ce6cdc98203a0a315938de0cc292903c42bb6..7182fdfd1f1df13b05016400f985f8cd797a353a 100644
--- a/src/commands/sudo.rs
+++ b/src/commands/sudo.rs
@@ -1,14 +1,7 @@
 use crate::*;
 
-use sp_core::{crypto::AccountId32, sr25519::Pair};
-use subxt::tx::{BaseExtrinsicParamsBuilder, PairSigner};
-
 /// set sudo key
-pub async fn set_key(
-	pair: Pair,
-	client: &Client,
-	new_key: AccountId32,
-) -> Result<(), subxt::Error> {
+pub async fn set_key(pair: Pair, client: &Client, new_key: AccountId) -> Result<(), subxt::Error> {
 	let progress = client
 		.tx()
 		.sign_and_submit_then_watch(
diff --git a/src/commands/transfer.rs b/src/commands/transfer.rs
index c0ebc081276debf7d95bd5ec255fefd3ff7d6931..ca6ab53aa1f9ac22c452677c144d9773a0f9b606 100644
--- a/src/commands/transfer.rs
+++ b/src/commands/transfer.rs
@@ -1,36 +1,33 @@
 use crate::*;
 
-use sp_core::{crypto::AccountId32, sr25519::Pair};
-use subxt::tx::{BaseExtrinsicParamsBuilder, PairSigner};
-
 #[cfg(any(feature = "dev", feature = "gdev"))] // find how to get runtime calls
 type Call = runtime::runtime_types::gdev_runtime::RuntimeCall;
 type BalancesCall = runtime::runtime_types::pallet_balances::pallet::Call;
 
+/// transfer balance to target
 pub async fn transfer(
-	pair: Pair,
-	client: &Client,
+	data: &Data,
 	balance: u64,
-	dest: AccountId32,
+	dest: AccountId,
 	keep_alive: bool,
 ) -> Result<(), subxt::Error> {
 	let progress = if keep_alive {
-		client
+		data.client()
 			.tx()
 			.sign_and_submit_then_watch(
 				&runtime::tx().balances().transfer(dest.into(), balance),
-				&PairSigner::new(pair),
+				&PairSigner::new(data.keypair()),
 				BaseExtrinsicParamsBuilder::new(),
 			)
 			.await?
 	} else {
-		client
+		data.client()
 			.tx()
 			.sign_and_submit_then_watch(
 				&runtime::tx()
 					.balances()
 					.transfer_keep_alive(dest.into(), balance),
-				&PairSigner::new(pair),
+				&PairSigner::new(data.keypair()),
 				BaseExtrinsicParamsBuilder::new(),
 			)
 			.await?
@@ -44,11 +41,11 @@ pub async fn transfer(
 	Ok(())
 }
 
+/// transfer balance to multiple target
 pub async fn transfer_multiple(
-	pair: Pair,
-	client: &Client,
+	data: &Data,
 	amount: u64,
-	dests: Vec<AccountId32>,
+	dests: Vec<AccountId>,
 ) -> Result<(), subxt::Error> {
 	// build the list of transactions from the destination accounts
 	let transactions: Vec<Call> = dests
@@ -62,11 +59,12 @@ pub async fn transfer_multiple(
 		.collect();
 
 	// wrap these calls in a batch call
-	let progress = client
+	let progress = data
+		.client()
 		.tx()
 		.sign_and_submit_then_watch(
 			&runtime::tx().utility().batch(transactions),
-			&PairSigner::new(pair.clone()),
+			&PairSigner::new(data.keypair()),
 			BaseExtrinsicParamsBuilder::new(),
 		)
 		.await?;
diff --git a/src/keys.rs b/src/keys.rs
index fa75289ed70775d3b3dbaeb1111da00423075ff9..8df0ebae6656bd7ac0d58b29c7eb91cd739509df 100644
--- a/src/keys.rs
+++ b/src/keys.rs
@@ -1,9 +1,7 @@
-use anyhow::{anyhow, Result};
+use crate::*;
+
 use clap::builder::OsStr;
-use sp_core::{
-	crypto::{AccountId32, Pair as _, Ss58Codec},
-	sr25519::Pair,
-};
+use sp_core::crypto::Ss58Codec;
 use std::str::FromStr;
 
 #[allow(dead_code)]
@@ -50,7 +48,7 @@ impl From<SecretFormat> for OsStr {
 	}
 }
 
-pub fn pair_from_str(secret_format: SecretFormat, secret: &str) -> Result<Pair> {
+pub fn pair_from_str(secret_format: SecretFormat, secret: &str) -> anyhow::Result<Pair> {
 	match secret_format {
 		SecretFormat::Seed => {
 			let mut seed = [0; 32];
@@ -81,12 +79,12 @@ pub fn get_keys(
 	address: &Option<String>,
 	secret: &Option<String>,
 	needed_keys: NeededKeys,
-) -> Result<(Option<AccountId32>, Option<Pair>)> {
+) -> anyhow::Result<(Option<AccountId>, Option<Pair>)> {
 	// Get from args
 	let mut account_id = match (address, secret) {
 		(Some(address), Some(secret)) => {
 			let pair = pair_from_str(secret_format, secret)?;
-			let address = AccountId32::from_string(address)
+			let address = AccountId::from_string(address)
 				.map_err(|_| anyhow!("Invalid address {}", address))?;
 			assert_eq!(
 				address,
@@ -99,9 +97,9 @@ pub fn get_keys(
 			let pair = pair_from_str(secret_format, secret)?;
 			return Ok((Some(pair.public().into()), Some(pair)));
 		}
-		(Some(address), None) => Some(
-			AccountId32::from_str(address).map_err(|_| anyhow!("Invalid address {}", address))?,
-		),
+		(Some(address), None) => {
+			Some(AccountId::from_str(address).map_err(|_| anyhow!("Invalid address {}", address))?)
+		}
 		(None, None) => None,
 	};
 
diff --git a/src/main.rs b/src/main.rs
index 410f2a60408ef93e872ee97a3bab7738f1e4af05..6074dc48c119b838a1a621b25bcaae35cecbbe21 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -157,11 +157,6 @@ impl From<anyhow::Error> for GcliError {
 
 #[derive(Clone, Debug, clap::Subcommand, Default)]
 pub enum Subcommand {
-	/// Fetch account balance
-	#[default]
-	Balance,
-	/// Show address corresponding to given arguments
-	ShowAddress,
 	#[clap(hide = true)]
 	Repart {
 		// Number of transactions per block to target
@@ -174,27 +169,14 @@ pub enum Subcommand {
 	SpamRoll {
 		actual_repart: usize,
 	},
-	Transfer {
-		/// Amount to transfer
-		amount: u64,
-		/// Destination address
-		dest: AccountId,
-		/// Prevent from going below account existential deposit
-		#[clap(short = 'k', long = "keep-alive")]
-		keep_alive: bool,
-	},
-	/// Transfer the same amount for each space-separated address.
-	/// If an address appears mutiple times, it will get multiple times the same amount
-	TransferMultiple {
-		/// Amount given to each destination address
-		amount: u64,
-		/// List of target addresses
-		dests: Vec<AccountId>,
-	},
 	/// Get information about runtime
 	RuntimeInfo,
+	#[default]
 	/// Check current block
 	CurrentBlock,
+	/// Account subcommands
+	#[clap(subcommand)]
+	Account(commands::account::Subcommand),
 	/// Identity subcommands
 	#[clap(subcommand)]
 	Identity(commands::identity::Subcommand),
@@ -228,19 +210,6 @@ async fn main() -> Result<(), GcliError> {
 	let mut data = Data::new(args.clone());
 
 	match args.subcommand {
-		Subcommand::Balance => {
-			data = data
-				.build_address()
-				.build_client()
-				.await?
-				.fetch_system_properties()
-				.await?;
-			commands::account::get_balance(data).await?
-		}
-		Subcommand::ShowAddress => {
-			data = data.build_address();
-			println!("address is: {}", data.address());
-		}
 		Subcommand::Repart {
 			target,
 			actual_repart,
@@ -277,45 +246,6 @@ async fn main() -> Result<(), GcliError> {
 			)
 			.await?
 		}
-		Subcommand::Transfer {
-			amount,
-			dest,
-			keep_alive,
-		} => {
-			data = data.build_client().await?;
-			commands::transfer::transfer(
-				get_keys(
-					args.secret_format,
-					&args.address,
-					&args.secret,
-					NeededKeys::Secret,
-				)?
-				.1
-				.unwrap(),
-				data.client(),
-				amount,
-				dest,
-				keep_alive,
-			)
-			.await?;
-		}
-		Subcommand::TransferMultiple { amount, dests } => {
-			data = data.build_client().await?;
-			commands::transfer::transfer_multiple(
-				get_keys(
-					args.secret_format,
-					&args.address,
-					&args.secret,
-					NeededKeys::Secret,
-				)?
-				.1
-				.unwrap(),
-				data.client(),
-				amount,
-				dests,
-			)
-			.await?;
-		}
 		Subcommand::RuntimeInfo => {
 			data = data.build_client().await?.fetch_system_properties().await?;
 			commands::runtime::runtime_info(data).await;
@@ -332,6 +262,7 @@ async fn main() -> Result<(), GcliError> {
 					.unwrap()
 			);
 		}
+		Subcommand::Account(subcommand) => commands::account::handle_command(data, subcommand).await?,
 		Subcommand::Identity(subcommand) => commands::identity::handle_command(data, subcommand).await?,
 		Subcommand::Smith(subcommand) => commands::smith::handle_command(data, subcommand).await?,
 		Subcommand::Tech(subcommand) => commands::collective::handle_command(data, subcommand).await?,