use inquire::Select;
#[derive(Debug, Clone, interactive_clap::InteractiveClap)]
#[interactive_clap(input_context = crate::GlobalContext)]
#[interactive_clap(output_context = DeleteAccountContext)]
pub struct DeleteAccount {
#[interactive_clap(skip_default_input_arg)]
account_id: crate::types::account_id::AccountId,
#[interactive_clap(named_arg)]
beneficiary: BeneficiaryAccount,
}
#[derive(Debug, Clone)]
pub struct DeleteAccountContext {
global_context: crate::GlobalContext,
account_id: unc_primitives::types::AccountId,
}
impl DeleteAccountContext {
pub fn from_previous_context(
previous_context: crate::GlobalContext,
scope: &<DeleteAccount as interactive_clap::ToInteractiveClapContextScope>::InteractiveClapContextScope,
) -> color_eyre::eyre::Result<Self> {
Ok(Self {
global_context: previous_context,
account_id: scope.account_id.clone().into(),
})
}
}
impl DeleteAccount {
pub fn input_account_id(
context: &crate::GlobalContext,
) -> color_eyre::eyre::Result<Option<crate::types::account_id::AccountId>> {
crate::common::input_signer_account_id_from_used_account_list(
&context.config.credentials_home_dir,
"What Account ID to be deleted?",
)
}
}
#[derive(Debug, Clone, interactive_clap::InteractiveClap)]
#[interactive_clap(input_context = DeleteAccountContext)]
#[interactive_clap(output_context = BeneficiaryAccountContext)]
pub struct BeneficiaryAccount {
#[interactive_clap(skip_default_input_arg)]
beneficiary_account_id: crate::types::account_id::AccountId,
#[interactive_clap(named_arg)]
network_config: crate::network_for_transaction::NetworkForTransactionArgs,
}
#[derive(Debug, Clone)]
pub struct BeneficiaryAccountContext {
global_context: crate::GlobalContext,
account_id: unc_primitives::types::AccountId,
beneficiary_account_id: unc_primitives::types::AccountId,
}
impl BeneficiaryAccountContext {
pub fn from_previous_context(
previous_context: DeleteAccountContext,
scope: &<BeneficiaryAccount as interactive_clap::ToInteractiveClapContextScope>::InteractiveClapContextScope,
) -> color_eyre::eyre::Result<Self> {
Ok(Self {
global_context: previous_context.global_context,
account_id: previous_context.account_id,
beneficiary_account_id: scope.beneficiary_account_id.clone().into(),
})
}
}
impl From<BeneficiaryAccountContext> for crate::commands::ActionContext {
fn from(item: BeneficiaryAccountContext) -> Self {
let on_after_getting_network_callback: crate::commands::OnAfterGettingNetworkCallback =
std::sync::Arc::new({
let account_id = item.account_id.clone();
move |_network_config| {
Ok(crate::commands::PrepopulatedTransaction {
signer_id: account_id.clone(),
receiver_id: account_id.clone(),
actions: vec![unc_primitives::transaction::Action::DeleteAccount(
unc_primitives::transaction::DeleteAccountAction {
beneficiary_id: item.beneficiary_account_id.clone(),
},
)],
})
}
});
Self {
global_context: item.global_context,
interacting_with_account_ids: vec![item.account_id],
on_after_getting_network_callback,
on_before_signing_callback: std::sync::Arc::new(
|_prepolulated_unsinged_transaction, _network_config| Ok(()),
),
on_before_sending_transaction_callback: std::sync::Arc::new(
|_signed_transaction, _network_config, _message| Ok(()),
),
on_after_sending_transaction_callback: std::sync::Arc::new(
|_outcome_view, _network_config| Ok(()),
),
}
}
}
impl BeneficiaryAccount {
pub fn input_beneficiary_account_id(
context: &DeleteAccountContext,
) -> color_eyre::eyre::Result<Option<crate::types::account_id::AccountId>> {
loop {
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));
}
#[derive(derive_more::Display)]
enum ConfirmOptions {
#[display(
fmt = "Yes, I want to check if account <{}> exists. (It is free of charge, and only requires Internet access)",
account_id
)]
Yes {
account_id: crate::types::account_id::AccountId,
},
#[display(fmt = "No, I know this account exists and want to continue.")]
No,
}
let select_choose_input =
Select::new("\nDo you want to check the existence of the specified account so that you don't lose tokens?",
vec![ConfirmOptions::Yes{account_id: beneficiary_account_id.clone()}, ConfirmOptions::No],
)
.prompt()?;
if let ConfirmOptions::Yes { account_id } = select_choose_input {
if crate::common::find_network_where_account_exist(
&context.global_context,
account_id.clone().into(),
)
.is_none()
{
eprintln!("\nHeads up! You will lose remaining unc tokens on the account you delete if you specify the account <{}> as the beneficiary as it does not exist on [{}] networks.",
account_id,
context.global_context.config.network_names().join(", ")
);
if !crate::common::ask_if_different_account_id_wanted()? {
return Ok(Some(account_id));
}
} else {
return Ok(Some(account_id));
};
} else {
return Ok(Some(beneficiary_account_id));
};
}
}
}