diff --git a/Cargo.lock b/Cargo.lock index ee03d0c..f28523d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -983,6 +983,19 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "console" +version = "0.15.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "054ccb5b10f9f2cbf51eb355ca1d05c2d279ce1804688d0db74b4733a5aeafd8" +dependencies = [ + "encode_unicode", + "libc", + "once_cell", + "unicode-width", + "windows-sys 0.59.0", +] + [[package]] name = "const-oid" version = "0.9.6" @@ -1460,6 +1473,12 @@ dependencies = [ "zeroize", ] +[[package]] +name = "encode_unicode" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" + [[package]] name = "enum-ordinalize" version = "4.3.0" @@ -2299,6 +2318,19 @@ dependencies = [ "hashbrown 0.15.5", ] +[[package]] +name = "indicatif" +version = "0.17.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "183b3088984b400f4cfac3620d5e076c84da5364016b4f49473de574b2586235" +dependencies = [ + "console", + "number_prefix", + "portable-atomic", + "unicode-width", + "web-time", +] + [[package]] name = "inout" version = "0.1.4" @@ -2858,6 +2890,12 @@ dependencies = [ "libc", ] +[[package]] +name = "number_prefix" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" + [[package]] name = "object" version = "0.36.7" @@ -3253,6 +3291,12 @@ dependencies = [ "universal-hash", ] +[[package]] +name = "portable-atomic" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" + [[package]] name = "potential_utf" version = "0.1.3" @@ -3494,6 +3538,7 @@ dependencies = [ "colored", "dirs", "hex", + "indicatif", "jsonrpsee", "parity-scale-codec", "qp-dilithium-crypto", @@ -5509,6 +5554,12 @@ version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" +[[package]] +name = "unicode-width" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" + [[package]] name = "unicode-xid" version = "0.2.6" diff --git a/Cargo.toml b/Cargo.toml index bcd74ba..d0ede29 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -35,6 +35,7 @@ thiserror = "2.0" # Terminal UI colored = "3.0" +indicatif = "0.17" # Additional utilities sha2 = "0.10" diff --git a/src/cli/common.rs b/src/cli/common.rs index a019b83..7328737 100644 --- a/src/cli/common.rs +++ b/src/cli/common.rs @@ -113,25 +113,15 @@ pub async fn get_incremented_nonce_with_client( Ok(incremented_nonce) } -/// Default function for transaction submission, waits until transaction is in the best block +/// Submit transaction with optional finalization check +/// +/// By default (finalized=false), waits until transaction is in the best block (fast) +/// With finalized=true, waits until transaction is in a finalized block (slow in PoW chains) pub async fn submit_transaction( quantus_client: &crate::chain::client::QuantusClient, from_keypair: &crate::wallet::QuantumKeyPair, call: Call, tip: Option, -) -> crate::error::Result -where - Call: subxt::tx::Payload, -{ - submit_transaction_with_finalization(quantus_client, from_keypair, call, tip, false).await -} - -/// Helper function to submit transaction with an optional finalization check -pub async fn submit_transaction_with_finalization( - quantus_client: &crate::chain::client::QuantusClient, - from_keypair: &crate::wallet::QuantumKeyPair, - call: Call, - tip: Option, finalized: bool, ) -> crate::error::Result where @@ -332,23 +322,64 @@ async fn wait_tx_inclusion( tx_progress: &mut TxProgress>, finalized: bool, ) -> Result<()> { + use indicatif::{ProgressBar, ProgressStyle}; + + // Create spinner (only in non-verbose mode) + let spinner = if !crate::log::is_verbose() { + let pb = ProgressBar::new_spinner(); + pb.set_style( + ProgressStyle::default_spinner() + .tick_chars("⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏") + .template("{spinner:.cyan} {msg} {elapsed:.dim}") + .unwrap(), + ); + + if finalized { + pb.set_message("Waiting for finalized block..."); + } else { + pb.set_message("Waiting for block inclusion..."); + } + + pb.enable_steady_tick(std::time::Duration::from_millis(100)); + Some(pb) + } else { + None + }; + while let Some(Ok(status)) = tx_progress.next().await { crate::log_verbose!(" Transaction status: {:?}", status); + match status { + TxStatus::Validated => + if let Some(ref pb) = spinner { + pb.set_message("Transaction validated ✓"); + }, TxStatus::InBestBlock(block_hash) => { crate::log_verbose!(" Transaction included in block: {:?}", block_hash); if finalized { + if let Some(ref pb) = spinner { + pb.set_message("In best block, waiting for finalization..."); + } continue; } else { + if let Some(pb) = spinner { + pb.finish_with_message("✅ Transaction included in block!"); + } break; }; }, TxStatus::InFinalizedBlock(block_hash) => { crate::log_verbose!(" Transaction finalized in block: {:?}", block_hash); + if let Some(pb) = spinner { + pb.finish_with_message("✅ Transaction finalized!"); + } break; }, TxStatus::Error { message } | TxStatus::Invalid { message } => { crate::log_error!(" Transaction error: {}", message); + if let Some(pb) = spinner { + pb.finish_with_message("❌ Transaction error!"); + } break; }, _ => continue, diff --git a/src/cli/generic_call.rs b/src/cli/generic_call.rs index 40fa30b..242341f 100644 --- a/src/cli/generic_call.rs +++ b/src/cli/generic_call.rs @@ -165,14 +165,20 @@ async fn submit_balance_transfer( subxt::ext::subxt_core::utils::MultiAddress::Id(to_account_id_subxt), amount, ); - crate::cli::common::submit_transaction(quantus_client, from_keypair, transfer_call, tip) - .await + crate::cli::common::submit_transaction( + quantus_client, + from_keypair, + transfer_call, + tip, + finalized, + ) + .await } else { let transfer_call = quantus_subxt::api::tx().balances().transfer_allow_death( subxt::ext::subxt_core::utils::MultiAddress::Id(to_account_id_subxt), amount, ); - crate::cli::common::submit_transaction_with_finalization( + crate::cli::common::submit_transaction( quantus_client, from_keypair, transfer_call, @@ -203,7 +209,7 @@ async fn submit_system_remark( let remark_call = quantus_subxt::api::tx().system().remark(remark.as_bytes().to_vec()); - crate::cli::common::submit_transaction_with_finalization( + crate::cli::common::submit_transaction( quantus_client, from_keypair, remark_call, @@ -259,14 +265,8 @@ async fn submit_tech_collective_add_member( }, )); - crate::cli::common::submit_transaction_with_finalization( - quantus_client, - from_keypair, - sudo_call, - None, - finalized, - ) - .await + crate::cli::common::submit_transaction(quantus_client, from_keypair, sudo_call, None, finalized) + .await } /// Submit tech collective remove member @@ -302,14 +302,8 @@ async fn submit_tech_collective_remove_member( }, )); - crate::cli::common::submit_transaction_with_finalization( - quantus_client, - from_keypair, - sudo_call, - None, - finalized, - ) - .await + crate::cli::common::submit_transaction(quantus_client, from_keypair, sudo_call, None, finalized) + .await } /// Submit tech collective vote @@ -330,14 +324,8 @@ async fn submit_tech_collective_vote( let vote_call = quantus_subxt::api::tx().tech_collective().vote(referendum_index, aye); - crate::cli::common::submit_transaction_with_finalization( - quantus_client, - from_keypair, - vote_call, - None, - finalized, - ) - .await + crate::cli::common::submit_transaction(quantus_client, from_keypair, vote_call, None, finalized) + .await } /// Submit reversible transfer @@ -374,7 +362,7 @@ async fn submit_reversible_transfer( amount, ); - crate::cli::common::submit_transaction_with_finalization( + crate::cli::common::submit_transaction( quantus_client, from_keypair, schedule_call, diff --git a/src/cli/high_security.rs b/src/cli/high_security.rs index dcce978..ed2ae18 100644 --- a/src/cli/high_security.rs +++ b/src/cli/high_security.rs @@ -160,7 +160,7 @@ pub async fn handle_high_security_command( .reversible_transfers() .set_high_security(delay_value, interceptor_subxt); - let tx_hash = crate::cli::common::submit_transaction_with_finalization( + let tx_hash = crate::cli::common::submit_transaction( &quantus_client, &keypair, tx_call, diff --git a/src/cli/mod.rs b/src/cli/mod.rs index f505027..5232cf3 100644 --- a/src/cli/mod.rs +++ b/src/cli/mod.rs @@ -272,19 +272,25 @@ pub async fn execute_command( Commands::Scheduler(scheduler_cmd) => scheduler::handle_scheduler_command(scheduler_cmd, node_url, finalized).await, Commands::Storage(storage_cmd) => - storage::handle_storage_command(storage_cmd, node_url).await, + storage::handle_storage_command(storage_cmd, node_url, finalized).await, Commands::TechCollective(tech_collective_cmd) => - tech_collective::handle_tech_collective_command(tech_collective_cmd, node_url).await, + tech_collective::handle_tech_collective_command( + tech_collective_cmd, + node_url, + finalized, + ) + .await, Commands::Preimage(preimage_cmd) => preimage::handle_preimage_command(preimage_cmd, node_url, finalized).await, Commands::TechReferenda(tech_referenda_cmd) => - tech_referenda::handle_tech_referenda_command(tech_referenda_cmd, node_url).await, + tech_referenda::handle_tech_referenda_command(tech_referenda_cmd, node_url, finalized) + .await, Commands::Referenda(referenda_cmd) => - referenda::handle_referenda_command(referenda_cmd, node_url).await, + referenda::handle_referenda_command(referenda_cmd, node_url, finalized).await, Commands::Treasury(treasury_cmd) => - treasury::handle_treasury_command(treasury_cmd, node_url).await, + treasury::handle_treasury_command(treasury_cmd, node_url, finalized).await, Commands::Runtime(runtime_cmd) => - runtime::handle_runtime_command(runtime_cmd, node_url).await, + runtime::handle_runtime_command(runtime_cmd, node_url, finalized).await, Commands::Call { pallet, call, diff --git a/src/cli/preimage.rs b/src/cli/preimage.rs index d09e065..267f91a 100644 --- a/src/cli/preimage.rs +++ b/src/cli/preimage.rs @@ -309,7 +309,7 @@ async fn request_preimage( let request_call = quantus_subxt::api::tx().preimage().request_preimage(preimage_hash); // Submit transaction - let tx_hash = crate::cli::common::submit_transaction_with_finalization( + let tx_hash = crate::cli::common::submit_transaction( quantus_client, &keypair, request_call, @@ -346,7 +346,7 @@ async fn note_preimage( let note_call = quantus_subxt::api::tx().preimage().note_preimage(content); // Submit transaction - let tx_hash = crate::cli::common::submit_transaction_with_finalization( + let tx_hash = crate::cli::common::submit_transaction( quantus_client, &keypair, note_call, @@ -410,7 +410,7 @@ async fn create_preimage( log_print!("📝 Submitting preimage..."); let note_preimage_tx = quantus_subxt::api::tx().preimage().note_preimage(bounded_bytes); - let preimage_tx_hash = crate::cli::common::submit_transaction_with_finalization( + let preimage_tx_hash = crate::cli::common::submit_transaction( quantus_client, &keypair, note_preimage_tx, diff --git a/src/cli/recovery.rs b/src/cli/recovery.rs index e6de0b4..57f7792 100644 --- a/src/cli/recovery.rs +++ b/src/cli/recovery.rs @@ -190,7 +190,7 @@ pub async fn handle_recovery_command( .recovery() .initiate_recovery(subxt::ext::subxt_core::utils::MultiAddress::Id(lost_id)); - let tx_hash = crate::cli::common::submit_transaction_with_finalization( + let tx_hash = crate::cli::common::submit_transaction( &quantus_client, &rescuer_key, call, @@ -225,7 +225,7 @@ pub async fn handle_recovery_command( subxt::ext::subxt_core::utils::MultiAddress::Id(lost_id), subxt::ext::subxt_core::utils::MultiAddress::Id(rescuer_id), ); - let tx_hash = crate::cli::common::submit_transaction_with_finalization( + let tx_hash = crate::cli::common::submit_transaction( &quantus_client, &friend_key, call, @@ -253,14 +253,19 @@ pub async fn handle_recovery_command( let call = quantus_subxt::api::tx() .recovery() .claim_recovery(subxt::ext::subxt_core::utils::MultiAddress::Id(lost_id)); - let tx_hash = - crate::cli::common::submit_transaction(&quantus_client, &rescuer_key, call, None) - .await - .map_err(|e| { - crate::error::QuantusError::NetworkError(format!( - "Failed to submit claim_recovery transaction: {e}" - )) - })?; + let tx_hash = crate::cli::common::submit_transaction( + &quantus_client, + &rescuer_key, + call, + None, + finalized, + ) + .await + .map_err(|e| { + crate::error::QuantusError::NetworkError(format!( + "Failed to submit claim_recovery transaction: {e}" + )) + })?; log_success!("✅ Claim submitted successfully {:?}", tx_hash); }, @@ -358,7 +363,7 @@ pub async fn handle_recovery_command( .recovery() .as_recovered(subxt::ext::subxt_core::utils::MultiAddress::Id(lost_id), inner_call); - let tx_hash = match crate::cli::common::submit_transaction_with_finalization( + let tx_hash = match crate::cli::common::submit_transaction( &quantus_client, &rescuer_key, call, @@ -469,7 +474,7 @@ pub async fn handle_recovery_command( .recovery() .as_recovered(subxt::ext::subxt_core::utils::MultiAddress::Id(lost_id), inner_call); - let tx_hash = match crate::cli::common::submit_transaction_with_finalization( + let tx_hash = match crate::cli::common::submit_transaction( &quantus_client, &rescuer_key, call, @@ -498,7 +503,7 @@ pub async fn handle_recovery_command( let call = quantus_subxt::api::tx() .recovery() .close_recovery(subxt::ext::subxt_core::utils::MultiAddress::Id(rescuer_id)); - let tx_hash = crate::cli::common::submit_transaction_with_finalization( + let tx_hash = crate::cli::common::submit_transaction( &quantus_client, &lost_key, call, @@ -528,7 +533,7 @@ pub async fn handle_recovery_command( let call = quantus_subxt::api::tx() .recovery() .cancel_recovered(subxt::ext::subxt_core::utils::MultiAddress::Id(lost_id)); - let tx_hash = crate::cli::common::submit_transaction_with_finalization( + let tx_hash = crate::cli::common::submit_transaction( &quantus_client, &rescuer_key, call, diff --git a/src/cli/referenda.rs b/src/cli/referenda.rs index 5071cb3..75f7be5 100644 --- a/src/cli/referenda.rs +++ b/src/cli/referenda.rs @@ -173,6 +173,7 @@ pub enum ReferendaCommands { pub async fn handle_referenda_command( command: ReferendaCommands, node_url: &str, + finalized: bool, ) -> crate::error::Result<()> { let quantus_client = crate::chain::client::QuantusClient::new(node_url).await?; @@ -185,6 +186,7 @@ pub async fn handle_referenda_command( password, password_file, &origin, + finalized, ) .await, ReferendaCommands::Submit { preimage_hash, from, password, password_file, origin } => @@ -195,6 +197,7 @@ pub async fn handle_referenda_command( password, password_file, &origin, + finalized, ) .await, ReferendaCommands::List => list_proposals(&quantus_client).await, @@ -202,7 +205,15 @@ pub async fn handle_referenda_command( get_proposal_details(&quantus_client, index, decode).await, ReferendaCommands::Status { index } => get_proposal_status(&quantus_client, index).await, ReferendaCommands::PlaceDecisionDeposit { index, from, password, password_file } => - place_decision_deposit(&quantus_client, index, &from, password, password_file).await, + place_decision_deposit( + &quantus_client, + index, + &from, + password, + password_file, + finalized, + ) + .await, ReferendaCommands::Vote { index, aye, @@ -221,12 +232,29 @@ pub async fn handle_referenda_command( &from, password, password_file, + finalized, ) .await, ReferendaCommands::RefundSubmissionDeposit { index, from, password, password_file } => - refund_submission_deposit(&quantus_client, index, &from, password, password_file).await, + refund_submission_deposit( + &quantus_client, + index, + &from, + password, + password_file, + finalized, + ) + .await, ReferendaCommands::RefundDecisionDeposit { index, from, password, password_file } => - refund_decision_deposit(&quantus_client, index, &from, password, password_file).await, + refund_decision_deposit( + &quantus_client, + index, + &from, + password, + password_file, + finalized, + ) + .await, ReferendaCommands::Config => get_config(&quantus_client).await, } } @@ -239,6 +267,7 @@ async fn submit_remark_proposal( password: Option, password_file: Option, origin_type: &str, + finalized: bool, ) -> crate::error::Result<()> { use qp_poseidon::PoseidonHasher; @@ -272,7 +301,7 @@ async fn submit_remark_proposal( log_print!("📝 Submitting preimage..."); let note_preimage_tx = quantus_subxt::api::tx().preimage().note_preimage(bounded_bytes); let preimage_tx_hash = - submit_transaction(quantus_client, &keypair, note_preimage_tx, None).await?; + submit_transaction(quantus_client, &keypair, note_preimage_tx, None, finalized).await?; log_print!("✅ Preimage transaction submitted: {:?}", preimage_tx_hash); // Wait for preimage transaction confirmation @@ -328,7 +357,8 @@ async fn submit_remark_proposal( let submit_call = quantus_subxt::api::tx().referenda().submit(origin_caller, proposal, enactment); - let tx_hash = submit_transaction(quantus_client, &keypair, submit_call, None).await?; + let tx_hash = + submit_transaction(quantus_client, &keypair, submit_call, None, finalized).await?; log_print!( "✅ {} Referendum proposal submitted! Hash: {:?}", "SUCCESS".bright_green().bold(), @@ -347,6 +377,7 @@ async fn submit_proposal( password: Option, password_file: Option, origin_type: &str, + finalized: bool, ) -> crate::error::Result<()> { log_print!("📝 Submitting Proposal to Referenda"); log_print!(" 🔗 Preimage hash: {}", preimage_hash.bright_cyan()); @@ -443,7 +474,8 @@ async fn submit_proposal( let submit_call = quantus_subxt::api::tx().referenda().submit(origin_caller, proposal, enactment); - let tx_hash = submit_transaction(quantus_client, &keypair, submit_call, None).await?; + let tx_hash = + submit_transaction(quantus_client, &keypair, submit_call, None, finalized).await?; log_print!( "✅ {} Referendum proposal submitted! Hash: {:?}", "SUCCESS".bright_green().bold(), @@ -653,6 +685,7 @@ async fn place_decision_deposit( from: &str, password: Option, password_file: Option, + finalized: bool, ) -> crate::error::Result<()> { log_print!("📋 Placing decision deposit for Referendum #{}", index); log_print!(" 🔑 Placed by: {}", from.bright_yellow()); @@ -660,7 +693,8 @@ async fn place_decision_deposit( let keypair = crate::wallet::load_keypair_from_wallet(from, password, password_file)?; let deposit_call = quantus_subxt::api::tx().referenda().place_decision_deposit(index); - let tx_hash = submit_transaction(quantus_client, &keypair, deposit_call, None).await?; + let tx_hash = + submit_transaction(quantus_client, &keypair, deposit_call, None, finalized).await?; log_success!("✅ Decision deposit placed! Hash: {:?}", tx_hash.to_string().bright_yellow()); Ok(()) } @@ -675,6 +709,7 @@ async fn vote_on_referendum( from: &str, password: Option, password_file: Option, + finalized: bool, ) -> crate::error::Result<()> { log_print!("🗳️ Voting on Referendum #{}", index); log_print!(" 📊 Vote: {}", if aye { "AYE ✅".bright_green() } else { "NAY ❌".bright_red() }); @@ -706,7 +741,7 @@ async fn vote_on_referendum( }; let vote_call = quantus_subxt::api::tx().conviction_voting().vote(index, vote); - let tx_hash = submit_transaction(quantus_client, &keypair, vote_call, None).await?; + let tx_hash = submit_transaction(quantus_client, &keypair, vote_call, None, finalized).await?; log_print!( "✅ {} Vote transaction submitted! Hash: {:?}", @@ -764,6 +799,7 @@ async fn refund_submission_deposit( from: &str, password: Option, password_file: Option, + finalized: bool, ) -> crate::error::Result<()> { log_print!("💰 Refunding submission deposit for Referendum #{}", index); log_print!(" 🔑 Refund to: {}", from.bright_yellow()); @@ -774,7 +810,8 @@ async fn refund_submission_deposit( // Create refund_submission_deposit call let refund_call = quantus_subxt::api::tx().referenda().refund_submission_deposit(index); - let tx_hash = submit_transaction(quantus_client, &keypair, refund_call, None).await?; + let tx_hash = + submit_transaction(quantus_client, &keypair, refund_call, None, finalized).await?; log_print!( "✅ {} Refund transaction submitted! Hash: {:?}", "SUCCESS".bright_green().bold(), @@ -792,6 +829,7 @@ async fn refund_decision_deposit( from: &str, password: Option, password_file: Option, + finalized: bool, ) -> crate::error::Result<()> { log_print!("💰 Refunding decision deposit for Referendum #{}", index); log_print!(" 🔑 Refund to: {}", from.bright_yellow()); @@ -802,7 +840,8 @@ async fn refund_decision_deposit( // Create refund_decision_deposit call let refund_call = quantus_subxt::api::tx().referenda().refund_decision_deposit(index); - let tx_hash = submit_transaction(quantus_client, &keypair, refund_call, None).await?; + let tx_hash = + submit_transaction(quantus_client, &keypair, refund_call, None, finalized).await?; log_print!( "✅ {} Refund transaction submitted! Hash: {:?}", "SUCCESS".bright_green().bold(), diff --git a/src/cli/reversible.rs b/src/cli/reversible.rs index 1323ee8..29b6dd8 100644 --- a/src/cli/reversible.rs +++ b/src/cli/reversible.rs @@ -136,7 +136,7 @@ pub async fn schedule_transfer( .schedule_transfer(subxt::ext::subxt_core::utils::MultiAddress::Id(to_account_id), amount); // Submit the transaction - let tx_hash = crate::cli::common::submit_transaction_with_finalization( + let tx_hash = crate::cli::common::submit_transaction( quantus_client, from_keypair, transfer_call, @@ -171,7 +171,7 @@ pub async fn cancel_transaction( let cancel_call = quantus_subxt::api::tx().reversible_transfers().cancel(tx_hash); // Submit the transaction - let tx_hash_result = crate::cli::common::submit_transaction_with_finalization( + let tx_hash_result = crate::cli::common::submit_transaction( quantus_client, from_keypair, cancel_call, @@ -228,7 +228,7 @@ pub async fn schedule_transfer_with_delay( ); // Submit the transaction - let tx_hash = crate::cli::common::submit_transaction_with_finalization( + let tx_hash = crate::cli::common::submit_transaction( quantus_client, from_keypair, transfer_call, diff --git a/src/cli/runtime.rs b/src/cli/runtime.rs index 1b3971c..39db259 100644 --- a/src/cli/runtime.rs +++ b/src/cli/runtime.rs @@ -49,6 +49,7 @@ pub async fn update_runtime( wasm_code: Vec, from_keypair: &QuantumKeyPair, force: bool, + finalized: bool, ) -> crate::error::Result { log_verbose!("🔄 Updating runtime..."); @@ -95,12 +96,18 @@ pub async fn update_runtime( log_print!("📡 Submitting runtime update transaction..."); log_print!("⏳ This may take longer than usual due to WASM size..."); - let tx_hash = crate::cli::common::submit_transaction_with_finalization( + if !finalized { + log_print!( + "💡 Note: Waiting for best block (not finalized) due to PoW chain characteristics" + ); + } + + let tx_hash = crate::cli::common::submit_transaction( quantus_client, from_keypair, sudo_call, None, - true, + finalized, ) .await?; @@ -151,6 +158,7 @@ pub async fn calculate_wasm_hash(wasm_code: &[u8]) -> crate::error::Result crate::error::Result<()> { let quantus_client = crate::chain::client::QuantusClient::new(node_url).await?; @@ -187,7 +195,7 @@ pub async fn handle_runtime_command( log_print!("📊 WASM file size: {} bytes", wasm_code.len()); // Update runtime - update_runtime(&quantus_client, wasm_code, &keypair, force).await?; + update_runtime(&quantus_client, wasm_code, &keypair, force, finalized).await?; log_success!("🎉 Runtime update completed!"); log_print!( diff --git a/src/cli/scheduler.rs b/src/cli/scheduler.rs index 040a573..c1777a9 100644 --- a/src/cli/scheduler.rs +++ b/src/cli/scheduler.rs @@ -128,7 +128,7 @@ async fn schedule_remark( let keypair = crate::wallet::load_keypair_from_wallet(from, None, None)?; let schedule_tx = api::tx().scheduler().schedule(when_u32, maybe_periodic, priority, runtime_call); - let tx_hash = crate::cli::common::submit_transaction_with_finalization( + let tx_hash = crate::cli::common::submit_transaction( quantus_client, &keypair, schedule_tx, diff --git a/src/cli/send.rs b/src/cli/send.rs index 72be9a4..05a9d95 100644 --- a/src/cli/send.rs +++ b/src/cli/send.rs @@ -216,7 +216,7 @@ pub async fn transfer_with_nonce( ) .await? } else { - crate::cli::common::submit_transaction_with_finalization( + crate::cli::common::submit_transaction( quantus_client, from_keypair, transfer_call, @@ -312,7 +312,7 @@ pub async fn batch_transfer( let tip_to_use = tip.unwrap_or(10_000_000_000); // Submit the batch transaction - let tx_hash = crate::cli::common::submit_transaction_with_finalization( + let tx_hash = crate::cli::common::submit_transaction( quantus_client, from_keypair, batch_call, diff --git a/src/cli/storage.rs b/src/cli/storage.rs index ee5d13c..9cf7a62 100644 --- a/src/cli/storage.rs +++ b/src/cli/storage.rs @@ -257,6 +257,7 @@ pub async fn set_storage_value( from_keypair: &crate::wallet::QuantumKeyPair, storage_key: Vec, value_bytes: Vec, + finalized: bool, ) -> crate::error::Result { log_verbose!("✍️ Creating set_storage transaction..."); @@ -269,9 +270,14 @@ pub async fn set_storage_value( // Wrap in Sudo::sudo call let sudo_call = quantus_subxt::api::tx().sudo().sudo(set_storage_call); - let tx_hash = - crate::cli::common::submit_transaction(quantus_client, from_keypair, sudo_call, None) - .await?; + let tx_hash = crate::cli::common::submit_transaction( + quantus_client, + from_keypair, + sudo_call, + None, + finalized, + ) + .await?; log_verbose!("📋 Set storage transaction submitted: {:?}", tx_hash); @@ -799,6 +805,7 @@ async fn get_storage_by_parts( pub async fn handle_storage_command( command: StorageCommands, node_url: &str, + finalized: bool, ) -> crate::error::Result<()> { log_print!("🗄️ Storage"); @@ -900,7 +907,8 @@ pub async fn handle_storage_command( // 4. Submit the set storage transaction let tx_hash = - set_storage_value(&quantus_client, &keypair, storage_key, value_bytes).await?; + set_storage_value(&quantus_client, &keypair, storage_key, value_bytes, finalized) + .await?; log_print!( "✅ {} Set storage transaction submitted! Hash: {:?}", diff --git a/src/cli/tech_collective.rs b/src/cli/tech_collective.rs index b96cc80..9568106 100644 --- a/src/cli/tech_collective.rs +++ b/src/cli/tech_collective.rs @@ -106,6 +106,7 @@ pub async fn add_member( quantus_client: &crate::chain::client::QuantusClient, from_keypair: &crate::wallet::QuantumKeyPair, who_address: &str, + finalized: bool, ) -> crate::error::Result { log_verbose!("🏛️ Adding member to Tech Collective..."); log_verbose!(" Member: {}", who_address.bright_cyan()); @@ -130,9 +131,14 @@ pub async fn add_member( // Wrap in Sudo::sudo call let sudo_call = quantus_subxt::api::tx().sudo().sudo(add_member_call); - let tx_hash = - crate::cli::common::submit_transaction(quantus_client, from_keypair, sudo_call, None) - .await?; + let tx_hash = crate::cli::common::submit_transaction( + quantus_client, + from_keypair, + sudo_call, + None, + finalized, + ) + .await?; log_verbose!("📋 Add member transaction submitted: {:?}", tx_hash); @@ -144,6 +150,7 @@ pub async fn remove_member( quantus_client: &crate::chain::client::QuantusClient, from_keypair: &crate::wallet::QuantumKeyPair, who_address: &str, + finalized: bool, ) -> crate::error::Result { log_verbose!("🏛️ Removing member from Tech Collective..."); log_verbose!(" Member: {}", who_address.bright_cyan()); @@ -169,9 +176,14 @@ pub async fn remove_member( // Wrap in Sudo::sudo call let sudo_call = quantus_subxt::api::tx().sudo().sudo(remove_member_call); - let tx_hash = - crate::cli::common::submit_transaction(quantus_client, from_keypair, sudo_call, None) - .await?; + let tx_hash = crate::cli::common::submit_transaction( + quantus_client, + from_keypair, + sudo_call, + None, + finalized, + ) + .await?; log_verbose!("📋 Remove member transaction submitted: {:?}", tx_hash); @@ -184,6 +196,7 @@ pub async fn vote_on_referendum( from_keypair: &crate::wallet::QuantumKeyPair, referendum_index: u32, aye: bool, + finalized: bool, ) -> crate::error::Result { log_verbose!("🗳️ Voting on referendum..."); log_verbose!(" Referendum: {}", referendum_index); @@ -194,9 +207,14 @@ pub async fn vote_on_referendum( // Create the TechCollective::vote call let vote_call = quantus_subxt::api::tx().tech_collective().vote(referendum_index, aye); - let tx_hash = - crate::cli::common::submit_transaction(quantus_client, from_keypair, vote_call, None) - .await?; + let tx_hash = crate::cli::common::submit_transaction( + quantus_client, + from_keypair, + vote_call, + None, + finalized, + ) + .await?; log_verbose!("📋 Vote transaction submitted: {:?}", tx_hash); @@ -334,6 +352,7 @@ pub async fn get_sudo_account( pub async fn handle_tech_collective_command( command: TechCollectiveCommands, node_url: &str, + finalized: bool, ) -> crate::error::Result<()> { log_print!("🏛️ Tech Collective"); @@ -349,7 +368,7 @@ pub async fn handle_tech_collective_command( let keypair = crate::wallet::load_keypair_from_wallet(&from, password, password_file)?; // Submit transaction - let tx_hash = add_member(&quantus_client, &keypair, &who).await?; + let tx_hash = add_member(&quantus_client, &keypair, &who, finalized).await?; log_print!( "✅ {} Add member transaction submitted! Hash: {:?}", @@ -367,7 +386,7 @@ pub async fn handle_tech_collective_command( let keypair = crate::wallet::load_keypair_from_wallet(&from, password, password_file)?; // Submit transaction - let tx_hash = remove_member(&quantus_client, &keypair, &who).await?; + let tx_hash = remove_member(&quantus_client, &keypair, &who, finalized).await?; log_print!( "✅ {} Remove member transaction submitted! Hash: {:?}", @@ -389,7 +408,8 @@ pub async fn handle_tech_collective_command( // Submit transaction let tx_hash = - vote_on_referendum(&quantus_client, &keypair, referendum_index, aye).await?; + vote_on_referendum(&quantus_client, &keypair, referendum_index, aye, finalized) + .await?; log_print!( "✅ {} Vote transaction submitted! Hash: {:?}", diff --git a/src/cli/tech_referenda.rs b/src/cli/tech_referenda.rs index 03e5e04..682bc2d 100644 --- a/src/cli/tech_referenda.rs +++ b/src/cli/tech_referenda.rs @@ -187,13 +187,21 @@ pub enum TechReferendaCommands { pub async fn handle_tech_referenda_command( command: TechReferendaCommands, node_url: &str, + finalized: bool, ) -> crate::error::Result<()> { let quantus_client = crate::chain::client::QuantusClient::new(node_url).await?; match command { TechReferendaCommands::Submit { preimage_hash, from, password, password_file } => - submit_runtime_upgrade(&quantus_client, &preimage_hash, &from, password, password_file) - .await, + submit_runtime_upgrade( + &quantus_client, + &preimage_hash, + &from, + password, + password_file, + finalized, + ) + .await, TechReferendaCommands::SubmitWithPreimage { wasm_file, from, password, password_file } => submit_runtime_upgrade_with_preimage( &quantus_client, @@ -201,6 +209,7 @@ pub async fn handle_tech_referenda_command( &from, password, password_file, + finalized, ) .await, TechReferendaCommands::List => list_proposals(&quantus_client).await, @@ -208,17 +217,41 @@ pub async fn handle_tech_referenda_command( TechReferendaCommands::Status { index } => get_proposal_status(&quantus_client, index).await, TechReferendaCommands::PlaceDecisionDeposit { index, from, password, password_file } => - place_decision_deposit(&quantus_client, index, &from, password, password_file).await, + place_decision_deposit( + &quantus_client, + index, + &from, + password, + password_file, + finalized, + ) + .await, TechReferendaCommands::Cancel { index, from, password, password_file } => - cancel_proposal(&quantus_client, index, &from, password, password_file).await, + cancel_proposal(&quantus_client, index, &from, password, password_file, finalized).await, TechReferendaCommands::Kill { index, from, password, password_file } => - kill_proposal(&quantus_client, index, &from, password, password_file).await, + kill_proposal(&quantus_client, index, &from, password, password_file, finalized).await, TechReferendaCommands::Nudge { index, from, password, password_file } => - nudge_proposal(&quantus_client, index, &from, password, password_file).await, + nudge_proposal(&quantus_client, index, &from, password, password_file, finalized).await, TechReferendaCommands::RefundSubmissionDeposit { index, from, password, password_file } => - refund_submission_deposit(&quantus_client, index, &from, password, password_file).await, + refund_submission_deposit( + &quantus_client, + index, + &from, + password, + password_file, + finalized, + ) + .await, TechReferendaCommands::RefundDecisionDeposit { index, from, password, password_file } => - refund_decision_deposit(&quantus_client, index, &from, password, password_file).await, + refund_decision_deposit( + &quantus_client, + index, + &from, + password, + password_file, + finalized, + ) + .await, TechReferendaCommands::Config => get_config(&quantus_client).await, } } @@ -230,6 +263,7 @@ async fn submit_runtime_upgrade( from: &str, password: Option, password_file: Option, + finalized: bool, ) -> crate::error::Result<()> { log_print!("📝 Submitting Runtime Upgrade Proposal to Tech Referenda"); log_print!(" 🔗 Preimage hash: {}", preimage_hash.bright_cyan()); @@ -302,7 +336,8 @@ async fn submit_runtime_upgrade( .tech_referenda() .submit(origin_caller, proposal, enactment); - let tx_hash = submit_transaction(quantus_client, &keypair, submit_call, None).await?; + let tx_hash = + submit_transaction(quantus_client, &keypair, submit_call, None, finalized).await?; log_print!( "✅ {} Runtime upgrade proposal submitted! Hash: {:?}", "SUCCESS".bright_green().bold(), @@ -320,6 +355,7 @@ async fn submit_runtime_upgrade_with_preimage( from: &str, password: Option, password_file: Option, + finalized: bool, ) -> crate::error::Result<()> { use qp_poseidon::PoseidonHasher; @@ -367,7 +403,7 @@ async fn submit_runtime_upgrade_with_preimage( log_print!("📝 Submitting preimage..."); let note_preimage_tx = quantus_subxt::api::tx().preimage().note_preimage(bounded_bytes); let preimage_tx_hash = - submit_transaction(quantus_client, &keypair, note_preimage_tx, None).await?; + submit_transaction(quantus_client, &keypair, note_preimage_tx, None, finalized).await?; log_print!("✅ Preimage transaction submitted: {:?}", preimage_tx_hash); // Wait for preimage transaction confirmation @@ -400,7 +436,8 @@ async fn submit_runtime_upgrade_with_preimage( .tech_referenda() .submit(origin_caller, proposal, enactment); - let tx_hash = submit_transaction(quantus_client, &keypair, submit_call, None).await?; + let tx_hash = + submit_transaction(quantus_client, &keypair, submit_call, None, finalized).await?; log_print!( "✅ {} Runtime upgrade proposal submitted! Hash: {:?}", "SUCCESS".bright_green().bold(), @@ -537,6 +574,7 @@ async fn place_decision_deposit( from: &str, password: Option, password_file: Option, + finalized: bool, ) -> crate::error::Result<()> { log_print!("📋 Placing decision deposit for Tech Referendum #{}", index); log_print!(" 🔑 Placed by: {}", from.bright_yellow()); @@ -544,7 +582,8 @@ async fn place_decision_deposit( let keypair = crate::wallet::load_keypair_from_wallet(from, password, password_file)?; let deposit_call = quantus_subxt::api::tx().tech_referenda().place_decision_deposit(index); - let tx_hash = submit_transaction(quantus_client, &keypair, deposit_call, None).await?; + let tx_hash = + submit_transaction(quantus_client, &keypair, deposit_call, None, finalized).await?; log_success!("✅ Decision deposit placed! Hash: {:?}", tx_hash.to_string().bright_yellow()); Ok(()) } @@ -556,6 +595,7 @@ async fn cancel_proposal( from: &str, password: Option, password_file: Option, + finalized: bool, ) -> crate::error::Result<()> { log_print!("❌ Cancelling Tech Referendum #{}", index); log_print!(" 🔑 Cancelled by: {}", from.bright_yellow()); @@ -568,7 +608,7 @@ async fn cancel_proposal( }); let sudo_call = quantus_subxt::api::tx().sudo().sudo(inner); - let tx_hash = submit_transaction(quantus_client, &keypair, sudo_call, None).await?; + let tx_hash = submit_transaction(quantus_client, &keypair, sudo_call, None, finalized).await?; log_success!("✅ Referendum cancelled! Hash: {:?}", tx_hash.to_string().bright_yellow()); Ok(()) } @@ -580,6 +620,7 @@ async fn kill_proposal( from: &str, password: Option, password_file: Option, + finalized: bool, ) -> crate::error::Result<()> { log_print!("💀 Killing Tech Referendum #{}", index); log_print!(" 🔑 Killed by: {}", from.bright_yellow()); @@ -592,7 +633,7 @@ async fn kill_proposal( }); let sudo_call = quantus_subxt::api::tx().sudo().sudo(inner); - let tx_hash = submit_transaction(quantus_client, &keypair, sudo_call, None).await?; + let tx_hash = submit_transaction(quantus_client, &keypair, sudo_call, None, finalized).await?; log_success!("✅ Referendum killed! Hash: {:?}", tx_hash.to_string().bright_yellow()); Ok(()) } @@ -604,6 +645,7 @@ async fn nudge_proposal( from: &str, password: Option, password_file: Option, + finalized: bool, ) -> crate::error::Result<()> { log_print!("🔄 Nudging Tech Referendum #{}", index); log_print!(" 🔑 Nudged by: {}", from.bright_yellow()); @@ -615,7 +657,7 @@ async fn nudge_proposal( ); let sudo_call = quantus_subxt::api::tx().sudo().sudo(inner); - let tx_hash = submit_transaction(quantus_client, &keypair, sudo_call, None).await?; + let tx_hash = submit_transaction(quantus_client, &keypair, sudo_call, None, finalized).await?; log_success!("✅ Referendum nudged! Hash: {:?}", tx_hash.to_string().bright_yellow()); Ok(()) } @@ -666,6 +708,7 @@ async fn refund_submission_deposit( from: &str, password: Option, password_file: Option, + finalized: bool, ) -> crate::error::Result<()> { log_print!("💰 Refunding submission deposit for Tech Referendum #{}", index); log_print!(" 🔑 Refund to: {}", from.bright_yellow()); @@ -676,7 +719,8 @@ async fn refund_submission_deposit( // Create refund_submission_deposit call for TechReferenda instance let refund_call = quantus_subxt::api::tx().tech_referenda().refund_submission_deposit(index); - let tx_hash = submit_transaction(quantus_client, &keypair, refund_call, None).await?; + let tx_hash = + submit_transaction(quantus_client, &keypair, refund_call, None, finalized).await?; log_print!( "✅ {} Refund transaction submitted! Hash: {:?}", "SUCCESS".bright_green().bold(), @@ -695,6 +739,7 @@ async fn refund_decision_deposit( from: &str, password: Option, password_file: Option, + finalized: bool, ) -> crate::error::Result<()> { log_print!("💰 Refunding decision deposit for Tech Referendum #{}", index); log_print!(" 🔑 Refund to: {}", from.bright_yellow()); @@ -705,7 +750,8 @@ async fn refund_decision_deposit( // Create refund_decision_deposit call for TechReferenda instance let refund_call = quantus_subxt::api::tx().tech_referenda().refund_decision_deposit(index); - let tx_hash = submit_transaction(quantus_client, &keypair, refund_call, None).await?; + let tx_hash = + submit_transaction(quantus_client, &keypair, refund_call, None, finalized).await?; log_print!( "✅ {} Refund transaction submitted! Hash: {:?}", "SUCCESS".bright_green().bold(), diff --git a/src/cli/treasury.rs b/src/cli/treasury.rs index 4577025..2bfb87a 100644 --- a/src/cli/treasury.rs +++ b/src/cli/treasury.rs @@ -116,6 +116,7 @@ pub enum TreasuryCommands { pub async fn handle_treasury_command( command: TreasuryCommands, node_url: &str, + finalized: bool, ) -> crate::error::Result<()> { let quantus_client = crate::chain::client::QuantusClient::new(node_url).await?; @@ -139,15 +140,26 @@ pub async fn handle_treasury_command( &from, password, password_file, + finalized, ) .await, TreasuryCommands::Payout { index, from, password, password_file } => - payout_spend(&quantus_client, index, &from, password, password_file).await, + payout_spend(&quantus_client, index, &from, password, password_file, finalized).await, TreasuryCommands::CheckStatus { index, from, password, password_file } => - check_spend_status(&quantus_client, index, &from, password, password_file).await, + check_spend_status(&quantus_client, index, &from, password, password_file, finalized) + .await, TreasuryCommands::ListSpends => list_spends(&quantus_client).await, TreasuryCommands::SpendSudo { beneficiary, amount, from, password, password_file } => - spend_sudo(&quantus_client, &beneficiary, &amount, &from, password, password_file).await, + spend_sudo( + &quantus_client, + &beneficiary, + &amount, + &from, + password, + password_file, + finalized, + ) + .await, } } @@ -285,6 +297,7 @@ async fn submit_spend_referendum( from: &str, password: Option, password_file: Option, + finalized: bool, ) -> crate::error::Result<()> { use qp_poseidon::PoseidonHasher; use sp_core::crypto::{AccountId32 as SpAccountId32, Ss58Codec}; @@ -339,7 +352,7 @@ async fn submit_spend_referendum( // Submit preimage let preimage_call = quantus_subxt::api::tx().preimage().note_preimage(encoded_call.clone()); let preimage_tx_hash = - submit_transaction(quantus_client, &keypair, preimage_call, None).await?; + submit_transaction(quantus_client, &keypair, preimage_call, None, finalized).await?; log_print!("✅ Preimage created {:?}", preimage_tx_hash); @@ -381,7 +394,8 @@ async fn submit_spend_referendum( ); let submit_call = quantus_subxt::api::tx().referenda().submit(origin_caller, proposal, enactment); - let submit_tx_hash = submit_transaction(quantus_client, &keypair, submit_call, None).await?; + let submit_tx_hash = + submit_transaction(quantus_client, &keypair, submit_call, None, finalized).await?; log_print!( "✅ {} Treasury spend referendum submitted! {:?}", @@ -408,6 +422,7 @@ async fn payout_spend( from: &str, password: Option, password_file: Option, + finalized: bool, ) -> crate::error::Result<()> { log_print!("💸 Paying out Treasury Spend #{}", index); @@ -417,7 +432,8 @@ async fn payout_spend( // Create payout call let payout_call = quantus_subxt::api::tx().treasury_pallet().payout(index); - let tx_hash = submit_transaction(quantus_client, &keypair, payout_call, None).await?; + let tx_hash = + submit_transaction(quantus_client, &keypair, payout_call, None, finalized).await?; log_print!( "✅ {} Payout transaction submitted! Hash: {:?}", "SUCCESS".bright_green().bold(), @@ -437,6 +453,7 @@ async fn check_spend_status( from: &str, password: Option, password_file: Option, + finalized: bool, ) -> crate::error::Result<()> { log_print!("🔍 Checking Treasury Spend #{} status", index); @@ -446,7 +463,7 @@ async fn check_spend_status( // Create check_status call let check_call = quantus_subxt::api::tx().treasury_pallet().check_status(index); - let tx_hash = submit_transaction(quantus_client, &keypair, check_call, None).await?; + let tx_hash = submit_transaction(quantus_client, &keypair, check_call, None, finalized).await?; log_print!( "✅ {} Check status transaction submitted! Hash: {:?}", "SUCCESS".bright_green().bold(), @@ -514,6 +531,7 @@ async fn spend_sudo( from: &str, password: Option, password_file: Option, + finalized: bool, ) -> crate::error::Result<()> { use sp_core::crypto::{AccountId32 as SpAccountId32, Ss58Codec}; @@ -555,7 +573,7 @@ async fn spend_sudo( // Submit transaction log_print!("📡 Submitting sudo transaction..."); - let tx_hash = submit_transaction(quantus_client, &keypair, sudo_call, None).await?; + let tx_hash = submit_transaction(quantus_client, &keypair, sudo_call, None, finalized).await?; log_print!( "✅ {} Sudo transaction submitted! Hash: {:?}", "SUCCESS".bright_green().bold(), diff --git a/src/config/mod.rs b/src/config/mod.rs index 3c97e86..c6d7ac8 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -3,7 +3,7 @@ //! This module handles runtime compatibility information. /// List of runtime spec versions that this CLI is compatible with -pub const COMPATIBLE_RUNTIME_VERSIONS: &[u32] = &[115]; +pub const COMPATIBLE_RUNTIME_VERSIONS: &[u32] = &[115, 116]; /// Check if a runtime version is compatible with this CLI pub fn is_runtime_compatible(spec_version: u32) -> bool {