quantus_cli/cli/
high_security.rs1use crate::{
2 chain::quantus_subxt, cli::address_format::QuantusSS58, log_error, log_print, log_success,
3 log_verbose,
4};
5use clap::Subcommand;
6use colored::Colorize;
7use sp_core::crypto::{AccountId32 as SpAccountId32, Ss58Codec};
8
9#[derive(Subcommand, Debug)]
11pub enum HighSecurityCommands {
12 Status {
14 #[arg(long)]
16 account: String,
17 },
18
19 Set {
21 #[arg(long)]
23 interceptor: String,
24
25 #[arg(long, conflicts_with = "delay_seconds")]
27 delay_blocks: Option<u32>,
28
29 #[arg(long, conflicts_with = "delay_blocks")]
31 delay_seconds: Option<u64>,
32
33 #[arg(short, long)]
35 from: String,
36
37 #[arg(short, long)]
39 password: Option<String>,
40
41 #[arg(long)]
43 password_file: Option<String>,
44 },
45}
46
47pub async fn handle_high_security_command(
49 command: HighSecurityCommands,
50 node_url: &str,
51 finalized: bool,
52) -> crate::error::Result<()> {
53 let quantus_client = crate::chain::client::QuantusClient::new(node_url).await?;
54
55 match command {
56 HighSecurityCommands::Status { account } => {
57 log_print!("🔍 Checking High Security Status");
58
59 let resolved_account = crate::cli::common::resolve_address(&account)?;
61 let account_id_sp = SpAccountId32::from_ss58check(&resolved_account).map_err(|e| {
62 crate::error::QuantusError::Generic(format!(
63 "Invalid account address '{resolved_account}': {e:?}"
64 ))
65 })?;
66 let account_id_bytes: [u8; 32] = *account_id_sp.as_ref();
67 let account_id = subxt::ext::subxt_core::utils::AccountId32::from(account_id_bytes);
68
69 let account_ss58 = account_id.to_quantus_ss58();
71
72 let storage_addr = quantus_subxt::api::storage()
74 .reversible_transfers()
75 .high_security_accounts(account_id);
76 let latest = quantus_client.get_latest_block().await?;
77 let value = quantus_client
78 .client()
79 .storage()
80 .at(latest)
81 .fetch(&storage_addr)
82 .await
83 .map_err(|e| {
84 crate::error::QuantusError::NetworkError(format!("Fetch error: {e:?}"))
85 })?;
86
87 log_print!("📋 Account: {}", account_ss58.bright_cyan());
88
89 if let Some(high_security_data) = value {
90 log_success!("✅ High Security: ENABLED");
91
92 let interceptor_ss58 = high_security_data.interceptor.to_quantus_ss58();
94
95 log_print!("🛡️ Guardian/Interceptor: {}", interceptor_ss58.bright_green());
96
97 match high_security_data.delay {
99 quantus_subxt::api::runtime_types::qp_scheduler::BlockNumberOrTimestamp::BlockNumber(blocks) => {
100 log_print!("⏱️ Delay: {} blocks", blocks.to_string().bright_yellow());
101 },
102 quantus_subxt::api::runtime_types::qp_scheduler::BlockNumberOrTimestamp::Timestamp(ms) => {
103 let seconds = ms / 1000;
104 log_print!("⏱️ Delay: {} seconds", seconds.to_string().bright_yellow());
105 },
106 }
107 } else {
108 log_print!("❌ High Security: DISABLED");
109 log_print!("💡 This account does not have high-security reversibility enabled.");
110 }
111
112 Ok(())
113 },
114
115 HighSecurityCommands::Set {
116 interceptor,
117 delay_blocks,
118 delay_seconds,
119 from,
120 password,
121 password_file,
122 } => {
123 log_print!("🛡️ Set High Security");
124 log_verbose!("📦 Using wallet: {}", from.bright_blue().bold());
125 let keypair = crate::wallet::load_keypair_from_wallet(&from, password, password_file)?;
126
127 let interceptor_resolved = crate::cli::common::resolve_address(&interceptor)?;
129 let interceptor_sp =
130 SpAccountId32::from_ss58check(&interceptor_resolved).map_err(|e| {
131 crate::error::QuantusError::Generic(format!(
132 "Invalid interceptor address '{interceptor_resolved}': {e:?}"
133 ))
134 })?;
135 let interceptor_bytes: [u8; 32] = *interceptor_sp.as_ref();
136 let interceptor_subxt =
137 subxt::ext::subxt_core::utils::AccountId32::from(interceptor_bytes);
138
139 use quantus_subxt::api::reversible_transfers::calls::types::set_high_security::Delay as HsDelay;
141 let delay_value = match (delay_blocks, delay_seconds) {
142 (Some(blocks), None) => HsDelay::BlockNumber(blocks),
143 (None, Some(seconds)) => HsDelay::Timestamp(seconds * 1000), (None, None) => {
146 log_error!("❌ You must specify either --delay-blocks or --delay-seconds");
147 return Err(crate::error::QuantusError::Generic(
148 "Missing delay parameter".to_string(),
149 ));
150 },
151 (Some(_), Some(_)) => {
152 unreachable!("clap conflicts_with ensures these are mutually exclusive")
153 },
154 };
155
156 log_verbose!("✍️ Creating set_high_security extrinsic...");
157
158 let tx_call = quantus_subxt::api::tx()
160 .reversible_transfers()
161 .set_high_security(delay_value, interceptor_subxt);
162
163 let tx_hash = crate::cli::common::submit_transaction(
164 &quantus_client,
165 &keypair,
166 tx_call,
167 None,
168 finalized,
169 )
170 .await?;
171
172 log_success!("✅ SUCCESS High security set! Hash: 0x{}", hex::encode(tx_hash.as_ref()));
173
174 Ok(())
175 },
176 }
177}