From 6275ed4910988a65661c95265ed87bd25c96a26c Mon Sep 17 00:00:00 2001 From: FroVolod Date: Wed, 26 Jun 2024 16:01:36 +0300 Subject: [PATCH 1/9] added indicator for ViewStatus --- src/commands/transaction/view_status/mod.rs | 52 ++++++++++++--------- 1 file changed, 29 insertions(+), 23 deletions(-) diff --git a/src/commands/transaction/view_status/mod.rs b/src/commands/transaction/view_status/mod.rs index 6167ddf5a..0036b8dd4 100644 --- a/src/commands/transaction/view_status/mod.rs +++ b/src/commands/transaction/view_status/mod.rs @@ -23,30 +23,9 @@ impl TransactionInfoContext { ) -> color_eyre::eyre::Result { let on_after_getting_network_callback: crate::network::OnAfterGettingNetworkCallback = std::sync::Arc::new({ - let transaction_hash = scope.transaction_hash; + let tx_hash: near_primitives::hash::CryptoHash = scope.transaction_hash.into(); - move |network_config| { - let query_view_transaction_status = network_config - .json_rpc_client() - .blocking_call( - near_jsonrpc_client::methods::tx::RpcTransactionStatusRequest { - transaction_info: - near_jsonrpc_client::methods::tx::TransactionInfo::TransactionId { - tx_hash: transaction_hash.into(), - sender_account_id: "near".parse::()?, - }, - wait_until: near_primitives::views::TxExecutionStatus::Final, - }, - ) - .wrap_err_with(|| { - format!( - "Failed to fetch query for view transaction on network <{}>", - network_config.network_name - ) - })?; - eprintln!("Transaction status: {:#?}", query_view_transaction_status); - Ok(()) - } + move |network_config| get_transaction_status(network_config, tx_hash) }); Ok(Self(crate::network::NetworkContext { @@ -62,3 +41,30 @@ impl From for crate::network::NetworkContext { item.0 } } + +#[tracing::instrument(name = "Getting transaction status ...", skip_all)] +fn get_transaction_status( + network_config: &crate::config::NetworkConfig, + tx_hash: near_primitives::hash::CryptoHash, +) -> crate::CliResult { + let query_view_transaction_status = network_config + .json_rpc_client() + .blocking_call( + near_jsonrpc_client::methods::tx::RpcTransactionStatusRequest { + transaction_info: + near_jsonrpc_client::methods::tx::TransactionInfo::TransactionId { + tx_hash, + sender_account_id: "near".parse::()?, + }, + wait_until: near_primitives::views::TxExecutionStatus::Final, + }, + ) + .wrap_err_with(|| { + format!( + "Failed to fetch query for view transaction on network <{}>", + network_config.network_name + ) + })?; + eprintln!("\nTransaction status: {:#?}", query_view_transaction_status); + Ok(()) +} From cb04a7981502c7e25e83caf6fdb54b1528926704 Mon Sep 17 00:00:00 2001 From: FroVolod Date: Wed, 26 Jun 2024 18:37:51 +0300 Subject: [PATCH 2/9] added indicator for ReconstructTransaction --- .../reconstruct_transaction/mod.rs | 28 ++----------------- src/commands/transaction/view_status/mod.rs | 21 ++++++++------ 2 files changed, 16 insertions(+), 33 deletions(-) diff --git a/src/commands/transaction/reconstruct_transaction/mod.rs b/src/commands/transaction/reconstruct_transaction/mod.rs index 677292b09..5cb43a298 100644 --- a/src/commands/transaction/reconstruct_transaction/mod.rs +++ b/src/commands/transaction/reconstruct_transaction/mod.rs @@ -1,8 +1,6 @@ use color_eyre::eyre::{Context, ContextCompat}; use interactive_clap::ToCliArgs; -use crate::common::JsonRpcClientExt; - #[derive(Debug, Clone, interactive_clap::InteractiveClap)] #[interactive_clap(input_context = crate::GlobalContext)] #[interactive_clap(output_context = TransactionInfoContext)] @@ -27,34 +25,14 @@ impl TransactionInfoContext { let on_after_getting_network_callback: crate::network::OnAfterGettingNetworkCallback = std::sync::Arc::new({ - let transaction_hash = scope.transaction_hash; + let tx_hash: near_primitives::hash::CryptoHash = scope.transaction_hash.into(); move |network_config| { - let query_view_transaction_status = network_config - .json_rpc_client() - .blocking_call( - near_jsonrpc_client::methods::tx::RpcTransactionStatusRequest { - transaction_info: - near_jsonrpc_client::methods::tx::TransactionInfo::TransactionId { - tx_hash: transaction_hash.into(), - sender_account_id: "near".parse::()?, - }, - wait_until: near_primitives::views::TxExecutionStatus::Final - }, - ) - .wrap_err_with(|| { - format!( - "Failed to fetch query for view transaction on network <{}>", - network_config.network_name - ) - })?; - - let query_view_transaction_status = query_view_transaction_status + let query_view_transaction_status = super::view_status::get_transaction_info(network_config, tx_hash)? .final_execution_outcome .wrap_err_with(|| { format!( - "Failed to get the final execution outcome for the transaction {}", - transaction_hash + "Failed to get the final execution outcome for the transaction {tx_hash}" ) })? .into_outcome(); diff --git a/src/commands/transaction/view_status/mod.rs b/src/commands/transaction/view_status/mod.rs index 0036b8dd4..3075b9b00 100644 --- a/src/commands/transaction/view_status/mod.rs +++ b/src/commands/transaction/view_status/mod.rs @@ -1,4 +1,5 @@ use color_eyre::eyre::Context; +use tracing_indicatif::span_ext::IndicatifSpanExt; use crate::common::JsonRpcClientExt; @@ -25,7 +26,12 @@ impl TransactionInfoContext { std::sync::Arc::new({ let tx_hash: near_primitives::hash::CryptoHash = scope.transaction_hash.into(); - move |network_config| get_transaction_status(network_config, tx_hash) + move |network_config| { + let query_view_transaction_status = + get_transaction_info(network_config, tx_hash)?; + eprintln!("\nTransaction status: {:#?}", query_view_transaction_status); + Ok(()) + } }); Ok(Self(crate::network::NetworkContext { @@ -42,12 +48,13 @@ impl From for crate::network::NetworkContext { } } -#[tracing::instrument(name = "Getting transaction status ...", skip_all)] -fn get_transaction_status( +#[tracing::instrument(name = "Getting information about transaction", skip_all)] +pub fn get_transaction_info( network_config: &crate::config::NetworkConfig, tx_hash: near_primitives::hash::CryptoHash, -) -> crate::CliResult { - let query_view_transaction_status = network_config +) -> color_eyre::eyre::Result { + tracing::Span::current().pb_set_message(&format!("{tx_hash} ...")); + network_config .json_rpc_client() .blocking_call( near_jsonrpc_client::methods::tx::RpcTransactionStatusRequest { @@ -64,7 +71,5 @@ fn get_transaction_status( "Failed to fetch query for view transaction on network <{}>", network_config.network_name ) - })?; - eprintln!("\nTransaction status: {:#?}", query_view_transaction_status); - Ok(()) + }) } From 32503997dd798943b9d7e018b98687fcc285ff91 Mon Sep 17 00:00:00 2001 From: FroVolod Date: Fri, 28 Jun 2024 10:34:54 +0300 Subject: [PATCH 3/9] updated NearAllowance --- src/types/near_allowance.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/types/near_allowance.rs b/src/types/near_allowance.rs index c48af3d65..b1ef4d40e 100644 --- a/src/types/near_allowance.rs +++ b/src/types/near_allowance.rs @@ -40,6 +40,10 @@ impl NearAllowance { pub fn optional_near_token(&self) -> Option { self.0 } + + pub fn from_yoctonear(value: u128) -> Self { + Self(Some(crate::types::near_token::NearToken::from_yoctonear(value))) + } } impl interactive_clap::ToCli for NearAllowance { @@ -88,4 +92,11 @@ mod tests { None ) } + #[test] + fn near_allowance_from_yoctonear() { + assert_eq!( + NearAllowance::from_yoctonear(20_000_000_000_000_000_000_000).0, + crate::types::near_token::NearToken::from_str("0.02 NEAR").ok() + ) + } } From 81d57f5326e69c34af537242d98e586a2bf51cd2 Mon Sep 17 00:00:00 2001 From: FroVolod Date: Fri, 28 Jun 2024 10:55:13 +0300 Subject: [PATCH 4/9] refactored ReconstructTransaction --- src/commands/transaction/reconstruct_transaction/mod.rs | 3 ++- src/types/near_allowance.rs | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/commands/transaction/reconstruct_transaction/mod.rs b/src/commands/transaction/reconstruct_transaction/mod.rs index 5cb43a298..2a0804c08 100644 --- a/src/commands/transaction/reconstruct_transaction/mod.rs +++ b/src/commands/transaction/reconstruct_transaction/mod.rs @@ -267,7 +267,8 @@ fn get_access_key_permission( ) => Ok(Some( add_key::CliAccessKeyPermission::GrantFunctionCallAccess( add_key::access_key_type::CliFunctionCallType { - allowance: allowance.map(crate::types::near_token::NearToken::from_yoctonear), + allowance: allowance + .map(crate::types::near_allowance::NearAllowance::from_yoctonear), receiver_account_id: Some(receiver_id.parse()?), method_names: Some(crate::types::vec_string::VecString(method_names)), access_key_mode: Some(add_key::CliAccessKeyMode::UseManuallyProvidedPublicKey( diff --git a/src/types/near_allowance.rs b/src/types/near_allowance.rs index b1ef4d40e..0b5a3ce4d 100644 --- a/src/types/near_allowance.rs +++ b/src/types/near_allowance.rs @@ -42,7 +42,9 @@ impl NearAllowance { } pub fn from_yoctonear(value: u128) -> Self { - Self(Some(crate::types::near_token::NearToken::from_yoctonear(value))) + Self(Some(crate::types::near_token::NearToken::from_yoctonear( + value, + ))) } } From dc48aa4276af6cdd1e6015a3c4d072d158d47b60 Mon Sep 17 00:00:00 2001 From: FroVolod Date: Fri, 28 Jun 2024 13:00:46 +0300 Subject: [PATCH 5/9] refactored construct-transaction --- .../add_action/add_key/access_key_type/mod.rs | 13 ++++++++----- .../add_action_1/add_action/call_function/mod.rs | 10 ++++++++++ .../add_action_1/add_action/delete_account/mod.rs | 13 ++++++++++--- .../add_action_1/add_action/stake/mod.rs | 2 ++ .../add_action/add_key/access_key_type/mod.rs | 13 ++++++++----- .../add_action_2/add_action/call_function/mod.rs | 10 ++++++++++ .../add_action_2/add_action/delete_account/mod.rs | 13 ++++++++++--- .../add_action_2/add_action/stake/mod.rs | 2 ++ .../add_action/add_key/access_key_type/mod.rs | 13 ++++++++----- .../add_action_3/add_action/call_function/mod.rs | 10 ++++++++++ .../add_action_3/add_action/delete_account/mod.rs | 13 ++++++++++--- .../add_action_3/add_action/stake/mod.rs | 2 ++ 12 files changed, 90 insertions(+), 24 deletions(-) diff --git a/src/commands/transaction/construct_transaction/add_action_1/add_action/add_key/access_key_type/mod.rs b/src/commands/transaction/construct_transaction/add_action_1/add_action/add_key/access_key_type/mod.rs index 2bd08486c..49b1643f9 100644 --- a/src/commands/transaction/construct_transaction/add_action_1/add_action/add_key/access_key_type/mod.rs +++ b/src/commands/transaction/construct_transaction/add_action_1/add_action/add_key/access_key_type/mod.rs @@ -49,7 +49,7 @@ impl From for AccessKeyPermissionContext { pub struct FunctionCallType { #[interactive_clap(long)] #[interactive_clap(skip_default_input_arg)] - allowance: crate::types::near_token::NearToken, + allowance: crate::types::near_allowance::NearAllowance, #[interactive_clap(long)] /// Enter a receiver to use by this access key to pay for function call gas and transaction fees: receiver_account_id: crate::types::account_id::AccountId, @@ -70,7 +70,10 @@ impl FunctionCallTypeContext { ) -> color_eyre::eyre::Result { let access_key_permission = near_primitives::account::AccessKeyPermission::FunctionCall( near_primitives::account::FunctionCallPermission { - allowance: Some(scope.allowance.as_yoctonear()), + allowance: scope + .allowance + .optional_near_token() + .map(|allowance| allowance.as_yoctonear()), receiver_id: scope.receiver_account_id.to_string(), method_names: scope.method_names.clone().into(), }, @@ -131,10 +134,10 @@ impl FunctionCallType { pub fn input_allowance( _context: &super::super::super::super::ConstructTransactionContext, - ) -> color_eyre::eyre::Result> { - let allowance_near_balance: crate::types::near_token::NearToken = + ) -> color_eyre::eyre::Result> { + let allowance_near_balance: crate::types::near_allowance::NearAllowance = CustomType::new("Enter the allowance, a budget this access key can use to pay for transaction fees (example: 10NEAR or 0.5near or 10000yoctonear):") - .with_starting_input("0.25 NEAR") + .with_starting_input("unlimited") .prompt()?; Ok(Some(allowance_near_balance)) } diff --git a/src/commands/transaction/construct_transaction/add_action_1/add_action/call_function/mod.rs b/src/commands/transaction/construct_transaction/add_action_1/add_action/call_function/mod.rs index a23e87dd3..e2e933722 100644 --- a/src/commands/transaction/construct_transaction/add_action_1/add_action/call_function/mod.rs +++ b/src/commands/transaction/construct_transaction/add_action_1/add_action/call_function/mod.rs @@ -4,6 +4,7 @@ use inquire::CustomType; #[interactive_clap(input_context = super::super::super::ConstructTransactionContext)] #[interactive_clap(output_context = FunctionCallActionContext)] pub struct FunctionCallAction { + #[interactive_clap(skip_default_input_arg)] /// What is the name of the function? function_name: String, #[interactive_clap(value_enum)] @@ -58,6 +59,15 @@ impl FunctionCallAction { crate::commands::contract::call_function::call_function_args_type::input_function_args_type( ) } + + fn input_function_name( + context: &super::super::super::ConstructTransactionContext, + ) -> color_eyre::eyre::Result> { + crate::commands::contract::call_function::input_call_function_name( + &context.global_context, + &context.receiver_account_id, + ) + } } #[derive(Debug, Clone, interactive_clap::InteractiveClap)] diff --git a/src/commands/transaction/construct_transaction/add_action_1/add_action/delete_account/mod.rs b/src/commands/transaction/construct_transaction/add_action_1/add_action/delete_account/mod.rs index 23d300605..2fb6b9578 100644 --- a/src/commands/transaction/construct_transaction/add_action_1/add_action/delete_account/mod.rs +++ b/src/commands/transaction/construct_transaction/add_action_1/add_action/delete_account/mod.rs @@ -1,4 +1,4 @@ -use inquire::{CustomType, Select}; +use inquire::Select; #[derive(Debug, Clone, interactive_clap::InteractiveClap)] #[interactive_clap(input_context = super::super::super::ConstructTransactionContext)] @@ -46,8 +46,15 @@ impl DeleteAccountAction { context: &super::super::super::ConstructTransactionContext, ) -> color_eyre::eyre::Result> { loop { - let beneficiary_account_id: crate::types::account_id::AccountId = - CustomType::new("What is the beneficiary account ID?").prompt()?; + let beneficiary_account_id = if let Some(account_id) = + crate::common::input_non_signer_account_id_from_used_account_list( + &context.global_context.config.credentials_home_dir, + "What is the beneficiary account ID?", + )? { + account_id + } else { + return Ok(None); + }; if context.global_context.offline { return Ok(Some(beneficiary_account_id)); diff --git a/src/commands/transaction/construct_transaction/add_action_1/add_action/stake/mod.rs b/src/commands/transaction/construct_transaction/add_action_1/add_action/stake/mod.rs index 5df4e7b07..f9242cdb9 100644 --- a/src/commands/transaction/construct_transaction/add_action_1/add_action/stake/mod.rs +++ b/src/commands/transaction/construct_transaction/add_action_1/add_action/stake/mod.rs @@ -2,7 +2,9 @@ #[interactive_clap(input_context = super::super::super::ConstructTransactionContext)] #[interactive_clap(output_context = StakeActionContext)] pub struct StakeAction { + /// Enter the amount to stake: (example: 10000NEAR) stake_amount: crate::types::near_token::NearToken, + /// Validator key which will be used to sign transactions on behalf of signer_id: public_key: crate::types::public_key::PublicKey, #[interactive_clap(subcommand)] next_action: super::super::super::add_action_2::NextAction, diff --git a/src/commands/transaction/construct_transaction/add_action_2/add_action/add_key/access_key_type/mod.rs b/src/commands/transaction/construct_transaction/add_action_2/add_action/add_key/access_key_type/mod.rs index 2bd08486c..49b1643f9 100644 --- a/src/commands/transaction/construct_transaction/add_action_2/add_action/add_key/access_key_type/mod.rs +++ b/src/commands/transaction/construct_transaction/add_action_2/add_action/add_key/access_key_type/mod.rs @@ -49,7 +49,7 @@ impl From for AccessKeyPermissionContext { pub struct FunctionCallType { #[interactive_clap(long)] #[interactive_clap(skip_default_input_arg)] - allowance: crate::types::near_token::NearToken, + allowance: crate::types::near_allowance::NearAllowance, #[interactive_clap(long)] /// Enter a receiver to use by this access key to pay for function call gas and transaction fees: receiver_account_id: crate::types::account_id::AccountId, @@ -70,7 +70,10 @@ impl FunctionCallTypeContext { ) -> color_eyre::eyre::Result { let access_key_permission = near_primitives::account::AccessKeyPermission::FunctionCall( near_primitives::account::FunctionCallPermission { - allowance: Some(scope.allowance.as_yoctonear()), + allowance: scope + .allowance + .optional_near_token() + .map(|allowance| allowance.as_yoctonear()), receiver_id: scope.receiver_account_id.to_string(), method_names: scope.method_names.clone().into(), }, @@ -131,10 +134,10 @@ impl FunctionCallType { pub fn input_allowance( _context: &super::super::super::super::ConstructTransactionContext, - ) -> color_eyre::eyre::Result> { - let allowance_near_balance: crate::types::near_token::NearToken = + ) -> color_eyre::eyre::Result> { + let allowance_near_balance: crate::types::near_allowance::NearAllowance = CustomType::new("Enter the allowance, a budget this access key can use to pay for transaction fees (example: 10NEAR or 0.5near or 10000yoctonear):") - .with_starting_input("0.25 NEAR") + .with_starting_input("unlimited") .prompt()?; Ok(Some(allowance_near_balance)) } diff --git a/src/commands/transaction/construct_transaction/add_action_2/add_action/call_function/mod.rs b/src/commands/transaction/construct_transaction/add_action_2/add_action/call_function/mod.rs index 8c0fe2bbf..4837102af 100644 --- a/src/commands/transaction/construct_transaction/add_action_2/add_action/call_function/mod.rs +++ b/src/commands/transaction/construct_transaction/add_action_2/add_action/call_function/mod.rs @@ -4,6 +4,7 @@ use inquire::CustomType; #[interactive_clap(input_context = super::super::super::ConstructTransactionContext)] #[interactive_clap(output_context = FunctionCallActionContext)] pub struct FunctionCallAction { + #[interactive_clap(skip_default_input_arg)] /// What is the name of the function? function_name: String, #[interactive_clap(value_enum)] @@ -58,6 +59,15 @@ impl FunctionCallAction { crate::commands::contract::call_function::call_function_args_type::input_function_args_type( ) } + + fn input_function_name( + context: &super::super::super::ConstructTransactionContext, + ) -> color_eyre::eyre::Result> { + crate::commands::contract::call_function::input_call_function_name( + &context.global_context, + &context.receiver_account_id, + ) + } } #[derive(Debug, Clone, interactive_clap::InteractiveClap)] diff --git a/src/commands/transaction/construct_transaction/add_action_2/add_action/delete_account/mod.rs b/src/commands/transaction/construct_transaction/add_action_2/add_action/delete_account/mod.rs index f3410cc1e..4655d4c34 100644 --- a/src/commands/transaction/construct_transaction/add_action_2/add_action/delete_account/mod.rs +++ b/src/commands/transaction/construct_transaction/add_action_2/add_action/delete_account/mod.rs @@ -1,4 +1,4 @@ -use inquire::{CustomType, Select}; +use inquire::Select; #[derive(Debug, Clone, interactive_clap::InteractiveClap)] #[interactive_clap(input_context = super::super::super::ConstructTransactionContext)] @@ -46,8 +46,15 @@ impl DeleteAccountAction { context: &super::super::super::ConstructTransactionContext, ) -> color_eyre::eyre::Result> { loop { - let beneficiary_account_id: crate::types::account_id::AccountId = - CustomType::new("What is the beneficiary account ID?").prompt()?; + let beneficiary_account_id = if let Some(account_id) = + crate::common::input_non_signer_account_id_from_used_account_list( + &context.global_context.config.credentials_home_dir, + "What is the beneficiary account ID?", + )? { + account_id + } else { + return Ok(None); + }; if context.global_context.offline { return Ok(Some(beneficiary_account_id)); diff --git a/src/commands/transaction/construct_transaction/add_action_2/add_action/stake/mod.rs b/src/commands/transaction/construct_transaction/add_action_2/add_action/stake/mod.rs index da6a50014..370cc2d75 100644 --- a/src/commands/transaction/construct_transaction/add_action_2/add_action/stake/mod.rs +++ b/src/commands/transaction/construct_transaction/add_action_2/add_action/stake/mod.rs @@ -2,7 +2,9 @@ #[interactive_clap(input_context = super::super::super::ConstructTransactionContext)] #[interactive_clap(output_context = StakeActionContext)] pub struct StakeAction { + /// Enter the amount to stake: (example: 10000NEAR) stake_amount: crate::types::near_token::NearToken, + /// Validator key which will be used to sign transactions on behalf of signer_id: public_key: crate::types::public_key::PublicKey, #[interactive_clap(subcommand)] next_action: super::super::super::add_action_3::NextAction, diff --git a/src/commands/transaction/construct_transaction/add_action_3/add_action/add_key/access_key_type/mod.rs b/src/commands/transaction/construct_transaction/add_action_3/add_action/add_key/access_key_type/mod.rs index 2bd08486c..49b1643f9 100644 --- a/src/commands/transaction/construct_transaction/add_action_3/add_action/add_key/access_key_type/mod.rs +++ b/src/commands/transaction/construct_transaction/add_action_3/add_action/add_key/access_key_type/mod.rs @@ -49,7 +49,7 @@ impl From for AccessKeyPermissionContext { pub struct FunctionCallType { #[interactive_clap(long)] #[interactive_clap(skip_default_input_arg)] - allowance: crate::types::near_token::NearToken, + allowance: crate::types::near_allowance::NearAllowance, #[interactive_clap(long)] /// Enter a receiver to use by this access key to pay for function call gas and transaction fees: receiver_account_id: crate::types::account_id::AccountId, @@ -70,7 +70,10 @@ impl FunctionCallTypeContext { ) -> color_eyre::eyre::Result { let access_key_permission = near_primitives::account::AccessKeyPermission::FunctionCall( near_primitives::account::FunctionCallPermission { - allowance: Some(scope.allowance.as_yoctonear()), + allowance: scope + .allowance + .optional_near_token() + .map(|allowance| allowance.as_yoctonear()), receiver_id: scope.receiver_account_id.to_string(), method_names: scope.method_names.clone().into(), }, @@ -131,10 +134,10 @@ impl FunctionCallType { pub fn input_allowance( _context: &super::super::super::super::ConstructTransactionContext, - ) -> color_eyre::eyre::Result> { - let allowance_near_balance: crate::types::near_token::NearToken = + ) -> color_eyre::eyre::Result> { + let allowance_near_balance: crate::types::near_allowance::NearAllowance = CustomType::new("Enter the allowance, a budget this access key can use to pay for transaction fees (example: 10NEAR or 0.5near or 10000yoctonear):") - .with_starting_input("0.25 NEAR") + .with_starting_input("unlimited") .prompt()?; Ok(Some(allowance_near_balance)) } diff --git a/src/commands/transaction/construct_transaction/add_action_3/add_action/call_function/mod.rs b/src/commands/transaction/construct_transaction/add_action_3/add_action/call_function/mod.rs index 9dc71bfab..8ad49d5d0 100644 --- a/src/commands/transaction/construct_transaction/add_action_3/add_action/call_function/mod.rs +++ b/src/commands/transaction/construct_transaction/add_action_3/add_action/call_function/mod.rs @@ -4,6 +4,7 @@ use inquire::CustomType; #[interactive_clap(input_context = super::super::super::ConstructTransactionContext)] #[interactive_clap(output_context = FunctionCallActionContext)] pub struct FunctionCallAction { + #[interactive_clap(skip_default_input_arg)] /// What is the name of the function? function_name: String, #[interactive_clap(value_enum)] @@ -58,6 +59,15 @@ impl FunctionCallAction { crate::commands::contract::call_function::call_function_args_type::input_function_args_type( ) } + + fn input_function_name( + context: &super::super::super::ConstructTransactionContext, + ) -> color_eyre::eyre::Result> { + crate::commands::contract::call_function::input_call_function_name( + &context.global_context, + &context.receiver_account_id, + ) + } } #[derive(Debug, Clone, interactive_clap::InteractiveClap)] diff --git a/src/commands/transaction/construct_transaction/add_action_3/add_action/delete_account/mod.rs b/src/commands/transaction/construct_transaction/add_action_3/add_action/delete_account/mod.rs index 9dd17b769..30122a090 100644 --- a/src/commands/transaction/construct_transaction/add_action_3/add_action/delete_account/mod.rs +++ b/src/commands/transaction/construct_transaction/add_action_3/add_action/delete_account/mod.rs @@ -1,4 +1,4 @@ -use inquire::{CustomType, Select}; +use inquire::Select; #[derive(Debug, Clone, interactive_clap::InteractiveClap)] #[interactive_clap(input_context = super::super::super::ConstructTransactionContext)] @@ -46,8 +46,15 @@ impl DeleteAccountAction { context: &super::super::super::ConstructTransactionContext, ) -> color_eyre::eyre::Result> { loop { - let beneficiary_account_id: crate::types::account_id::AccountId = - CustomType::new("What is the beneficiary account ID?").prompt()?; + let beneficiary_account_id = if let Some(account_id) = + crate::common::input_non_signer_account_id_from_used_account_list( + &context.global_context.config.credentials_home_dir, + "What is the beneficiary account ID?", + )? { + account_id + } else { + return Ok(None); + }; if context.global_context.offline { return Ok(Some(beneficiary_account_id)); diff --git a/src/commands/transaction/construct_transaction/add_action_3/add_action/stake/mod.rs b/src/commands/transaction/construct_transaction/add_action_3/add_action/stake/mod.rs index 6c258876b..b2abf7407 100644 --- a/src/commands/transaction/construct_transaction/add_action_3/add_action/stake/mod.rs +++ b/src/commands/transaction/construct_transaction/add_action_3/add_action/stake/mod.rs @@ -2,7 +2,9 @@ #[interactive_clap(input_context = super::super::super::ConstructTransactionContext)] #[interactive_clap(output_context = StakeActionContext)] pub struct StakeAction { + /// Enter the amount to stake: (example: 10000NEAR) stake_amount: crate::types::near_token::NearToken, + /// Validator key which will be used to sign transactions on behalf of signer_id: public_key: crate::types::public_key::PublicKey, #[interactive_clap(subcommand)] next_action: super::super::super::add_action_last::NextAction, From d6a8901f7c77d2e7ac4a32b7a6dd34d9a9d27254 Mon Sep 17 00:00:00 2001 From: FroVolod Date: Sun, 30 Jun 2024 12:10:26 +0300 Subject: [PATCH 6/9] refactored FunctionCallType --- .../account/add_key/access_key_type/mod.rs | 30 +++++++++---------- .../add_action/add_key/access_key_type/mod.rs | 24 +++++++-------- .../add_action/add_key/access_key_type/mod.rs | 24 +++++++-------- .../add_action/add_key/access_key_type/mod.rs | 24 +++++++-------- .../reconstruct_transaction/mod.rs | 20 ++++++++++--- src/js_command_match/add_key.rs | 4 +-- 6 files changed, 69 insertions(+), 57 deletions(-) diff --git a/src/commands/account/add_key/access_key_type/mod.rs b/src/commands/account/add_key/access_key_type/mod.rs index c86504d26..6f70aee9f 100644 --- a/src/commands/account/add_key/access_key_type/mod.rs +++ b/src/commands/account/add_key/access_key_type/mod.rs @@ -55,11 +55,11 @@ pub struct FunctionCallType { #[interactive_clap(skip_default_input_arg)] allowance: crate::types::near_allowance::NearAllowance, #[interactive_clap(long)] - /// Enter a receiver to use by this access key to pay for function call gas and transaction fees: - receiver_account_id: crate::types::account_id::AccountId, + /// You chose to limit the access key to only sign transactions for a specific contract. Enter the contract account ID: + contract_account_id: crate::types::account_id::AccountId, #[interactive_clap(long)] #[interactive_clap(skip_default_input_arg)] - method_names: crate::types::vec_string::VecString, + function_names: crate::types::vec_string::VecString, #[interactive_clap(subcommand)] access_key_mode: super::AccessKeyMode, } @@ -69,8 +69,8 @@ pub struct FunctionCallTypeContext { global_context: crate::GlobalContext, signer_account_id: near_primitives::types::AccountId, allowance: Option, - receiver_account_id: crate::types::account_id::AccountId, - method_names: crate::types::vec_string::VecString, + contract_account_id: crate::types::account_id::AccountId, + function_names: crate::types::vec_string::VecString, } impl FunctionCallTypeContext { @@ -82,8 +82,8 @@ impl FunctionCallTypeContext { global_context: previous_context.global_context, signer_account_id: previous_context.owner_account_id.into(), allowance: scope.allowance.optional_near_token(), - receiver_account_id: scope.receiver_account_id.clone(), - method_names: scope.method_names.clone(), + contract_account_id: scope.contract_account_id.clone(), + function_names: scope.function_names.clone(), }) } } @@ -96,8 +96,8 @@ impl From for AccessTypeContext { permission: near_primitives::account::AccessKeyPermission::FunctionCall( near_primitives::account::FunctionCallPermission { allowance: item.allowance.map(|allowance| allowance.as_yoctonear()), - receiver_id: item.receiver_account_id.to_string(), - method_names: item.method_names.into(), + receiver_id: item.contract_account_id.to_string(), + method_names: item.function_names.into(), }, ), } @@ -105,7 +105,7 @@ impl From for AccessTypeContext { } impl FunctionCallType { - pub fn input_method_names( + pub fn input_function_names( _context: &super::AddKeyCommandContext, ) -> color_eyre::eyre::Result> { #[derive(strum_macros::Display)] @@ -125,16 +125,16 @@ impl FunctionCallType { ) .prompt()?; if let ConfirmOptions::Yes = select_choose_input { - let mut input_method_names = Text::new("Enter a comma-separated list of method names that will be allowed to be called in a transaction signed by this access key:") + let mut input_function_names = Text::new("Enter a comma-separated list of function names that will be allowed to be called in a transaction signed by this access key:") .prompt()?; - if input_method_names.contains('\"') { - input_method_names.clear() + if input_function_names.contains('\"') { + input_function_names.clear() }; - if input_method_names.is_empty() { + if input_function_names.is_empty() { Ok(Some(crate::types::vec_string::VecString(vec![]))) } else { Ok(Some(crate::types::vec_string::VecString::from_str( - &input_method_names, + &input_function_names, )?)) } } else { diff --git a/src/commands/transaction/construct_transaction/add_action_1/add_action/add_key/access_key_type/mod.rs b/src/commands/transaction/construct_transaction/add_action_1/add_action/add_key/access_key_type/mod.rs index 49b1643f9..6bad4a7b0 100644 --- a/src/commands/transaction/construct_transaction/add_action_1/add_action/add_key/access_key_type/mod.rs +++ b/src/commands/transaction/construct_transaction/add_action_1/add_action/add_key/access_key_type/mod.rs @@ -51,11 +51,11 @@ pub struct FunctionCallType { #[interactive_clap(skip_default_input_arg)] allowance: crate::types::near_allowance::NearAllowance, #[interactive_clap(long)] - /// Enter a receiver to use by this access key to pay for function call gas and transaction fees: - receiver_account_id: crate::types::account_id::AccountId, + /// You chose to limit the access key to only sign transactions for a specific contract. Enter the contract account ID: + contract_account_id: crate::types::account_id::AccountId, #[interactive_clap(long)] #[interactive_clap(skip_default_input_arg)] - method_names: crate::types::vec_string::VecString, + function_names: crate::types::vec_string::VecString, #[interactive_clap(subcommand)] access_key_mode: super::AccessKeyMode, } @@ -74,8 +74,8 @@ impl FunctionCallTypeContext { .allowance .optional_near_token() .map(|allowance| allowance.as_yoctonear()), - receiver_id: scope.receiver_account_id.to_string(), - method_names: scope.method_names.clone().into(), + receiver_id: scope.contract_account_id.to_string(), + method_names: scope.function_names.clone().into(), }, ); Ok(Self(AccessKeyPermissionContext { @@ -95,7 +95,7 @@ impl From for AccessKeyPermissionContext { } impl FunctionCallType { - pub fn input_method_names( + pub fn input_function_names( _context: &super::super::super::super::ConstructTransactionContext, ) -> color_eyre::eyre::Result> { eprintln!(); @@ -114,17 +114,17 @@ impl FunctionCallType { ) .prompt()?; if let ConfirmOptions::Yes = select_choose_input { - let mut input_method_names = - Text::new("Enter a comma-separated list of method names that will be allowed to be called in a transaction signed by this access key:") + let mut input_function_names = + Text::new("Enter a comma-separated list of function names that will be allowed to be called in a transaction signed by this access key:") .prompt()?; - if input_method_names.contains('\"') { - input_method_names.clear() + if input_function_names.contains('\"') { + input_function_names.clear() }; - if input_method_names.is_empty() { + if input_function_names.is_empty() { Ok(Some(crate::types::vec_string::VecString(vec![]))) } else { Ok(Some(crate::types::vec_string::VecString::from_str( - &input_method_names, + &input_function_names, )?)) } } else { diff --git a/src/commands/transaction/construct_transaction/add_action_2/add_action/add_key/access_key_type/mod.rs b/src/commands/transaction/construct_transaction/add_action_2/add_action/add_key/access_key_type/mod.rs index 49b1643f9..6bad4a7b0 100644 --- a/src/commands/transaction/construct_transaction/add_action_2/add_action/add_key/access_key_type/mod.rs +++ b/src/commands/transaction/construct_transaction/add_action_2/add_action/add_key/access_key_type/mod.rs @@ -51,11 +51,11 @@ pub struct FunctionCallType { #[interactive_clap(skip_default_input_arg)] allowance: crate::types::near_allowance::NearAllowance, #[interactive_clap(long)] - /// Enter a receiver to use by this access key to pay for function call gas and transaction fees: - receiver_account_id: crate::types::account_id::AccountId, + /// You chose to limit the access key to only sign transactions for a specific contract. Enter the contract account ID: + contract_account_id: crate::types::account_id::AccountId, #[interactive_clap(long)] #[interactive_clap(skip_default_input_arg)] - method_names: crate::types::vec_string::VecString, + function_names: crate::types::vec_string::VecString, #[interactive_clap(subcommand)] access_key_mode: super::AccessKeyMode, } @@ -74,8 +74,8 @@ impl FunctionCallTypeContext { .allowance .optional_near_token() .map(|allowance| allowance.as_yoctonear()), - receiver_id: scope.receiver_account_id.to_string(), - method_names: scope.method_names.clone().into(), + receiver_id: scope.contract_account_id.to_string(), + method_names: scope.function_names.clone().into(), }, ); Ok(Self(AccessKeyPermissionContext { @@ -95,7 +95,7 @@ impl From for AccessKeyPermissionContext { } impl FunctionCallType { - pub fn input_method_names( + pub fn input_function_names( _context: &super::super::super::super::ConstructTransactionContext, ) -> color_eyre::eyre::Result> { eprintln!(); @@ -114,17 +114,17 @@ impl FunctionCallType { ) .prompt()?; if let ConfirmOptions::Yes = select_choose_input { - let mut input_method_names = - Text::new("Enter a comma-separated list of method names that will be allowed to be called in a transaction signed by this access key:") + let mut input_function_names = + Text::new("Enter a comma-separated list of function names that will be allowed to be called in a transaction signed by this access key:") .prompt()?; - if input_method_names.contains('\"') { - input_method_names.clear() + if input_function_names.contains('\"') { + input_function_names.clear() }; - if input_method_names.is_empty() { + if input_function_names.is_empty() { Ok(Some(crate::types::vec_string::VecString(vec![]))) } else { Ok(Some(crate::types::vec_string::VecString::from_str( - &input_method_names, + &input_function_names, )?)) } } else { diff --git a/src/commands/transaction/construct_transaction/add_action_3/add_action/add_key/access_key_type/mod.rs b/src/commands/transaction/construct_transaction/add_action_3/add_action/add_key/access_key_type/mod.rs index 49b1643f9..6bad4a7b0 100644 --- a/src/commands/transaction/construct_transaction/add_action_3/add_action/add_key/access_key_type/mod.rs +++ b/src/commands/transaction/construct_transaction/add_action_3/add_action/add_key/access_key_type/mod.rs @@ -51,11 +51,11 @@ pub struct FunctionCallType { #[interactive_clap(skip_default_input_arg)] allowance: crate::types::near_allowance::NearAllowance, #[interactive_clap(long)] - /// Enter a receiver to use by this access key to pay for function call gas and transaction fees: - receiver_account_id: crate::types::account_id::AccountId, + /// You chose to limit the access key to only sign transactions for a specific contract. Enter the contract account ID: + contract_account_id: crate::types::account_id::AccountId, #[interactive_clap(long)] #[interactive_clap(skip_default_input_arg)] - method_names: crate::types::vec_string::VecString, + function_names: crate::types::vec_string::VecString, #[interactive_clap(subcommand)] access_key_mode: super::AccessKeyMode, } @@ -74,8 +74,8 @@ impl FunctionCallTypeContext { .allowance .optional_near_token() .map(|allowance| allowance.as_yoctonear()), - receiver_id: scope.receiver_account_id.to_string(), - method_names: scope.method_names.clone().into(), + receiver_id: scope.contract_account_id.to_string(), + method_names: scope.function_names.clone().into(), }, ); Ok(Self(AccessKeyPermissionContext { @@ -95,7 +95,7 @@ impl From for AccessKeyPermissionContext { } impl FunctionCallType { - pub fn input_method_names( + pub fn input_function_names( _context: &super::super::super::super::ConstructTransactionContext, ) -> color_eyre::eyre::Result> { eprintln!(); @@ -114,17 +114,17 @@ impl FunctionCallType { ) .prompt()?; if let ConfirmOptions::Yes = select_choose_input { - let mut input_method_names = - Text::new("Enter a comma-separated list of method names that will be allowed to be called in a transaction signed by this access key:") + let mut input_function_names = + Text::new("Enter a comma-separated list of function names that will be allowed to be called in a transaction signed by this access key:") .prompt()?; - if input_method_names.contains('\"') { - input_method_names.clear() + if input_function_names.contains('\"') { + input_function_names.clear() }; - if input_method_names.is_empty() { + if input_function_names.is_empty() { Ok(Some(crate::types::vec_string::VecString(vec![]))) } else { Ok(Some(crate::types::vec_string::VecString::from_str( - &input_method_names, + &input_function_names, )?)) } } else { diff --git a/src/commands/transaction/reconstruct_transaction/mod.rs b/src/commands/transaction/reconstruct_transaction/mod.rs index 2a0804c08..d63adfb27 100644 --- a/src/commands/transaction/reconstruct_transaction/mod.rs +++ b/src/commands/transaction/reconstruct_transaction/mod.rs @@ -1,3 +1,5 @@ +use std::str::FromStr; + use color_eyre::eyre::{Context, ContextCompat}; use interactive_clap::ToCliArgs; @@ -267,10 +269,20 @@ fn get_access_key_permission( ) => Ok(Some( add_key::CliAccessKeyPermission::GrantFunctionCallAccess( add_key::access_key_type::CliFunctionCallType { - allowance: allowance - .map(crate::types::near_allowance::NearAllowance::from_yoctonear), - receiver_account_id: Some(receiver_id.parse()?), - method_names: Some(crate::types::vec_string::VecString(method_names)), + allowance: { + match allowance { + Some(yoctonear) => { + Some(crate::types::near_allowance::NearAllowance::from_yoctonear( + yoctonear, + )) + } + None => Some(crate::types::near_allowance::NearAllowance::from_str( + "unlimited", + )?), + } + }, + contract_account_id: Some(receiver_id.parse()?), + function_names: Some(crate::types::vec_string::VecString(method_names)), access_key_mode: Some(add_key::CliAccessKeyMode::UseManuallyProvidedPublicKey( add_key::use_public_key::CliAddAccessKeyAction { public_key: Some(public_key.into()), diff --git a/src/js_command_match/add_key.rs b/src/js_command_match/add_key.rs index 49139f3d6..297527d05 100644 --- a/src/js_command_match/add_key.rs +++ b/src/js_command_match/add_key.rs @@ -28,9 +28,9 @@ impl AddKeyArgs { "grant-function-call-access".to_owned(), "--allowance".to_owned(), allowance, - "--receiver-account-id".to_owned(), + "--contract-account-id".to_owned(), contract_id.to_owned(), - "--method-names".to_owned(), + "--function-names".to_owned(), self.method_names.join(","), "use-manually-provided-public-key".to_owned(), self.access_key.to_owned(), From 38a794249603801fe4a5d1aa886adf00a26f5837 Mon Sep 17 00:00:00 2001 From: FroVolod Date: Sun, 30 Jun 2024 13:44:26 +0300 Subject: [PATCH 7/9] Update src/commands/transaction/construct_transaction/add_action_3/add_action/stake/mod.rs Co-authored-by: Vlad Frolov --- .../construct_transaction/add_action_3/add_action/stake/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/commands/transaction/construct_transaction/add_action_3/add_action/stake/mod.rs b/src/commands/transaction/construct_transaction/add_action_3/add_action/stake/mod.rs index b2abf7407..c3a69ed60 100644 --- a/src/commands/transaction/construct_transaction/add_action_3/add_action/stake/mod.rs +++ b/src/commands/transaction/construct_transaction/add_action_3/add_action/stake/mod.rs @@ -4,7 +4,7 @@ pub struct StakeAction { /// Enter the amount to stake: (example: 10000NEAR) stake_amount: crate::types::near_token::NearToken, - /// Validator key which will be used to sign transactions on behalf of signer_id: + /// Enter the public key of the validator key pair used on your NEAR node (see validator_key.json): public_key: crate::types::public_key::PublicKey, #[interactive_clap(subcommand)] next_action: super::super::super::add_action_last::NextAction, From 46aab2f00fbe8d9416b155aa8c0baad0a842ef3e Mon Sep 17 00:00:00 2001 From: FroVolod Date: Sun, 30 Jun 2024 13:49:18 +0300 Subject: [PATCH 8/9] fixed message --- .../construct_transaction/add_action_1/add_action/stake/mod.rs | 2 +- .../construct_transaction/add_action_2/add_action/stake/mod.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/commands/transaction/construct_transaction/add_action_1/add_action/stake/mod.rs b/src/commands/transaction/construct_transaction/add_action_1/add_action/stake/mod.rs index f9242cdb9..2dad4765e 100644 --- a/src/commands/transaction/construct_transaction/add_action_1/add_action/stake/mod.rs +++ b/src/commands/transaction/construct_transaction/add_action_1/add_action/stake/mod.rs @@ -4,7 +4,7 @@ pub struct StakeAction { /// Enter the amount to stake: (example: 10000NEAR) stake_amount: crate::types::near_token::NearToken, - /// Validator key which will be used to sign transactions on behalf of signer_id: + /// Enter the public key of the validator key pair used on your NEAR node (see validator_key.json): public_key: crate::types::public_key::PublicKey, #[interactive_clap(subcommand)] next_action: super::super::super::add_action_2::NextAction, diff --git a/src/commands/transaction/construct_transaction/add_action_2/add_action/stake/mod.rs b/src/commands/transaction/construct_transaction/add_action_2/add_action/stake/mod.rs index 370cc2d75..262f15e0e 100644 --- a/src/commands/transaction/construct_transaction/add_action_2/add_action/stake/mod.rs +++ b/src/commands/transaction/construct_transaction/add_action_2/add_action/stake/mod.rs @@ -4,7 +4,7 @@ pub struct StakeAction { /// Enter the amount to stake: (example: 10000NEAR) stake_amount: crate::types::near_token::NearToken, - /// Validator key which will be used to sign transactions on behalf of signer_id: + /// Enter the public key of the validator key pair used on your NEAR node (see validator_key.json): public_key: crate::types::public_key::PublicKey, #[interactive_clap(subcommand)] next_action: super::super::super::add_action_3::NextAction, From fd3f0e3838b2d5e2f6ee71ebdaf31c6a57b36021 Mon Sep 17 00:00:00 2001 From: FroVolod Date: Sun, 30 Jun 2024 20:46:02 +0300 Subject: [PATCH 9/9] refactored BeneficiaryAccount --- src/commands/account/delete_account/mod.rs | 6 ++++++ .../add_action_1/add_action/delete_account/mod.rs | 6 ++++++ .../add_action_2/add_action/delete_account/mod.rs | 6 ++++++ .../add_action_3/add_action/delete_account/mod.rs | 6 ++++++ 4 files changed, 24 insertions(+) diff --git a/src/commands/account/delete_account/mod.rs b/src/commands/account/delete_account/mod.rs index fca14041a..30b43d53c 100644 --- a/src/commands/account/delete_account/mod.rs +++ b/src/commands/account/delete_account/mod.rs @@ -1,3 +1,4 @@ +use color_eyre::owo_colors::OwoColorize; use inquire::Select; #[derive(Debug, Clone, interactive_clap::InteractiveClap)] @@ -124,6 +125,11 @@ impl BeneficiaryAccount { return Ok(None); }; + if beneficiary_account_id.0 == context.account_id { + eprintln!("{}", "You have selected a beneficiary account ID that will now be deleted. This will result in the loss of your funds. So make your choice again.".red()); + continue; + } + if context.global_context.offline { return Ok(Some(beneficiary_account_id)); } diff --git a/src/commands/transaction/construct_transaction/add_action_1/add_action/delete_account/mod.rs b/src/commands/transaction/construct_transaction/add_action_1/add_action/delete_account/mod.rs index 2fb6b9578..1d0c04fe2 100644 --- a/src/commands/transaction/construct_transaction/add_action_1/add_action/delete_account/mod.rs +++ b/src/commands/transaction/construct_transaction/add_action_1/add_action/delete_account/mod.rs @@ -1,3 +1,4 @@ +use color_eyre::owo_colors::OwoColorize; use inquire::Select; #[derive(Debug, Clone, interactive_clap::InteractiveClap)] @@ -56,6 +57,11 @@ impl DeleteAccountAction { return Ok(None); }; + if beneficiary_account_id.0 == context.signer_account_id { + eprintln!("{}", "You have selected a beneficiary account ID that will now be deleted. This will result in the loss of your funds. So make your choice again.".red()); + continue; + } + if context.global_context.offline { return Ok(Some(beneficiary_account_id)); } diff --git a/src/commands/transaction/construct_transaction/add_action_2/add_action/delete_account/mod.rs b/src/commands/transaction/construct_transaction/add_action_2/add_action/delete_account/mod.rs index 4655d4c34..9b7977704 100644 --- a/src/commands/transaction/construct_transaction/add_action_2/add_action/delete_account/mod.rs +++ b/src/commands/transaction/construct_transaction/add_action_2/add_action/delete_account/mod.rs @@ -1,3 +1,4 @@ +use color_eyre::owo_colors::OwoColorize; use inquire::Select; #[derive(Debug, Clone, interactive_clap::InteractiveClap)] @@ -56,6 +57,11 @@ impl DeleteAccountAction { return Ok(None); }; + if beneficiary_account_id.0 == context.signer_account_id { + eprintln!("{}", "You have selected a beneficiary account ID that will now be deleted. This will result in the loss of your funds. So make your choice again.".red()); + continue; + } + if context.global_context.offline { return Ok(Some(beneficiary_account_id)); } diff --git a/src/commands/transaction/construct_transaction/add_action_3/add_action/delete_account/mod.rs b/src/commands/transaction/construct_transaction/add_action_3/add_action/delete_account/mod.rs index 30122a090..556d13cf6 100644 --- a/src/commands/transaction/construct_transaction/add_action_3/add_action/delete_account/mod.rs +++ b/src/commands/transaction/construct_transaction/add_action_3/add_action/delete_account/mod.rs @@ -1,3 +1,4 @@ +use color_eyre::owo_colors::OwoColorize; use inquire::Select; #[derive(Debug, Clone, interactive_clap::InteractiveClap)] @@ -56,6 +57,11 @@ impl DeleteAccountAction { return Ok(None); }; + if beneficiary_account_id.0 == context.signer_account_id { + eprintln!("{}", "You have selected a beneficiary account ID that will now be deleted. This will result in the loss of your funds. So make your choice again.".red()); + continue; + } + if context.global_context.offline { return Ok(Some(beneficiary_account_id)); }