solana transfer now requires --allow-unfunded-recipient if the recipient doesn't exist (bp #16060) (#16067)
* transfer now requires --allow-unfunded-recipient if the recipient doesn't exist (cherry picked from commit3dff5c9dee) * Avoid RPC in `--sign-only` mode Co-authored-by: Trent Nelson <trent.a.b.nelson@gmail.com> (cherry picked from commit6271665ba6) Co-authored-by: Michael Vines <mvines@gmail.com>
This commit is contained in:
		| @@ -360,6 +360,7 @@ pub enum CliCommand { | |||||||
|         from: SignerIndex, |         from: SignerIndex, | ||||||
|         sign_only: bool, |         sign_only: bool, | ||||||
|         dump_transaction_message: bool, |         dump_transaction_message: bool, | ||||||
|  |         allow_unfunded_recipient: bool, | ||||||
|         no_wait: bool, |         no_wait: bool, | ||||||
|         blockhash_query: BlockhashQuery, |         blockhash_query: BlockhashQuery, | ||||||
|         nonce_account: Option<Pubkey>, |         nonce_account: Option<Pubkey>, | ||||||
| @@ -865,6 +866,7 @@ pub fn parse_command( | |||||||
|             let (fee_payer, fee_payer_pubkey) = |             let (fee_payer, fee_payer_pubkey) = | ||||||
|                 signer_of(matches, FEE_PAYER_ARG.name, wallet_manager)?; |                 signer_of(matches, FEE_PAYER_ARG.name, wallet_manager)?; | ||||||
|             let (from, from_pubkey) = signer_of(matches, "from", wallet_manager)?; |             let (from, from_pubkey) = signer_of(matches, "from", wallet_manager)?; | ||||||
|  |             let allow_unfunded_recipient = matches.is_present("allow_unfunded_recipient"); | ||||||
|  |  | ||||||
|             let mut bulk_signers = vec![fee_payer, from]; |             let mut bulk_signers = vec![fee_payer, from]; | ||||||
|             if nonce_account.is_some() { |             if nonce_account.is_some() { | ||||||
| @@ -886,6 +888,7 @@ pub fn parse_command( | |||||||
|                     to, |                     to, | ||||||
|                     sign_only, |                     sign_only, | ||||||
|                     dump_transaction_message, |                     dump_transaction_message, | ||||||
|  |                     allow_unfunded_recipient, | ||||||
|                     no_wait, |                     no_wait, | ||||||
|                     blockhash_query, |                     blockhash_query, | ||||||
|                     nonce_account, |                     nonce_account, | ||||||
| @@ -1139,6 +1142,7 @@ fn process_transfer( | |||||||
|     from: SignerIndex, |     from: SignerIndex, | ||||||
|     sign_only: bool, |     sign_only: bool, | ||||||
|     dump_transaction_message: bool, |     dump_transaction_message: bool, | ||||||
|  |     allow_unfunded_recipient: bool, | ||||||
|     no_wait: bool, |     no_wait: bool, | ||||||
|     blockhash_query: &BlockhashQuery, |     blockhash_query: &BlockhashQuery, | ||||||
|     nonce_account: Option<&Pubkey>, |     nonce_account: Option<&Pubkey>, | ||||||
| @@ -1153,6 +1157,21 @@ fn process_transfer( | |||||||
|     let (recent_blockhash, fee_calculator) = |     let (recent_blockhash, fee_calculator) = | ||||||
|         blockhash_query.get_blockhash_and_fee_calculator(rpc_client, config.commitment)?; |         blockhash_query.get_blockhash_and_fee_calculator(rpc_client, config.commitment)?; | ||||||
|  |  | ||||||
|  |     if !sign_only && !allow_unfunded_recipient { | ||||||
|  |         let recipient_balance = rpc_client | ||||||
|  |             .get_balance_with_commitment(to, config.commitment)? | ||||||
|  |             .value; | ||||||
|  |         if recipient_balance == 0 { | ||||||
|  |             return Err(format!( | ||||||
|  |                 "The recipient address ({}) is not funded. \ | ||||||
|  |                                 Add `--allow-unfunded-recipient` to complete the transfer \ | ||||||
|  |                                ", | ||||||
|  |                 to | ||||||
|  |             ) | ||||||
|  |             .into()); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|     let nonce_authority = config.signers[nonce_authority]; |     let nonce_authority = config.signers[nonce_authority]; | ||||||
|     let fee_payer = config.signers[fee_payer]; |     let fee_payer = config.signers[fee_payer]; | ||||||
|  |  | ||||||
| @@ -1822,6 +1841,7 @@ pub fn process_command(config: &CliConfig) -> ProcessResult { | |||||||
|             from, |             from, | ||||||
|             sign_only, |             sign_only, | ||||||
|             dump_transaction_message, |             dump_transaction_message, | ||||||
|  |             allow_unfunded_recipient, | ||||||
|             no_wait, |             no_wait, | ||||||
|             ref blockhash_query, |             ref blockhash_query, | ||||||
|             ref nonce_account, |             ref nonce_account, | ||||||
| @@ -1837,6 +1857,7 @@ pub fn process_command(config: &CliConfig) -> ProcessResult { | |||||||
|             *from, |             *from, | ||||||
|             *sign_only, |             *sign_only, | ||||||
|             *dump_transaction_message, |             *dump_transaction_message, | ||||||
|  |             *allow_unfunded_recipient, | ||||||
|             *no_wait, |             *no_wait, | ||||||
|             blockhash_query, |             blockhash_query, | ||||||
|             nonce_account.as_ref(), |             nonce_account.as_ref(), | ||||||
| @@ -2205,6 +2226,12 @@ pub fn app<'ab, 'v>(name: &str, about: &'ab str, version: &'v str) -> App<'ab, ' | |||||||
|                         .requires("derived_address_seed") |                         .requires("derived_address_seed") | ||||||
|                         .hidden(true) |                         .hidden(true) | ||||||
|                 ) |                 ) | ||||||
|  |                 .arg( | ||||||
|  |                     Arg::with_name("allow_unfunded_recipient") | ||||||
|  |                         .long("allow-unfunded-recipient") | ||||||
|  |                         .takes_value(false) | ||||||
|  |                         .help("Complete the transfer even if the recipient address is not funded") | ||||||
|  |                 ) | ||||||
|                 .offline_args() |                 .offline_args() | ||||||
|                 .nonce_args(false) |                 .nonce_args(false) | ||||||
|                 .arg(fee_payer_arg()), |                 .arg(fee_payer_arg()), | ||||||
| @@ -2908,6 +2935,7 @@ mod tests { | |||||||
|                     from: 0, |                     from: 0, | ||||||
|                     sign_only: false, |                     sign_only: false, | ||||||
|                     dump_transaction_message: false, |                     dump_transaction_message: false, | ||||||
|  |                     allow_unfunded_recipient: false, | ||||||
|                     no_wait: false, |                     no_wait: false, | ||||||
|                     blockhash_query: BlockhashQuery::All(blockhash_query::Source::Cluster), |                     blockhash_query: BlockhashQuery::All(blockhash_query::Source::Cluster), | ||||||
|                     nonce_account: None, |                     nonce_account: None, | ||||||
| @@ -2933,6 +2961,7 @@ mod tests { | |||||||
|                     from: 0, |                     from: 0, | ||||||
|                     sign_only: false, |                     sign_only: false, | ||||||
|                     dump_transaction_message: false, |                     dump_transaction_message: false, | ||||||
|  |                     allow_unfunded_recipient: false, | ||||||
|                     no_wait: false, |                     no_wait: false, | ||||||
|                     blockhash_query: BlockhashQuery::All(blockhash_query::Source::Cluster), |                     blockhash_query: BlockhashQuery::All(blockhash_query::Source::Cluster), | ||||||
|                     nonce_account: None, |                     nonce_account: None, | ||||||
| @@ -2945,11 +2974,12 @@ mod tests { | |||||||
|             } |             } | ||||||
|         ); |         ); | ||||||
|  |  | ||||||
|         // Test Transfer no-wait |         // Test Transfer no-wait and --allow-unfunded-recipient | ||||||
|         let test_transfer = test_commands.clone().get_matches_from(vec![ |         let test_transfer = test_commands.clone().get_matches_from(vec![ | ||||||
|             "test", |             "test", | ||||||
|             "transfer", |             "transfer", | ||||||
|             "--no-wait", |             "--no-wait", | ||||||
|  |             "--allow-unfunded-recipient", | ||||||
|             &to_string, |             &to_string, | ||||||
|             "42", |             "42", | ||||||
|         ]); |         ]); | ||||||
| @@ -2962,6 +2992,7 @@ mod tests { | |||||||
|                     from: 0, |                     from: 0, | ||||||
|                     sign_only: false, |                     sign_only: false, | ||||||
|                     dump_transaction_message: false, |                     dump_transaction_message: false, | ||||||
|  |                     allow_unfunded_recipient: true, | ||||||
|                     no_wait: true, |                     no_wait: true, | ||||||
|                     blockhash_query: BlockhashQuery::All(blockhash_query::Source::Cluster), |                     blockhash_query: BlockhashQuery::All(blockhash_query::Source::Cluster), | ||||||
|                     nonce_account: None, |                     nonce_account: None, | ||||||
| @@ -2995,6 +3026,7 @@ mod tests { | |||||||
|                     from: 0, |                     from: 0, | ||||||
|                     sign_only: true, |                     sign_only: true, | ||||||
|                     dump_transaction_message: false, |                     dump_transaction_message: false, | ||||||
|  |                     allow_unfunded_recipient: false, | ||||||
|                     no_wait: false, |                     no_wait: false, | ||||||
|                     blockhash_query: BlockhashQuery::None(blockhash), |                     blockhash_query: BlockhashQuery::None(blockhash), | ||||||
|                     nonce_account: None, |                     nonce_account: None, | ||||||
| @@ -3033,6 +3065,7 @@ mod tests { | |||||||
|                     from: 0, |                     from: 0, | ||||||
|                     sign_only: false, |                     sign_only: false, | ||||||
|                     dump_transaction_message: false, |                     dump_transaction_message: false, | ||||||
|  |                     allow_unfunded_recipient: false, | ||||||
|                     no_wait: false, |                     no_wait: false, | ||||||
|                     blockhash_query: BlockhashQuery::FeeCalculator( |                     blockhash_query: BlockhashQuery::FeeCalculator( | ||||||
|                         blockhash_query::Source::Cluster, |                         blockhash_query::Source::Cluster, | ||||||
| @@ -3075,6 +3108,7 @@ mod tests { | |||||||
|                     from: 0, |                     from: 0, | ||||||
|                     sign_only: false, |                     sign_only: false, | ||||||
|                     dump_transaction_message: false, |                     dump_transaction_message: false, | ||||||
|  |                     allow_unfunded_recipient: false, | ||||||
|                     no_wait: false, |                     no_wait: false, | ||||||
|                     blockhash_query: BlockhashQuery::FeeCalculator( |                     blockhash_query: BlockhashQuery::FeeCalculator( | ||||||
|                         blockhash_query::Source::NonceAccount(nonce_address), |                         blockhash_query::Source::NonceAccount(nonce_address), | ||||||
| @@ -3115,6 +3149,7 @@ mod tests { | |||||||
|                     from: 0, |                     from: 0, | ||||||
|                     sign_only: false, |                     sign_only: false, | ||||||
|                     dump_transaction_message: false, |                     dump_transaction_message: false, | ||||||
|  |                     allow_unfunded_recipient: false, | ||||||
|                     no_wait: false, |                     no_wait: false, | ||||||
|                     blockhash_query: BlockhashQuery::All(blockhash_query::Source::Cluster), |                     blockhash_query: BlockhashQuery::All(blockhash_query::Source::Cluster), | ||||||
|                     nonce_account: None, |                     nonce_account: None, | ||||||
|   | |||||||
| @@ -294,6 +294,7 @@ fn test_create_account_with_seed() { | |||||||
|         from: 0, |         from: 0, | ||||||
|         sign_only: true, |         sign_only: true, | ||||||
|         dump_transaction_message: true, |         dump_transaction_message: true, | ||||||
|  |         allow_unfunded_recipient: true, | ||||||
|         no_wait: false, |         no_wait: false, | ||||||
|         blockhash_query: BlockhashQuery::None(nonce_hash), |         blockhash_query: BlockhashQuery::None(nonce_hash), | ||||||
|         nonce_account: Some(nonce_address), |         nonce_account: Some(nonce_address), | ||||||
| @@ -318,6 +319,7 @@ fn test_create_account_with_seed() { | |||||||
|         from: 0, |         from: 0, | ||||||
|         sign_only: false, |         sign_only: false, | ||||||
|         dump_transaction_message: true, |         dump_transaction_message: true, | ||||||
|  |         allow_unfunded_recipient: true, | ||||||
|         no_wait: false, |         no_wait: false, | ||||||
|         blockhash_query: BlockhashQuery::FeeCalculator( |         blockhash_query: BlockhashQuery::FeeCalculator( | ||||||
|             blockhash_query::Source::NonceAccount(nonce_address), |             blockhash_query::Source::NonceAccount(nonce_address), | ||||||
|   | |||||||
| @@ -52,6 +52,7 @@ fn test_transfer() { | |||||||
|         from: 0, |         from: 0, | ||||||
|         sign_only: false, |         sign_only: false, | ||||||
|         dump_transaction_message: false, |         dump_transaction_message: false, | ||||||
|  |         allow_unfunded_recipient: true, | ||||||
|         no_wait: false, |         no_wait: false, | ||||||
|         blockhash_query: BlockhashQuery::All(blockhash_query::Source::Cluster), |         blockhash_query: BlockhashQuery::All(blockhash_query::Source::Cluster), | ||||||
|         nonce_account: None, |         nonce_account: None, | ||||||
| @@ -71,6 +72,7 @@ fn test_transfer() { | |||||||
|         from: 0, |         from: 0, | ||||||
|         sign_only: false, |         sign_only: false, | ||||||
|         dump_transaction_message: false, |         dump_transaction_message: false, | ||||||
|  |         allow_unfunded_recipient: true, | ||||||
|         no_wait: false, |         no_wait: false, | ||||||
|         blockhash_query: BlockhashQuery::All(blockhash_query::Source::Cluster), |         blockhash_query: BlockhashQuery::All(blockhash_query::Source::Cluster), | ||||||
|         nonce_account: None, |         nonce_account: None, | ||||||
| @@ -102,6 +104,7 @@ fn test_transfer() { | |||||||
|         from: 0, |         from: 0, | ||||||
|         sign_only: true, |         sign_only: true, | ||||||
|         dump_transaction_message: false, |         dump_transaction_message: false, | ||||||
|  |         allow_unfunded_recipient: true, | ||||||
|         no_wait: false, |         no_wait: false, | ||||||
|         blockhash_query: BlockhashQuery::None(blockhash), |         blockhash_query: BlockhashQuery::None(blockhash), | ||||||
|         nonce_account: None, |         nonce_account: None, | ||||||
| @@ -122,6 +125,7 @@ fn test_transfer() { | |||||||
|         from: 0, |         from: 0, | ||||||
|         sign_only: false, |         sign_only: false, | ||||||
|         dump_transaction_message: false, |         dump_transaction_message: false, | ||||||
|  |         allow_unfunded_recipient: true, | ||||||
|         no_wait: false, |         no_wait: false, | ||||||
|         blockhash_query: BlockhashQuery::FeeCalculator(blockhash_query::Source::Cluster, blockhash), |         blockhash_query: BlockhashQuery::FeeCalculator(blockhash_query::Source::Cluster, blockhash), | ||||||
|         nonce_account: None, |         nonce_account: None, | ||||||
| @@ -167,6 +171,7 @@ fn test_transfer() { | |||||||
|         from: 0, |         from: 0, | ||||||
|         sign_only: false, |         sign_only: false, | ||||||
|         dump_transaction_message: false, |         dump_transaction_message: false, | ||||||
|  |         allow_unfunded_recipient: true, | ||||||
|         no_wait: false, |         no_wait: false, | ||||||
|         blockhash_query: BlockhashQuery::FeeCalculator( |         blockhash_query: BlockhashQuery::FeeCalculator( | ||||||
|             blockhash_query::Source::NonceAccount(nonce_account.pubkey()), |             blockhash_query::Source::NonceAccount(nonce_account.pubkey()), | ||||||
| @@ -219,6 +224,7 @@ fn test_transfer() { | |||||||
|         from: 0, |         from: 0, | ||||||
|         sign_only: true, |         sign_only: true, | ||||||
|         dump_transaction_message: false, |         dump_transaction_message: false, | ||||||
|  |         allow_unfunded_recipient: true, | ||||||
|         no_wait: false, |         no_wait: false, | ||||||
|         blockhash_query: BlockhashQuery::None(nonce_hash), |         blockhash_query: BlockhashQuery::None(nonce_hash), | ||||||
|         nonce_account: Some(nonce_account.pubkey()), |         nonce_account: Some(nonce_account.pubkey()), | ||||||
| @@ -238,6 +244,7 @@ fn test_transfer() { | |||||||
|         from: 0, |         from: 0, | ||||||
|         sign_only: false, |         sign_only: false, | ||||||
|         dump_transaction_message: false, |         dump_transaction_message: false, | ||||||
|  |         allow_unfunded_recipient: true, | ||||||
|         no_wait: false, |         no_wait: false, | ||||||
|         blockhash_query: BlockhashQuery::FeeCalculator( |         blockhash_query: BlockhashQuery::FeeCalculator( | ||||||
|             blockhash_query::Source::NonceAccount(nonce_account.pubkey()), |             blockhash_query::Source::NonceAccount(nonce_account.pubkey()), | ||||||
| @@ -307,6 +314,7 @@ fn test_transfer_multisession_signing() { | |||||||
|         from: 1, |         from: 1, | ||||||
|         sign_only: true, |         sign_only: true, | ||||||
|         dump_transaction_message: false, |         dump_transaction_message: false, | ||||||
|  |         allow_unfunded_recipient: true, | ||||||
|         no_wait: false, |         no_wait: false, | ||||||
|         blockhash_query: BlockhashQuery::None(blockhash), |         blockhash_query: BlockhashQuery::None(blockhash), | ||||||
|         nonce_account: None, |         nonce_account: None, | ||||||
| @@ -336,6 +344,7 @@ fn test_transfer_multisession_signing() { | |||||||
|         from: 1, |         from: 1, | ||||||
|         sign_only: true, |         sign_only: true, | ||||||
|         dump_transaction_message: false, |         dump_transaction_message: false, | ||||||
|  |         allow_unfunded_recipient: true, | ||||||
|         no_wait: false, |         no_wait: false, | ||||||
|         blockhash_query: BlockhashQuery::None(blockhash), |         blockhash_query: BlockhashQuery::None(blockhash), | ||||||
|         nonce_account: None, |         nonce_account: None, | ||||||
| @@ -362,6 +371,7 @@ fn test_transfer_multisession_signing() { | |||||||
|         from: 1, |         from: 1, | ||||||
|         sign_only: false, |         sign_only: false, | ||||||
|         dump_transaction_message: false, |         dump_transaction_message: false, | ||||||
|  |         allow_unfunded_recipient: true, | ||||||
|         no_wait: false, |         no_wait: false, | ||||||
|         blockhash_query: BlockhashQuery::FeeCalculator(blockhash_query::Source::Cluster, blockhash), |         blockhash_query: BlockhashQuery::FeeCalculator(blockhash_query::Source::Cluster, blockhash), | ||||||
|         nonce_account: None, |         nonce_account: None, | ||||||
| @@ -410,6 +420,7 @@ fn test_transfer_all() { | |||||||
|         from: 0, |         from: 0, | ||||||
|         sign_only: false, |         sign_only: false, | ||||||
|         dump_transaction_message: false, |         dump_transaction_message: false, | ||||||
|  |         allow_unfunded_recipient: true, | ||||||
|         no_wait: false, |         no_wait: false, | ||||||
|         blockhash_query: BlockhashQuery::All(blockhash_query::Source::Cluster), |         blockhash_query: BlockhashQuery::All(blockhash_query::Source::Cluster), | ||||||
|         nonce_account: None, |         nonce_account: None, | ||||||
| @@ -423,6 +434,53 @@ fn test_transfer_all() { | |||||||
|     check_recent_balance(49_999, &rpc_client, &recipient_pubkey); |     check_recent_balance(49_999, &rpc_client, &recipient_pubkey); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | #[test] | ||||||
|  | fn test_transfer_unfunded_recipient() { | ||||||
|  |     solana_logger::setup(); | ||||||
|  |     let mint_keypair = Keypair::new(); | ||||||
|  |     let test_validator = TestValidator::with_custom_fees(mint_keypair.pubkey(), 1); | ||||||
|  |     let faucet_addr = run_local_faucet(mint_keypair, None); | ||||||
|  |  | ||||||
|  |     let rpc_client = | ||||||
|  |         RpcClient::new_with_commitment(test_validator.rpc_url(), CommitmentConfig::processed()); | ||||||
|  |  | ||||||
|  |     let default_signer = Keypair::new(); | ||||||
|  |  | ||||||
|  |     let mut config = CliConfig::recent_for_tests(); | ||||||
|  |     config.json_rpc_url = test_validator.rpc_url(); | ||||||
|  |     config.signers = vec![&default_signer]; | ||||||
|  |  | ||||||
|  |     let sender_pubkey = config.signers[0].pubkey(); | ||||||
|  |     let recipient_pubkey = Pubkey::new(&[1u8; 32]); | ||||||
|  |  | ||||||
|  |     request_and_confirm_airdrop(&rpc_client, &faucet_addr, &sender_pubkey, 50_000, &config) | ||||||
|  |         .unwrap(); | ||||||
|  |     check_recent_balance(50_000, &rpc_client, &sender_pubkey); | ||||||
|  |     check_recent_balance(0, &rpc_client, &recipient_pubkey); | ||||||
|  |  | ||||||
|  |     check_ready(&rpc_client); | ||||||
|  |  | ||||||
|  |     // Plain ole transfer | ||||||
|  |     config.command = CliCommand::Transfer { | ||||||
|  |         amount: SpendAmount::All, | ||||||
|  |         to: recipient_pubkey, | ||||||
|  |         from: 0, | ||||||
|  |         sign_only: false, | ||||||
|  |         dump_transaction_message: false, | ||||||
|  |         allow_unfunded_recipient: false, | ||||||
|  |         no_wait: false, | ||||||
|  |         blockhash_query: BlockhashQuery::All(blockhash_query::Source::Cluster), | ||||||
|  |         nonce_account: None, | ||||||
|  |         nonce_authority: 0, | ||||||
|  |         fee_payer: 0, | ||||||
|  |         derived_address_seed: None, | ||||||
|  |         derived_address_program_id: None, | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     // Expect failure due to unfunded recipient and the lack of the `allow_unfunded_recipient` flag | ||||||
|  |     process_command(&config).unwrap_err(); | ||||||
|  | } | ||||||
|  |  | ||||||
| #[test] | #[test] | ||||||
| fn test_transfer_with_seed() { | fn test_transfer_with_seed() { | ||||||
|     solana_logger::setup(); |     solana_logger::setup(); | ||||||
| @@ -466,6 +524,7 @@ fn test_transfer_with_seed() { | |||||||
|         from: 0, |         from: 0, | ||||||
|         sign_only: false, |         sign_only: false, | ||||||
|         dump_transaction_message: false, |         dump_transaction_message: false, | ||||||
|  |         allow_unfunded_recipient: true, | ||||||
|         no_wait: false, |         no_wait: false, | ||||||
|         blockhash_query: BlockhashQuery::All(blockhash_query::Source::Cluster), |         blockhash_query: BlockhashQuery::All(blockhash_query::Source::Cluster), | ||||||
|         nonce_account: None, |         nonce_account: None, | ||||||
|   | |||||||
| @@ -72,6 +72,7 @@ fn test_vote_authorize_and_withdraw() { | |||||||
|         from: 0, |         from: 0, | ||||||
|         sign_only: false, |         sign_only: false, | ||||||
|         dump_transaction_message: false, |         dump_transaction_message: false, | ||||||
|  |         allow_unfunded_recipient: true, | ||||||
|         no_wait: false, |         no_wait: false, | ||||||
|         blockhash_query: BlockhashQuery::All(blockhash_query::Source::Cluster), |         blockhash_query: BlockhashQuery::All(blockhash_query::Source::Cluster), | ||||||
|         nonce_account: None, |         nonce_account: None, | ||||||
|   | |||||||
| @@ -71,7 +71,7 @@ with the private keypair corresponding to the sender's public key in the | |||||||
| transaction. | transaction. | ||||||
|  |  | ||||||
| ```bash | ```bash | ||||||
| solana transfer --from <KEYPAIR> <RECIPIENT_ACCOUNT_ADDRESS> 5 --url https://devnet.solana.com --fee-payer <KEYPAIR> | solana transfer --from <KEYPAIR> <RECIPIENT_ACCOUNT_ADDRESS> 5 --allow-unfunded-recipient --url https://devnet.solana.com --fee-payer <KEYPAIR> | ||||||
| ``` | ``` | ||||||
|  |  | ||||||
| where you replace `<KEYPAIR>` with the path to a keypair in your first wallet, | where you replace `<KEYPAIR>` with the path to a keypair in your first wallet, | ||||||
| @@ -118,7 +118,7 @@ Save this seed phrase to recover your new keypair: | |||||||
| clump panic cousin hurt coast charge engage fall eager urge win love   # If this was a real wallet, never share these words on the internet like this! | clump panic cousin hurt coast charge engage fall eager urge win love   # If this was a real wallet, never share these words on the internet like this! | ||||||
| ==================================================================== | ==================================================================== | ||||||
|  |  | ||||||
| $ solana transfer --from my_solana_wallet.json 7S3P4HxJpyyigGzodYwHtCxZyUQe9JiBMHyRWXArAaKv 5 --url https://devnet.solana.com --fee-payer my_solana_wallet.json  # Transferring tokens to the public address of the paper wallet | $ solana transfer --from my_solana_wallet.json 7S3P4HxJpyyigGzodYwHtCxZyUQe9JiBMHyRWXArAaKv 5 --allow-unfunded-recipient --url https://devnet.solana.com --fee-payer my_solana_wallet.json  # Transferring tokens to the public address of the paper wallet | ||||||
| 3gmXvykAd1nCQQ7MjosaHLf69Xyaqyq1qw2eu1mgPyYXd5G4v1rihhg1CiRw35b9fHzcftGKKEu4mbUeXY2pEX2z  # This is the transaction signature | 3gmXvykAd1nCQQ7MjosaHLf69Xyaqyq1qw2eu1mgPyYXd5G4v1rihhg1CiRw35b9fHzcftGKKEu4mbUeXY2pEX2z  # This is the transaction signature | ||||||
|  |  | ||||||
| $ solana balance DYw8jCTfwHNRJhhmFcbXvVDTqWMEVFBX6ZKUmG5CNSKK --url https://devnet.solana.com | $ solana balance DYw8jCTfwHNRJhhmFcbXvVDTqWMEVFBX6ZKUmG5CNSKK --url https://devnet.solana.com | ||||||
|   | |||||||
| @@ -388,7 +388,7 @@ will wait and track progress on stderr until the transaction has been finalized | |||||||
| by the cluster. If the transaction fails, it will report any transaction errors. | by the cluster. If the transaction fails, it will report any transaction errors. | ||||||
|  |  | ||||||
| ```bash | ```bash | ||||||
| solana transfer <USER_ADDRESS> <AMOUNT> --keypair <KEYPAIR> --url http://localhost:8899 | solana transfer <USER_ADDRESS> <AMOUNT> --allow-unfunded-recipient --keypair <KEYPAIR> --url http://localhost:8899 | ||||||
| ``` | ``` | ||||||
|  |  | ||||||
| The [Solana Javascript SDK](https://github.com/solana-labs/solana-web3.js) | The [Solana Javascript SDK](https://github.com/solana-labs/solana-web3.js) | ||||||
| @@ -420,7 +420,7 @@ In the command-line tool, pass the `--no-wait` argument to send a transfer | |||||||
| asynchronously, and include your recent blockhash with the `--blockhash` argument: | asynchronously, and include your recent blockhash with the `--blockhash` argument: | ||||||
|  |  | ||||||
| ```bash | ```bash | ||||||
| solana transfer <USER_ADDRESS> <AMOUNT> --no-wait --blockhash <RECENT_BLOCKHASH> --keypair <KEYPAIR> --url http://localhost:8899 | solana transfer <USER_ADDRESS> <AMOUNT> --no-wait --allow-unfunded-recipient --blockhash <RECENT_BLOCKHASH> --keypair <KEYPAIR> --url http://localhost:8899 | ||||||
| ``` | ``` | ||||||
|  |  | ||||||
| You can also build, sign, and serialize the transaction manually, and fire it off to | You can also build, sign, and serialize the transaction manually, and fire it off to | ||||||
|   | |||||||
| @@ -102,7 +102,9 @@ if ((airdrops_enabled)); then | |||||||
|     echo "--keypair argument must be provided" |     echo "--keypair argument must be provided" | ||||||
|     exit 1 |     exit 1 | ||||||
|   fi |   fi | ||||||
|   $solana_cli "${common_args[@]}" --keypair "$SOLANA_CONFIG_DIR/faucet.json" transfer "$keypair" "$stake_sol" |   $solana_cli \ | ||||||
|  |     "${common_args[@]}" --keypair "$SOLANA_CONFIG_DIR/faucet.json" \ | ||||||
|  |     transfer --allow-unfunded-recipient "$keypair" "$stake_sol" | ||||||
| fi | fi | ||||||
|  |  | ||||||
| if [[ -n $keypair ]]; then | if [[ -n $keypair ]]; then | ||||||
|   | |||||||
| @@ -274,7 +274,9 @@ setup_validator_accounts() { | |||||||
|       echo "Adding $node_sol to validator identity account:" |       echo "Adding $node_sol to validator identity account:" | ||||||
|       ( |       ( | ||||||
|         set -x |         set -x | ||||||
|         $solana_cli --keypair "$SOLANA_CONFIG_DIR/faucet.json" --url "$rpc_url" transfer "$identity" "$node_sol" |         $solana_cli \ | ||||||
|  |           --keypair "$SOLANA_CONFIG_DIR/faucet.json" --url "$rpc_url" \ | ||||||
|  |           transfer --allow-unfunded-recipient "$identity" "$node_sol" | ||||||
|       ) || return $? |       ) || return $? | ||||||
|     fi |     fi | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user