Add --allow-empty-recipient to `transfer` command

This commit is contained in:
Michael Vines 2021-02-22 10:38:45 -08:00
parent 76ecbd6bfe
commit a782f3e52f
1 changed files with 62 additions and 54 deletions

View File

@ -413,11 +413,13 @@ fn resolve_mint_info(
} }
} }
#[allow(clippy::too_many_arguments)]
fn command_transfer( fn command_transfer(
config: &Config, config: &Config,
sender: Pubkey, sender: Pubkey,
ui_amount: Option<f64>, ui_amount: Option<f64>,
recipient: Pubkey, recipient: Pubkey,
allow_empty_recipient: bool,
fund_recipient: bool, fund_recipient: bool,
mint_address: Option<Pubkey>, mint_address: Option<Pubkey>,
mint_decimals: Option<u8>, mint_decimals: Option<u8>,
@ -453,67 +455,65 @@ fn command_transfer(
let mut recipient_token_account = recipient; let mut recipient_token_account = recipient;
let mut minimum_balance_for_rent_exemption = 0; let mut minimum_balance_for_rent_exemption = 0;
if let Some(account_data) = config let recipient_account_owner = config
.rpc_client .rpc_client
.get_account_with_commitment(&recipient, config.rpc_client.commitment())? .get_account_with_commitment(&recipient, config.rpc_client.commitment())?
.value .value
{ .map(|account_data| account_data.owner);
if account_data.owner == system_program::id() {
recipient_token_account = get_associated_token_address(&recipient, &mint_pubkey);
println!(
" Recipient associated token account: {}",
recipient_token_account
);
let needs_funding = if let Some(recipient_token_account_data) = config if recipient_account_owner.is_none() && !allow_empty_recipient {
.rpc_client return Err("Error: The recipient has no balance. \
.get_account_with_commitment( Add `--allow-empty-recipient` to complete the transfer \
&recipient_token_account, "
config.rpc_client.commitment(), .into());
)? }
.value
{ if Some(spl_token::id()) != recipient_account_owner {
if recipient_token_account_data.owner == system_program::id() { recipient_token_account = get_associated_token_address(&recipient, &mint_pubkey);
true println!(
} else if recipient_token_account_data.owner == spl_token::id() { " Recipient associated token account: {}",
false recipient_token_account
} else { );
return Err(
format!("Error: Unsupported recipient address: {}", recipient).into(), let needs_funding = if let Some(recipient_token_account_data) = config
); .rpc_client
} .get_account_with_commitment(&recipient_token_account, config.rpc_client.commitment())?
} else { .value
{
if recipient_token_account_data.owner == system_program::id() {
true true
}; } else if recipient_token_account_data.owner == spl_token::id() {
false
if needs_funding { } else {
if fund_recipient { return Err(format!("Error: Unsupported recipient address: {}", recipient).into());
minimum_balance_for_rent_exemption += config }
.rpc_client } else {
.get_minimum_balance_for_rent_exemption(Account::LEN)?; true
println!( };
" Funding recipient: {} ({} SOL)",
recipient_token_account, if needs_funding {
lamports_to_sol(minimum_balance_for_rent_exemption) if fund_recipient {
); minimum_balance_for_rent_exemption += config
instructions.push(create_associated_token_account( .rpc_client
&config.fee_payer, .get_minimum_balance_for_rent_exemption(Account::LEN)?;
&recipient, println!(
&mint_pubkey, " Funding recipient: {} ({} SOL)",
)); recipient_token_account,
} else { lamports_to_sol(minimum_balance_for_rent_exemption)
return Err( );
"Error: Recipient's associated token account does not exist. \ instructions.push(create_associated_token_account(
Add `--fund-recipient` to fund their account" &config.fee_payer,
.into(), &recipient,
); &mint_pubkey,
} ));
} else {
return Err(
"Error: Recipient's associated token account does not exist. \
Add `--fund-recipient` to fund their account"
.into(),
);
} }
} else if account_data.owner != spl_token::id() {
return Err(format!("Error: Unsupported recipient address: {}", recipient).into());
} }
} else {
return Err(format!("Error: Recipient does not exist: {}", recipient).into());
} }
instructions.push(transfer_checked( instructions.push(transfer_checked(
@ -1291,6 +1291,12 @@ fn main() {
Otherwise assume the recipient address is a user wallet and transfer to \ Otherwise assume the recipient address is a user wallet and transfer to \
the associated token account") the associated token account")
) )
.arg(
Arg::with_name("allow_empty_recipient")
.long("allow-empty-recipient")
.takes_value(false)
.help("Complete the transfer even if the recipient account does not exist")
)
.arg( .arg(
Arg::with_name("fund_recipient") Arg::with_name("fund_recipient")
.long("fund-recipient") .long("fund-recipient")
@ -1801,11 +1807,13 @@ fn main() {
pubkey_of_signer(arg_matches, MINT_ADDRESS_ARG.name, &mut wallet_manager).unwrap(); pubkey_of_signer(arg_matches, MINT_ADDRESS_ARG.name, &mut wallet_manager).unwrap();
let mint_decimals = value_of::<u8>(&arg_matches, MINT_DECIMALS_ARG.name); let mint_decimals = value_of::<u8>(&arg_matches, MINT_DECIMALS_ARG.name);
let fund_recipient = matches.is_present("fund_recipient"); let fund_recipient = matches.is_present("fund_recipient");
let allow_empty_recipient = matches.is_present("allow_empty_recipient");
command_transfer( command_transfer(
&config, &config,
sender, sender,
amount, amount,
recipient, recipient,
allow_empty_recipient,
fund_recipient, fund_recipient,
mint_address, mint_address,
mint_decimals, mint_decimals,