### Install Rust Toolchain and Components Source: https://github.com/anza-xyz/solana-sdk/blob/master/README.md Installs rustc, cargo, and rustfmt using the official Rust installation script and sets up the environment. ```console curl https://sh.rustup.rs -sSf | sh source $HOME/.cargo/env rustup component add rustfmt ``` -------------------------------- ### Example: Fetching and Using Recent Blockhash Source: https://github.com/anza-xyz/solana-sdk/blob/master/_autodocs/api-reference/hash.md Illustrates fetching the latest blockhash from an RPC client and then parsing a hardcoded string into a Hash. This example shows practical usage in a client application. ```rust use solana_hash::Hash; use solana_rpc_client::rpc_client::RpcClient; use std::str::FromStr; let client = RpcClient::new("http://localhost:8899".to_string()); // Get recent blockhash from RPC let (blockhash, last_valid_block_height) = client.get_latest_blockhash()?; println!("Recent blockhash: {}", blockhash); // Parse from string let parsed: Hash = "11111111111111111111111111111111".parse()?; // Use in transaction let recent_blockhash = blockhash; ``` -------------------------------- ### Install Nightly Rust Toolchain for Testing Source: https://github.com/anza-xyz/solana-sdk/blob/master/README.md Installs the nightly Rust toolchain and necessary components like `llvm-tools-preview` for advanced testing features. ```console ./cargo nightly tree ``` ```console rustup component add llvm-tools-preview --toolchain= ``` -------------------------------- ### Transfer Lamports Example Source: https://github.com/anza-xyz/solana-sdk/blob/master/_autodocs/api-reference/account-info.md Demonstrates how to transfer lamports between two accounts using mutable borrows of their lamports. Ensure sufficient balance before transfer. ```rust use solana_account_info::AccountInfo; pub fn transfer_lamports( from: &AccountInfo, to: &AccountInfo, amount: u64, ) -> Result<(), solana_program_error::ProgramError> { // Reduce source lamports let mut from_lamports = from.try_borrow_mut_lamports()?; **from_lamports = from_lamports.saturating_sub(amount); // Increase destination lamports let mut to_lamports = to.try_borrow_mut_lamports()?; **to_lamports += amount; Ok(()) } ``` -------------------------------- ### EpochInfo JSON Serialization Example Source: https://github.com/anza-xyz/solana-sdk/blob/master/_autodocs/api-reference/epoch-info.md Demonstrates the JSON structure of an EpochInfo object, as produced by serde. ```json { "epoch": 500, "slotIndex": 150000, "slotsInEpoch": 432000, "absoluteSlot": 216000000, "blockHeight": 215800000, "transactionCount": 50000000000 } ``` -------------------------------- ### Complete Signing and Verification Example Source: https://github.com/anza-xyz/solana-sdk/blob/master/_autodocs/api-reference/signature.md Demonstrates the complete process of creating a keypair, signing a message, converting the signature to a base58 string and back, and finally verifying the signature using both standard and strict methods. ```APIDOC ## Example: Complete Signing and Verification This example showcases the end-to-end usage of the `Signature` type within the Solana SDK. ### Usage 1. **Keypair Creation**: Instantiate a new `Keypair` to obtain a public key and a private key. 2. **Message Signing**: Use the `Keypair`'s `sign_message` method to generate a digital signature for a given byte array. 3. **Base58 Conversion**: Convert the `Signature` object to its base58 string representation and parse it back to a `Signature` object to demonstrate interoperability. 4. **Signature Verification**: Verify the authenticity of the signature against the public key and the original message using `verify` and `verify_strict` methods. ```rust use solana_signature::Signature; use solana_keypair::Keypair; use solana_signer::Signer; use std::str::FromStr; // Create keypair let keypair = Keypair::new(); let address = keypair.pubkey(); // Sign message let message = b"Transaction data"; let signature = keypair.sign_message(message); // Convert to/from base58 let sig_str = signature.to_string(); let parsed_sig: Signature = sig_str.parse()?; assert_eq!(signature, parsed_sig); // Verify assert!(parsed_sig.verify(address.as_ref(), message)); // Verify strict (no malleable signatures) assert!(parsed_sig.verify_strict(address.as_ref(), message)); ``` ### Related Types - `Keypair`: Used to generate public/private key pairs and sign messages. - `Address`: Represents a public key, used for verification. - `Signer`: A trait that defines the signing capabilities, implemented by `Keypair`. - `ParseSignatureError`: An error type returned during the parsing of a signature string. ``` -------------------------------- ### Zeroize Example Source: https://github.com/anza-xyz/solana-sdk/blob/master/_autodocs/types.md Demonstrates how to use the `Zeroize` trait to securely clear sensitive data like keypair bytes from memory. ```APIDOC ## Zeroize Trait Usage ### Description Example of using the `Zeroize` trait to clear sensitive data from memory. ### Usage ```rust use zeroize::Zeroize; let mut keypair_bytes = keypair.to_bytes(); keypair_bytes.zeroize(); // Clear from memory ``` ### Applies To - `Keypair` - Secret key data - `Signature` - Can be zeroed but not required. ``` -------------------------------- ### Commitment Level Serialization Examples Source: https://github.com/anza-xyz/solana-sdk/blob/master/_autodocs/api-reference/commitment-config.md These JSON examples illustrate the serialization of different commitment levels ('finalized', 'confirmed', 'processed') for use with serde. ```json { "commitment": "finalized" } ``` ```json { "commitment": "confirmed" } ``` ```json { "commitment": "processed" } ``` -------------------------------- ### Write Data to Account Example Source: https://github.com/anza-xyz/solana-sdk/blob/master/_autodocs/api-reference/account-info.md Shows how to write data to an account's data buffer. This function checks if the provided data fits within the account's allocated space. ```rust use solana_account_info::AccountInfo; pub fn write_data( account: &AccountInfo, data: &[u8], ) -> Result<(), solana_program_error::ProgramError> { let mut account_data = account.try_borrow_mut_data()?; if data.len() > account_data.len() { return Err(solana_program_error::ProgramError::AccountDataTooSmall); } account_data[..data.len()].copy_from_slice(data); Ok(()) } ``` -------------------------------- ### Default and Zero Rent Configuration Source: https://github.com/anza-xyz/solana-sdk/blob/master/_autodocs/api-reference/rent.md Provides methods to get the default Rent configuration or create a zero-rent configuration for testing. ```APIDOC ### Default and Zero Rent ```rust impl Default for Rent { fn default() -> Self { ... } } ``` Returns default rent configuration. ```rust pub fn free() -> Self ``` Create a Rent configuration that charges no lamports (for testing). **Returns**: Rent with lamports_per_byte = 0 ```rust pub fn with_lamports_per_byte(lamports_per_byte: u64) -> Self ``` Create Rent with specified rate. **Parameters**: | Parameter | Type | Description | |-----------|------|-------------| | lamports_per_byte | u64 | Custom rent rate | **Returns**: Rent ``` -------------------------------- ### Getting Rent in Programs Source: https://github.com/anza-xyz/solana-sdk/blob/master/_autodocs/api-reference/rent.md Demonstrates two methods for accessing the Rent sysvar within Solana programs: from a sysvar account or direct access. ```APIDOC ## Getting Rent in Programs ```rust use solana_sysvar::Rent; use solana_sysvar::Sysvar; // Method 1: From sysvar account pub fn rent_from_account(accounts: &[AccountInfo]) -> Result { let rent_account = &accounts[0]; Rent::from_account_info(rent_account) } // Method 2: Direct access pub fn rent_direct() -> Result { Rent::get() } ``` ``` -------------------------------- ### `log!` Macro with String Truncation (Start) Source: https://github.com/anza-xyz/solana-sdk/blob/master/program-log/README.md Use the `log!` macro with the `:<.10` format specifier to truncate strings from the start, limiting the output to a specified width. ```rust use solana_program_log::log; let program_name = "solana-program"; // log message: "...program" log!("{:<.10}", program_name); ``` -------------------------------- ### Create FeeRateGovernor with Targets Source: https://github.com/anza-xyz/solana-sdk/blob/master/_autodocs/api-reference/fee-calculator.md Initialize a FeeRateGovernor with target lamports per signature and target signatures per slot. These values guide the dynamic fee adjustment. ```rust pub fn new( target_lamports_per_signature: u64, target_signatures_per_slot: u64, ) -> Self ``` -------------------------------- ### Logger with String Truncation (Start) Source: https://github.com/anza-xyz/solana-sdk/blob/master/program-log/README.md Append strings to the logger with truncation from the start using `Attribute::TruncateStart`. This limits the displayed string length by removing characters from the beginning. ```rust use solana_program_log::{Attribute, Logger}; let program_name = "solana-program"; let mut logger = Logger::<100>::default(); logger.append_with_args(program_name, &[Attribute::TruncateStart(10)]); // log message: "...program" logger.log(); ``` -------------------------------- ### Check Rust Version Source: https://github.com/anza-xyz/solana-sdk/blob/master/_autodocs/configuration.md Verify the installed Rust compiler version. Ensure it meets the minimum supported version for the Solana SDK. ```bash rustc --version # >= 1.89.0 (as of SDK 4.0) ``` -------------------------------- ### Client-Side Transaction Error Handling Source: https://github.com/anza-xyz/solana-sdk/blob/master/_autodocs/errors.md Demonstrates how to handle transaction errors on the client-side using `solana-rpc-client` and `solana-transaction-error`. This example specifically checks for `BlockhashNotFound` errors. ```rust use solana_rpc_client::rpc_client::RpcClient; use solana_transaction_error::TransactionError; let client = RpcClient::new("http://localhost:8899".to_string()); match client.send_and_confirm_transaction(&transaction) { Ok(signature) => println!("Success: {}", signature), Err(e) => match e.kind { solana_client::client_error::ClientErrorKind::TransactionError( TransactionError::BlockhashNotFound ) => { println!("Blockhash expired, get new one"); } _ => println!("Error: {:?}", e), } } ``` -------------------------------- ### Get EpochInfo via RPC Source: https://github.com/anza-xyz/solana-sdk/blob/master/_autodocs/api-reference/epoch-info.md Retrieves the current EpochInfo from the Solana RPC endpoint and prints basic details. ```rust use solana_rpc_client::rpc_client::RpcClient; let client = RpcClient::new("http://localhost:8899".to_string()); let epoch_info = client.get_epoch_info()?; println!("Epoch: {}", epoch_info.epoch); println!("Slot: {}/{}", epoch_info.slot_index, epoch_info.slots_in_epoch ); println!("Progress: {:.2}%", (epoch_info.slot_index as f64 / epoch_info.slots_in_epoch as f64) * 100.0 ); ``` -------------------------------- ### Get Default Rent Configuration Source: https://github.com/anza-xyz/solana-sdk/blob/master/_autodocs/api-reference/rent.md Retrieves the default Rent configuration, which includes the standard lamports per byte rate. ```rust impl Default for Rent { fn default() -> Self { ... } } ``` -------------------------------- ### Monitor Epoch Progress Source: https://github.com/anza-xyz/solana-sdk/blob/master/_autodocs/api-reference/epoch-info.md A function to get the current epoch progress as a fraction. Requires an RpcClient. ```rust use solana_rpc_client::rpc_client::RpcClient; pub fn get_epoch_progress(client: &RpcClient) -> Result> { let epoch_info = client.get_epoch_info()?; let progress = epoch_info.slot_index as f64 / epoch_info.slots_in_epoch as f64; Ok(progress) } ``` -------------------------------- ### Get Signature Bytes Reference Source: https://github.com/anza-xyz/solana-sdk/blob/master/_autodocs/api-reference/signature.md Provides a byte slice reference to the underlying 64 bytes of the signature. ```rust pub fn as_ref(&self) -> &[u8] ``` -------------------------------- ### Get Balance with Confirmed Commitment Source: https://github.com/anza-xyz/solana-sdk/blob/master/_autodocs/configuration.md Fetch an account's balance using the RpcClient, specifying a 'confirmed' commitment level. This is an alternative to the default 'finalized' commitment. ```rust use solana_commitment_config::CommitmentConfig; use solana_rpc_client::rpc_client::RpcClient; let client = RpcClient::new("http://localhost:8899".to_string()); // Most RPC calls default to finalized commitment // Specify different commitment: let balance = client.get_balance_with_commitment( &pubkey, CommitmentConfig::confirmed(), )?; ``` -------------------------------- ### no_std Compilation Setup Source: https://github.com/anza-xyz/solana-sdk/blob/master/_autodocs/configuration.md Configure Rust for no_std compilation, suitable for embedded environments. This requires disabling the 'std' feature and potentially enabling 'alloc'. ```rust #![no_std] use solana_address::Address; use solana_signature::Signature; // No standard library or allocations ``` -------------------------------- ### Getting the Clock Source: https://github.com/anza-xyz/solana-sdk/blob/master/_autodocs/api-reference/clock.md Demonstrates how to retrieve the current Clock sysvar within a Solana program. This can be done by accessing a specific account or directly using the Clock sysvar ID. ```APIDOC ## Getting the Clock ### Description Retrieves the current `Clock` sysvar, which contains network time and slot information. This can be accessed either by providing the `Clock` account as an argument or by directly calling `Clock::get()`. ### Usage ```rust use solana_sysvar::clock::Clock; use solana_sysvar::Sysvar; use solana_program::account_info::AccountInfo; use solana_program::entrypoint::ProgramResult; // Option 1: Accessing via an AccountInfo pub fn get_clock_from_account(accounts: &[AccountInfo]) -> ProgramResult { let clock_account = &accounts[0]; let clock: Clock = Clock::from_account_info(clock_account)?; // Use the clock data Ok(()) } // Option 2: Directly from Clock sysvar ID pub fn get_clock_directly() -> ProgramResult { let clock: Clock = Clock::get()?; // Use the clock data Ok(()) } ``` ### Fields - `slot`: Current slot number (u64) - `epoch_start_timestamp`: Unix timestamp of the start of the current epoch (i64) - `epoch`: Current epoch number (u64) - `leader_schedule_epoch`: Epoch for which the leader schedule was calculated (u64) - `unix_timestamp`: Approximate real-world time in seconds since the Unix epoch (i64) ``` -------------------------------- ### Add Solana SDK from GitHub Source: https://github.com/anza-xyz/solana-sdk/blob/master/_autodocs/configuration.md Include the Solana SDK from a GitHub repository. Use this for development or to access unstable versions. ```toml [dependencies] solana-sdk = { git = "https://github.com/anza-xyz/solana-sdk", branch = "main" } ``` -------------------------------- ### Basic BLS Keypair, Sign, and Verify Source: https://github.com/anza-xyz/solana-sdk/blob/master/bls-signatures/README.md Demonstrates the fundamental workflow of generating a BLS keypair, signing a message, and verifying the signature using the Keypair's methods. ```rust use solana_bls_signatures::keypair::Keypair; // 1. Generate a new random BLS keypair let keypair = Keypair::new(); let message = b"hello, alpenglow!"; // 2. Sign the message let signature = keypair.sign(message); // 3. Verify the signature // You can verify it directly against the keypair... assert!(keypair.verify(&signature, message).is_ok()); // ...or you can verify it directly against the public key assert!(keypair.public.verify_signature(&signature, message).is_ok()); ``` -------------------------------- ### Get Reference to Address Bytes Source: https://github.com/anza-xyz/solana-sdk/blob/master/_autodocs/api-reference/address.md Provides a reference to the address as a 32-byte array. ```rust pub const fn as_array(&self) -> &[u8; 32] ``` -------------------------------- ### Load Keypair from Wallet File Source: https://github.com/anza-xyz/solana-sdk/blob/master/_autodocs/api-reference/keypair.md Shows how to load a Solana keypair from a base58 encoded string, typically read from a wallet file like `~/.config/solana/id.json`. This requires the wallet contents to be available as a string. ```rust use solana_keypair::Keypair; // Read from Solana CLI wallet file (~/.config/solana/id.json) let keypair = Keypair::from_base58_string(&wallet_contents)?; ``` -------------------------------- ### Build Solana SDK from Local Path Source: https://github.com/anza-xyz/solana-sdk/blob/master/_autodocs/configuration.md Compile the Solana SDK from a local directory using Cargo. This is useful for development and testing local changes. ```bash cd /path/to/solana-sdk cargo build -p solana-sdk ``` -------------------------------- ### Lamports Access and Manipulation Source: https://github.com/anza-xyz/solana-sdk/blob/master/_autodocs/api-reference/account-info.md Methods for getting, borrowing, and mutating the account's lamport balance. ```APIDOC ## lamports ### Description Get current lamport balance. ### Method `&self` (Rust method) ### Returns `u64` --- ## try_lamports ### Description Get lamports, returning error if borrow fails. ### Method `&self` (Rust method) ### Returns `Result` ### Errors ProgramError::AccountBorrowFailed --- ## try_borrow_lamports ### Description Borrow lamports for reading. ### Method `&self` (Rust method) ### Returns `Result, ProgramError>` --- ## try_borrow_mut_lamports ### Description Borrow lamports for mutation. ### Method `&self` (Rust method) ### Returns `Result, ProgramError>` ### Errors ProgramError::AccountBorrowFailed ### Example ```rust use solana_account_info::AccountInfo; pub fn transfer_lamports( from: &AccountInfo, to: &AccountInfo, amount: u64, ) -> Result<(), solana_program_error::ProgramError> { // Reduce source lamports let mut from_lamports = from.try_borrow_mut_lamports()?; **from_lamports = from_lamports.saturating_sub(amount); // Increase destination lamports let mut to_lamports = to.try_borrow_mut_lamports()?; **to_lamports += amount; Ok(()) } ``` ``` -------------------------------- ### Create and Sign a Solana Transaction Source: https://github.com/anza-xyz/solana-sdk/blob/master/_autodocs/api-reference/keypair.md Demonstrates how to create a new keypair, define instructions, and construct a signed transaction using the Solana SDK. Ensure you obtain a recent blockhash from an RPC endpoint. ```rust use solana_keypair::Keypair; use solana_signer::Signer; use solana_transaction::Transaction; use solana_message::Message; use solana_instruction::Instruction; // Create a new keypair let payer = Keypair::new(); // Create instructions let instruction = Instruction { program_id: my_program, accounts: vec![], data: vec![], }; // Create and sign transaction let message = Message::new(&[instruction], Some(&payer.pubkey())); let recent_blockhash = /* get from RPC */; let transaction = Transaction::new(&[&payer], message, recent_blockhash); ``` -------------------------------- ### Get Hash as Byte Slice Source: https://github.com/anza-xyz/solana-sdk/blob/master/_autodocs/api-reference/hash.md Provides access to the underlying 32 bytes of the hash as a slice. ```rust pub fn as_bytes(&self) -> &[u8] ``` -------------------------------- ### Complete Signing and Verification Source: https://github.com/anza-xyz/solana-sdk/blob/master/_autodocs/api-reference/signature.md Demonstrates the full process of creating a keypair, signing a message, converting the signature to and from a base58 string, and verifying the signature. ```rust use solana_signature::Signature; use solana_keypair::Keypair; use solana_signer::Signer; use std::str::FromStr; // Create keypair let keypair = Keypair::new(); let address = keypair.pubkey(); // Sign message let message = b"Transaction data"; let signature = keypair.sign_message(message); // Convert to/from base58 let sig_str = signature.to_string(); let parsed_sig: Signature = sig_str.parse()?; assert_eq!(signature, parsed_sig); // Verify assert!(parsed_sig.verify(address.as_ref(), message)); // Verify strict (no malleable signatures) assert!(parsed_sig.verify_strict(address.as_ref(), message)); ``` -------------------------------- ### Data Access and Manipulation Source: https://github.com/anza-xyz/solana-sdk/blob/master/_autodocs/api-reference/account-info.md Methods for getting the size of, checking emptiness of, and borrowing or mutating account data. ```APIDOC ## data_len ### Description Get account data length. ### Method `&self` (Rust method) ### Returns `usize` --- ## try_data_len ### Description Get data length, returning error if borrow fails. ### Method `&self` (Rust method) ### Returns `Result` --- ## data_is_empty ### Description Check if account data is empty. ### Method `&self` (Rust method) ### Returns `bool` --- ## try_data_is_empty ### Description Check if empty with error handling. ### Method `&self` (Rust method) ### Returns `Result` --- ## try_borrow_data ### Description Borrow data for reading. ### Method `&self` (Rust method) ### Returns `Result, ProgramError>` --- ## try_borrow_mut_data ### Description Borrow data for mutation. ### Method `&self` (Rust method) ### Returns `Result, ProgramError>` ### Errors ProgramError::AccountBorrowFailed ### Example ```rust use solana_account_info::AccountInfo; pub fn write_data( account: &AccountInfo, data: &[u8], ) -> Result<(), solana_program_error::ProgramError> { let mut account_data = account.try_borrow_mut_data()?; if data.len() > account_data.len() { return Err(solana_program_error::ProgramError::AccountDataTooSmall); } account_data[..data.len()].copy_from_slice(data); Ok(()) } ``` ``` -------------------------------- ### Connect to Solana Mainnet RPC Source: https://github.com/anza-xyz/solana-sdk/blob/master/_autodocs/configuration.md Instantiate an RpcClient to connect to the Solana Mainnet Beta network. ```rust use solana_rpc_client::rpc_client::RpcClient; // Mainnet let client = RpcClient::new("https://api.mainnet-beta.solana.com".to_string()); ``` -------------------------------- ### Run Benchmarks Source: https://github.com/anza-xyz/solana-sdk/blob/master/README.md Executes the benchmark suite for the Solana SDK. ```console ./scripts/test-bench.sh ``` -------------------------------- ### On-Chain Program Builds with SBF Source: https://github.com/anza-xyz/solana-sdk/blob/master/_autodocs/configuration.md Build Solana programs for the BPF target using Cargo SBF. Use the --release flag for optimizations and --lto for Link-Time Optimization. ```bash cargo build-sbf # Or with optimizations: cargo build-sbf --release # With LTO: cargo build-sbf --lto ``` -------------------------------- ### Connect to Solana Devnet RPC Source: https://github.com/anza-xyz/solana-sdk/blob/master/_autodocs/configuration.md Instantiate an RpcClient to connect to the Solana Devnet. ```rust use solana_rpc_client::rpc_client::RpcClient; // Devnet let client = RpcClient::new("https://api.devnet.solana.com".to_string()); ``` -------------------------------- ### Off-Chain Client Builds with Cargo Source: https://github.com/anza-xyz/solana-sdk/blob/master/_autodocs/configuration.md Build off-chain Solana clients using standard Cargo commands. Use the --release flag for optimized builds. ```bash cargo build cargo build --release ``` -------------------------------- ### Connect to Solana Testnet RPC Source: https://github.com/anza-xyz/solana-sdk/blob/master/_autodocs/configuration.md Instantiate an RpcClient to connect to the Solana Testnet. ```rust use solana_rpc_client::rpc_client::RpcClient; // Testnet let client = RpcClient::new("https://api.testnet.solana.com".to_string()); ``` -------------------------------- ### Add solana-program-log to Project Source: https://github.com/anza-xyz/solana-sdk/blob/master/program-log/README.md Add the solana-program-log crate to your project's dependencies using Cargo. ```bash cargo add solana-program-log ``` -------------------------------- ### Get Secret Key Bytes Source: https://github.com/anza-xyz/solana-sdk/blob/master/_autodocs/api-reference/keypair.md Retrieve a reference to the 32-byte secret key using `secret_bytes()`. Ensure this secret key is protected from exposure. ```rust use solana_keypair::Keypair; let keypair = Keypair::new(); let secret_bytes = keypair.secret_bytes(); ``` -------------------------------- ### Create Rent Configuration with Custom Rate Source: https://github.com/anza-xyz/solana-sdk/blob/master/_autodocs/api-reference/rent.md Instantiates a Rent configuration with a specified lamports per byte rate, allowing for custom rent policies. ```rust pub fn with_lamports_per_byte(lamports_per_byte: u64) -> Self ``` -------------------------------- ### Sysvar Trait Source: https://github.com/anza-xyz/solana-sdk/blob/master/_autodocs/types.md The `Sysvar` trait is implemented by all sysvar types (e.g., Clock, Rent) and provides methods to get their size and deserialize them from account information. ```APIDOC ## Sysvar Trait ### Description Provides methods for sysvar types to get their size and deserialize from account info. ### Methods - `size_of() -> usize`: Returns the size of the sysvar. - `from_account_info(account_info: &AccountInfo) -> Result`: Deserializes the sysvar from account information. - `get() -> Result`: Retrieves the sysvar. ### Implemented By All sysvar types (e.g., Clock, Rent). ``` -------------------------------- ### Create Account with Solana System Interface Source: https://github.com/anza-xyz/solana-sdk/blob/master/system-interface/README.md Use this function to create a new account on the Solana blockchain. It calculates the required rent exemption and constructs the necessary transaction. ```rust use solana_rpc_client::rpc_client::RpcClient; use solana_sdk::{ signature::{Keypair, Signer}, transaction::Transaction, }; use solana_system_interface::instruction; use anyhow::Result; fn create_account( client: &RpcClient, payer: &Keypair, new_account: &Keypair, owning_program: &Pubkey, space: u64, ) -> Result<()> { let rent = client.get_minimum_balance_for_rent_exemption(space.try_into()?)?; let instr = instruction::create_account( &payer.pubkey(), &new_account.pubkey(), rent, space, owning_program, ); let blockhash = client.get_latest_blockhash()?; let tx = Transaction::new_signed_with_payer( &[instr], Some(&payer.pubkey()), &[payer, new_account], blockhash, ); let _sig = client.send_and_confirm_transaction(&tx)?; Ok(()) } ``` -------------------------------- ### Get Public Key (Address) Source: https://github.com/anza-xyz/solana-sdk/blob/master/_autodocs/api-reference/keypair.md Retrieve the public key (address) associated with a keypair using the `pubkey()` method, which is part of the `Signer` trait implementation. ```rust use solana_keypair::Keypair; use solana_signer::Signer; let keypair = Keypair::new(); let address = keypair.pubkey(); ``` -------------------------------- ### Standard Solana Program Entrypoint Source: https://github.com/anza-xyz/solana-sdk/blob/master/_autodocs/configuration.md Define the standard entrypoint for a Solana program using the `entrypoint!` macro and `process_instruction` function. This function handles incoming program instructions. ```rust use solana_program::{ account_info::AccountInfo, entrypoint, pubkey::Pubkey, program_error::ProgramError, }; entrypoint!(process_instruction); pub fn process_instruction( program_id: &Pubkey, accounts: &[AccountInfo], instruction_data: &[u8], ) -> Result<(), ProgramError> { // Program logic Ok(()) } ``` -------------------------------- ### Full Client Configuration in Cargo.toml Source: https://github.com/anza-xyz/solana-sdk/blob/master/_autodocs/configuration.md Enable most features for off-chain Solana clients. This includes SDK and client configurations. Add this to your Cargo.toml file. ```toml [dependencies] solana-sdk = { version = "4.0", features = ["full"] } solana-client = { version = "4.0", features = ["blocking"] } ``` -------------------------------- ### Get Clock Sysvar Source: https://github.com/anza-xyz/solana-sdk/blob/master/_autodocs/api-reference/clock.md Retrieves the Clock sysvar from the accounts list or directly using Clock::get(). Requires the Clock account to be passed in accounts. ```rust use solana_sysvar::clock::Clock; use solana_sysvar::Sysvar; pub fn get_clock(accounts: &[AccountInfo]) -> Result { let clock_account = &accounts[0]; Clock::from_account_info(clock_account) } // Or directly from Clock sysvar ID pub fn get_clock_direct() -> Result { Clock::get() } ``` -------------------------------- ### RPC Client Integration with Commitment Source: https://github.com/anza-xyz/solana-sdk/blob/master/_autodocs/api-reference/commitment-config.md Demonstrates how to use CommitmentConfig with an RpcClient to fetch data at different commitment levels. ```rust use solana_rpc_client::rpc_client::RpcClient; use solana_commitment_config::CommitmentConfig; let client = RpcClient::new("http://localhost:8899".to_string()); // Get balance with specific commitment let balance = client.get_balance_with_commitment( &pubkey, CommitmentConfig::confirmed(), )?; // Get account with finalized commitment let account = client.get_account_with_commitment( &pubkey, CommitmentConfig::finalized(), )?; // Get transaction status with confirmed commitment let status = client.get_signature_status_with_commitment( &signature, CommitmentConfig::confirmed(), )?; ``` -------------------------------- ### Clone Solana SDK Repository Source: https://github.com/anza-xyz/solana-sdk/blob/master/README.md Clones the Solana SDK from GitHub and navigates into the repository directory. ```console git clone https://github.com/anza-xyz/solana-sdk.git cd solana-sdk ``` -------------------------------- ### Instruction Construction with Bincode Serialization Source: https://github.com/anza-xyz/solana-sdk/blob/master/_autodocs/api-reference/instruction.md Creates an Instruction using bincode serialization for the instruction data. ```APIDOC ### Construction with Bincode Serialization ```rust #[cfg(feature = "bincode")] pub fn new_with_bincode( program_id: Pubkey, data: &T, accounts: Vec, ) -> Instruction ``` Create instruction with bincode serialization. **Parameters**: Same as `new_with_borsh` **Returns**: Instruction ``` -------------------------------- ### Get Epoch Info RPC Method Source: https://github.com/anza-xyz/solana-sdk/blob/master/_autodocs/api-reference/epoch-info.md Retrieves the current EpochInfo from the Solana network using the RpcClient. This method is the primary way to access epoch-related data for the client. ```APIDOC ## GET /getEpochInfo ### Description Retrieves the current epoch information for the Solana network. ### Method GET ### Endpoint /getEpochInfo ### Parameters None ### Request Example None ### Response #### Success Response (200) - **epoch** (u64) - Current epoch number (starts at 0) - **slotIndex** (u64) - Slot within the current epoch (0 to slots_in_epoch - 1) - **slotsInEpoch** (u64) - Total number of slots in this epoch - **absoluteSlot** (u64) - Total slots since genesis - **blockHeight** (u64) - Total blocks confirmed since genesis - **transactionCount** (Option) - Total transactions since genesis (may be None) #### Response Example ```json { "epoch": 500, "slotIndex": 150000, "slotsInEpoch": 432000, "absoluteSlot": 216000000, "blockHeight": 215800000, "transactionCount": 50000000000 } ``` ``` -------------------------------- ### Get Current Solana Transaction Fees Source: https://github.com/anza-xyz/solana-sdk/blob/master/_autodocs/api-reference/fee-calculator.md Fetches the current fee rate governor from the Solana RPC and calculates the current fee per signature. Requires an active RpcClient connection. ```rust use solana_rpc_client::rpc_client::RpcClient; let client = RpcClient::new("http://localhost:8899".to_string()); // Get recent fee estimate let fee_rate_governor = client.get_fee_rate_governor()?; let current_fee = fee_rate_governor.create_fee_calculator(); println!("Current fee per signature: {} lamports", current_fee.lamports_per_signature); ``` -------------------------------- ### Minimal Program Configuration in Cargo.toml Source: https://github.com/anza-xyz/solana-sdk/blob/master/_autodocs/configuration.md Configure a minimal Solana program by disabling unnecessary features. This is useful for on-chain programs. Add this to your Cargo.toml file. ```toml [dependencies] solana-program = { version = "4.0", features = ["no-entrypoint"] } [lib] crate-type = ["cdylib"] ``` -------------------------------- ### Create Zero Rent Configuration Source: https://github.com/anza-xyz/solana-sdk/blob/master/_autodocs/api-reference/rent.md Creates a Rent configuration where no lamports are charged, typically used for testing purposes to bypass rent calculations. ```rust pub fn free() -> Self Create Rent with specified rate. Parameters: | Parameter | Type | Description | |-----------|------|-------------| | lamports_per_byte | u64 | Custom rent rate | Returns: Rent ``` -------------------------------- ### Connect to Local Solana RPC Source: https://github.com/anza-xyz/solana-sdk/blob/master/_autodocs/configuration.md Instantiate an RpcClient to connect to a local Solana validator instance. ```rust use solana_rpc_client::rpc_client::RpcClient; // Local let client = RpcClient::new("http://localhost:8899".to_string()); ``` -------------------------------- ### AccountMeta Construction Methods Source: https://github.com/anza-xyz/solana-sdk/blob/master/_autodocs/api-reference/instruction.md Provides methods to create `AccountMeta` instances for read-only, writable, or signer accounts. ```rust pub fn new(pubkey: Pubkey, is_signer: bool, is_writable: bool) -> Self ``` ```rust pub fn new_readonly(pubkey: Pubkey, is_signer: bool) -> Self ``` ```rust pub const fn new_writable(pubkey: Pubkey, is_signer: bool) -> Self ``` ```rust use solana_instruction::AccountMeta; use solana_address::Address; use std::str::FromStr; let account_address = Address::from_str("My11111111111111111111111111111111111111111")?; // Read-only account let readonly = AccountMeta::new_readonly(account_address, false); // Writable account (not a signer) let writable = AccountMeta::new_writable(account_address, false); // Signer account let signer = AccountMeta::new(account_address, true, true); ``` -------------------------------- ### Create FeeCalculator Instance Source: https://github.com/anza-xyz/solana-sdk/blob/master/_autodocs/api-reference/fee-calculator.md Instantiate a FeeCalculator with a specified lamports per signature rate. This is useful for setting a fixed fee for transactions. ```rust use solana_fee_calculator::FeeCalculator; let fee_calc = FeeCalculator::new(5000); ``` -------------------------------- ### Enable All Features in Cargo.toml Source: https://github.com/anza-xyz/solana-sdk/blob/master/_autodocs/configuration.md Use this to enable all features for the Solana SDK, except deprecated ones. Add this to your Cargo.toml file. ```toml [dependencies] solana-sdk = { version = "4.0", features = ["full"] } ``` -------------------------------- ### BLS Signature Type Flexibility and Verification Approaches Source: https://github.com/anza-xyz/solana-sdk/blob/master/bls-signatures/README.md Illustrates how to convert between different BLS signature representations (Compressed, Uncompressed, Affine, Projective) and demonstrates two primary verification approaches: via the public key and via the signature itself. ```rust use solana_bls_signatures::{ keypair::Keypair, pubkey::VerifySignature, signature::{Signature, SignatureCompressed, SignatureAffine, SignatureProjective, VerifiableSignature}, }; let keypair = Keypair::new(); let message = b"ergonomics test"; // The default `.sign()` returns a SignatureProjective let sig_projective: SignatureProjective = keypair.sign(message); // Easily convert into other representations let sig_affine: SignatureAffine = sig_projective.into(); let sig_compressed: SignatureCompressed = sig_projective.into(); // 96 bytes let sig_uncompressed: Signature = sig_projective.into(); // 192 bytes // Approach A: Verify via the Public Key // You can pass projective, affine, or byte-level signatures keypair.public.verify_signature(&sig_projective, message).unwrap(); keypair.public.verify_signature(&sig_affine, message).unwrap(); keypair.public.verify_signature(&sig_compressed, message).unwrap(); keypair.public.verify_signature(&sig_uncompressed, message).unwrap(); // Approach B: Verify via the Signature // Import `VerifiableSignature` and call `.verify()` on the signature itself sig_projective.verify(&keypair.public, message).unwrap(); sig_affine.verify(&keypair.public, message).unwrap(); sig_compressed.verify(&keypair.public, message).unwrap(); sig_uncompressed.verify(&keypair.public, message).unwrap(); ``` -------------------------------- ### Add Solana SDK to Cargo Dependencies Source: https://github.com/anza-xyz/solana-sdk/blob/master/_autodocs/configuration.md Include the Solana SDK and program crates in your project's `Cargo.toml` file. Specify versions for crates.io. ```toml [dependencies] solana-sdk = "4.0.1" solana-program = "4.0.0" ``` -------------------------------- ### Grow Account Data Size Source: https://github.com/anza-xyz/solana-sdk/blob/master/_autodocs/api-reference/account-info.md Demonstrates how to safely grow an account's data size, ensuring the increase does not exceed a predefined limit per instruction. The new bytes are initialized to zero. ```rust pub fn grow_account( account: &AccountInfo, new_size: usize, ) -> Result<(), solana_program_error::ProgramError> { // Grow by up to 10KB per instruction let current_size = account.data_len(); if new_size > current_size + 10_240 { return Err(solana_program_error::ProgramError::InvalidRealloc); } account.realloc(new_size, true)?; Ok(()) } ``` -------------------------------- ### Construct Transaction from Instructions Source: https://github.com/anza-xyz/solana-sdk/blob/master/_autodocs/api-reference/instruction.md Combine multiple instructions into a Message and then into a Transaction. This requires a payer account and a recent blockhash. ```rust use solana_instruction::Instruction; use solana_message::Message; use solana_transaction::Transaction; let instructions = vec![instruction1, instruction2]; let message = Message::new(&instructions, Some(&payer.pubkey())); let transaction = Transaction::new(&[&payer], message, recent_blockhash); ``` -------------------------------- ### Run Cargo Tests Source: https://github.com/anza-xyz/solana-sdk/blob/master/README.md Executes the test suite for the Solana SDK using Cargo. ```console cargo test ``` -------------------------------- ### Create a Rent-Exempt Account Source: https://github.com/anza-xyz/solana-sdk/blob/master/_autodocs/api-reference/rent.md Creates a new account and ensures it has at least the minimum balance required for rent exemption. Checks for sufficient funds before creation. ```rust use solana_rent::Rent; pub fn create_rent_exempt_account( payer: &Signer, new_account: &Signer, program_id: &Pubkey, lamports: u64, space: usize, ) -> Result<(), ProgramError> { let rent = Rent::get()?; let required = rent.minimum_balance(space); if lamports < required { return Err(ProgramError::InsufficientFunds); } // Create account with required lamports Ok(()) } ``` -------------------------------- ### Create Instruction with Raw Bytes Source: https://github.com/anza-xyz/solana-sdk/blob/master/_autodocs/api-reference/instruction.md Use this function to create an Instruction with raw byte data. Ensure the program ID, data, and account metadata are correctly provided. ```rust use solana_instruction::Instruction; use solana_address::Address; use std::str::FromStr; let program_id = Address::from_str("MyProgram1111111111111111111111111111111111")?; let account = Address::from_str("MyAccount1111111111111111111111111111111111")?; let instruction = Instruction::new_with_bytes( program_id, &[0, 1, 2, 3], // Custom instruction data vec![], // No accounts for this example ); ``` -------------------------------- ### Generate Code Coverage Report Source: https://github.com/anza-xyz/solana-sdk/blob/master/README.md Generates code coverage statistics and opens the report in a web browser. Requires `llvm-tools-preview`. ```console ./scripts/test-coverage.sh ``` ```console $ open target/cov/lcov-local/index.html ``` -------------------------------- ### Try Calculate Minimum Balance Source: https://github.com/anza-xyz/solana-sdk/blob/master/_autodocs/api-reference/rent.md Attempts to calculate the minimum balance for rent exemption, returning None if the data length exceeds the maximum allowed (10 MiB). ```rust let min_balance = rent.try_minimum_balance(1024)?; ``` -------------------------------- ### Check Code Formatting Source: https://github.com/anza-xyz/solana-sdk/blob/master/README.md Runs `rustfmt` as a check to ensure code adheres to the project's formatting standards. ```console ./scripts/check-fmt.sh ``` -------------------------------- ### Run Stable Test Suite Source: https://github.com/anza-xyz/solana-sdk/blob/master/README.md Executes the standard test suite using a stable Rust toolchain via a helper script. ```console ./scripts/test-stable.sh ``` -------------------------------- ### Signature Construction Source: https://github.com/anza-xyz/solana-sdk/blob/master/_autodocs/api-reference/signature.md Create a Signature from a 64-byte source. This method is essential for initializing signature objects from raw byte data. ```APIDOC ## Signature Construction ### Description Create signature from 64-byte source. ### Method `pub fn from>(val: T) -> Self` ### Parameters #### Path Parameters - **val** (T) - Required - 64-byte source ### Returns Signature ``` -------------------------------- ### Save and Load Keypair to/from File Source: https://github.com/anza-xyz/solana-sdk/blob/master/_autodocs/api-reference/keypair.md Illustrates persistent storage of a Solana keypair by saving its base58 encoded string to a file and then loading it back. This is useful for applications that need to reuse keypairs across sessions. ```rust use solana_keypair::Keypair; use std::fs; let keypair = Keypair::new(); // Save to file let base58 = keypair.to_base58_string(); fs::write("keypair.json", base58)?; // Load from file let contents = fs::read_to_string("keypair.json")?; let loaded = Keypair::from_base58_string(&contents)?; ``` -------------------------------- ### RPC Client Integration Source: https://github.com/anza-xyz/solana-sdk/blob/master/_autodocs/api-reference/commitment-config.md Demonstrates how to use CommitmentConfig with the Solana RPC client to specify commitment levels for various RPC calls. ```APIDOC ## RPC Integration ### Using with RPC Client ```rust use solana_rpc_client::rpc_client::RpcClient; use solana_commitment_config::CommitmentConfig; let client = RpcClient::new("http://localhost:8899".to_string()); // Get balance with specific commitment let balance = client.get_balance_with_commitment( &pubkey, CommitmentConfig::confirmed(), )?; // Get account with finalized commitment let account = client.get_account_with_commitment( &pubkey, CommitmentConfig::finalized(), )?; // Get transaction status with confirmed commitment let status = client.get_signature_status_with_commitment( &signature, CommitmentConfig::confirmed(), )?; ``` ``` -------------------------------- ### Instruction::new_with_bytes Source: https://github.com/anza-xyz/solana-sdk/blob/master/_autodocs/api-reference/instruction.md Constructs an Instruction using raw byte data, a program ID, and a list of accounts. ```APIDOC ## Instruction::new_with_bytes ### Description Create instruction with raw byte data. ### Method Signature ```rust pub fn new_with_bytes( program_id: Pubkey, data: &[u8], accounts: Vec, ) -> Instruction ``` ### Parameters #### Path Parameters - **program_id** (Pubkey) - Required - Program to execute - **data** (&[u8]) - Required - Raw instruction data - **accounts** (Vec) - Required - Account metadata list ### Request Example ```rust use solana_instruction::Instruction; use solana_address::Address; use std::str::FromStr; let program_id = Address::from_str("MyProgram1111111111111111111111111111111111")?; let account = Address::from_str("MyAccount1111111111111111111111111111111111")?; let instruction = Instruction::new_with_bytes( program_id, &[0, 1, 2, 3], // Custom instruction data vec![], // No accounts for this example ); ``` ``` -------------------------------- ### Instruction Construction with Bincode Serialization Source: https://github.com/anza-xyz/solana-sdk/blob/master/_autodocs/api-reference/instruction.md Creates an `Instruction` with data serialized using Bincode. Parameters are the same as `new_with_borsh`. ```rust #[cfg(feature = "bincode")] pub fn new_with_bincode( program_id: Pubkey, data: &T, accounts: Vec, ) -> Instruction ``` -------------------------------- ### FeeCalculator::new Source: https://github.com/anza-xyz/solana-sdk/blob/master/_autodocs/api-reference/fee-calculator.md Creates a new FeeCalculator instance with a specified fee rate per signature. ```APIDOC ## FeeCalculator::new ### Description Create fee calculator with specified rate. ### Method `new(lamports_per_signature: u64) -> Self` ### Parameters #### Path Parameters - **lamports_per_signature** (u64) - Required - Fee per signature in lamports ### Returns FeeCalculator ### Example ```rust use solana_fee_calculator::FeeCalculator; let fee_calc = FeeCalculator::new(5000); ``` ``` -------------------------------- ### Instruction Construction with Borsh Serialization Source: https://github.com/anza-xyz/solana-sdk/blob/master/_autodocs/api-reference/instruction.md Creates an Instruction using Borsh serialization for the instruction data. This is the preferred method for well-defined instruction schemas. ```APIDOC ## Instruction Methods ### Construction with Borsh Serialization ```rust #[cfg(feature = "borsh")] pub fn new_with_borsh( program_id: Pubkey, data: &T, accounts: Vec, ) -> Instruction ``` Create instruction with Borsh-serialized data. Preferred method for well-defined instruction schemas. **Parameters**: | Parameter | Type | Description | |-----------|------|-------------| | program_id | Pubkey | Program to execute | | data | &T | Instruction data to serialize with borsh | | accounts | Vec | Account metadata list | **Returns**: Instruction **Example**: ```rust use solana_instruction::{Instruction, AccountMeta}; use solana_address::Address; use borsh::{BorshSerialize, BorshDeserialize}; use std::str::FromStr; #[derive(BorshSerialize, BorshDeserialize)] pub enum MyInstruction { Transfer { amount: u64 }, Mint { amount: u64 }, } let program_id = Address::from_str("TokenProgram1111111111111111111111111111111")?; let from = Address::from_str("MyAccount1111111111111111111111111111111111")?; let to = Address::from_str("MyAccount2222222222222222222222222222222222")?; let instr_data = MyInstruction::Transfer { amount: 1000 }; let instruction = Instruction::new_with_borsh( program_id, &instr_data, vec![ AccountMeta::new(from, true), // from account, signer, writable AccountMeta::new(to, false), // to account, not signer, writable ], ); ``` ``` -------------------------------- ### Log a Simple Message Source: https://github.com/anza-xyz/solana-sdk/blob/master/program-log-macro/README.md Use this snippet to output a static string message using the `log!` macro. ```rust use solana_program_log::log; log!("a simple log"); ``` -------------------------------- ### Cargo Release Build Command Source: https://github.com/anza-xyz/solana-sdk/blob/master/_autodocs/configuration.md Compile the project with optimizations enabled. This is suitable for production deployments. ```bash cargo build --release ``` -------------------------------- ### Display and Formatting Source: https://github.com/anza-xyz/solana-sdk/blob/master/_autodocs/api-reference/address.md Address implements the `Display` and `Debug` traits for base58 encoding. ```APIDOC ## Display and Debug Implementation ### Description Address implements `Display` and `Debug` to show base58-encoded representation. ### Example ```rust use solana_address::Address; let address = Address::new_unique(); println!("{}", address); // base58 encoded println!("{:?}", address); // base58 encoded ``` ``` -------------------------------- ### Construct Keypair from Secret Key Array Source: https://github.com/anza-xyz/solana-sdk/blob/master/_autodocs/api-reference/keypair.md Construct a keypair from a provided 32-byte secret key array using `Keypair::new_from_array`. ```rust use solana_keypair::Keypair; let secret = [0u8; 32]; let keypair = Keypair::new_from_array(secret); ``` -------------------------------- ### Basic `log!` Macro Usage Source: https://github.com/anza-xyz/solana-sdk/blob/master/program-log/README.md Use the `log!` macro for simple message logging. It supports standard formatting arguments. ```rust use solana_program_log::log; let lamports = 1_000_000_000; log!("transfer amount: {}", lamports); // Logs the transfer amount in SOL (lamports with 9 decimal digits) log!("transfer amount (SOL): {:.9}", lamports); ``` -------------------------------- ### Check Clippy Lints Source: https://github.com/anza-xyz/solana-sdk/blob/master/README.md Runs `clippy` to check for common Rust lints and potential code improvements. ```console ./scripts/check-clippy.sh ```