Last active
August 27, 2024 09:49
-
-
Save topherPedersen/182128d9b10da9b5741a16f556b2c7af to your computer and use it in GitHub Desktop.
Solana 101: Hello, World Rust/Solana Program (from Figment.io's Solana 101 Course)
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::{BorshDeserialize, BorshSerialize}; | |
use solana_program::{ | |
account_info::{next_account_info, AccountInfo}, | |
entrypoint, | |
entrypoint::ProgramResult, | |
msg, | |
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); | |
// Program entrypoint's implementation | |
pub fn process_instruction( | |
program_id: &Pubkey, // Public key of the account the hello world program was loaded into | |
accounts: &[AccountInfo], // The account to say hello to | |
_instruction_data: &[u8], // Ignored, all helloworld instructions are hellos | |
) -> ProgramResult { | |
msg!("Hello World Rust program entrypoint"); | |
// Iterating accounts is safer then 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"); | |
return Err(ProgramError::IncorrectProgramId); | |
} | |
// Increment and store the number of times the account has been greeted | |
let mut greeting_account = GreetingAccount::try_from_slice(&account.data.borrow())?; | |
greeting_account.counter += 1; | |
greeting_account.serialize(&mut &mut account.data.borrow_mut()[..])?; | |
msg!("Greeted {} time(s)!", greeting_account.counter); | |
Ok(()) | |
} | |
// Sanity tests | |
#[cfg(test)] | |
mod test { | |
use super::*; | |
use solana_program::clock::Epoch; | |
use std::mem; | |
#[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(), | |
); | |
let instruction_data: Vec<u8> = Vec::new(); | |
let accounts = vec![account]; | |
assert_eq!( | |
GreetingAccount::try_from_slice(&accounts[0].data.borrow()) | |
.unwrap() | |
.counter, | |
0 | |
); | |
process_instruction(&program_id, &accounts, &instruction_data).unwrap(); | |
assert_eq!( | |
GreetingAccount::try_from_slice(&accounts[0].data.borrow()) | |
.unwrap() | |
.counter, | |
1 | |
); | |
process_instruction(&program_id, &accounts, &instruction_data).unwrap(); | |
assert_eq!( | |
GreetingAccount::try_from_slice(&accounts[0].data.borrow()) | |
.unwrap() | |
.counter, | |
2 | |
); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment