Learn everything about Solana
Review III - Implementing Add_Review
In this lesson, we are going to see how we can create a review and store it.
Here is the changes we have made to lib.rs in this video:
pub mod instruction;
pub mod state;
use borsh::BorshSerialize;
use crate::instruction::ReviewInstruction;
use crate::state::AccountState;
use crate::state::ReviewError;
use solana_program::{
account_info::{next_account_info, AccountInfo},
borsh0_10::try_from_slice_unchecked,
entrypoint,
entrypoint::ProgramResult,
msg,
program::invoke_signed,
program_error::ProgramError,
program_pack::IsInitialized,
pubkey::Pubkey,
system_instruction,
sysvar::{rent::Rent, Sysvar},
};
use std::convert::TryInto;
entrypoint!(process_instruction);
pub fn process_instruction(
program_id: &Pubkey,
accounts: &[AccountInfo],
instruction_data: &[u8],
) -> ProgramResult {
let instruction = ReviewInstruction::unpack(instruction_data)?;
match instruction {
ReviewInstruction::AddReview {
title,
rating,
description,
} => add_review(program_id, accounts, title, rating, description),
ReviewInstruction::UpdateReview {
title,
rating,
description,
} => update_review(program_id, accounts, title, rating, description),
}
}
pub fn add_review(
program_id: &Pubkey,
accounts: &[AccountInfo],
title: String,
rating: u8,
description: String,
) -> ProgramResult {
msg!("Adding review...");
msg!("Title: {}", title);
msg!("Rating: {}", rating);
msg!("Description: {}", description);
let account_info_iter = &mut accounts.iter();
let initializer = next_account_info(account_info_iter)?;
let pda_account = next_account_info(account_info_iter)?;
let system_program = next_account_info(account_info_iter)?;
if !initializer.is_signer {
msg!("Missing required signature");
return Err(ProgramError::MissingRequiredSignature);
}
let (pda, bump_seed) = Pubkey::find_program_address(
&[initializer.key.as_ref(), title.as_bytes().as_ref()],
program_id,
);
if pda != *pda_account.key {
msg!("Invalid seeds for PDA");
return Err(ProgramError::InvalidArgument);
}
if rating > 10 || rating < 1 {
return Err(ReviewError::InvalidRating.into());
}
let account_len: usize = 1000;
let rent = Rent::get()?;
let rent_lamports = rent.minimum_balance(account_len);
invoke_signed(
&system_instruction::create_account(
initializer.key,
pda_account.key,
rent_lamports,
account_len.try_into().unwrap(),
program_id,
),
&[
initializer.clone(),
pda_account.clone(),
system_program.clone(),
],
&[&[
initializer.key.as_ref(),
title.as_bytes().as_ref(),
&[bump_seed],
]],
)?;
msg!("PDA created: {}", pda);
msg!("unpacking state account");
let mut account_data =
try_from_slice_unchecked::<AccountState>(&pda_account.data.borrow()).unwrap();
msg!("borrowed account data");
msg!("checking if account is already initialized");
if account_data.is_initialized() {
msg!("Account already initialized");
return Err(ProgramError::AccountAlreadyInitialized);
}
account_data.title = title;
account_data.rating = rating;
account_data.description = description;
account_data.is_initialized = true;
msg!("serializing account");
account_data.serialize(&mut &mut pda_account.data.borrow_mut()[..])?;
msg!("state account serialized");
Ok(())
}
Comments
You need to enroll in the course to be able to comment!