use crate::ErrorVariant;
use std::fmt::Debug;
use super::{
create_signer,
parse_code_hash,
CLIExtrinsicOpts,
};
use anyhow::Result;
use contract_build::name_value_println;
use contract_extrinsics::{
DisplayEvents,
ExtrinsicOptsBuilder,
RemoveCommandBuilder,
RemoveExec,
TokenMetadata,
};
use ink_env::DefaultEnvironment;
use subxt::{
Config,
PolkadotConfig as DefaultConfig,
};
use subxt_signer::sr25519::Keypair;
#[derive(Debug, clap::Args)]
#[clap(name = "remove", about = "Remove a contract's code")]
pub struct RemoveCommand {
#[clap(long, value_parser = parse_code_hash)]
code_hash: Option<<DefaultConfig as Config>::Hash>,
#[clap(flatten)]
extrinsic_cli_opts: CLIExtrinsicOpts,
#[clap(long, conflicts_with = "verbose")]
output_json: bool,
}
impl RemoveCommand {
pub fn output_json(&self) -> bool {
self.output_json
}
pub async fn handle(&self) -> Result<(), ErrorVariant> {
let token_metadata =
TokenMetadata::query::<DefaultConfig>(&self.extrinsic_cli_opts.url).await?;
let signer: Keypair = create_signer(&self.extrinsic_cli_opts.suri)?;
let extrinsic_opts = ExtrinsicOptsBuilder::new(signer)
.file(self.extrinsic_cli_opts.file.clone())
.manifest_path(self.extrinsic_cli_opts.manifest_path.clone())
.url(self.extrinsic_cli_opts.url.clone())
.storage_deposit_limit(
self.extrinsic_cli_opts
.storage_deposit_limit
.clone()
.map(|bv| bv.denominate_balance(&token_metadata))
.transpose()?,
)
.done();
let remove_exec: RemoveExec<DefaultConfig, DefaultEnvironment, Keypair> =
RemoveCommandBuilder::new(extrinsic_opts)
.code_hash(self.code_hash)
.done()
.await?;
let remove_result = remove_exec.remove_code().await?;
let display_events =
DisplayEvents::from_events::<DefaultConfig, DefaultEnvironment>(
&remove_result.events,
Some(remove_exec.transcoder()),
&remove_exec.client().metadata(),
)?;
let output_events = if self.output_json() {
display_events.to_json()?
} else {
display_events.display_events::<DefaultEnvironment>(
self.extrinsic_cli_opts.verbosity().unwrap(),
&token_metadata,
)?
};
if let Some(code_removed) = remove_result.code_removed {
let remove_result: <DefaultConfig as Config>::Hash = code_removed.code_hash;
if self.output_json() {
let json_object = serde_json::json!({
"events": serde_json::from_str::<serde_json::Value>(&output_events)?,
"code_hash": remove_result,
});
let json_object = serde_json::to_string_pretty(&json_object)?;
println!("{}", json_object);
} else {
println!("{}", output_events);
name_value_println!("Code hash", format!("{remove_result:?}"));
}
Result::<(), ErrorVariant>::Ok(())
} else {
let error_code_hash = hex::encode(remove_exec.final_code_hash());
Err(anyhow::anyhow!(
"Error removing the code for the supplied code hash: {}",
error_code_hash
)
.into())
}
}
}