diff --git a/orchestrator/gorc/src/commands/cosmos_to_eth.rs b/orchestrator/gorc/src/commands/cosmos_to_eth.rs index a67c6ac99..63c0b73bc 100644 --- a/orchestrator/gorc/src/commands/cosmos_to_eth.rs +++ b/orchestrator/gorc/src/commands/cosmos_to_eth.rs @@ -12,11 +12,33 @@ const TIMEOUT: Duration = Duration::from_secs(60); /// This command, send Cosmos to Ethereum #[derive(Command, Debug, Default, Parser)] +#[clap( + long_about = "DESCRIPTION \n\n Send Cosmos token to Eth chain.\n This command sends Cosmos token to the Eth chain via the Gravity bridge. \n This command takes the Gravity denom, tx amount, Cosmos keyname, Eth destination, number of times \n transaction should be made and if the transaction should be made immediately or wait for the next \n batch." +)] pub struct CosmosToEthCmd { - pub args: Vec, + /// Gravity denom + #[clap(short, long)] + gravity_denom: String, + + /// Tx amount. + #[clap(short, long)] + amount: String, + /// Cosmos keyname. #[clap(short, long)] - pub flag_no_batch: bool, + cosmos_key: String, + + /// Ethereum address + #[clap(short, long)] + eth_dest: String, + + /// The number of times transactions should repeat itself, default is 1. + #[clap(short, long, default_value = "1")] + times: String, + + /// Boolean, True if you want to wait until someone requests a batch for this token type and False if you want to request a batch to push transaction along immediately. + #[clap(short = 'f', long)] + pub wait_for_batch: bool, } pub fn one_eth() -> f64 { @@ -45,15 +67,14 @@ pub fn print_eth(input: Uint256) -> String { impl Runnable for CosmosToEthCmd { fn run(&self) { let config = APP.config(); - let gravity_denom = self.args.get(0).expect("denom is required"); - let gravity_denom = gravity_denom.to_string(); + let gravity_denom = self.gravity_denom.clone(); let is_cosmos_originated = !gravity_denom.starts_with("gravity"); - let amount = self.args.get(1).expect("amount is required"); + let amount = self.amount.clone(); let amount: Uint256 = amount.parse().expect("cannot parse amount"); - let cosmos_key = self.args.get(2).expect("name is required"); - let cosmos_key = config.load_deep_space_key(cosmos_key.to_string()); + let cosmos_key = self.cosmos_key.clone(); + let cosmos_key = config.load_deep_space_key(cosmos_key); let cosmos_prefix = config.cosmos.prefix.trim(); let cosmos_address = cosmos_key.to_address(cosmos_prefix).unwrap(); @@ -98,7 +119,7 @@ impl Runnable for CosmosToEthCmd { denom: gravity_denom.clone(), }; - let eth_dest = self.args.get(3).expect("ethereum destination is required"); + let eth_dest = self.eth_dest.clone(); let eth_dest: EthAddress = eth_dest.parse().expect("cannot parse ethereum address"); check_for_fee_denom(&gravity_denom, cosmos_address, &contact).await; @@ -115,7 +136,7 @@ impl Runnable for CosmosToEthCmd { println!("Cosmos balances {:?}", balances); - let times = self.args.get(4).expect("times is required"); + let times = self.times.clone(); let times = times.parse::().expect("cannot parse times"); match found { @@ -164,7 +185,7 @@ impl Runnable for CosmosToEthCmd { } if successful_sends > 0 { - if !self.flag_no_batch { + if !self.wait_for_batch { println!("Requesting a batch to push transaction along immediately"); send_request_batch_tx(cosmos_key, gravity_denom,config.cosmos.gas_price.as_tuple(), &contact,config.cosmos.gas_adjustment) .await diff --git a/orchestrator/gorc/src/commands/deploy/erc20.rs b/orchestrator/gorc/src/commands/deploy/erc20.rs index 760e2f50a..0435ae873 100644 --- a/orchestrator/gorc/src/commands/deploy/erc20.rs +++ b/orchestrator/gorc/src/commands/deploy/erc20.rs @@ -14,12 +14,17 @@ use tokio::time::sleep as delay_for; /// Deploy Erc20 #[derive(Command, Debug, Parser)] +#[clap( + long_about = "DESCRIPTION \n\n Deploy ERC20 tokens via the Gravity Bridge.\n This command takes a token denom, Ethereum key and gas multiplier." +)] pub struct Erc20 { - args: Vec, - + /// Erc20 token denom. + #[clap(short, long)] + denom: String, + /// Ethereum ID representing a Keystore entry. #[clap(short, long)] ethereum_key: String, - + /// Ethereum gas multiplier, default is 1. #[clap(short, long, default_value_t = 1.0)] gas_multiplier: f64, } @@ -38,7 +43,7 @@ impl Runnable for Erc20 { impl Erc20 { async fn deploy(&self) { - let denom = self.args.get(0).expect("denom is required"); + let denom = self.denom.clone(); let config = APP.config(); diff --git a/orchestrator/gorc/src/commands/eth_to_cosmos.rs b/orchestrator/gorc/src/commands/eth_to_cosmos.rs index 81b482c1a..6f2ec949d 100644 --- a/orchestrator/gorc/src/commands/eth_to_cosmos.rs +++ b/orchestrator/gorc/src/commands/eth_to_cosmos.rs @@ -15,24 +15,49 @@ const TIMEOUT: Duration = Duration::from_secs(60); /// This command send Ethereum to Cosmos #[derive(Command, Debug, Default, Parser)] +#[clap( + long_about = "DESCRIPTION \n\n Send Eth token to Cosmos chain.\n This command sends Eth token to the Cosmos chain via the Gravity bridge. \n It takes the tx amount, Eth keyname, contract address, Cosmos token destination, number of times \n and the ERC20 token contract address." +)] pub struct EthToCosmosCmd { - pub args: Vec, + /// Erc20 contract address. + #[clap(short = 'E', long)] + erc20_address: String, + + /// Tx amount. + #[clap(short, long)] + init_amount: String, + + /// Eth keyname. + #[clap(short, long)] + ethereum_key: String, + + /// Cosmos address + #[clap(short, long)] + cosmos_dest: String, + + /// The number of times transactions should repeat itself, default is 1. + #[clap(short, long, default_value = "1")] + times: String, + + /// Contract address. + #[clap(short = 'C', long)] + contract_address: String, } impl Runnable for EthToCosmosCmd { fn run(&self) { let config = APP.config(); - let erc20_address = self.args.get(0).expect("erc20 address is required"); + let erc20_address = self.erc20_address.clone(); let erc20_address: EthAddress = erc20_address .parse() .expect("Invalid ERC20 contract address!"); - let ethereum_key = self.args.get(1).expect("key is required"); - let ethereum_wallet = config.load_ethers_wallet(ethereum_key.clone()); + let ethereum_wallet = config.load_ethers_wallet(self.ethereum_key.clone()); - let contract_address = self.args.get(2).expect("contract address is required"); - let contract_address: EthAddress = - contract_address.parse().expect("Invalid contract address!"); + let contract_address: EthAddress = self + .contract_address + .parse() + .expect("Invalid contract address!"); let cosmos_prefix = config.cosmos.prefix.trim(); let eth_rpc = config.ethereum.rpc.trim(); @@ -56,22 +81,20 @@ impl Runnable for EthToCosmosCmd { let eth_client = SignerMiddleware::new(provider, ethereum_wallet.clone().with_chain_id(chain_id)); let eth_client = Arc::new(eth_client); - let cosmos_dest = self.args.get(3).expect("cosmos destination is required"); - let cosmos_dest: CosmosAddress = cosmos_dest.parse().unwrap(); + let cosmos_dest: CosmosAddress = self.cosmos_dest.parse().unwrap(); let ethereum_address = eth_client.address(); check_for_eth(ethereum_address, eth_client.clone()).await; - - let init_amount = self.args.get(4).expect("amount is required"); - let amount = U256::from_dec_str(init_amount).expect("cannot parse amount as U256"); + let amount = + U256::from_dec_str(&self.init_amount).expect("cannot parse amount as U256"); let erc20_balance = get_erc20_balance(erc20_address, ethereum_address, eth_client.clone()) .await .expect("Failed to get balance, check ERC20 contract address"); - let times = self.args.get(5).expect("times is required"); + let times = self.times.clone(); let times_usize = times.parse::().expect("cannot parse times as usize"); - let times_u256 = U256::from_dec_str(times).expect("cannot parse times as U256"); + let times_u256 = U256::from_dec_str(×).expect("cannot parse times as U256"); if erc20_balance == 0u8.into() { panic!( @@ -89,7 +112,7 @@ impl Runnable for EthToCosmosCmd { for _ in 0..times_usize { println!( "Sending {} / {} to Cosmos from {} to {}", - init_amount.parse::().unwrap(), + self.init_amount.parse::().unwrap(), erc20_address, ethereum_address, cosmos_dest diff --git a/orchestrator/gorc/src/commands/keys.rs b/orchestrator/gorc/src/commands/keys.rs index e9dee1b08..1f55acd75 100644 --- a/orchestrator/gorc/src/commands/keys.rs +++ b/orchestrator/gorc/src/commands/keys.rs @@ -10,9 +10,10 @@ use crate::commands::keys::eth::EthKeysCmd; #[derive(Command, Debug, Parser, Runnable)] pub enum KeysCmd { - #[clap(subcommand)] - Cosmos(CosmosKeysCmd), - + /// Manage Ethereum keys. #[clap(subcommand)] Eth(EthKeysCmd), + /// Manage Cosmos keys. + #[clap(subcommand)] + Cosmos(CosmosKeysCmd), } diff --git a/orchestrator/gorc/src/commands/keys/cosmos/add.rs b/orchestrator/gorc/src/commands/keys/cosmos/add.rs index 597a4c823..836c81676 100644 --- a/orchestrator/gorc/src/commands/keys/cosmos/add.rs +++ b/orchestrator/gorc/src/commands/keys/cosmos/add.rs @@ -8,9 +8,14 @@ use std::path; /// Add a new Cosmos Key #[derive(Command, Debug, Default, Parser)] +#[clap( + long_about = "DESCRIPTION \n\n Create a new Cosmos Key.\n This command creates a new Cosmos key. When provided an overwrite option, which if set to true,\n overwrites an existing key in the keystore with the same keyname." +)] pub struct AddCosmosKeyCmd { - pub args: Vec, + /// Cosmos keyname + pub name: String, + /// Overwrite key with the same name in the keystore when set to true. Takes a Boolean. #[clap(short, long)] pub overwrite: bool, } @@ -21,8 +26,7 @@ impl Runnable for AddCosmosKeyCmd { let keystore = path::Path::new(&config.keystore); let keystore = FsKeyStore::create_or_open(keystore).expect("Could not open keystore"); - let name = self.args.get(0).expect("name is required"); - let name = name.parse().expect("Could not parse name"); + let name = self.name.parse().expect("Could not parse name"); if let Ok(_info) = keystore.info(&name) { if !self.overwrite { eprintln!("Key already exists, exiting."); @@ -49,8 +53,8 @@ impl Runnable for AddCosmosKeyCmd { keystore.store(&name, &key).expect("Could not store key"); - let args = vec![name.to_string()]; - let show_cmd = ShowCosmosKeyCmd { args }; + let name = name.to_string(); + let show_cmd = ShowCosmosKeyCmd { name }; show_cmd.run(); } } diff --git a/orchestrator/gorc/src/commands/keys/cosmos/delete.rs b/orchestrator/gorc/src/commands/keys/cosmos/delete.rs index 6d01beed9..b6df2b11b 100644 --- a/orchestrator/gorc/src/commands/keys/cosmos/delete.rs +++ b/orchestrator/gorc/src/commands/keys/cosmos/delete.rs @@ -5,11 +5,15 @@ use std::path::Path; /// Delete a Cosmos Key #[derive(Command, Debug, Default, Parser)] +#[clap( + long_about = "DESCRIPTION \n\n Delete a Cosmos Key.\n This command deletes a Cosmos key from your keystore when provided with the keyname." +)] pub struct DeleteCosmosKeyCmd { - pub args: Vec, + /// Cosmos keyname in keystore. + pub name: String, } -/// The `gork keys cosmos delete [name] ` subcommand: delete the given key +/// The `gorc keys cosmos delete [name] ` subcommand: delete the given key impl Runnable for DeleteCosmosKeyCmd { fn run(&self) { let config = APP.config(); @@ -17,8 +21,7 @@ impl Runnable for DeleteCosmosKeyCmd { let keystore = Path::new(&config.keystore); let keystore = signatory::FsKeyStore::create_or_open(keystore).unwrap(); // Collect key name from args. - let name = self.args.get(0).expect("name is required"); - let name = name.parse().expect("Could not parse name"); + let name = self.name.parse().expect("Could not parse name"); // Delete keyname after locating file from path and key name. let _delete_key = FsKeyStore::delete(&keystore, &name).unwrap(); } diff --git a/orchestrator/gorc/src/commands/keys/cosmos/list.rs b/orchestrator/gorc/src/commands/keys/cosmos/list.rs index c6228d6a8..f9c1a3743 100644 --- a/orchestrator/gorc/src/commands/keys/cosmos/list.rs +++ b/orchestrator/gorc/src/commands/keys/cosmos/list.rs @@ -5,6 +5,9 @@ use std::path::Path; /// List all Cosmos Keys #[derive(Command, Debug, Default, Parser)] +#[clap( + long_about = "DESCRIPTION \n\n List all Cosmos keys in keystore.\n This command lists all Cosmos keys and their addresses from the keystore." +)] pub struct ListCosmosKeyCmd {} // Entry point for `gorc keys cosmos list` @@ -20,8 +23,8 @@ impl Runnable for ListCosmosKeyCmd { if extension == "pem" { let name = path.file_stem().unwrap(); let name = name.to_str().unwrap(); - let args = vec![name.to_string()]; - let show_cmd = ShowCosmosKeyCmd { args }; + let name = name.to_string(); + let show_cmd = ShowCosmosKeyCmd { name }; show_cmd.run(); } } diff --git a/orchestrator/gorc/src/commands/keys/cosmos/recover.rs b/orchestrator/gorc/src/commands/keys/cosmos/recover.rs index a53dfe3b8..3d9524337 100644 --- a/orchestrator/gorc/src/commands/keys/cosmos/recover.rs +++ b/orchestrator/gorc/src/commands/keys/cosmos/recover.rs @@ -7,11 +7,19 @@ use std::path; /// Recover a Cosmos Key #[derive(Command, Debug, Default, Parser)] +#[clap( + long_about = "DESCRIPTION \n\n Recover an external Cosmos key.\n This command will recover a Cosmos key, storing it in the keystore. \n It takes a keyname and bip39-mnemonic." +)] pub struct RecoverCosmosKeyCmd { - pub args: Vec, + /// Cosmos keyname. + pub name: String, + /// Overwrite key with the same name in the keystore when set to true. Takes a Boolean. #[clap(short, long)] pub overwrite: bool, + + /// bip39-mnemonic optional. When absent you'll be prompted to enter it. + pub mnemonic: Option, } // `gorc keys cosmos recover [name] (bip39-mnemonic)` @@ -23,8 +31,7 @@ impl Runnable for RecoverCosmosKeyCmd { let keystore = path::Path::new(&config.keystore); let keystore = FsKeyStore::create_or_open(keystore).expect("Could not open keystore"); - let name = self.args.get(0).expect("name is required"); - let name = name.parse().expect("Could not parse name"); + let name = self.name.parse().expect("Could not parse name"); if let Ok(_info) = keystore.info(&name) { if !self.overwrite { eprintln!("Key already exists, exiting."); @@ -32,8 +39,8 @@ impl Runnable for RecoverCosmosKeyCmd { } } - let mnemonic = match self.args.get(1) { - Some(mnemonic) => mnemonic.clone(), + let mnemonic = match self.mnemonic.clone() { + Some(mnemonic) => mnemonic, None => rpassword::read_password_from_tty(Some("> Enter your bip39-mnemonic:\n")) .expect("Could not read mnemonic"), }; @@ -56,8 +63,8 @@ impl Runnable for RecoverCosmosKeyCmd { keystore.store(&name, &key).expect("Could not store key"); - let args = vec![name.to_string()]; - let show_cmd = ShowCosmosKeyCmd { args }; + let name = name.to_string(); + let show_cmd = ShowCosmosKeyCmd { name }; show_cmd.run(); } } diff --git a/orchestrator/gorc/src/commands/keys/cosmos/rename.rs b/orchestrator/gorc/src/commands/keys/cosmos/rename.rs index d8458f0c8..f38b13edf 100644 --- a/orchestrator/gorc/src/commands/keys/cosmos/rename.rs +++ b/orchestrator/gorc/src/commands/keys/cosmos/rename.rs @@ -4,9 +4,17 @@ use std::path; /// Rename a Cosmos Key #[derive(Command, Debug, Default, Parser)] +#[clap( + long_about = "DESCRIPTION \n\n Rename a Cosmos key.\n This command will rename a Cosmos key in the keystore. It takes the existing keyname and new \n keyname." +)] pub struct RenameCosmosKeyCmd { - pub args: Vec, + /// Cosmos keyname in keystore. + pub name: String, + /// New keyname to replace name in keystore. + pub new_name: String, + + /// Overwrite key with the same name in the keystore when set to true. Takes a Boolean. #[clap(short, long)] pub overwrite: bool, } @@ -18,11 +26,9 @@ impl Runnable for RenameCosmosKeyCmd { let keystore = path::Path::new(&config.keystore); let keystore = signatory::FsKeyStore::create_or_open(keystore).unwrap(); - let name = self.args.get(0).expect("name is required"); - let name = name.parse().expect("Could not parse name"); + let name = self.name.parse().expect("Could not parse name"); - let new_name = self.args.get(1).expect("new_name is required"); - let new_name = new_name.parse().expect("Could not parse new_name"); + let new_name = self.new_name.parse().expect("Could not parse new_name"); if let Ok(_info) = keystore.info(&new_name) { if !self.overwrite { println!("Key already exists, exiting."); diff --git a/orchestrator/gorc/src/commands/keys/cosmos/show.rs b/orchestrator/gorc/src/commands/keys/cosmos/show.rs index f6d1a72f7..2a2095e59 100644 --- a/orchestrator/gorc/src/commands/keys/cosmos/show.rs +++ b/orchestrator/gorc/src/commands/keys/cosmos/show.rs @@ -3,15 +3,19 @@ use abscissa_core::{clap::Parser, Application, Command, Runnable}; /// Show a Cosmos Key #[derive(Command, Debug, Default, Parser)] +#[clap( + long_about = "DESCRIPTION \n\n Show details of a Cosmos key in the keystore.\n This command shows details of a Cosmos key in the keystore, it takes the name of the key." +)] pub struct ShowCosmosKeyCmd { - pub args: Vec, + /// Cosmos keyname + pub name: String, } // Entry point for `gorc keys cosmos show [name]` impl Runnable for ShowCosmosKeyCmd { fn run(&self) { let config = APP.config(); - let name = self.args.get(0).expect("name is required"); + let name = self.name.clone(); let key = config.load_deep_space_key(name.clone()); let address = key diff --git a/orchestrator/gorc/src/commands/keys/eth/add.rs b/orchestrator/gorc/src/commands/keys/eth/add.rs index d9a101893..b3d640dd9 100644 --- a/orchestrator/gorc/src/commands/keys/eth/add.rs +++ b/orchestrator/gorc/src/commands/keys/eth/add.rs @@ -8,12 +8,18 @@ use std::path; /// Add a new Eth Key #[derive(Command, Debug, Default, Parser)] +#[clap( + long_about = "DESCRIPTION \n\n Create a new Eth Key.\n This command creates a new Eth key. It has an overwrite option, which if set to true, overwrites\n an existing key in the keystore with the same keyname." +)] pub struct AddEthKeyCmd { - pub args: Vec, + /// Eth keyname. + pub name: String, + /// Overwrite key with the same name in the keystore when set to true. Takes a Boolean. #[clap(short, long)] pub overwrite: bool, + /// Show private key after creation of key. #[clap(short, long)] show_private_key: bool, } @@ -26,8 +32,7 @@ impl Runnable for AddEthKeyCmd { let keystore = path::Path::new(&config.keystore); let keystore = FsKeyStore::create_or_open(keystore).expect("Could not open keystore"); - let name = self.args.get(0).expect("name is required"); - let name = name.parse().expect("Could not parse name"); + let name = self.name.parse().expect("Could not parse name"); if let Ok(_info) = keystore.info(&name) { if !self.overwrite { eprintln!("Key already exists, exiting."); @@ -55,7 +60,7 @@ impl Runnable for AddEthKeyCmd { keystore.store(&name, &key).expect("Could not store key"); let show_cmd = ShowEthKeyCmd { - args: vec![name.to_string()], + name: name.to_string(), show_private_key: self.show_private_key, show_name: false, }; diff --git a/orchestrator/gorc/src/commands/keys/eth/delete.rs b/orchestrator/gorc/src/commands/keys/eth/delete.rs index b5d0e580f..28276bc2f 100644 --- a/orchestrator/gorc/src/commands/keys/eth/delete.rs +++ b/orchestrator/gorc/src/commands/keys/eth/delete.rs @@ -5,8 +5,12 @@ use std::path; /// Delete an Eth Key #[derive(Command, Debug, Default, Parser)] +#[clap( + long_about = "DESCRIPTION \n\n Delete an Eth Key.\n This command deletes an Eth key from your keystore when provided with the keyname." +)] pub struct DeleteEthKeyCmd { - pub args: Vec, + /// Eth keyname. + pub name: String, } // Entry point for `gorc keys eth delete [name]` @@ -16,9 +20,7 @@ impl Runnable for DeleteEthKeyCmd { let config = APP.config(); let keystore = path::Path::new(&config.keystore); let keystore = FsKeyStore::create_or_open(keystore).expect("Could not open keystore"); - - let name = self.args.get(0).expect("name is required"); - let name = name.parse().expect("Could not parse name"); + let name = self.name.parse().expect("Could not parse name"); keystore.delete(&name).expect("Could not delete key"); } } diff --git a/orchestrator/gorc/src/commands/keys/eth/import.rs b/orchestrator/gorc/src/commands/keys/eth/import.rs index 7be53bc56..1b4a7235b 100644 --- a/orchestrator/gorc/src/commands/keys/eth/import.rs +++ b/orchestrator/gorc/src/commands/keys/eth/import.rs @@ -8,14 +8,23 @@ use std::path; ///Import an Eth Key #[derive(Command, Debug, Default, Parser)] +#[clap( + long_about = "DESCRIPTION \n\n Import an external Eth key.\n This command will import an Eth key, storing it in the keystore. \n It takes a keyname and the key you want to import." +)] pub struct ImportEthKeyCmd { - pub args: Vec, + /// Eth keyname. + pub name: String, + /// Overwrite key with the same name in the keystore when set to true. Takes a Boolean. #[clap(short, long)] pub overwrite: bool, + /// Show private key when set to true. Takes a Boolean. #[clap(short, long)] show_private_key: bool, + + /// Eth key you want to import. + pub key: Option, } // Entry point for `gorc keys eth import [name] (private-key)` @@ -27,8 +36,7 @@ impl Runnable for ImportEthKeyCmd { let keystore = path::Path::new(&config.keystore); let keystore = FsKeyStore::create_or_open(keystore).expect("Could not open keystore"); - let name = self.args.get(0).expect("name is required"); - let name = name.parse().expect("Could not parse name"); + let name = self.name.parse().expect("Could not parse name"); if let Ok(_info) = keystore.info(&name) { if !self.overwrite { eprintln!("Key already exists, exiting."); @@ -36,8 +44,8 @@ impl Runnable for ImportEthKeyCmd { } } - let key = match self.args.get(1) { - Some(private_key) => private_key.clone(), + let key = match self.key.clone() { + Some(private_key) => private_key, None => rpassword::read_password_from_tty(Some("> Enter your private-key:\n")) .expect("Could not read private-key"), }; @@ -55,7 +63,7 @@ impl Runnable for ImportEthKeyCmd { keystore.store(&name, &key).expect("Could not store key"); let show_cmd = ShowEthKeyCmd { - args: vec![name.to_string()], + name: name.to_string(), show_private_key: self.show_private_key, show_name: false, }; diff --git a/orchestrator/gorc/src/commands/keys/eth/list.rs b/orchestrator/gorc/src/commands/keys/eth/list.rs index 7eeb2ee08..198988106 100644 --- a/orchestrator/gorc/src/commands/keys/eth/list.rs +++ b/orchestrator/gorc/src/commands/keys/eth/list.rs @@ -5,7 +5,11 @@ use std::path; /// List all Eth Keys #[derive(Command, Debug, Default, Parser)] +#[clap( + long_about = "DESCRIPTION \n\n List all Eth keys in keystore.\n This command lists all Eth keys and their addresses from the keystore." +)] pub struct ListEthKeyCmd { + /// Show private key when set to true. Takes a Boolean. #[clap(short, long)] pub show_private_key: bool, } @@ -24,7 +28,7 @@ impl Runnable for ListEthKeyCmd { let name = path.file_stem().unwrap(); let name = name.to_str().unwrap(); let show_cmd = ShowEthKeyCmd { - args: vec![name.to_string()], + name: name.to_string(), show_private_key: self.show_private_key, show_name: true, }; diff --git a/orchestrator/gorc/src/commands/keys/eth/recover.rs b/orchestrator/gorc/src/commands/keys/eth/recover.rs index a66906a43..a15ac7f42 100644 --- a/orchestrator/gorc/src/commands/keys/eth/recover.rs +++ b/orchestrator/gorc/src/commands/keys/eth/recover.rs @@ -7,14 +7,23 @@ use std::path; /// Recover an Eth Key #[derive(Command, Debug, Default, Parser)] +#[clap( + long_about = "DESCRIPTION \n\n Recover an external Eth key.\n This command will recover an Eth key, storing it in the keystore. \n It takes a keyname and bip39-mnemonic." +)] pub struct RecoverEthKeyCmd { - pub args: Vec, + /// Cosmos keyname. + pub name: String, + /// Overwrite key with the same name in the keystore when set to true. Takes a Boolean. #[clap(short, long)] pub overwrite: bool, + /// bip39-mnemonic optional. When absent you'll be prompted to enter it. + pub mnemonic: Option, + + /// Show private key when set to true. Takes a Boolean. #[clap(short, long)] - show_private_key: bool, + pub show_private_key: bool, } // Entry point for `gorc keys eth recover [name] (bip39-mnemonic)` @@ -26,8 +35,7 @@ impl Runnable for RecoverEthKeyCmd { let keystore = path::Path::new(&config.keystore); let keystore = FsKeyStore::create_or_open(keystore).expect("Could not open keystore"); - let name = self.args.get(0).expect("name is required"); - let name = name.parse().expect("Could not parse name"); + let name = self.name.parse().expect("Could not parse name"); if let Ok(_info) = keystore.info(&name) { if !self.overwrite { eprintln!("Key already exists, exiting."); @@ -35,8 +43,8 @@ impl Runnable for RecoverEthKeyCmd { } } - let mnemonic = match self.args.get(1) { - Some(mnemonic) => mnemonic.clone(), + let mnemonic = match self.mnemonic.clone() { + Some(mnemonic) => mnemonic, None => rpassword::read_password_from_tty(Some("> Enter your bip39-mnemonic:\n")) .expect("Could not read mnemonic"), }; @@ -60,7 +68,7 @@ impl Runnable for RecoverEthKeyCmd { keystore.store(&name, &key).expect("Could not store key"); let show_cmd = ShowEthKeyCmd { - args: vec![name.to_string()], + name: name.to_string(), show_private_key: self.show_private_key, show_name: false, }; diff --git a/orchestrator/gorc/src/commands/keys/eth/rename.rs b/orchestrator/gorc/src/commands/keys/eth/rename.rs index c2cb34443..cfd4529ac 100644 --- a/orchestrator/gorc/src/commands/keys/eth/rename.rs +++ b/orchestrator/gorc/src/commands/keys/eth/rename.rs @@ -5,9 +5,17 @@ use std::path; /// Rename an Eth Key #[derive(Command, Debug, Default, Parser)] +#[clap( + long_about = "DESCRIPTION \n\n Rename an Eth key.\n This command will rename an Eth key in the keystore. It takes the existing keyname and new keyname." +)] pub struct RenameEthKeyCmd { - pub args: Vec, + /// Eth keyname + pub name: String, + /// New keyname to replace name in keystore. + pub new_name: String, + + /// Overwrite key with the same name in the keystore when set to true. Takes a Boolean. #[clap(short, long)] pub overwrite: bool, } @@ -19,11 +27,9 @@ impl Runnable for RenameEthKeyCmd { let keystore = path::Path::new(&config.keystore); let keystore = FsKeyStore::create_or_open(keystore).expect("Could not open keystore"); - let name = self.args.get(0).expect("name is required"); - let name = name.parse().expect("Could not parse name"); + let name = self.name.parse().expect("Could not parse name"); - let new_name = self.args.get(1).expect("new-name is required"); - let new_name = new_name.parse().expect("Could not parse new-name"); + let new_name = self.new_name.parse().expect("Could not parse new-name"); if let Ok(_info) = keystore.info(&new_name) { if !self.overwrite { eprintln!("Key already exists, exiting."); diff --git a/orchestrator/gorc/src/commands/keys/eth/show.rs b/orchestrator/gorc/src/commands/keys/eth/show.rs index 9035b0d29..dec3f15b3 100644 --- a/orchestrator/gorc/src/commands/keys/eth/show.rs +++ b/orchestrator/gorc/src/commands/keys/eth/show.rs @@ -3,12 +3,18 @@ use abscissa_core::{clap::Parser, Application, Command, Runnable}; /// Show an Eth Key #[derive(Command, Debug, Default, Parser)] +#[clap( + long_about = "DESCRIPTION \n\n Show details of an Eth key in the keystore.\n This command shows details of an Eth key in the keystore, it takes the name of the key." +)] pub struct ShowEthKeyCmd { - pub args: Vec, + /// Cosmos keyname + pub name: String, + /// Show private key when set to true. Takes a Boolean. #[clap(short, long)] pub show_private_key: bool, + /// Show key name when set to true. Takes a Boolean. #[clap(short = 'n', long)] pub show_name: bool, } @@ -17,7 +23,7 @@ pub struct ShowEthKeyCmd { impl Runnable for ShowEthKeyCmd { fn run(&self) { let config = APP.config(); - let name = self.args.get(0).expect("name is required"); + let name = self.name.clone(); // TODO(bolten): is ethers wallet even capable of printing the public and // private keys? for now, leaving load_clarity_key in config.rs and // maintaining the functionality here diff --git a/orchestrator/gorc/src/commands/orchestrator/start.rs b/orchestrator/gorc/src/commands/orchestrator/start.rs index ed11027f3..05aef1839 100644 --- a/orchestrator/gorc/src/commands/orchestrator/start.rs +++ b/orchestrator/gorc/src/commands/orchestrator/start.rs @@ -16,13 +16,19 @@ use std::{cmp::min, sync::Arc}; /// Start the Orchestrator #[derive(Command, Debug, Parser)] +#[clap( + long_about = "DESCRIPTION \n\n Start the Orchestrator via the Gravity Bridge.\n This command loads a Cosmos and Ethereum key with their keyname from the keystore.\n It also takes an Orchestrator_only field which when set to true, starts the Orchestrator only\n without the relayer and when set to false, starts the Orchestrator with the relayer." +)] pub struct StartCommand { + /// Cosmos keyname from keystore. #[clap(short, long)] cosmos_key: String, + /// Ethereum keyname from keystore. #[clap(short, long)] ethereum_key: String, + /// Boolean, when set to true starts the Orchestrator only and false starts Orchestrator and Relayer. #[clap(short, long)] orchestrator_only: bool, } diff --git a/orchestrator/gorc/src/commands/query/cosmos.rs b/orchestrator/gorc/src/commands/query/cosmos.rs index 3fad04191..3f7d11b92 100644 --- a/orchestrator/gorc/src/commands/query/cosmos.rs +++ b/orchestrator/gorc/src/commands/query/cosmos.rs @@ -6,8 +6,10 @@ use abscissa_core::{clap::Parser, Command, Runnable}; /// Query cosmos chain #[derive(Command, Debug, Parser)] pub enum Cosmos { + /// Query the balance in a Cosmos account. Balance(Balance), + /// Query gravity keys. GravityKeys(GravityKeys), } @@ -20,7 +22,8 @@ impl Runnable for Cosmos { #[derive(Command, Debug, Parser)] pub struct Balance { - free: Vec, + /// Cosmos keyname + key_name: String, #[clap(short, long)] help: bool, @@ -28,14 +31,14 @@ pub struct Balance { impl Runnable for Balance { fn run(&self) { - assert!(self.free.len() == 1); - let _key_name = self.free[0].clone(); + let _key_name = self.key_name.clone(); } } #[derive(Command, Debug, Parser)] pub struct GravityKeys { - free: Vec, + /// Gravity keyname + key_name: String, #[clap(short, long)] help: bool, @@ -44,8 +47,7 @@ pub struct GravityKeys { impl Runnable for GravityKeys { /// Start the application. fn run(&self) { - assert!(self.free.len() == 1); - let _key_name = self.free[0].clone(); + let _key_name = self.key_name.clone(); abscissa_tokio::run(&APP, async { unimplemented!() }).unwrap_or_else(|e| { status_err!("executor exited with error: {}", e); diff --git a/orchestrator/gorc/src/commands/query/eth.rs b/orchestrator/gorc/src/commands/query/eth.rs index 1737db1af..5bdf73fcf 100644 --- a/orchestrator/gorc/src/commands/query/eth.rs +++ b/orchestrator/gorc/src/commands/query/eth.rs @@ -6,8 +6,10 @@ use abscissa_core::{clap::Parser, Command, Runnable}; /// Query Eth chain #[derive(Command, Debug, Parser)] pub enum Eth { + /// Query balance in an Ethereum account. Balance(Balance), + /// Query Ethereum Contract. Contract(Contract), } @@ -20,7 +22,8 @@ impl Runnable for Eth { #[derive(Command, Debug, Parser)] pub struct Balance { - free: Vec, + /// Eth keyname + key_name: String, #[clap(short, long)] help: bool, @@ -28,8 +31,7 @@ pub struct Balance { impl Runnable for Balance { fn run(&self) { - assert!(self.free.len() == 1); - let _key_name = self.free[0].clone(); + let _key_name = self.key_name.clone(); abscissa_tokio::run(&APP, async { unimplemented!() }).unwrap_or_else(|e| { status_err!("executor exited with error: {}", e); diff --git a/orchestrator/gorc/src/commands/sign_delegate_keys.rs b/orchestrator/gorc/src/commands/sign_delegate_keys.rs index af7054d4b..95960cc88 100644 --- a/orchestrator/gorc/src/commands/sign_delegate_keys.rs +++ b/orchestrator/gorc/src/commands/sign_delegate_keys.rs @@ -1,27 +1,30 @@ use crate::{application::APP, prelude::*}; use abscissa_core::{clap::Parser, Application, Command, Runnable}; -use ethers::{prelude::Signer, utils::keccak256}; use gravity_proto::gravity as proto; use std::time::Duration; /// Sign delegate keys command #[derive(Command, Debug, Default, Parser)] pub struct SignDelegateKeysCmd { - pub args: Vec, + /// Ethereum keyname + ethereum_key: String, + + /// Validator address + val_address: String, + + /// nonce + nonce: Option, } impl Runnable for SignDelegateKeysCmd { fn run(&self) { let config = APP.config(); abscissa_tokio::run_with_actix(&APP, async { - let name = self.args.get(0).expect("ethereum-key-name is required"); - let ethereum_wallet = config.load_ethers_wallet(name.clone()); - - let val = self.args.get(1).expect("validator-address is required"); - let address = val.parse().expect("Could not parse address"); + let key = config.load_clarity_key(self.ethereum_key.clone()); + let address = self.val_address.parse().expect("Could not parse address"); - let nonce: u64 = match self.args.get(2) { - Some(nonce) => nonce.parse().expect("cannot parse nonce"), + let nonce: u64 = match self.nonce { + Some(nonce) => nonce, None => { let timeout = Duration::from_secs(10); let contact = deep_space::Contact::new( @@ -38,7 +41,7 @@ impl Runnable for SignDelegateKeysCmd { }; let msg = proto::DelegateKeysSignMsg { - validator_address: val.clone(), + validator_address: self.val_address.clone(), nonce, }; @@ -46,11 +49,7 @@ impl Runnable for SignDelegateKeysCmd { let mut buf = bytes::BytesMut::with_capacity(size); prost::Message::encode(&msg, &mut buf).expect("Failed to encode DelegateKeysSignMsg!"); - let data = keccak256(buf); - let signature = ethereum_wallet - .sign_message(data) - .await - .expect("Could not sign DelegateKeysSignMsg"); + let signature = key.sign_ethereum_msg(&buf); println!("{}", signature); }) diff --git a/orchestrator/gorc/src/commands/tx/cosmos.rs b/orchestrator/gorc/src/commands/tx/cosmos.rs index c99bf2a72..9af2521a7 100644 --- a/orchestrator/gorc/src/commands/tx/cosmos.rs +++ b/orchestrator/gorc/src/commands/tx/cosmos.rs @@ -3,12 +3,12 @@ use crate::{application::APP, prelude::*, utils::*}; use abscissa_core::{clap::Parser, Command, Runnable}; use clarity::Uint256; +use cosmos_gravity::crypto::PrivateKey as CosmosPrivateKey; use cosmos_gravity::send::send_to_eth; use deep_space::coin::Coin; use ethers::types::Address as EthAddress; use gravity_proto::gravity::DenomToErc20Request; use gravity_utils::connection_prep::{check_for_fee_denom, create_rpc_connections}; -use cosmos_gravity::crypto::PrivateKey as CosmosPrivateKey; use regex::Regex; use std::process::exit; @@ -27,8 +27,18 @@ impl Runnable for Cosmos { } #[derive(Command, Debug, Parser)] +#[clap( + long_about = "DESCRIPTION \n\n Send transactions from Cosmos to Ethereum chain.\n This command sends tx from the Cosmos chain to the Eth chain.\n It takes the Cosmos key, Eth address and amount." +)] pub struct SendToEth { - free: Vec, + /// Cosmos key name + cosmos_key: String, + + /// Eth Address + eth_addr: String, + + /// ERC20 coin amount + erc20_amount: String, #[clap(short, long)] help: bool, @@ -54,10 +64,9 @@ fn get_cosmos_key(_key_name: &str) -> CosmosPrivateKey { impl Runnable for SendToEth { fn run(&self) { - assert!(self.free.len() == 3); - let from_cosmos_key = self.free[0].clone(); - let to_eth_addr = self.free[1].clone(); //TODO parse this to an Eth Address - let erc_20_coin = self.free[2].clone(); // 1231234uatom + let from_cosmos_key = self.cosmos_key.clone(); + let to_eth_addr = self.eth_addr.clone(); //TODO parse this to an Eth Address + let erc_20_coin = self.erc20_amount.clone(); // 1231234uatom let (amount, denom) = parse_denom(&erc_20_coin); let amount: Uint256 = amount.parse().expect("Could not parse amount"); @@ -150,8 +159,18 @@ impl Runnable for SendToEth { } #[derive(Command, Debug, Parser)] +#[clap( + long_about = "DESCRIPTION \n\n Send transactions across the Cosmos chain.\n This command sends tx from one Cosmos account to another.\n It takes the sender's key, reciever's address and amount." +)] pub struct Send { - free: Vec, + /// Sender's keyname + from_key: String, + + /// Reciever's address. + to_addr: String, + + /// Amount to be sent. + amount: String, #[clap(short, long)] help: bool, @@ -160,10 +179,9 @@ pub struct Send { impl Runnable for Send { /// Start the application. fn run(&self) { - assert!(self.free.len() == 3); - let _from_key = self.free[0].clone(); - let _to_addr = self.free[1].clone(); - let _coin_amount = self.free[2].clone(); + let _from_key = self.from_key.clone(); + let _to_addr = self.to_addr.clone(); + let _coin_amount = self.amount.clone(); abscissa_tokio::run_with_actix(&APP, async { unimplemented!() }).unwrap_or_else(|e| { status_err!("executor exited with error: {}", e); diff --git a/orchestrator/gorc/src/commands/tx/eth.rs b/orchestrator/gorc/src/commands/tx/eth.rs index 4f12f5de5..f90c3d80d 100644 --- a/orchestrator/gorc/src/commands/tx/eth.rs +++ b/orchestrator/gorc/src/commands/tx/eth.rs @@ -17,8 +17,6 @@ use std::sync::Arc; #[derive(Command, Debug, Parser)] pub enum Eth { SendToCosmos(SendToCosmos), - - Send(Send), } impl Runnable for Eth { @@ -27,7 +25,17 @@ impl Runnable for Eth { #[derive(Command, Debug, Parser)] pub struct SendToCosmos { - free: Vec, + /// Eth key name + key_name: String, + + /// Cosmos address + cosmos_addr: String, + + /// ERC20 contract address + erc20_addr: String, + + /// Amount + amount: String, #[clap(short, long)] help: bool, @@ -41,17 +49,18 @@ fn lookup_eth_key(_key: String) -> LocalWallet { impl Runnable for SendToCosmos { fn run(&self) { - assert!(self.free.len() == 4); - let from_eth_key = self.free[0].clone(); - let to_cosmos_addr: CosmosAddress = self.free[1] + let from_eth_key = self.key_name.clone(); + let to_cosmos_addr: CosmosAddress = self + .cosmos_addr .clone() .parse() .expect("Expected a valid Cosmos Address"); - let erc20_contract: EthAddress = self.free[2] + let erc20_contract: EthAddress = self + .erc20_addr .clone() .parse() .expect("Expected a valid Eth Address"); - let erc20_amount = self.free[3].clone(); + let erc20_amount = self.amount.clone(); let ethereum_wallet = lookup_eth_key(from_eth_key); println!( @@ -127,15 +136,3 @@ impl Runnable for SendToCosmos { }); } } - -#[derive(Command, Debug, Parser)] -pub struct Send { - free: Vec, - - #[clap(short, long)] - help: bool, -} - -impl Runnable for Send { - fn run(&self) {} -} diff --git a/orchestrator/orchestrator/src/ethereum_event_watcher.rs b/orchestrator/orchestrator/src/ethereum_event_watcher.rs index 8c189fcae..ad31e5ac6 100644 --- a/orchestrator/orchestrator/src/ethereum_event_watcher.rs +++ b/orchestrator/orchestrator/src/ethereum_event_watcher.rs @@ -5,8 +5,8 @@ use crate::get_with_retry::get_block_number_with_retry; use crate::get_with_retry::get_chain_id_with_retry; use crate::metrics; use cosmos_gravity::build; -use cosmos_gravity::query::get_last_event_nonce; use cosmos_gravity::crypto::PrivateKey as CosmosPrivateKey; +use cosmos_gravity::query::get_last_event_nonce; use deep_space::{Contact, Msg}; use ethereum_gravity::types::EthClient; use ethers::prelude::*; diff --git a/orchestrator/orchestrator/src/main_loop.rs b/orchestrator/orchestrator/src/main_loop.rs index fc2a5e0da..38dcd79df 100644 --- a/orchestrator/orchestrator/src/main_loop.rs +++ b/orchestrator/orchestrator/src/main_loop.rs @@ -9,6 +9,7 @@ use crate::{ ethereum_event_watcher::check_for_events, metrics::metrics_main_loop, oracle_resync::get_last_checked_block, }; +use cosmos_gravity::crypto::PrivateKey as CosmosPrivateKey; use cosmos_gravity::send::send_main_loop; use cosmos_gravity::{ build, @@ -19,7 +20,6 @@ use cosmos_gravity::{ }; use deep_space::client::ChainStatus; use deep_space::error::CosmosGrpcError; -use cosmos_gravity::crypto::PrivateKey as CosmosPrivateKey; use deep_space::{Contact, Msg}; use ethereum_gravity::types::EthClient; use ethereum_gravity::utils::get_gravity_id; diff --git a/orchestrator/register_delegate_keys/src/main.rs b/orchestrator/register_delegate_keys/src/main.rs index 02fa06dc0..457dc7fbf 100644 --- a/orchestrator/register_delegate_keys/src/main.rs +++ b/orchestrator/register_delegate_keys/src/main.rs @@ -6,15 +6,15 @@ extern crate serde_derive; extern crate lazy_static; use clarity::PrivateKey as EthPrivateKey; +use cosmos_gravity::crypto::PrivateKey as CosmosPrivateKey; use cosmos_gravity::send::update_gravity_delegate_addresses; -use deep_space::{coin::Coin, mnemonic::Mnemonic}; +use deep_space::mnemonic::Mnemonic; use docopt::Docopt; use ethers::core::k256::ecdsa::SigningKey; use ethers::prelude::*; use gravity_utils::connection_prep::check_for_fee_denom; use gravity_utils::connection_prep::{create_rpc_connections, wait_for_cosmos_node_ready}; use log::error; -use cosmos_gravity::crypto::PrivateKey as CosmosPrivateKey; use rand::{thread_rng, Rng}; use std::time::Duration; diff --git a/orchestrator/test_runner/src/orch_keys_update.rs b/orchestrator/test_runner/src/orch_keys_update.rs index ffb14322e..623957ff3 100644 --- a/orchestrator/test_runner/src/orch_keys_update.rs +++ b/orchestrator/test_runner/src/orch_keys_update.rs @@ -1,9 +1,9 @@ //! This test verifies that live updating of orchestrator keys works correctly use crate::utils::ValidatorKeys; +use cosmos_gravity::crypto::PrivateKey as CosmosPrivateKey; use cosmos_gravity::send::update_gravity_delegate_addresses; use deep_space::address::Address as CosmosAddress; -use cosmos_gravity::crypto::PrivateKey as CosmosPrivateKey; use deep_space::Contact; use ethers::types::Address as EthAddress; use ethers::{core::k256::ecdsa::SigningKey, prelude::*}; diff --git a/orchestrator/test_runner/src/utils.rs b/orchestrator/test_runner/src/utils.rs index a7197f203..d90df7815 100644 --- a/orchestrator/test_runner/src/utils.rs +++ b/orchestrator/test_runner/src/utils.rs @@ -1,7 +1,7 @@ use crate::one_eth; +use cosmos_gravity::crypto::PrivateKey as CosmosPrivateKey; use deep_space::address::Address as CosmosAddress; use deep_space::coin::Coin; -use cosmos_gravity::crypto::PrivateKey as CosmosPrivateKey; use deep_space::Contact; use ethereum_gravity::{erc20_utils::get_erc20_balance, types::EthClient}; use ethers::core::k256::ecdsa::SigningKey;