diff --git a/src/commands/blockchain.rs b/src/commands/blockchain.rs
index 626ace7ae4becfbcd301de8d3e89532d1d6cb7e2..85d53d55b49a7a01538f1a07b3fc29286c31039f 100644
--- a/src/commands/blockchain.rs
+++ b/src/commands/blockchain.rs
@@ -1,5 +1,57 @@
 use crate::*;
 
+/// define blockchain subcommands
+#[derive(Clone, Default, Debug, clap::Parser)]
+pub enum Subcommand {
+	#[clap(hide = true)]
+	Repart {
+		// Number of transactions per block to target
+		target: u32,
+		#[clap(short = 'o', long = "old-repart")]
+		// Old/actual repartition
+		actual_repart: Option<u32>,
+	},
+	#[clap(hide = true)]
+	SpamRoll { actual_repart: usize },
+	/// Get information about runtime
+	RuntimeInfo,
+	/// Check current block
+	#[default]
+	CurrentBlock,
+}
+
+/// handle blockchain 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::Repart {
+			target,
+			actual_repart,
+		} => {
+			commands::net_test::repart(&data, target, actual_repart).await?
+		}
+		Subcommand::SpamRoll { actual_repart } => {
+			commands::net_test::spam_roll(&data, actual_repart).await?
+		}
+		Subcommand::RuntimeInfo => {
+			data = data.fetch_system_properties().await?;
+			commands::runtime::runtime_info(data).await;
+		}
+		Subcommand::CurrentBlock => {
+			println!(
+				"current block on {}: {}",
+				data.cfg.duniter_endpoint,
+				data.client()
+					.storage()
+					.fetch(&runtime::storage().system().number(), None)
+					.await?
+					.unwrap()
+			);
+		}
+	}
+	Ok(())
+}
+
 /// get genesis hash
 pub async fn fetch_genesis_hash(data: &Data) -> Result<Hash, anyhow::Error> {
 	Ok(data
diff --git a/src/commands/net_test.rs b/src/commands/net_test.rs
index e1c3c38ad4eafb2996e6a207a5e7c971cb94d5bf..f216b6fb5fc513a67dce0c5b179758744155a3a4 100644
--- a/src/commands/net_test.rs
+++ b/src/commands/net_test.rs
@@ -4,14 +4,13 @@ use sp_core::DeriveJunction;
 use subxt::ext::sp_runtime::MultiAddress;
 
 pub async fn repart(
-	pair: Pair,
-	client: &Client,
+	data: &Data,
 	target: u32,
 	actual_repart: Option<u32>,
 ) -> anyhow::Result<()> {
 	let mut pairs = Vec::new();
 	for i in actual_repart.unwrap_or_default()..target {
-		let pair_i = pair
+		let pair_i = data.keypair()
 			.derive(std::iter::once(DeriveJunction::hard::<u32>(i)), None)
 			.map_err(|_| anyhow!("Fail to derive //{}", i))?
 			.0;
@@ -29,7 +28,7 @@ pub async fn repart(
 			.await?;
 		signer.increment_nonce();*/
 
-		if let Some(pair_i_account) = client
+		if let Some(pair_i_account) = data.client()
 			.storage()
 			.fetch(
 				&runtime::storage().system().account(&pair_i.public().into()),
@@ -44,11 +43,12 @@ pub async fn repart(
 	Ok(())
 }
 
-pub async fn spam_roll(pair: Pair, client: &Client, actual_repart: usize) -> anyhow::Result<()> {
+pub async fn spam_roll(data: &Data, actual_repart: usize) -> anyhow::Result<()> {
+	let client = data.client();
 	let mut nonce = 0;
 	let mut pairs = Vec::<(PairSigner<Runtime, Pair>, AccountId)>::with_capacity(actual_repart);
 	for i in 0..actual_repart {
-		let pair_i = pair
+		let pair_i = data.keypair()
 			.derive(std::iter::once(DeriveJunction::hard::<u32>(i as u32)), None)
 			.map_err(|_| anyhow!("Fail to derive //{}", i))?
 			.0;
diff --git a/src/main.rs b/src/main.rs
index ce62d6ea95e3ae8412da4576bf80fbff48d64de5..071115e16afcd884946a77aaa5189f00ecf469d5 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -45,7 +45,7 @@ pub struct Args {
 	/// Overwrite duniter websocket RPC endpoint
 	#[clap(short, long)]
 	url: Option<String>,
-	/// Chose target network
+	/// Target network (local, gdev, gtest...)
 	#[clap(short, long)]
 	network: Option<String>,
 }
@@ -53,43 +53,35 @@ pub struct Args {
 /// define subcommands
 #[derive(Clone, Debug, clap::Subcommand, Default)]
 pub enum Subcommand {
-	#[clap(hide = true)]
-	Repart {
-		// Number of transactions per block to target
-		target: u32,
-		#[clap(short = 'o', long = "old-repart")]
-		// Old/actual repartition
-		actual_repart: Option<u32>,
-	},
-	#[clap(hide = true)]
-	SpamRoll { actual_repart: usize },
-	/// Get information about runtime
-	RuntimeInfo,
+	/// Nothing
 	#[default]
-	/// Check current block
-	CurrentBlock,
-	/// Account subcommands
+	#[clap(hide = true)]
+	DoNothing,
+	/// Account (balance, transfer...)
 	#[clap(subcommand)]
 	Account(commands::account::Subcommand),
-	/// Identity subcommands
+	/// Identity (get, create, confirm, revoke...)
 	#[clap(subcommand)]
 	Identity(commands::identity::Subcommand),
-	/// Smith subcommands
+	/// Smith (certify, go-online, go-offline...)
 	#[clap(subcommand)]
 	Smith(commands::smith::Subcommand),
-	/// Tech subcommands
+	/// Tech (list members, proposals, vote...)
 	#[clap(subcommand)]
 	Tech(commands::collective::Subcommand),
-	/// Universal Dividend subcommands
+	/// Universal Dividend (claim...)
 	#[clap(subcommand)]
 	Ud(commands::ud::Subcommand),
-	/// Oneshot account subcommands
+	/// Oneshot account (balance, create, consume...)
 	#[clap(subcommand)]
 	Oneshot(commands::oneshot::Subcommand),
-	/// Indexer subcommands
+	/// Blockchain (current block, runtime info...)
+	#[clap(subcommand)]
+	Blockchain(commands::blockchain::Subcommand),
+	/// Indexer (check, latest block)
 	#[clap(subcommand)]
 	Indexer(indexer::Subcommand),
-	/// Config subcommands
+	/// Config (show, save...)
 	#[clap(subcommand)]
 	Config(conf::Subcommand),
 }
@@ -101,63 +93,11 @@ async fn main() -> Result<(), GcliError> {
 	env_logger::init();
 
 	// parse argument and initialize data
-	let args = Args::parse();
-	let mut data = Data::new(args.clone());
+	let data = Data::new(Args::parse());
 
 	// match subcommands
-	match args.subcommand {
-		Subcommand::Repart {
-			target,
-			actual_repart,
-		} => {
-			data = data.build_client().await?;
-			commands::net_test::repart(
-				get_keys(
-					args.secret_format,
-					&args.address,
-					&args.secret,
-					NeededKeys::Secret,
-				)?
-				.1
-				.unwrap(),
-				data.client(),
-				target,
-				actual_repart,
-			)
-			.await?
-		}
-		Subcommand::SpamRoll { actual_repart } => {
-			data = data.build_client().await?;
-			commands::net_test::spam_roll(
-				get_keys(
-					args.secret_format,
-					&args.address,
-					&args.secret,
-					NeededKeys::Secret,
-				)?
-				.1
-				.unwrap(),
-				data.client(),
-				actual_repart,
-			)
-			.await?
-		}
-		Subcommand::RuntimeInfo => {
-			data = data.build_client().await?.fetch_system_properties().await?;
-			commands::runtime::runtime_info(data).await;
-		}
-		Subcommand::CurrentBlock => {
-			data = data.build_client().await?;
-			println!(
-				"current block on {}: {}",
-				data.cfg.duniter_endpoint,
-				data.client()
-					.storage()
-					.fetch(&runtime::storage().system().number(), None)
-					.await?
-					.unwrap()
-			);
-		}
+	match data.args.subcommand.clone() {
+		Subcommand::DoNothing => {}
 		Subcommand::Account(subcommand) => {
 			commands::account::handle_command(data, subcommand).await?
 		}
@@ -172,6 +112,7 @@ async fn main() -> Result<(), GcliError> {
 		Subcommand::Oneshot(subcommand) => {
 			commands::oneshot::handle_command(data, subcommand).await?
 		}
+		Subcommand::Blockchain(subcommand) => commands::blockchain::handle_command(data, subcommand).await?,
 		Subcommand::Indexer(subcommand) => indexer::handle_command(data, subcommand).await?,
 		Subcommand::Config(subcommand) => conf::handle_command(data, subcommand)?,
 	}