Transferring SOL
Creating an Account
use std::time::Duration; use anyhow::anyhow; use jsonrpsee::tracing::debug; use solana_program::system_program; use solana_sdk::{ account::Account, signature::{Keypair, Signer}, }; use tokio::time::sleep; use crate::{client::TestClient, SLEEP_DURATION_SECONDS}; /// Prepares a Solana transaction for a create_account instruction. /// Returns a base58-encoded string representation of the prepared transaction. pub fn prepare_new_account_transaction( payer: &Keypair, new_account: &Keypair, rent: u64, blockhash: Hash, ) -> Transaction { let instruction = system_instruction::create_account( &payer.pubkey(), &new_account.pubkey(), rent, 0, &system_program::id(), ); Transaction::new_signed_with_payer( &[instruction], Some(&payer.pubkey()), &[payer, new_account], blockhash, ) } pub(crate) async fn create_account( client: &TestClient, payer: &Keypair, new_account: &Keypair, amount: u64, ) -> anyhow::Result<()> { debug!("Create new account"); // Get initial balance let payer_initial_balance = client .svm_get_account_balance(payer.pubkey()) .await .map_err(|e| anyhow!("Failed to get payer's initial balance: {e}"))?; // Get latest blockhash let latest_blockhash = client .svm_get_latest_blockhash() .await .map_err(|e| anyhow!("Failed to retrieve the latest blockhash: {e}"))?; let create_acc_tx = prepare_new_account_transaction(payer, new_account, amount, latest_blockhash); let total_gas_fee_estimate = client .get_total_fee_for_transaction(&create_acc_tx) .await .map_err(|e| anyhow!("Failed to get total fee estimate for transaction: {e}"))?; let tx_hash = client .svm_send_transaction(&create_acc_tx) .await .map_err(|e| anyhow!("Failed to send a transaction: {e}"))? .to_string(); // Wait for transactions to process and persist changes sleep(Duration::from_secs(SLEEP_DURATION_SECONDS)).await; // Check accounts and balances // Check payer's post balance let payer_post_balance = client .svm_get_account_balance(payer.pubkey()) .await .map_err(|e| anyhow!("Failed to get payer's post balance: {e}"))?; let expected_balance = payer_initial_balance - amount - total_gas_fee_estimate; // Check new account's post balance let new_acc_balance = client .svm_get_account_balance(new_account.pubkey()) .await .map_err(|e| anyhow!("Failed to get new account's balance: {e}"))?; // Check new account's info let new_acc_info = client .svm_get_account_info(new_account.pubkey()) .await .map_err(|e| anyhow!("Failed to retrieve new account: {e}"))?; let new_acc_key = new_account.pubkey(); Ok(()) }
Transferring SOL
/// Prepares a Solana transaction for a transfer instruction. /// Returns a base58-encoded string representation of the prepared transaction. pub fn prepare_sol_transfer_transaction( payer: &Keypair, receiver: &Pubkey, lamports: u64, blockhash: Hash, ) -> Transaction { let instruction = system_instruction::transfer(&payer.pubkey(), receiver, lamports); Transaction::new_signed_with_payer(&[instruction], Some(&payer.pubkey()), &[payer], blockhash) } pub(crate) async fn transfer_sol( client: &TestClient, sender: &Keypair, receiver: &Keypair, amount: u64, ) -> anyhow::Result<()> { // Get initial balances let sender_initial_balance = client .svm_get_account_balance(sender.pubkey()) .await .map_err(|e| anyhow!("Failed to get sender's initial balance: {e}"))?; let receiver_initial_balance = client .svm_get_account_balance(receiver.pubkey()) .await .map_err(|e| anyhow!("Failed to get receiver's initial balance: {e}"))?; // Get latest blockhash let latest_blockhash = client .svm_get_latest_blockhash() .await .map_err(|e| anyhow!("Failed to retrieve the latest blockhash: {e}"))?; // Send and publish transaction let sol_transfer_tx = prepare_sol_transfer_transaction(sender, &receiver.pubkey(), amount, latest_blockhash); let total_gas_fee_estimate = client .get_total_fee_for_transaction(&sol_transfer_tx) .await .map_err(|e| anyhow!("Failed to get total fee estimate for transaction: {e}"))?; let tx_hash = client .svm_send_transaction(&sol_transfer_tx) .await .map_err(|e| anyhow!("Failed to send a transaction: {e}"))? .to_string(); // Wait for transactions to process and persist changes sleep(Duration::from_secs(SLEEP_DURATION_SECONDS)).await; // Check balances post transfer // Check sender's post balance let sender_post_balance = client .svm_get_account_balance(sender.pubkey()) .await .map_err(|e| anyhow!("Failed to get sender's post balance: {e}"))?; // Check receiver's post balance let receiver_post_balance = client .svm_get_account_balance(receiver.pubkey()) .await .map_err(|e| anyhow!("Failed to get receiver's post balance: {e}"))?; Ok(()) }
Last updated
Was this helpful?