Created
April 29, 2024 17:18
-
-
Save siexp/6f8c0b4a58f189c90f709984b4c4aa79 to your computer and use it in GitHub Desktop.
RUST + SOLANA FOR BEGINNERS
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use borsh::{BorshSerialize, BorshDeserialize}; | |
use solana_program::{ | |
account_info::{next_account_info, AccountInfo}, | |
entrypoint, | |
msg, | |
entrypoint::ProgramResult, | |
program_error::ProgramError, | |
pubkey::Pubkey, | |
}; | |
/// Define the type of state stored in accounts | |
#[derive(BorshSerialize, BorshDeserialize, Debug)] | |
pub struct GreetingAccount { | |
/// number of greetings | |
pub counter: u32, | |
} | |
// Declare and export the program's entrypoint | |
entrypoint!(process_instruction); | |
pub fn process_instruction( | |
program_id: &Pubkey, | |
accounts: &[AccountInfo], | |
_instruction_data: &[u8], | |
) -> ProgramResult { | |
msg!("Rust program entrypoint"); | |
// Iterating accounts is safer than indexing | |
let accounts_iter =&mut accounts.iter(); | |
// Get the account to say hello to | |
let account = next_account_info(accounts_iter)?; | |
// The account must be owned by the program in order to modify its data | |
if account.owner != program_id { | |
msg!("Greeted account {} does not have the correct program id", account.owner); | |
return Err(ProgramError::IncorrectProgramId); | |
} else { | |
msg!("Greeted account {} have correct program id", account.owner); | |
} | |
let mut greeting_data = GreetingAccount::try_from_slice(&account.data.borrow())?; | |
greeting_data.counter += 1; | |
greeting_data.serialize(&mut &mut account.data.borrow_mut()[..])?; | |
msg!("Greeted {} time(s)!", greeting_data.counter); | |
Ok(()) | |
} | |
#[cfg(test)] | |
mod tests { | |
use super::*; | |
use solana_program::clock::Epoch; | |
use std::mem; | |
use borsh::{from_slice, to_vec}; | |
#[test] | |
fn test_greeting_from_slice() { | |
let key = Pubkey::default(); | |
let mut lamports = 0; | |
let mut data = vec![0; mem::size_of::<u32>()]; | |
let owner = Pubkey::default(); | |
let account = AccountInfo::new( | |
&key, | |
false, | |
true, | |
&mut lamports, | |
&mut data, | |
&owner, | |
false, | |
Epoch::default(), | |
); | |
let accounts = [account]; | |
let mut greeting_array = accounts[0].data.try_borrow_mut().unwrap(); | |
let mut greeting_data: GreetingAccount = from_slice::<GreetingAccount>(&greeting_array[..]).unwrap(); | |
assert_eq!(greeting_data.counter, 0); | |
greeting_data.counter += 1; | |
greeting_array[..].copy_from_slice(&to_vec(&greeting_data).unwrap()); | |
assert_eq!(greeting_data.counter, 1); | |
} | |
#[test] | |
fn test_sanity() { | |
let program_id = Pubkey::default(); | |
let key = Pubkey::default(); | |
let mut lamports = 0; | |
let mut data = vec![0; mem::size_of::<u32>()]; | |
let owner = Pubkey::default(); | |
let account = AccountInfo::new( | |
&key, | |
false, | |
true, | |
&mut lamports, | |
&mut data, | |
&owner, | |
false, | |
Epoch::default(), | |
); | |
// This is example how to read data from account in tests | |
{ | |
let accounts = vec![account]; | |
let greeting_array = accounts[0].data.try_borrow().unwrap(); | |
let greeting_data: GreetingAccount = from_slice::<GreetingAccount>(&greeting_array[..]).unwrap(); | |
assert_eq!(greeting_data.counter, 0); | |
} | |
// This is example how to test `method` execution | |
{ | |
let instruction_data: Vec<u8> = Vec::new(); | |
process_instruction(&program_id, &accounts, &instruction_data).unwrap(); | |
let greeting_array1 = accounts[0].data.try_borrow().unwrap(); | |
let greeting_data1: GreetingAccount = from_slice::<GreetingAccount>(&greeting_array1[..]).unwrap(); | |
assert_eq!(greeting_data1.counter, 1); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment