use std::path::PathBuf;
use cargo_tangle::create::BlueprintType;
use cargo_tangle::{create, deploy, keys};
use clap::{Parser, Subcommand};
use keys::KeyType;
#[derive(Parser, Debug)]
#[clap(
bin_name = "cargo-tangle",
version,
propagate_version = true,
arg_required_else_help = true
)]
struct Cli {
#[command(flatten)]
manifest: clap_cargo::Manifest,
#[command(flatten)]
features: clap_cargo::Features,
#[command(subcommand)]
command: Commands,
}
#[derive(Subcommand, Debug)]
enum Commands {
#[command(visible_alias = "bp")]
Blueprint {
#[command(subcommand)]
subcommand: GadgetCommands,
},
}
#[derive(Subcommand, Debug)]
pub enum GadgetCommands {
#[command(visible_alias = "c")]
Create {
#[arg(short, long, value_name = "NAME", env = "NAME")]
name: String,
#[command(flatten)]
source: Option<create::Source>,
#[command(flatten)]
blueprint_type: Option<BlueprintType>,
},
#[command(visible_alias = "d")]
Deploy {
#[arg(
long,
value_name = "URL",
default_value = "https://rpc.tangle.tools",
env
)]
http_rpc_url: String,
#[arg(
long,
value_name = "URL",
default_value = "wss://rpc.tangle.tools",
env
)]
ws_rpc_url: String,
#[arg(short, long, value_name = "PACKAGE", env = "CARGO_PACKAGE")]
package: Option<String>,
},
Keygen {
#[arg(short, long, value_enum)]
key_type: KeyType,
#[arg(short, long)]
path: Option<PathBuf>,
#[arg(short, long, value_name = "SEED_HEX", env = "SEED")]
seed: Option<String>,
#[arg(long)]
show_secret: bool,
},
}
#[tokio::main]
#[allow(clippy::needless_return)]
async fn main() -> color_eyre::Result<()> {
color_eyre::install()?;
init_tracing_subscriber();
let args: Vec<String> = if std::env::args()
.nth(1)
.map(|x| x.eq("tangle"))
.unwrap_or(false)
{
std::env::args().skip(1).collect()
} else {
std::env::args().collect()
};
let cli = Cli::parse_from(args);
match cli.command {
Commands::Blueprint { subcommand } => match subcommand {
GadgetCommands::Create {
name,
source,
blueprint_type,
} => {
create::new_blueprint(name, source, blueprint_type)?;
}
GadgetCommands::Deploy {
http_rpc_url,
ws_rpc_url,
package,
} => {
let manifest_path = cli
.manifest
.manifest_path
.unwrap_or_else(|| PathBuf::from("Cargo.toml"));
let _ = deploy::deploy_to_tangle(deploy::Opts {
http_rpc_url,
ws_rpc_url,
manifest_path,
pkg_name: package,
signer: None,
signer_evm: None,
})
.await?;
}
GadgetCommands::Keygen {
key_type,
path,
seed,
show_secret,
} => {
let seed = seed.map(hex::decode).transpose()?;
keys::generate_key(key_type, path, seed.as_deref(), show_secret)?;
}
},
}
Ok(())
}
fn init_tracing_subscriber() {
use tracing_subscriber::fmt::format::FmtSpan;
use tracing_subscriber::prelude::*;
let fmt_layer = tracing_subscriber::fmt::layer()
.with_target(false)
.with_span_events(FmtSpan::CLOSE)
.pretty();
tracing_subscriber::registry()
.with(tracing_subscriber::EnvFilter::from_default_env())
.with(fmt_layer)
.init();
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn verify_cli() {
use clap::CommandFactory;
Cli::command().debug_assert();
}
}