diff --git a/Cargo.toml b/Cargo.toml index 00232b5..7c2f5fc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -57,6 +57,7 @@ uint = "0.9.5" [dev-dependencies] tempfile = "3.8.1" +casper-types = { version = "5.0.0", features = ["std", "json-schema", "testing"] } [patch.crates-io] casper-types = { git = "https://github.com/casper-network/casper-node.git", branch = "feat-2.0" } diff --git a/lib/cli/tests.rs b/lib/cli/tests.rs index 4741867..f5187ea 100644 --- a/lib/cli/tests.rs +++ b/lib/cli/tests.rs @@ -447,10 +447,12 @@ mod transaction { use super::*; use crate::{cli::TransactionV1BuilderError, Error::TransactionBuild}; use casper_types::{ - bytesrepr::Bytes, PackageAddr, TransactionArgs, TransactionEntryPoint, - TransactionInvocationTarget, TransactionRuntime, TransactionTarget, TransferTarget, + bytesrepr::Bytes, system::auction::Reservation, PackageAddr, TransactionArgs, + TransactionEntryPoint, TransactionInvocationTarget, TransactionRuntime, TransactionTarget, + TransferTarget, }; use once_cell::sync::Lazy; + use rand::{thread_rng, Rng}; use serde_json::json; static SAMPLE_TRANSACTION: Lazy = Lazy::new(|| { json!({"Version1": { @@ -555,8 +557,9 @@ mod transaction { public_key, delegation_rate: 0, amount, - minimum_delegation_amount, - maximum_delegation_amount, + minimum_delegation_amount: Some(minimum_delegation_amount), + maximum_delegation_amount: Some(maximum_delegation_amount), + reserved_slots: None, }; let transaction = @@ -593,6 +596,7 @@ mod transaction { amount_cl ); } + #[test] fn should_create_delegate_transaction() { let delegator_secret_key = SecretKey::generate_ed25519().unwrap(); @@ -670,6 +674,55 @@ mod transaction { ); } + #[test] + fn should_create_activate_bid_transaction() { + let secret_key = SecretKey::generate_ed25519().unwrap(); + + let validator = PublicKey::from(&secret_key); + + let validator_cl = &CLValue::from_t(&validator).unwrap(); + + let transaction_str_params = TransactionStrParams { + secret_key: "", + timestamp: "", + ttl: "30min", + chain_name: "activate-bid", + initiator_addr: SAMPLE_ACCOUNT.to_string(), + session_args_simple: vec![], + session_args_json: "", + pricing_mode: "fixed", + output_path: "", + payment_amount: "100", + gas_price_tolerance: "10", + additional_computation_factor: "0", + receipt: SAMPLE_DIGEST, + standard_payment: "true", + transferred_value: "0", + session_entry_point: None, + chunked_args: None, + }; + let transaction_string_params = transaction_str_params; + + let transaction_builder_params = TransactionBuilderParams::ActivateBid { validator }; + + let transaction = + create_transaction(transaction_builder_params, transaction_string_params, true); + + assert!(transaction.is_ok(), "{:?}", transaction); + let transaction_v1 = unwrap_transaction(transaction); + assert_eq!(transaction_v1.chain_name(), "activate-bid"); + assert_eq!( + transaction_v1 + .deserialize_field::(ARGS_MAP_KEY) + .unwrap() + .into_named() + .unwrap() + .get("validator") + .unwrap(), + validator_cl + ); + } + #[test] fn should_create_withdraw_bid_transaction() { let secret_key = SecretKey::generate_ed25519().unwrap(); @@ -898,6 +951,206 @@ mod transaction { ); } + #[test] + fn should_create_change_bid_public_key_transaction() { + let secret_key = SecretKey::generate_ed25519().unwrap(); + let public_key = PublicKey::from(&secret_key); + + let secret_key = SecretKey::generate_ed25519().unwrap(); + let new_public_key = PublicKey::from(&secret_key); + + let public_key_cl = &CLValue::from_t(&public_key).unwrap(); + let new_public_key_cl = &CLValue::from_t(&new_public_key).unwrap(); + + let transaction_string_params = TransactionStrParams { + secret_key: "", + timestamp: "", + ttl: "30min", + chain_name: "change-bid-public-key-test", + initiator_addr: SAMPLE_ACCOUNT.to_string(), + session_args_simple: vec![], + session_args_json: "", + pricing_mode: "fixed", + output_path: "", + payment_amount: "100", + gas_price_tolerance: "10", + additional_computation_factor: "", + receipt: SAMPLE_DIGEST, + standard_payment: "true", + transferred_value: "0", + session_entry_point: None, + chunked_args: None, + }; + + let transaction_builder_params = TransactionBuilderParams::ChangeBidPublicKey { + public_key, + new_public_key, + }; + + let transaction = + create_transaction(transaction_builder_params, transaction_string_params, true); + + assert!(transaction.is_ok(), "{:?}", transaction); + let transaction_v1 = unwrap_transaction(transaction); + assert_eq!(transaction_v1.chain_name(), "change-bid-public-key-test"); + assert_eq!( + transaction_v1 + .deserialize_field::(ARGS_MAP_KEY) + .unwrap() + .into_named() + .unwrap() + .get("public_key") + .unwrap(), + public_key_cl + ); + assert!(transaction_v1 + .deserialize_field::(ARGS_MAP_KEY) + .unwrap() + .into_named() + .unwrap() + .get("new_public_key") + .is_some()); + assert_eq!( + transaction_v1 + .deserialize_field::(ARGS_MAP_KEY) + .unwrap() + .into_named() + .unwrap() + .get("new_public_key") + .unwrap(), + new_public_key_cl + ); + } + + #[test] + fn should_create_add_reservations_transaction() { + let mut rng = thread_rng(); + + let reservations = (0..rng.gen_range(1..10)) + .map(|_| { + let secret_key = SecretKey::generate_ed25519().unwrap(); + let validator_public_key = PublicKey::from(&secret_key); + + let delegator_kind = rng.gen(); + + let delegation_rate = rng.gen_range(0..50); + Reservation::new(validator_public_key, delegator_kind, delegation_rate) + }) + .collect(); + + let reservations_cl = &CLValue::from_t(&reservations).unwrap(); + + let transaction_string_params = TransactionStrParams { + secret_key: "", + timestamp: "", + ttl: "30min", + chain_name: "add-reservations-test", + initiator_addr: SAMPLE_ACCOUNT.to_string(), + session_args_simple: vec![], + session_args_json: "", + pricing_mode: "fixed", + output_path: "", + payment_amount: "100", + gas_price_tolerance: "10", + additional_computation_factor: "", + receipt: SAMPLE_DIGEST, + standard_payment: "true", + transferred_value: "0", + session_entry_point: None, + chunked_args: None, + }; + + let transaction_builder_params = TransactionBuilderParams::AddReservations { reservations }; + + let transaction = + create_transaction(transaction_builder_params, transaction_string_params, true); + + assert!(transaction.is_ok(), "{:?}", transaction); + let transaction_v1 = unwrap_transaction(transaction); + assert_eq!(transaction_v1.chain_name(), "add-reservations-test"); + assert_eq!( + transaction_v1 + .deserialize_field::(ARGS_MAP_KEY) + .unwrap() + .into_named() + .unwrap() + .get("reservations") + .unwrap(), + reservations_cl + ); + } + + #[test] + fn should_create_cancel_reservations_transaction() { + let mut rng = thread_rng(); + + let validator_secret_key = SecretKey::generate_ed25519().unwrap(); + let validator = PublicKey::from(&validator_secret_key); + + let validator_cl = &CLValue::from_t(&validator).unwrap(); + + let delegators = (0..rng.gen_range(1..10)) + .map(|_| { + let secret_key = SecretKey::generate_ed25519().unwrap(); + PublicKey::from(&secret_key) + }) + .collect(); + + let delegators_cl = &CLValue::from_t(&delegators).unwrap(); + + let transaction_string_params = TransactionStrParams { + secret_key: "", + timestamp: "", + ttl: "30min", + chain_name: "cancel-reservations-test", + initiator_addr: SAMPLE_ACCOUNT.to_string(), + session_args_simple: vec![], + session_args_json: "", + pricing_mode: "fixed", + output_path: "", + payment_amount: "100", + gas_price_tolerance: "10", + additional_computation_factor: "", + receipt: SAMPLE_DIGEST, + standard_payment: "true", + transferred_value: "0", + session_entry_point: None, + chunked_args: None, + }; + + let transaction_builder_params = TransactionBuilderParams::CancelReservations { + validator, + delegators, + }; + + let transaction = + create_transaction(transaction_builder_params, transaction_string_params, true); + + assert!(transaction.is_ok(), "{:?}", transaction); + let transaction_v1 = unwrap_transaction(transaction); + assert_eq!(transaction_v1.chain_name(), "cancel-reservations-test"); + assert_eq!( + transaction_v1 + .deserialize_field::(ARGS_MAP_KEY) + .unwrap() + .into_named() + .unwrap() + .get("validator") + .unwrap(), + validator_cl + ); + assert_eq!( + transaction_v1 + .deserialize_field::(ARGS_MAP_KEY) + .unwrap() + .into_named() + .unwrap() + .get("delegators") + .unwrap(), + delegators_cl + ); + } + #[test] fn should_create_invocable_entity_transaction() { let entity_addr: EntityAddr = EntityAddr::new_account([0u8; 32]); @@ -1337,8 +1590,9 @@ mod transaction { public_key: PublicKey::from_hex(SAMPLE_ACCOUNT).unwrap(), delegation_rate: 0, amount: U512::from(10), - minimum_delegation_amount, - maximum_delegation_amount, + minimum_delegation_amount: Some(minimum_delegation_amount), + maximum_delegation_amount: Some(maximum_delegation_amount), + reserved_slots: None, }; let transaction = create_transaction(transaction_builder_params, transaction_string_params, true); @@ -1374,8 +1628,9 @@ mod transaction { public_key: PublicKey::from_hex(SAMPLE_ACCOUNT).unwrap(), delegation_rate: 0, amount: U512::from(10), - minimum_delegation_amount, - maximum_delegation_amount, + minimum_delegation_amount: Some(minimum_delegation_amount), + maximum_delegation_amount: Some(maximum_delegation_amount), + reserved_slots: Some(0), }; let transaction = create_transaction(transaction_builder_params, transaction_string_params, false); diff --git a/lib/cli/transaction.rs b/lib/cli/transaction.rs index d5c6544..096fbf6 100644 --- a/lib/cli/transaction.rs +++ b/lib/cli/transaction.rs @@ -228,14 +228,15 @@ pub fn make_transaction_builder( amount, minimum_delegation_amount, maximum_delegation_amount, + reserved_slots, } => { let transaction_builder = TransactionV1Builder::new_add_bid( public_key, delegation_rate, amount, - Some(minimum_delegation_amount), - Some(maximum_delegation_amount), - None, //TODO - fix this, CLI should handle this parameter + minimum_delegation_amount, + maximum_delegation_amount, + reserved_slots, )?; Ok(transaction_builder) } @@ -361,6 +362,30 @@ pub fn make_transaction_builder( let transaction_builder = TransactionV1Builder::new_withdraw_bid(public_key, amount)?; Ok(transaction_builder) } + TransactionBuilderParams::ActivateBid { validator } => { + let transaction_builder = TransactionV1Builder::new_activate_bid(validator)?; + Ok(transaction_builder) + } + TransactionBuilderParams::ChangeBidPublicKey { + public_key, + new_public_key, + } => { + let transaction_builder = + TransactionV1Builder::new_change_bid_public_key(public_key, new_public_key)?; + Ok(transaction_builder) + } + TransactionBuilderParams::AddReservations { reservations } => { + let transaction_builder = TransactionV1Builder::new_add_reservations(reservations)?; + Ok(transaction_builder) + } + TransactionBuilderParams::CancelReservations { + validator, + delegators, + } => { + let transaction_builder = + TransactionV1Builder::new_cancel_reservations(validator, delegators)?; + Ok(transaction_builder) + } } } diff --git a/lib/cli/transaction_builder_params.rs b/lib/cli/transaction_builder_params.rs index fb8374d..a9582b5 100644 --- a/lib/cli/transaction_builder_params.rs +++ b/lib/cli/transaction_builder_params.rs @@ -1,6 +1,7 @@ -use casper_types::bytesrepr::Bytes; -use casper_types::TransactionRuntime; -use casper_types::{AddressableEntityHash, PackageHash, PublicKey, TransferTarget, URef, U512}; +use casper_types::{ + bytesrepr::Bytes, system::auction::Reservation, AddressableEntityHash, PackageHash, PublicKey, + TransactionRuntime, TransferTarget, URef, U512, +}; /// An enum representing the parameters needed to construct a transaction builder /// for the commands concerning the creation of a transaction @@ -16,9 +17,11 @@ pub enum TransactionBuilderParams<'a> { /// The amount to be bid in the add bid transaction amount: U512, /// The minimum amount to be delegated - minimum_delegation_amount: u64, + minimum_delegation_amount: Option, /// The maximum amount to be delegated - maximum_delegation_amount: u64, + maximum_delegation_amount: Option, + /// Number of delegator slots which can be reserved for specific delegators + reserved_slots: Option, }, /// Parameters for the delegate variant of the transaction builder Delegate { @@ -49,6 +52,25 @@ pub enum TransactionBuilderParams<'a> { /// The new validator for the redelegate transaction new_validator: PublicKey, }, + /// Parameters for the change bid public key variant of the transaction builder + ChangeBidPublicKey { + /// The validator for the change bid public key transaction + public_key: PublicKey, + /// New validator for the change bid public key transaction + new_public_key: PublicKey, + }, + /// Parameters for the add reservations variant of the transaction builder + AddReservations { + /// List of reservations for the add reservations transaction + reservations: Vec, + }, + /// Parameters for the cancel reservations variant of the transaction builder + CancelReservations { + /// The validator for the cancel reservations transaction + validator: PublicKey, + /// List of delegatora for the cancel reservations transaction + delegators: Vec, + }, /// Parameters for the invocable entity variant of the transaction builder InvocableEntity { /// The entity hash for the invocable entity transaction @@ -128,4 +150,9 @@ pub enum TransactionBuilderParams<'a> { /// The amount to be withdrawn in the withdraw bid transaction amount: U512, }, + /// Parameters for the activate bid variant of the transaction builder + ActivateBid { + /// The public key for the activate bid transaction + validator: PublicKey, + }, } diff --git a/src/transaction/creation_common.rs b/src/transaction/creation_common.rs index 3f4f31b..31351dc 100644 --- a/src/transaction/creation_common.rs +++ b/src/transaction/creation_common.rs @@ -35,6 +35,9 @@ pub(super) enum DisplayOrder { ChainName, MaximumDelegationRate, MinimumDelegationRate, + ReservedSlots, + Reservations, + Delegators, Source, SessionArgSimple, SessionArgsJson, @@ -42,6 +45,7 @@ pub(super) enum DisplayOrder { SessionEntryPoint, SessionVersion, PublicKey, + NewPublicKey, PackageAlias, PackageAddr, EntityAlias, @@ -931,6 +935,46 @@ pub(super) mod public_key { } } +pub(super) mod new_public_key { + use super::*; + use casper_client::cli::CliError; + use casper_types::{crypto, AsymmetricType, PublicKey}; + + pub const ARG_NAME: &str = "new-public-key"; + const ARG_VALUE_NAME: &str = "FORMATTED STRING or PATH"; + const ARG_HELP: &str = + "The hex-encoded public key of the account that the validator bid will be transferred to. \ + This must be a properly formatted public key. The public key may instead be read \ + in from a file, in which case enter the path to the file as the --new-public-key \ + argument."; + + pub fn arg(order: usize) -> Arg { + Arg::new(ARG_NAME) + .long(ARG_NAME) + .required(true) + .value_name(ARG_VALUE_NAME) + .help(ARG_HELP) + .display_order(order) + } + + pub fn get(matches: &ArgMatches) -> Result { + let value = matches + .get_one::(ARG_NAME) + .map(String::as_str) + .unwrap_or_default(); + common::public_key::try_read_from_file(value) + } + + pub(super) fn parse_public_key(value: &str) -> Result { + let public_key = + PublicKey::from_hex(value).map_err(|error| casper_client::Error::CryptoError { + context: "new public key", + error: crypto::ErrorExt::from(error), + })?; + Ok(public_key) + } +} + pub(super) mod entity_addr { use super::*; use casper_client::cli::CliError; @@ -1029,7 +1073,7 @@ pub(super) mod session_entry_point { .long(ARG_NAME) .value_name(ARG_VALUE_NAME) .help(ARG_HELP) - .required(true) + .required(false) .display_order(DisplayOrder::SessionEntryPoint as usize) } @@ -1159,7 +1203,7 @@ mod minimum_delegation_amount { .value_name(ARG_VALUE_NAME) .alias(ALIAS) .help(ARG_HELP) - .required(true) + .required(false) .display_order(DisplayOrder::MinimumDelegationRate as usize) } @@ -1170,13 +1214,20 @@ mod minimum_delegation_amount { .unwrap_or_default() } - pub(super) fn parse_delegation_amount(value: &str) -> Result { - value - .parse::() - .map_err(|err| CliError::FailedToParseInt { - context: "Add Bid: Minimum delegation amount", - error: err, - }) + pub(super) fn parse_delegation_amount(value: &str) -> Result, CliError> { + let delegation_amount = if value.is_empty() { + None + } else { + Some( + value + .parse::() + .map_err(|err| CliError::FailedToParseInt { + context: "Add Bid: Minimum delegation amount", + error: err, + })?, + ) + }; + Ok(delegation_amount) } } @@ -1194,7 +1245,7 @@ mod maximum_delegation_amount { .value_name(ARG_VALUE_NAME) .alias(ALIAS) .help(ARG_HELP) - .required(true) + .required(false) .display_order(DisplayOrder::MaximumDelegationRate as usize) } @@ -1205,13 +1256,60 @@ mod maximum_delegation_amount { .unwrap_or_default() } - pub(super) fn parse_delegation_amount(value: &str) -> Result { - value - .parse::() - .map_err(|err| CliError::FailedToParseInt { - context: "Add Bid: Maximum delegation amount", - error: err, - }) + pub(super) fn parse_delegation_amount(value: &str) -> Result, CliError> { + let delegation_amount = if value.is_empty() { + None + } else { + Some( + value + .parse::() + .map_err(|err| CliError::FailedToParseInt { + context: "Add Bid: Maximum delegation amount", + error: err, + })?, + ) + }; + Ok(delegation_amount) + } +} + +mod reserved_slots { + use super::*; + use casper_client::cli::CliError; + pub const ARG_NAME: &str = "reserved-slots"; + const ARG_VALUE_NAME: &str = common::ARG_INTEGER; + const ARG_HELP: &str = "number of reserved delegator slots for the add-bid transaction"; + + pub fn arg() -> Arg { + Arg::new(ARG_NAME) + .long(ARG_NAME) + .value_name(ARG_VALUE_NAME) + .help(ARG_HELP) + .required(false) + .display_order(DisplayOrder::ReservedSlots as usize) + } + + pub fn get(matches: &ArgMatches) -> &str { + matches + .get_one::(ARG_NAME) + .map(String::as_str) + .unwrap_or_default() + } + + pub(super) fn parse_reserved_slots(value: &str) -> Result, CliError> { + let delegation_amount = if value.is_empty() { + None + } else { + Some( + value + .parse::() + .map_err(|err| CliError::FailedToParseInt { + context: "Add Bid: Reserved slots", + error: err, + })?, + ) + }; + Ok(delegation_amount) } } @@ -1219,8 +1317,7 @@ mod validator { use super::*; pub const ARG_NAME: &str = "validator"; const ARG_VALUE_NAME: &str = common::ARG_STRING; - const ARG_HELP: &str = - "the validator's public key (as a formatted string) for the delegate transaction"; + const ARG_HELP: &str = "the validator's public key (as a formatted string)"; pub fn arg() -> Arg { Arg::new(ARG_NAME) @@ -1325,6 +1422,88 @@ mod transaction_amount { } } +mod reservations { + use super::*; + use casper_client::cli::CliError; + use casper_types::system::auction::Reservation; + + pub const ARG_NAME: &str = "reservations"; + const ARG_VALUE_NAME: &str = "JSON serialized Vec"; + const ARG_HELP: &str = "list of reservations to add for the add-reservations transaction"; + + pub fn arg() -> Arg { + Arg::new(ARG_NAME) + .long(ARG_NAME) + .value_name(ARG_VALUE_NAME) + .help(ARG_HELP) + .required(true) + .display_order(DisplayOrder::Reservations as usize) + } + + pub fn get(matches: &ArgMatches) -> &str { + matches + .get_one::(ARG_NAME) + .map(String::as_str) + .unwrap_or_default() + } + + pub(super) fn parse_reservations(value: &str) -> Result, CliError> { + if !value.is_empty() { + serde_json::from_str(value).map_err(|_| { + CliError::InvalidCLValue( + "Failed to parse reservations for add-reservations".to_string(), + ) + }) + } else { + Err(CliError::InvalidArgument { + context: "parse_reservations", + error: "Reservations cannot be empty".to_string(), + }) + } + } +} + +mod delegators { + use super::*; + use casper_client::cli::CliError; + use casper_types::PublicKey; + + pub const ARG_NAME: &str = "delegators"; + const ARG_VALUE_NAME: &str = "JSON serialized Vec"; + const ARG_HELP: &str = "list of delegator public keys for the cancel-reservations transaction"; + + pub fn arg() -> Arg { + Arg::new(ARG_NAME) + .long(ARG_NAME) + .value_name(ARG_VALUE_NAME) + .help(ARG_HELP) + .required(true) + .display_order(DisplayOrder::Delegators as usize) + } + + pub fn get(matches: &ArgMatches) -> &str { + matches + .get_one::(ARG_NAME) + .map(String::as_str) + .unwrap_or_default() + } + + pub(super) fn parse_delegators(value: &str) -> Result, CliError> { + if !value.is_empty() { + serde_json::from_str(value).map_err(|_| { + CliError::InvalidCLValue( + "Failed to parse delegators for cancel-reservations".to_string(), + ) + }) + } else { + Err(CliError::InvalidArgument { + context: "parse_delegators", + error: "Delegators cannot be empty".to_string(), + }) + } + } +} + pub(super) mod add_bid { use super::*; use casper_client::cli::{CliError, TransactionBuilderParams, TransactionStrParams}; @@ -1367,12 +1546,16 @@ pub(super) mod add_bid { let maximum_delegation_amount = maximum_delegation_amount::parse_delegation_amount(maximum_amount_string)?; + let reserved_slots_str = reserved_slots::get(matches); + let reserved_slots = reserved_slots::parse_reserved_slots(reserved_slots_str)?; + let params = TransactionBuilderParams::AddBid { public_key, delegation_rate, amount, minimum_delegation_amount, maximum_delegation_amount, + reserved_slots, }; let transaction_str_params = build_transaction_str_params(matches, ACCEPT_SESSION_ARGS); @@ -1387,8 +1570,50 @@ pub(super) mod add_bid { .arg(transaction_amount::arg()) .arg(minimum_delegation_amount::arg()) .arg(maximum_delegation_amount::arg()) + .arg(reserved_slots::arg()) + } +} + +pub(super) mod activate_bid { + use super::*; + use casper_client::cli::{CliError, TransactionBuilderParams, TransactionStrParams}; + + pub const NAME: &str = "activate-bid"; + + const ACCEPT_SESSION_ARGS: bool = false; + + const ABOUT: &str = "Creates a new activate-bid transaction"; + pub fn build() -> Command { + apply_common_creation_options( + add_args(Command::new(NAME).about(ABOUT)), + false, + false, + ACCEPT_SESSION_ARGS, + ) + } + + pub fn put_transaction_build() -> Command { + add_rpc_args(build()) + } + + pub fn run( + matches: &ArgMatches, + ) -> Result<(TransactionBuilderParams, TransactionStrParams), CliError> { + let validator_str = validator::get(matches); + let validator = public_key::parse_public_key(validator_str)?; + + let params = TransactionBuilderParams::ActivateBid { validator }; + + let transaction_str_params = build_transaction_str_params(matches, ACCEPT_SESSION_ARGS); + + Ok((params, transaction_str_params)) + } + + fn add_args(activate_bid_subcommand: Command) -> Command { + activate_bid_subcommand.arg(validator::arg()) } } + pub(super) mod withdraw_bid { use super::*; use crate::cli::TransactionBuilderParams; @@ -1427,12 +1652,13 @@ pub(super) mod withdraw_bid { Ok((params, transaction_str_params)) } - fn add_args(add_bid_subcommand: Command) -> Command { - add_bid_subcommand + fn add_args(withdraw_bid_subcommand: Command) -> Command { + withdraw_bid_subcommand .arg(public_key::arg(DisplayOrder::PublicKey as usize)) .arg(transaction_amount::arg()) } } + pub(super) mod delegate { use super::*; use casper_client::cli::{CliError, TransactionBuilderParams}; @@ -1478,8 +1704,8 @@ pub(super) mod delegate { Ok((params, transaction_str_params)) } - fn add_args(add_bid_subcommand: Command) -> Command { - add_bid_subcommand + fn add_args(delegate_subcommand: Command) -> Command { + delegate_subcommand .arg(delegator::arg()) .arg(validator::arg()) .arg(transaction_amount::arg()) @@ -1494,7 +1720,7 @@ pub(super) mod undelegate { const ACCEPT_SESSION_ARGS: bool = false; - const ABOUT: &str = "Creates a new delegate transaction"; + const ABOUT: &str = "Creates a new undelegate transaction"; pub fn build() -> Command { apply_common_creation_options( @@ -1530,13 +1756,14 @@ pub(super) mod undelegate { Ok((params, transaction_str_params)) } - fn add_args(add_bid_subcommand: Command) -> Command { - add_bid_subcommand + fn add_args(undelegate_subcommand: Command) -> Command { + undelegate_subcommand .arg(delegator::arg()) .arg(validator::arg()) .arg(transaction_amount::arg()) } } + pub(super) mod redelegate { use super::*; use casper_client::cli::{CliError, TransactionBuilderParams}; @@ -1544,7 +1771,7 @@ pub(super) mod redelegate { pub const NAME: &str = "redelegate"; const ACCEPT_SESSION_ARGS: bool = false; - const ABOUT: &str = "Creates a new delegate transaction"; + const ABOUT: &str = "Creates a new redelegate transaction"; pub fn build() -> Command { apply_common_creation_options( @@ -1584,8 +1811,8 @@ pub(super) mod redelegate { Ok((params, transaction_str_params)) } - fn add_args(add_bid_subcommand: Command) -> Command { - add_bid_subcommand + fn add_args(redelegate_subcommand: Command) -> Command { + redelegate_subcommand .arg(delegator::arg()) .arg(validator::arg()) .arg(new_validator::arg()) @@ -1593,6 +1820,142 @@ pub(super) mod redelegate { } } +pub(super) mod change_bid_public_key { + use super::*; + use casper_client::cli::{CliError, TransactionBuilderParams, TransactionStrParams}; + + pub const NAME: &str = "change-bid-public-key"; + + const ACCEPT_SESSION_ARGS: bool = false; + + const ABOUT: &str = "Creates a new change-bid-public-key transaction"; + pub fn build() -> Command { + apply_common_creation_options( + add_args(Command::new(NAME).about(ABOUT)), + false, + false, + ACCEPT_SESSION_ARGS, + ) + } + + pub fn put_transaction_build() -> Command { + add_rpc_args(build()) + } + + pub fn run( + matches: &ArgMatches, + ) -> Result<(TransactionBuilderParams, TransactionStrParams), CliError> { + let public_key_str = public_key::get(matches)?; + let public_key = public_key::parse_public_key(&public_key_str)?; + + let new_public_key_str = new_public_key::get(matches)?; + let new_public_key = new_public_key::parse_public_key(&new_public_key_str)?; + + let params = TransactionBuilderParams::ChangeBidPublicKey { + public_key, + new_public_key, + }; + + let transaction_str_params = build_transaction_str_params(matches, ACCEPT_SESSION_ARGS); + + Ok((params, transaction_str_params)) + } + + fn add_args(change_bid_public_key_subcommand: Command) -> Command { + change_bid_public_key_subcommand + .arg(public_key::arg(DisplayOrder::PublicKey as usize)) + .arg(new_public_key::arg(DisplayOrder::NewPublicKey as usize)) + } +} + +pub(super) mod add_reservations { + use super::*; + use casper_client::cli::{CliError, TransactionBuilderParams, TransactionStrParams}; + + pub const NAME: &str = "add-reservations"; + + const ACCEPT_SESSION_ARGS: bool = false; + + const ABOUT: &str = "Creates a new add-reservations transaction"; + pub fn build() -> Command { + apply_common_creation_options( + add_args(Command::new(NAME).about(ABOUT)), + false, + false, + ACCEPT_SESSION_ARGS, + ) + } + + pub fn put_transaction_build() -> Command { + add_rpc_args(build()) + } + + pub fn run( + matches: &ArgMatches, + ) -> Result<(TransactionBuilderParams, TransactionStrParams), CliError> { + let reservations_str = reservations::get(matches); + let reservations = reservations::parse_reservations(reservations_str)?; + + let params = TransactionBuilderParams::AddReservations { reservations }; + + let transaction_str_params = build_transaction_str_params(matches, ACCEPT_SESSION_ARGS); + + Ok((params, transaction_str_params)) + } + + fn add_args(add_reservations_subcommand: Command) -> Command { + add_reservations_subcommand.arg(reservations::arg()) + } +} + +pub(super) mod cancel_reservations { + use super::*; + use casper_client::cli::{CliError, TransactionBuilderParams, TransactionStrParams}; + + pub const NAME: &str = "cancel-reservations"; + + const ACCEPT_SESSION_ARGS: bool = false; + + const ABOUT: &str = "Creates a new cancel-reservations transaction"; + pub fn build() -> Command { + apply_common_creation_options( + add_args(Command::new(NAME).about(ABOUT)), + false, + false, + ACCEPT_SESSION_ARGS, + ) + } + + pub fn put_transaction_build() -> Command { + add_rpc_args(build()) + } + + pub fn run( + matches: &ArgMatches, + ) -> Result<(TransactionBuilderParams, TransactionStrParams), CliError> { + let validator_str = validator::get(matches); + let validator = public_key::parse_public_key(validator_str)?; + + let delegators_str = delegators::get(matches); + let delegators = delegators::parse_delegators(delegators_str)?; + + let params = TransactionBuilderParams::CancelReservations { + validator, + delegators, + }; + + let transaction_str_params = build_transaction_str_params(matches, ACCEPT_SESSION_ARGS); + + Ok((params, transaction_str_params)) + } + + fn add_args(cancel_reservations_subcommand: Command) -> Command { + cancel_reservations_subcommand + .arg(validator::arg()) + .arg(delegators::arg()) + } +} + pub(super) mod invocable_entity { use super::*; use casper_client::cli::{CliError, TransactionBuilderParams}; @@ -1640,8 +2003,8 @@ pub(super) mod invocable_entity { Ok((params, transaction_str_params)) } - fn add_args(add_bid_subcommand: Command) -> Command { - add_bid_subcommand + fn add_args(invocable_entity_subcommand: Command) -> Command { + invocable_entity_subcommand .arg(entity_addr::arg()) .arg(session_entry_point::arg()) .arg(transaction_runtime::arg()) @@ -1649,6 +2012,7 @@ pub(super) mod invocable_entity { .arg(chunked_args::arg()) } } + pub(super) mod invocable_entity_alias { use super::*; use casper_client::cli::{CliError, TransactionBuilderParams}; @@ -1696,12 +2060,13 @@ pub(super) mod invocable_entity_alias { Ok((params, transaction_str_params)) } - fn add_args(add_bid_subcommand: Command) -> Command { - add_bid_subcommand + fn add_args(invocable_entity_alias_subcommand: Command) -> Command { + invocable_entity_alias_subcommand .arg(entity_alias_arg::arg()) .arg(session_entry_point::arg()) } } + pub(super) mod package { use super::*; use casper_client::cli::{CliError, TransactionBuilderParams}; @@ -1753,13 +2118,14 @@ pub(super) mod package { Ok((params, transaction_str_params)) } - fn add_args(add_bid_subcommand: Command) -> Command { - add_bid_subcommand + fn add_args(package_subcommand: Command) -> Command { + package_subcommand .arg(package_addr::arg()) .arg(session_version::arg()) .arg(session_entry_point::arg()) } } + pub(super) mod package_alias { use super::*; use casper_client::cli::{CliError, TransactionBuilderParams}; @@ -1812,13 +2178,14 @@ pub(super) mod package_alias { Ok((params, transaction_str_params)) } - fn add_args(add_bid_subcommand: Command) -> Command { - add_bid_subcommand + fn add_args(package_alias_subcommand: Command) -> Command { + package_alias_subcommand .arg(package_name_arg::arg()) .arg(session_version::arg()) .arg(session_entry_point::arg()) } } + pub(super) mod session { use super::*; use crate::cli::parse; @@ -1882,8 +2249,8 @@ pub(super) mod session { Ok((params, transaction_str_params)) } - fn add_args(add_bid_subcommand: Command) -> Command { - add_bid_subcommand + fn add_args(session_subcommand: Command) -> Command { + session_subcommand .arg(transaction_path::arg()) .arg(session_entry_point::arg()) .arg(is_install_upgrade::arg( @@ -1948,8 +2315,8 @@ pub(super) mod transfer { Ok((params, transaction_str_params)) } - fn add_args(add_bid_subcommand: Command) -> Command { - add_bid_subcommand + fn add_args(transfer_subcommand: Command) -> Command { + transfer_subcommand .arg(source::arg()) .arg(target::arg()) .arg(transfer_amount::arg()) @@ -2076,12 +2443,12 @@ pub(super) fn build_transaction_str_params( let maybe_output_path = output::get(matches).unwrap_or_default(); let initiator_addr = initiator_address::get(matches); - let session_entry_point = session_entry_point::get(matches); - let chunked_args = chunked_args::get(matches); if obtain_session_args { let session_args_simple = arg_simple::session::get(matches); let session_args_json = args_json::session::get(matches); + let session_entry_point = session_entry_point::get(matches); + let chunked_args = chunked_args::get(matches); TransactionStrParams { secret_key, timestamp, diff --git a/src/transaction/make.rs b/src/transaction/make.rs index e4b4c5b..411dc7f 100644 --- a/src/transaction/make.rs +++ b/src/transaction/make.rs @@ -4,8 +4,9 @@ use clap::{ArgMatches, Command}; use casper_client::cli::CliError; use super::creation_common::{ - add_bid, delegate, invocable_entity, invocable_entity_alias, package, package_alias, - redelegate, session, transfer, undelegate, withdraw_bid, DisplayOrder, + activate_bid, add_bid, add_reservations, cancel_reservations, change_bid_public_key, delegate, + invocable_entity, invocable_entity_alias, package, package_alias, redelegate, session, + transfer, undelegate, withdraw_bid, DisplayOrder, }; use crate::{command::ClientCommand, common, Success}; @@ -24,11 +25,15 @@ impl ClientCommand for MakeTransaction { Command::new(Self::NAME) .about(Self::ABOUT) .subcommand_required(true) - .subcommand(withdraw_bid::build()) .subcommand(add_bid::build()) + .subcommand(activate_bid::build()) + .subcommand(withdraw_bid::build()) .subcommand(delegate::build()) .subcommand(undelegate::build()) .subcommand(redelegate::build()) + .subcommand(change_bid_public_key::build()) + .subcommand(add_reservations::build()) + .subcommand(cancel_reservations::build()) .subcommand(invocable_entity::build()) .subcommand(invocable_entity_alias::build()) .subcommand(package::build()) @@ -45,10 +50,14 @@ impl ClientCommand for MakeTransaction { if let Some((subcommand, matches)) = matches.subcommand() { let (transaction_builder_params, transaction_str_params) = match subcommand { add_bid::NAME => add_bid::run(matches)?, + activate_bid::NAME => activate_bid::run(matches)?, withdraw_bid::NAME => withdraw_bid::run(matches)?, delegate::NAME => delegate::run(matches)?, undelegate::NAME => undelegate::run(matches)?, redelegate::NAME => redelegate::run(matches)?, + change_bid_public_key::NAME => change_bid_public_key::run(matches)?, + add_reservations::NAME => cancel_reservations::run(matches)?, + cancel_reservations::NAME => cancel_reservations::run(matches)?, invocable_entity::NAME => invocable_entity::run(matches)?, invocable_entity_alias::NAME => invocable_entity_alias::run(matches)?, package::NAME => package::run(matches)?, diff --git a/src/transaction/put.rs b/src/transaction/put.rs index 2150a47..6fc8de2 100644 --- a/src/transaction/put.rs +++ b/src/transaction/put.rs @@ -4,8 +4,9 @@ use clap::{ArgMatches, Command}; use casper_client::cli::CliError; use super::creation_common::{ - add_bid, delegate, invocable_entity, invocable_entity_alias, package, package_alias, - redelegate, session, transfer, undelegate, withdraw_bid, + activate_bid, add_bid, add_reservations, cancel_reservations, change_bid_public_key, delegate, + invocable_entity, invocable_entity_alias, package, package_alias, redelegate, session, + transfer, undelegate, withdraw_bid, }; use crate::{ @@ -25,11 +26,15 @@ impl ClientCommand for PutTransaction { .about(Self::ABOUT) .alias(ALIAS) .subcommand_required(true) - .subcommand(withdraw_bid::put_transaction_build()) .subcommand(add_bid::put_transaction_build()) + .subcommand(activate_bid::put_transaction_build()) + .subcommand(withdraw_bid::put_transaction_build()) .subcommand(delegate::put_transaction_build()) .subcommand(undelegate::put_transaction_build()) .subcommand(redelegate::put_transaction_build()) + .subcommand(change_bid_public_key::put_transaction_build()) + .subcommand(add_reservations::put_transaction_build()) + .subcommand(cancel_reservations::put_transaction_build()) .subcommand(invocable_entity::put_transaction_build()) .subcommand(invocable_entity_alias::put_transaction_build()) .subcommand(package::put_transaction_build()) @@ -49,10 +54,18 @@ impl ClientCommand for PutTransaction { verbosity_level, ) = match subcommand { add_bid::NAME => parse_rpc_args_and_run(matches, add_bid::run)?, + activate_bid::NAME => parse_rpc_args_and_run(matches, activate_bid::run)?, withdraw_bid::NAME => parse_rpc_args_and_run(matches, withdraw_bid::run)?, delegate::NAME => parse_rpc_args_and_run(matches, delegate::run)?, undelegate::NAME => parse_rpc_args_and_run(matches, undelegate::run)?, redelegate::NAME => parse_rpc_args_and_run(matches, redelegate::run)?, + change_bid_public_key::NAME => { + parse_rpc_args_and_run(matches, change_bid_public_key::run)? + } + add_reservations::NAME => parse_rpc_args_and_run(matches, add_reservations::run)?, + cancel_reservations::NAME => { + parse_rpc_args_and_run(matches, cancel_reservations::run)? + } invocable_entity::NAME => parse_rpc_args_and_run(matches, invocable_entity::run)?, invocable_entity_alias::NAME => { parse_rpc_args_and_run(matches, invocable_entity_alias::run)?