From e1d90819e01b800cea6f9147ad41b34bdb6d0eb2 Mon Sep 17 00:00:00 2001
From: Hugo Trentesaux <hugo@trentesaux.fr>
Date: Tue, 6 Jun 2023 15:10:12 +0200
Subject: [PATCH] WIP refac argument parsing

---
 src/commands/collective.rs |  23 +++-----
 src/commands/expire.rs     |  25 ++-------
 src/commands/identity.rs   |  17 ++----
 src/commands/net_test.rs   |   4 +-
 src/commands/oneshot.rs    |   8 +--
 src/commands/smith.rs      |  34 +++++-------
 src/commands/transfer.rs   |   4 +-
 src/conf.rs                |  43 ++++++++-------
 src/data.rs                |  30 ++++++++---
 src/main.rs                | 106 ++++++++++++++++++-------------------
 10 files changed, 133 insertions(+), 161 deletions(-)

diff --git a/src/commands/collective.rs b/src/commands/collective.rs
index 724a2d0..d95d9df 100644
--- a/src/commands/collective.rs
+++ b/src/commands/collective.rs
@@ -1,30 +1,19 @@
-use crate::indexer::*;
 use crate::*;
 
 use anyhow::Result;
 use sp_core::{sr25519::Pair, H256};
 use subxt::tx::{BaseExtrinsicParamsBuilder, PairSigner};
 
-pub async fn technical_committee_members(client: Client, args: &Args) -> Result<()> {
+pub async fn technical_committee_members(data: &Data) -> Result<()> {
+	let client = data.client();
+	let indexer = data.indexer.clone();
+
 	let parent_hash = client
 		.storage()
 		.fetch(&runtime::storage().system().parent_hash(), None)
 		.await?
 		.unwrap();
 
-	let gql_client = reqwest::Client::builder()
-		.user_agent("gcli/0.1.0")
-		.build()?;
-
-	let indexer = if args.no_indexer {
-		None
-	} else {
-		Some(Indexer {
-			gql_client,
-			gql_url: args.indexer.clone(),
-		})
-	};
-
 	for account_id in client
 		.storage()
 		.fetch(
@@ -64,7 +53,7 @@ pub async fn technical_committee_members(client: Client, args: &Args) -> Result<
 // TODO:
 // * better formatting (format pubkeys to SS58 and add usernames)
 // * display proposals indices
-pub async fn technical_committee_proposals(client: Client) -> Result<()> {
+pub async fn technical_committee_proposals(client: &Client) -> Result<()> {
 	let parent_hash = client
 		.storage()
 		.fetch(&runtime::storage().system().parent_hash(), None)
@@ -92,7 +81,7 @@ pub async fn technical_committee_proposals(client: Client) -> Result<()> {
 
 pub async fn technical_committee_vote(
 	pair: Pair,
-	client: Client,
+	client: &Client,
 	proposal_hash: H256,
 	proposal_index: u32,
 	vote: bool,
diff --git a/src/commands/expire.rs b/src/commands/expire.rs
index 7cc9647..96004ed 100644
--- a/src/commands/expire.rs
+++ b/src/commands/expire.rs
@@ -1,19 +1,12 @@
-use crate::indexer::*;
 use crate::*;
 
 use anyhow::Result;
 use futures::join;
 use std::collections::BTreeMap;
 
-pub async fn monitor_expirations(
-	client: Client,
-	blocks: u32,
-	sessions: u32,
-	args: &Args,
-) -> Result<()> {
-	let gql_client = reqwest::Client::builder()
-		.user_agent("gcli/0.1.0")
-		.build()?;
+pub async fn monitor_expirations(data: &Data, blocks: u32, sessions: u32) -> Result<()> {
+	let client = data.client();
+	let indexer = data.indexer.clone();
 
 	let parent_hash = client
 		.storage()
@@ -36,17 +29,7 @@ pub async fn monitor_expirations(
 	let end_block = current_block + blocks;
 	let end_session = current_session + sessions;
 
-	let mut identity_cache = cache::IdentityCache::new(
-		client.clone(),
-		if args.no_indexer {
-			None
-		} else {
-			Some(Indexer {
-				gql_client,
-				gql_url: args.indexer.clone(),
-			})
-		},
-	);
+	let mut identity_cache = cache::IdentityCache::new(client.clone(), indexer);
 
 	// Rotate keys
 	let mut must_rotate_keys_before_iter = client
diff --git a/src/commands/identity.rs b/src/commands/identity.rs
index 61e617a..b1e9d11 100644
--- a/src/commands/identity.rs
+++ b/src/commands/identity.rs
@@ -1,4 +1,3 @@
-use crate::indexer::*;
 use crate::*;
 
 use crate::commands::revocation::generate_revoc_doc;
@@ -12,23 +11,13 @@ use std::str::FromStr;
 use subxt::tx::{BaseExtrinsicParamsBuilder, PairSigner};
 
 pub async fn get_identity(
-	client: &Client,
+	data: &Data,
 	mut account_id: Option<AccountId32>,
 	mut identity_id: Option<u32>,
 	mut username: Option<String>,
-	args: &Args,
 ) -> Result<()> {
-	// build indexer if not disabled
-	let indexer = if args.no_indexer {
-		None
-	} else {
-		Some(Indexer {
-			gql_client: reqwest::Client::builder()
-				.user_agent("gcli/0.1.0")
-				.build()?,
-			gql_url: args.indexer.clone(),
-		})
-	};
+	let client = data.client();
+	let indexer = data.indexer.clone();
 
 	// fetch missing information
 	match (&account_id, identity_id, &username) {
diff --git a/src/commands/net_test.rs b/src/commands/net_test.rs
index 9a2c73b..228469c 100644
--- a/src/commands/net_test.rs
+++ b/src/commands/net_test.rs
@@ -9,7 +9,7 @@ use subxt::{
 
 pub async fn repart(
 	pair: Pair,
-	client: Client,
+	client: &Client,
 	target: u32,
 	actual_repart: Option<u32>,
 ) -> Result<()> {
@@ -48,7 +48,7 @@ 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) -> Result<()> {
 	let mut nonce = 0;
 	let mut pairs = Vec::<(PairSigner<Runtime, Pair>, AccountId32)>::with_capacity(actual_repart);
 	for i in 0..actual_repart {
diff --git a/src/commands/oneshot.rs b/src/commands/oneshot.rs
index c6d4fb9..15c53c3 100644
--- a/src/commands/oneshot.rs
+++ b/src/commands/oneshot.rs
@@ -6,7 +6,7 @@ use subxt::tx::{BaseExtrinsicParamsBuilder, PairSigner};
 
 pub async fn create_oneshot_account(
 	pair: Pair,
-	client: Client,
+	client: &Client,
 	balance: u64,
 	dest: AccountId32,
 ) -> Result<()> {
@@ -26,7 +26,7 @@ pub async fn create_oneshot_account(
 
 pub async fn consume_oneshot_account(
 	pair: Pair,
-	client: Client,
+	client: &Client,
 	dest: AccountId32,
 	dest_oneshot: bool,
 ) -> Result<()> {
@@ -60,7 +60,7 @@ pub async fn consume_oneshot_account(
 
 pub async fn consume_oneshot_account_with_remaining(
 	pair: Pair,
-	client: Client,
+	client: &Client,
 	balance: u64,
 	dest: AccountId32,
 	dest_oneshot: bool,
@@ -107,7 +107,7 @@ pub async fn consume_oneshot_account_with_remaining(
 	Ok(())
 }
 
-pub async fn oneshot_account_balance(client: Client, account: AccountId32) -> Result<()> {
+pub async fn oneshot_account_balance(client: &Client, account: AccountId32) -> Result<()> {
 	log::info!(
 		"{}",
 		client
diff --git a/src/commands/smith.rs b/src/commands/smith.rs
index b45d49b..a5f7a76 100644
--- a/src/commands/smith.rs
+++ b/src/commands/smith.rs
@@ -1,4 +1,3 @@
-use crate::indexer::Indexer;
 use crate::*;
 
 use anyhow::{anyhow, Result};
@@ -18,7 +17,11 @@ pub async fn rotate_keys(client: &Client) -> Result<SessionKeys> {
 		.map_err(|e| anyhow!("Session keys have wrong length: {:?}", e))
 }
 
-pub async fn set_session_keys(pair: Pair, client: Client, session_keys: SessionKeys) -> Result<()> {
+pub async fn set_session_keys(
+	pair: Pair,
+	client: &Client,
+	session_keys: SessionKeys,
+) -> Result<()> {
 	client
 		.tx()
 		.sign_and_submit_then_watch(
@@ -33,12 +36,12 @@ pub async fn set_session_keys(pair: Pair, client: Client, session_keys: SessionK
 	Ok(())
 }
 
-pub async fn update_session_keys(pair: Pair, client: Client) -> Result<()> {
+pub async fn update_session_keys(pair: Pair, client: &Client) -> Result<()> {
 	let session_keys = rotate_keys(&client).await?;
 	set_session_keys(pair, client, session_keys).await
 }
 
-pub async fn go_online(pair: Pair, client: Client) -> Result<()> {
+pub async fn go_online(pair: Pair, client: &Client) -> Result<()> {
 	if client
 		.storage()
 		.fetch(
@@ -65,7 +68,7 @@ pub async fn go_online(pair: Pair, client: Client) -> Result<()> {
 	Ok(())
 }
 
-pub async fn go_offline(pair: Pair, client: Client) -> Result<()> {
+pub async fn go_offline(pair: Pair, client: &Client) -> Result<()> {
 	client
 		.tx()
 		.sign_and_submit_then_watch(
@@ -78,7 +81,10 @@ pub async fn go_offline(pair: Pair, client: Client) -> Result<()> {
 	Ok(())
 }
 
-pub async fn online(client: Client, args: &Args) -> Result<()> {
+pub async fn online(data: &Data) -> Result<()> {
+	let client = data.client();
+	let indexer = data.indexer.clone();
+
 	let parent_hash = client
 		.clone()
 		.storage()
@@ -86,21 +92,7 @@ pub async fn online(client: Client, args: &Args) -> Result<()> {
 		.await?
 		.unwrap();
 
-	let gql_client = reqwest::Client::builder()
-		.user_agent("gcli/0.1.0")
-		.build()?;
-
-	let mut identity_cache = cache::IdentityCache::new(
-		client.clone(),
-		if args.no_indexer {
-			None
-		} else {
-			Some(Indexer {
-				gql_client,
-				gql_url: args.indexer.clone(),
-			})
-		},
-	);
+	let mut identity_cache = cache::IdentityCache::new(client.clone(), indexer);
 
 	let online_authorities = client
 		.storage()
diff --git a/src/commands/transfer.rs b/src/commands/transfer.rs
index b3cefa6..f9f7820 100644
--- a/src/commands/transfer.rs
+++ b/src/commands/transfer.rs
@@ -10,7 +10,7 @@ type BalancesCall = runtime::runtime_types::pallet_balances::pallet::Call;
 
 pub async fn transfer(
 	pair: Pair,
-	client: Client,
+	client: &Client,
 	balance: u64,
 	dest: AccountId32,
 	keep_alive: bool,
@@ -42,7 +42,7 @@ pub async fn transfer(
 
 pub async fn transfer_multiple(
 	pair: Pair,
-	client: Client,
+	client: &Client,
 	amount: u64,
 	dests: Vec<AccountId32>,
 ) -> Result<()> {
diff --git a/src/conf.rs b/src/conf.rs
index d292c8a..a1628a3 100644
--- a/src/conf.rs
+++ b/src/conf.rs
@@ -5,39 +5,39 @@ const APP_NAME: &str = "gcli";
 
 #[derive(Serialize, Deserialize, Debug)]
 pub struct Config {
-    duniter_endpoint: String,
-    indexer_endpoint: String,
+	pub duniter_endpoint: String,
+	pub indexer_endpoint: String,
 }
 
 impl std::default::Default for Config {
 	fn default() -> Self {
 		Self {
-            duniter_endpoint: String::from("ws://localhost:9944"),
-            indexer_endpoint: String::from("http://localhost:8080/v1/graphql"),
+			duniter_endpoint: String::from("ws://localhost:9944"),
+			indexer_endpoint: String::from("http://localhost:8080/v1/graphql"),
 		}
 	}
 }
 
 /// load config file and manage error if could not
 pub fn load_conf() -> Config {
-    match confy::load(APP_NAME, None) {
-        Ok(cfg) => cfg,
-        Err(e) => {
-            log::warn!("met error while loading config file");
-            log::error!("{}", e);
-            log::info!("removing the old conf file and creating a new one");
-            let cfg = Config::default();
-            confy::store(APP_NAME, None, &cfg).expect("unable to write default config");
-            cfg
-        }
-    }
+	match confy::load(APP_NAME, None) {
+		Ok(cfg) => cfg,
+		Err(e) => {
+			log::warn!("met error while loading config file");
+			log::error!("{}", e);
+			log::info!("removing the old conf file and creating a new one");
+			let cfg = Config::default();
+			confy::store(APP_NAME, None, &cfg).expect("unable to write default config");
+			cfg
+		}
+	}
 }
 
 #[derive(Clone, Default, Debug, clap::Parser)]
 pub enum Subcommand {
 	#[default]
-    /// Show config path
-    Where,
+	/// Show config path
+	Where,
 	/// Show config
 	Show,
 }
@@ -47,9 +47,12 @@ pub fn handle_command(data: Data, command: Subcommand) -> anyhow::Result<()> {
 	// match subcommand
 	match command {
 		Subcommand::Where => {
-            println!("{}", confy::get_configuration_file_path(APP_NAME, None)?.display());
-        }
-            Subcommand::Show => {
+			println!(
+				"{}",
+				confy::get_configuration_file_path(APP_NAME, None)?.display()
+			);
+		}
+		Subcommand::Show => {
 			println!("{:?}", data.cfg);
 		}
 	};
diff --git a/src/data.rs b/src/data.rs
index d3b1afe..2e2c399 100644
--- a/src/data.rs
+++ b/src/data.rs
@@ -50,6 +50,7 @@ impl Data {
 			token_symbol: "tokens".into(),
 			..Default::default()
 		}
+		.overwrite_from_args()
 	}
 	// --- getters ---
 	// the "unwrap" should not fail if data is well prepared
@@ -78,6 +79,16 @@ impl Data {
 		)
 	}
 	// --- mutators ---
+	/// use arguments to overwrite config
+	pub fn overwrite_from_args(mut self) -> Self {
+		if let Some(duniter_endpoint) = self.args.url.clone() {
+			self.cfg.duniter_endpoint = duniter_endpoint;
+		}
+		if let Some(indexer_endpoint) = self.args.indexer.clone() {
+			self.cfg.indexer_endpoint = indexer_endpoint
+		}
+		self
+	}
 	/// force an address if needed
 	pub fn build_address(mut self) -> Self {
 		self.address = Some(
@@ -109,12 +120,17 @@ impl Data {
 	/// 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.unwrap_or_else(|_| {
-			panic!(
-				"could not establish connection with the server {}",
-				self.args.url
-			)
-		}));
+		let duniter_endpoint = self.cfg.duniter_endpoint.clone();
+		self.client = Some(
+			Client::from_url(&duniter_endpoint)
+				.await
+				.unwrap_or_else(|_| {
+					panic!(
+						"could not establish connection with the server {}",
+						duniter_endpoint
+					)
+				}),
+		);
 		self
 	}
 	/// build an indexer if not disabled
@@ -127,7 +143,7 @@ impl Data {
 				gql_client: reqwest::Client::builder()
 					.user_agent("gcli/0.1.0")
 					.build()?,
-				gql_url: self.args.indexer.clone(),
+				gql_url: self.cfg.indexer_endpoint.clone(),
 			})
 		};
 		Ok(self)
diff --git a/src/main.rs b/src/main.rs
index 196cde2..82baddb 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -76,8 +76,8 @@ pub struct Args {
 	#[clap(subcommand)]
 	pub subcommand: Subcommand,
 	/// Overwrite indexer endpoint
-	#[clap(short, long, default_value = "")]
-	indexer: String,
+	#[clap(short, long)]
+	indexer: Option<String>,
 	/// Do not use indexer
 	#[clap(long)]
 	no_indexer: bool,
@@ -92,8 +92,8 @@ pub struct Args {
 	#[clap(short, long)]
 	address: Option<String>,
 	/// Overwrite duniter websocket RPC endpoint
-	#[clap(short, long, default_value = "")]
-	url: String,
+	#[clap(short, long)]
+	url: Option<String>,
 }
 
 /// track progress of transaction on the network
@@ -312,6 +312,7 @@ async fn main() -> Result<(), GcliError> {
 			track_progress(progress).await?
 		}
 		Subcommand::CreateOneshot { balance, dest } => {
+			data = data.build_client().await;
 			commands::oneshot::create_oneshot_account(
 				get_keys(
 					args.secret_format,
@@ -321,13 +322,14 @@ async fn main() -> Result<(), GcliError> {
 				)?
 				.1
 				.unwrap(),
-				Client::from_url(&args.url).await.unwrap(),
+				data.client(),
 				balance,
 				dest,
 			)
 			.await?
 		}
 		Subcommand::ConsumeOneshot { dest, dest_oneshot } => {
+			data = data.build_client().await;
 			commands::oneshot::consume_oneshot_account(
 				get_keys(
 					args.secret_format,
@@ -337,7 +339,7 @@ async fn main() -> Result<(), GcliError> {
 				)?
 				.1
 				.unwrap(),
-				Client::from_url(&args.url).await.unwrap(),
+				data.client(),
 				dest,
 				dest_oneshot,
 			)
@@ -350,6 +352,7 @@ async fn main() -> Result<(), GcliError> {
 			remaining_to,
 			remaining_to_oneshot,
 		} => {
+			data = data.build_client().await;
 			commands::oneshot::consume_oneshot_account_with_remaining(
 				get_keys(
 					args.secret_format,
@@ -359,7 +362,7 @@ async fn main() -> Result<(), GcliError> {
 				)?
 				.1
 				.unwrap(),
-				Client::from_url(&args.url).await.unwrap(),
+				data.client(),
 				balance,
 				dest,
 				dest_oneshot,
@@ -369,13 +372,8 @@ async fn main() -> Result<(), GcliError> {
 			.await?
 		}
 		Subcommand::Expire { blocks, sessions } => {
-			commands::expire::monitor_expirations(
-				Client::from_url(&args.url).await.unwrap(),
-				blocks,
-				sessions,
-				&args,
-			)
-			.await?
+			data = data.build_client().await;
+			commands::expire::monitor_expirations(&data, blocks, sessions).await?
 		}
 		Subcommand::Identity {
 			ref account_id,
@@ -384,11 +382,10 @@ async fn main() -> Result<(), GcliError> {
 		} => {
 			data = data.build_client().await;
 			commands::identity::get_identity(
-				data.client(),
+				&data,
 				account_id.clone(),
 				identity_id,
 				username.clone(),
-				&args,
 			)
 			.await?
 		}
@@ -404,6 +401,7 @@ async fn main() -> Result<(), GcliError> {
 			commands::revocation::print_revoc_sig(&data)
 		}
 		Subcommand::GoOffline => {
+			data = data.build_client().await;
 			commands::smith::go_offline(
 				get_keys(
 					args.secret_format,
@@ -413,11 +411,12 @@ async fn main() -> Result<(), GcliError> {
 				)?
 				.1
 				.unwrap(),
-				Client::from_url(&args.url).await.unwrap(),
+				data.client(),
 			)
 			.await?
 		}
 		Subcommand::GoOnline => {
+			data = data.build_client().await;
 			commands::smith::go_online(
 				get_keys(
 					args.secret_format,
@@ -427,24 +426,23 @@ async fn main() -> Result<(), GcliError> {
 				)?
 				.1
 				.unwrap(),
-				Client::from_url(&args.url).await.unwrap(),
+				data.client(),
 			)
 			.await?
 		}
 		Subcommand::OneshotBalance { account } => {
-			commands::oneshot::oneshot_account_balance(
-				Client::from_url(&args.url).await.unwrap(),
-				account,
-			)
-			.await?
+			data = data.build_client().await;
+			commands::oneshot::oneshot_account_balance(data.client(), account).await?
 		}
 		Subcommand::Online => {
-			commands::smith::online(Client::from_url(&args.url).await.unwrap(), &args).await?
+			data = data.build_client().await;
+			commands::smith::online(&data).await?
 		}
 		Subcommand::Repart {
 			target,
 			actual_repart,
 		} => {
+			data = data.build_client().await;
 			commands::net_test::repart(
 				get_keys(
 					args.secret_format,
@@ -454,13 +452,14 @@ async fn main() -> Result<(), GcliError> {
 				)?
 				.1
 				.unwrap(),
-				Client::from_url(&args.url).await.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,
@@ -470,7 +469,7 @@ async fn main() -> Result<(), GcliError> {
 				)?
 				.1
 				.unwrap(),
-				Client::from_url(&args.url).await.unwrap(),
+				data.client(),
 				actual_repart,
 			)
 			.await?
@@ -489,19 +488,15 @@ async fn main() -> Result<(), GcliError> {
 			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(),
-				&args,
-			)
-			.await?
+			data = data.build_client().await;
+			commands::collective::technical_committee_members(&data).await?
 		}
 		Subcommand::TechProposals => {
-			commands::collective::technical_committee_proposals(
-				Client::from_url(&args.url).await.unwrap(),
-			)
-			.await?
+			data = data.build_client().await;
+			commands::collective::technical_committee_proposals(data.client()).await?
 		}
 		Subcommand::TechVote { hash, index, vote } => {
+			data = data.build_client().await;
 			let vote = match vote {
 				0 => false,
 				1 => true,
@@ -516,7 +511,7 @@ async fn main() -> Result<(), GcliError> {
 				)?
 				.1
 				.unwrap(),
-				Client::from_url(&args.url).await.unwrap(),
+				data.client(),
 				hash, //H256::from_str(&hash).expect("Invalid hash formatting"),
 				index,
 				vote,
@@ -528,6 +523,7 @@ async fn main() -> Result<(), GcliError> {
 			dest,
 			keep_alive,
 		} => {
+			data = data.build_client().await;
 			commands::transfer::transfer(
 				get_keys(
 					args.secret_format,
@@ -537,7 +533,7 @@ async fn main() -> Result<(), GcliError> {
 				)?
 				.1
 				.unwrap(),
-				Client::from_url(&args.url).await.unwrap(),
+				data.client(),
 				amount,
 				dest,
 				keep_alive,
@@ -545,6 +541,7 @@ async fn main() -> Result<(), GcliError> {
 			.await?
 		}
 		Subcommand::TransferMultiple { amount, dests } => {
+			data = data.build_client().await;
 			commands::transfer::transfer_multiple(
 				get_keys(
 					args.secret_format,
@@ -554,25 +551,28 @@ async fn main() -> Result<(), GcliError> {
 				)?
 				.1
 				.unwrap(),
-				Client::from_url(&args.url).await.unwrap(),
+				data.client(),
 				amount,
 				dests,
 			)
 			.await?
 		}
-		Subcommand::UpdateKeys => commands::smith::update_session_keys(
-			get_keys(
-				args.secret_format,
-				&args.address,
-				&args.secret,
-				NeededKeys::Secret,
-			)?
-			.1
-			.unwrap(),
-			Client::from_url(&args.url).await.unwrap(),
-		)
-		.await
-		.unwrap(),
+		Subcommand::UpdateKeys => {
+			data = data.build_client().await;
+			commands::smith::update_session_keys(
+				get_keys(
+					args.secret_format,
+					&args.address,
+					&args.secret,
+					NeededKeys::Secret,
+				)?
+				.1
+				.unwrap(),
+				data.client(),
+			)
+			.await
+			.unwrap()
+		}
 		Subcommand::RuntimeInfo => {
 			data = data.build_client().await.fetch_system_properties().await?;
 			commands::runtime::runtime_info(data).await;
@@ -600,14 +600,14 @@ async fn main() -> Result<(), GcliError> {
 			if data.genesis_hash == data.indexer_genesis_hash {
 				println!(
 					"{} and {} have the same genesis hash: {}",
-					data.args.url,
+					data.cfg.duniter_endpoint,
 					data.indexer().gql_url,
 					data.genesis_hash
 				);
 			} else {
 				println!(
 					"⚠️ {} ({}) and {} ({}) do not share same genesis",
-					data.args.url,
+					data.cfg.duniter_endpoint,
 					data.genesis_hash,
 					data.indexer().gql_url,
 					data.indexer_genesis_hash
-- 
GitLab