pub mod build;
pub mod call;
pub mod decode;
pub mod encode;
pub mod info;
pub mod instantiate;
pub mod remove;
pub mod schema;
pub mod storage;
pub mod upload;
pub mod verify;
pub(crate) use self::{
build::{
BuildCommand,
CheckCommand,
},
call::CallCommand,
decode::DecodeCommand,
info::{
ExtendedContractInfo,
InfoCommand,
},
instantiate::InstantiateCommand,
remove::RemoveCommand,
schema::{
GenerateSchemaCommand,
VerifySchemaCommand,
},
storage::StorageCommand,
upload::UploadCommand,
verify::VerifyCommand,
};
use crate::{
anyhow,
PathBuf,
Weight,
};
use anyhow::{
Context,
Result,
};
use colored::Colorize;
use contract_build::{
name_value_println,
Verbosity,
VerbosityFlags,
DEFAULT_KEY_COL_WIDTH,
};
pub(crate) use contract_extrinsics::ErrorVariant;
use contract_extrinsics::{
Balance,
BalanceVariant,
};
use pallet_contracts_primitives::ContractResult;
use std::io::{
self,
Write,
};
pub use subxt::{
Config,
PolkadotConfig as DefaultConfig,
};
#[derive(Clone, Debug, clap::Args)]
pub struct CLIExtrinsicOpts {
#[clap(value_parser, conflicts_with = "manifest_path")]
file: Option<PathBuf>,
#[clap(long, value_parser)]
manifest_path: Option<PathBuf>,
#[clap(
name = "url",
long,
value_parser,
default_value = "ws://localhost:9944"
)]
url: url::Url,
#[clap(name = "suri", long, short)]
suri: String,
#[clap(flatten)]
verbosity: VerbosityFlags,
#[clap(short('x'), long)]
execute: bool,
#[clap(long)]
storage_deposit_limit: Option<BalanceVariant>,
#[clap(long)]
skip_dry_run: bool,
#[clap(short('y'), long)]
skip_confirm: bool,
}
impl CLIExtrinsicOpts {
pub fn verbosity(&self) -> Result<Verbosity> {
TryFrom::try_from(&self.verbosity)
}
}
const STORAGE_DEPOSIT_KEY: &str = "Storage Total Deposit";
pub const MAX_KEY_COL_WIDTH: usize = STORAGE_DEPOSIT_KEY.len() + 1;
pub fn display_contract_exec_result<R, const WIDTH: usize>(
result: &ContractResult<R, Balance, ()>,
) -> Result<()> {
let mut debug_message_lines = std::str::from_utf8(&result.debug_message)
.context("Error decoding UTF8 debug message bytes")?
.lines();
name_value_println!("Gas Consumed", format!("{:?}", result.gas_consumed), WIDTH);
name_value_println!("Gas Required", format!("{:?}", result.gas_required), WIDTH);
name_value_println!(
STORAGE_DEPOSIT_KEY,
format!("{:?}", result.storage_deposit),
WIDTH
);
if let Some(debug_message) = debug_message_lines.next() {
name_value_println!("Debug Message", format!("{debug_message}"), WIDTH);
}
for debug_message in debug_message_lines {
name_value_println!("", format!("{debug_message}"), WIDTH);
}
Ok(())
}
pub fn display_contract_exec_result_debug<R, const WIDTH: usize>(
result: &ContractResult<R, Balance, ()>,
) -> Result<()> {
let mut debug_message_lines = std::str::from_utf8(&result.debug_message)
.context("Error decoding UTF8 debug message bytes")?
.lines();
if let Some(debug_message) = debug_message_lines.next() {
name_value_println!("Debug Message", format!("{debug_message}"), WIDTH);
}
for debug_message in debug_message_lines {
name_value_println!("", format!("{debug_message}"), WIDTH);
}
Ok(())
}
pub fn display_dry_run_result_warning(command: &str) {
println!("Your {} call {} been executed.", command, "has not".bold());
println!(
"To submit the transaction and execute the call on chain, add {} flag to the command.",
"-x/--execute".bold()
);
}
pub fn prompt_confirm_tx<F: FnOnce()>(show_details: F) -> Result<()> {
println!(
"{} (skip with --skip-confirm or -y)",
"Confirm transaction details:".bright_white().bold()
);
show_details();
print!(
"{} ({}/n): ",
"Submit?".bright_white().bold(),
"Y".bright_white().bold()
);
let mut buf = String::new();
io::stdout().flush()?;
io::stdin().read_line(&mut buf)?;
match buf.trim().to_lowercase().as_str() {
"y" | "" => Ok(()),
"n" => Err(anyhow!("Transaction not submitted")),
c => Err(anyhow!("Expected either 'y' or 'n', got '{}'", c)),
}
}
pub fn print_dry_running_status(msg: &str) {
println!(
"{:>width$} {} (skip with --skip-dry-run)",
"Dry-running".green().bold(),
msg.bright_white().bold(),
width = DEFAULT_KEY_COL_WIDTH
);
}
pub fn print_gas_required_success(gas: Weight) {
println!(
"{:>width$} Gas required estimated at {}",
"Success!".green().bold(),
gas.to_string().bright_white(),
width = DEFAULT_KEY_COL_WIDTH
);
}
pub fn basic_display_format_extended_contract_info(info: &ExtendedContractInfo) {
name_value_println!("TrieId", info.trie_id, MAX_KEY_COL_WIDTH);
name_value_println!(
"Code Hash",
format!("{:?}", info.code_hash),
MAX_KEY_COL_WIDTH
);
name_value_println!(
"Storage Items",
format!("{:?}", info.storage_items),
MAX_KEY_COL_WIDTH
);
name_value_println!(
"Storage Items Deposit",
format!("{:?}", info.storage_items_deposit),
MAX_KEY_COL_WIDTH
);
name_value_println!(
STORAGE_DEPOSIT_KEY,
format!("{:?}", info.storage_total_deposit),
MAX_KEY_COL_WIDTH
);
name_value_println!(
"Source Language",
format!("{}", info.source_language),
MAX_KEY_COL_WIDTH
);
}
pub fn display_all_contracts(contracts: &[<DefaultConfig as Config>::AccountId]) {
contracts
.iter()
.for_each(|e: &<DefaultConfig as Config>::AccountId| println!("{}", e))
}