Skip to content

Commit 446665a

Browse files
committed
feat: Added pinocchio version of the program derived address program
1 parent 2e54ff1 commit 446665a

File tree

13 files changed

+476
-0
lines changed

13 files changed

+476
-0
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ members = [
2323
"basics/processing-instructions/anchor/programs/*",
2424
"basics/program-derived-addresses/native/program",
2525
"basics/program-derived-addresses/anchor/programs/*",
26+
"basics/program-derived-addresses/pinocchio/program",
2627
"basics/realloc/native/program",
2728
"basics/realloc/anchor/programs/*",
2829
"basics/rent/native/program",
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"scripts": {
3+
"test": "pnpm ts-mocha -p ./tsconfig.json -t 1000000 ./test/pageVisit.test.ts",
4+
"build-and-test": "cargo build-sbf --manifest-path=./program/Cargo.toml --sbf-out-dir=./tests/fixtures && pnpm test",
5+
"build": "cargo build-sbf --manifest-path=./program/Cargo.toml --sbf-out-dir=./program/target/so",
6+
"deploy": "solana program deploy ./program/target/so/hello_solana_program_pinocchio.so"
7+
},
8+
"dependencies": {
9+
"@solana/web3.js": "^1.47.3"
10+
},
11+
"devDependencies": {
12+
"@types/bn.js": "^5.1.0",
13+
"@types/chai": "^4.3.1",
14+
"@types/mocha": "^9.1.1",
15+
"@types/node": "^22.15.2",
16+
"chai": "^4.3.4",
17+
"mocha": "^9.0.3",
18+
"solana-bankrun": "^0.3.0",
19+
"ts-mocha": "^10.0.0",
20+
"typescript": "^4.3.5"
21+
}
22+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
[package]
2+
name = "pinocchio-program-derived-address"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
[lib]
7+
crate-type = ["cdylib", "lib"]
8+
9+
[dependencies]
10+
bytemuck = {version = "1.24.0", features = ["derive"]}
11+
pinocchio = "0.9.2"
12+
pinocchio-pubkey = "0.3.0"
13+
pinocchio-system = "0.3.0"
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
use bytemuck::{Pod, Zeroable};
2+
use pinocchio::{account_info::AccountInfo, msg, program_error::ProgramError};
3+
pub fn require(
4+
condition: bool,
5+
err: ProgramError,
6+
reason: Option<&str>,
7+
) -> Result<(), ProgramError> {
8+
if !condition {
9+
if let Some(error) = reason {
10+
msg!(error)
11+
}
12+
Err(err)
13+
} else {
14+
Ok(())
15+
}
16+
}
17+
18+
pub fn load<T>(account: &AccountInfo) -> Result<&mut T, ProgramError>
19+
where
20+
T: Pod + Zeroable,
21+
{
22+
let data = unsafe { account.borrow_mut_data_unchecked() };
23+
24+
bytemuck::try_from_bytes_mut::<T>(data).map_err(|_| ProgramError::InvalidAccountData)
25+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
use crate::{load, require, states::page_visit::PageVisits};
2+
use {
3+
pinocchio::{
4+
account_info::AccountInfo,
5+
instruction::{Seed, Signer},
6+
msg,
7+
program_error::ProgramError,
8+
pubkey::Pubkey,
9+
sysvars::{rent::Rent, Sysvar},
10+
ProgramResult,
11+
},
12+
pinocchio_system::instructions::CreateAccount,
13+
};
14+
15+
pub fn process_create_page(program_id: &Pubkey, accounts: &[AccountInfo]) -> ProgramResult {
16+
msg!("PageVisits Instruction: CreatePage");
17+
if let [creator, page_pda, _system_program] = accounts {
18+
require(
19+
creator.is_signer() && creator.is_writable(),
20+
ProgramError::MissingRequiredSignature,
21+
None,
22+
)?;
23+
24+
let bump = PageVisits::check_id(page_pda.key(), creator.key())?;
25+
26+
let seed_bumps = &[bump];
27+
let seeds = [
28+
Seed::from(PageVisits::PREFIX),
29+
Seed::from(creator.key().as_ref()),
30+
Seed::from(seed_bumps),
31+
];
32+
33+
let signer_seeds = Signer::from(&seeds);
34+
35+
CreateAccount {
36+
from: creator,
37+
lamports: Rent::get()?.minimum_balance(PageVisits::SIZE),
38+
owner: program_id,
39+
space: PageVisits::SIZE as u64,
40+
to: page_pda,
41+
}
42+
.invoke_signed(&[signer_seeds])?;
43+
44+
let page_data = load::<PageVisits>(page_pda)?;
45+
46+
page_data.page_visits = 0;
47+
page_data.bump = bump;
48+
49+
Ok(())
50+
} else {
51+
Err(ProgramError::NotEnoughAccountKeys)
52+
}
53+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
use crate::{require, states::page_visit::PageVisits};
2+
use pinocchio::{
3+
account_info::AccountInfo, msg, program_error::ProgramError, pubkey::Pubkey, ProgramResult,
4+
};
5+
6+
pub fn process_increament_page_visits(
7+
_program_id: &Pubkey,
8+
accounts: &[AccountInfo],
9+
) -> ProgramResult {
10+
msg!("PageVisits Instruction: IncrementPageVisits");
11+
if let [user, creator, page_pda, _system_program] = accounts {
12+
require(
13+
user.is_signer() && user.is_writable(),
14+
ProgramError::MissingRequiredSignature,
15+
None,
16+
)?;
17+
18+
let page_visit_data = PageVisits::check_id_with_bump(page_pda, creator.key())?;
19+
20+
page_visit_data.page_visits += 1;
21+
22+
Ok(())
23+
} else {
24+
Err(ProgramError::NotEnoughAccountKeys)
25+
}
26+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
use pinocchio::program_error::ProgramError;
2+
3+
pub mod create_page;
4+
pub mod increment_page_visits;
5+
6+
#[repr(u8)]
7+
pub enum CreatePageInstructions {
8+
CreatePage,
9+
IncrementPageVisits,
10+
}
11+
12+
impl TryFrom<&u8> for CreatePageInstructions {
13+
type Error = ProgramError;
14+
15+
fn try_from(value: &u8) -> Result<Self, Self::Error> {
16+
match *value {
17+
0 => Ok(CreatePageInstructions::CreatePage),
18+
1 => Ok(CreatePageInstructions::IncrementPageVisits),
19+
_ => Err(ProgramError::InvalidInstructionData),
20+
}
21+
}
22+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#![no_std]
2+
use pinocchio::{no_allocator, nostd_panic_handler, program_entrypoint};
3+
use pinocchio_pubkey::declare_id;
4+
mod processor;
5+
use processor::process_instruction;
6+
mod helper;
7+
pub use helper::*;
8+
mod instructions;
9+
mod states;
10+
declare_id!("8TpdLD58VBWsdzxRi2yRcmKJD9UcE2GuUrBwsyCwpbUN");
11+
12+
program_entrypoint!(process_instruction);
13+
no_allocator!();
14+
nostd_panic_handler!();
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
use crate::instructions::{create_page::*, increment_page_visits::*, CreatePageInstructions};
2+
use pinocchio::{
3+
account_info::AccountInfo, program_error::ProgramError, pubkey::Pubkey, ProgramResult,
4+
};
5+
6+
pub fn process_instruction(
7+
program_id: &Pubkey,
8+
accounts: &[AccountInfo],
9+
ix_data: &[u8],
10+
) -> ProgramResult {
11+
let (disc, _) = ix_data
12+
.split_first()
13+
.ok_or(ProgramError::InvalidInstructionData)?;
14+
15+
match CreatePageInstructions::try_from(disc)? {
16+
CreatePageInstructions::CreatePage => process_create_page(program_id, accounts)?,
17+
CreatePageInstructions::IncrementPageVisits => {
18+
process_increament_page_visits(program_id, accounts)?
19+
}
20+
}
21+
22+
Ok(())
23+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pub mod page_visit;

0 commit comments

Comments
 (0)