Skip to content
Snippets Groups Projects
main.rs 5.72 KiB
Newer Older
mod commands;
Hugo Trentesaux's avatar
Hugo Trentesaux committed
mod conf;
Hugo Trentesaux's avatar
Hugo Trentesaux committed
mod data;
mod display;
mod indexer;
mod runtime_config;
mod utils;
use anyhow::anyhow;
use clap::builder::OsStr;
Éloïs's avatar
Éloïs committed
use clap::Parser;
use codec::Encode;
Hugo Trentesaux's avatar
Hugo Trentesaux committed
use data::*;
use display::DisplayEvent;
Hugo Trentesaux's avatar
Hugo Trentesaux committed
use keys::*;
use runtime_config::*;
use serde::{Deserialize, Serialize};
use std::str::FromStr;
use subxt::{
	blocks::ExtrinsicEvents,
	config::DefaultExtrinsicParamsBuilder,
	events::StaticEvent,
	ext::sp_core::{sr25519, Pair as _},
Hugo Trentesaux's avatar
Hugo Trentesaux committed
	tx::{DefaultPayload, PairSigner, Payload, TxStatus},
use utils::*;
Éloïs's avatar
Éloïs committed

Hugo Trentesaux's avatar
Hugo Trentesaux committed
// alias
pub type StaticPayload<Calldata> = DefaultPayload<Calldata>;

/// define command line arguments
Hugo Trentesaux's avatar
Hugo Trentesaux committed
#[derive(Clone, clap::Parser, Debug, Default)]
Éloïs's avatar
Éloïs committed
#[clap(author, version, about, long_about = None)]
pub struct Args {
Hugo Trentesaux's avatar
Hugo Trentesaux committed
	/// Subcommands
	#[clap(subcommand)]
	pub subcommand: Subcommand,
	/// Overwrite indexer endpoint
	#[clap(short, long, conflicts_with_all=["no_indexer","network"])]
	indexer: Option<String>,
	/// Do not use indexer
	#[clap(long)]
	no_indexer: bool,
	/// Secret key or BIP39 mnemonic (only used when secret format is compatible)
	/// (eventually followed by derivation path)
	#[clap(short, long)]
	secret: Option<String>,
	/// Secret key format (seed, substrate, g1v1)
	#[clap(short = 'S', long)]
	secret_format: Option<SecretFormat>,
	/// SS58 Address
	#[clap(short, conflicts_with = "name")]
	address: Option<AccountId>,
	/// Name of an SS58 Address in the vault
	#[clap(short = 'v')]
	name: Option<String>,
	/// Overwrite duniter websocket RPC endpoint
	#[clap(short, long, conflicts_with = "network")]
	url: Option<String>,
	/// Target network (local, gdev, gtest...)
	#[clap(short, long)]
	network: Option<String>,
	/// prevent waiting for extrinsic completion
	#[clap(long)]
	no_wait: bool,
	/// Output format (human, json, ...)
	#[clap(short = 'o', long, default_value = OutputFormat::Human)]
	output_format: OutputFormat,
}

// TODO derive the fromstr implementation
/// secret format
#[derive(Clone, Copy, Debug, Eq, PartialEq, Default)]
enum OutputFormat {
	/// Human
	#[default]
	Human,
	/// JSON
	Json,
}
impl FromStr for OutputFormat {
	type Err = std::io::Error;

	fn from_str(s: &str) -> std::io::Result<Self> {
		match s {
			"human" => Ok(OutputFormat::Human),
			"json" => Ok(OutputFormat::Json),
			_ => Err(std::io::Error::from(std::io::ErrorKind::InvalidInput)),
		}
	}
}
impl From<OutputFormat> for &'static str {
	fn from(val: OutputFormat) -> &'static str {
		match val {
			OutputFormat::Human => "human",
			OutputFormat::Json => "json",
		}
	}
}
impl From<OutputFormat> for OsStr {
	fn from(val: OutputFormat) -> OsStr {
		OsStr::from(Into::<&str>::into(val))
	}
Éloïs's avatar
Éloïs committed
}

/// define subcommands
Hugo Trentesaux's avatar
Hugo Trentesaux committed
#[derive(Clone, Debug, clap::Subcommand, Default)]
Éloïs's avatar
Éloïs committed
pub enum Subcommand {
	#[clap(hide = true)]
	Nothing,
	/// Account (balance, transfer...)
	#[clap(subcommand)]
	Account(commands::account::Subcommand),
	/// Identity (get, create, confirm, revoke...)
	#[clap(subcommand)]
	Identity(commands::identity::Subcommand),
	/// Smith (certify, go-online, go-offline...)
	#[clap(subcommand)]
	Smith(commands::smith::Subcommand),
	/// Sudo (set key, sudo calls...)
	#[clap(hide = true)]
	#[clap(subcommand)]
	Sudo(commands::sudo::Subcommand),
	/// Tech (list members, proposals, vote...)
	#[clap(subcommand)]
	Tech(commands::collective::Subcommand),
	/// Universal Dividend (claim...)
	#[clap(subcommand)]
	Ud(commands::ud::Subcommand),
	/// Oneshot account (balance, create, consume...)
	#[clap(subcommand)]
	Oneshot(commands::oneshot::Subcommand),
	/// Blockchain (current block, runtime info...)
	#[clap(subcommand)]
	Blockchain(commands::blockchain::Subcommand),
	/// Indexer (check, latest block)
Hugo Trentesaux's avatar
Hugo Trentesaux committed
	#[clap(subcommand)]
	Indexer(indexer::Subcommand),
	/// Config (show, save...)
Hugo Trentesaux's avatar
Hugo Trentesaux committed
	#[clap(subcommand)]
	Config(conf::Subcommand),
	/// Key management (import, generate, list...)
	#[clap(subcommand)]
	Vault(commands::vault::Subcommand),
	/// Cesium
	#[clap(subcommand, hide = true)]
	Cesium(commands::cesium::Subcommand),
	/// Publish a new git tag with actual version
	#[clap(hide = true)]
	Publish,
Éloïs's avatar
Éloïs committed
}

/// main function
Éloïs's avatar
Éloïs committed
#[tokio::main(flavor = "current_thread")]
Hugo Trentesaux's avatar
Hugo Trentesaux committed
async fn main() -> Result<(), GcliError> {
Hugo Trentesaux's avatar
Hugo Trentesaux committed
	// init logger
	env_logger::init();
Éloïs's avatar
Éloïs committed

Hugo Trentesaux's avatar
Hugo Trentesaux committed
	// parse argument and initialize data
Éloïs's avatar
Éloïs committed

	// match subcommands
	let result = match data.args.subcommand.clone() {
		Subcommand::Nothing => Ok(()),
		Subcommand::Account(subcommand) => {
Hugo Trentesaux's avatar
Hugo Trentesaux committed
			commands::account::handle_command(data, subcommand).await
		}
		Subcommand::Identity(subcommand) => {
Hugo Trentesaux's avatar
Hugo Trentesaux committed
			commands::identity::handle_command(data, subcommand).await
Hugo Trentesaux's avatar
Hugo Trentesaux committed
		Subcommand::Smith(subcommand) => commands::smith::handle_command(data, subcommand).await,
		Subcommand::Sudo(subcommand) => commands::sudo::handle_command(data, subcommand).await,
		Subcommand::Tech(subcommand) => {
Hugo Trentesaux's avatar
Hugo Trentesaux committed
			commands::collective::handle_command(data, subcommand).await
Hugo Trentesaux's avatar
Hugo Trentesaux committed
		Subcommand::Ud(subcommand) => commands::ud::handle_command(data, subcommand).await,
		Subcommand::Oneshot(subcommand) => {
Hugo Trentesaux's avatar
Hugo Trentesaux committed
			commands::oneshot::handle_command(data, subcommand).await
		Subcommand::Blockchain(subcommand) => {
Hugo Trentesaux's avatar
Hugo Trentesaux committed
			commands::blockchain::handle_command(data, subcommand).await
Hugo Trentesaux's avatar
Hugo Trentesaux committed
		Subcommand::Indexer(subcommand) => indexer::handle_command(data, subcommand).await,
		Subcommand::Config(subcommand) => conf::handle_command(data, subcommand).await,
		Subcommand::Vault(subcommand) => commands::vault::handle_command(data, subcommand).await,
		Subcommand::Cesium(subcommand) => commands::cesium::handle_command(data, subcommand).await,
		Subcommand::Publish => commands::publish::handle_command().await,
	};
	if let Err(ref e) = result {
		println!("{}", e.to_string().red())
	// still return result for detailed error message
Éloïs's avatar
Éloïs committed
}