Skip to content

Commit 16068f8

Browse files
add basics/program-derived-addresses/steel (#343)
1 parent 2f244bf commit 16068f8

18 files changed

+1783
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
target
2+
test-ledger
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
[workspace]
2+
resolver = "2"
3+
members = ["api", "program"]
4+
5+
[workspace.package]
6+
version = "0.1.0"
7+
edition = "2021"
8+
license = "Apache-2.0"
9+
homepage = ""
10+
documentation = ""
11+
respository = ""
12+
readme = "./README.md"
13+
keywords = ["solana"]
14+
15+
[workspace.dependencies]
16+
program-derived-addresses-api = { path = "./api", version = "0.1.0" }
17+
bytemuck = "1.14"
18+
num_enum = "0.7"
19+
solana-program = "1.18"
20+
steel = "2.1"
21+
thiserror = "1.0"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Program Derived Addresses
2+
3+
This program demonstrates how to derive addresses. It will use a PDA to store a counter of visits and increment it.
4+
5+
## Building
6+
7+
```sh
8+
cargo build-sbf
9+
10+
```
11+
## Tests
12+
13+
This project includes both:
14+
- Rust tests: [`program/tests`](/program/tests) directory.
15+
- Node.js tests using [Bankrun](https://kevinheavey.github.io/solana-bankrun/): [`tests`](/tests) directory.
16+
17+
```sh
18+
# rust tests
19+
cargo test-sbf
20+
21+
# node tests
22+
pnpm build-and-test # this will also build the program
23+
#or
24+
pnpm test # if you have already built the program
25+
```
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
[package]
2+
name = "program-derived-addresses-api"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
[dependencies]
7+
bytemuck.workspace = true
8+
num_enum.workspace = true
9+
solana-program.workspace = true
10+
steel.workspace = true
11+
thiserror.workspace = true
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
/// Seed of the account PDA.
2+
pub const SEED: &[u8] = b"program-derived-addresses";
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
use steel::*;
2+
3+
use crate::state::PageVisits;
4+
5+
#[repr(u8)]
6+
#[derive(Clone, Copy, Debug, Eq, PartialEq, TryFromPrimitive)]
7+
pub enum ProgramDerivedAddressesInstruction {
8+
Create = 0,
9+
Increment = 1,
10+
}
11+
12+
#[repr(C)]
13+
#[derive(Clone, Copy, Debug, Pod, Zeroable)]
14+
pub struct Create {
15+
pub page_visits: PageVisits,
16+
}
17+
18+
#[repr(C)]
19+
#[derive(Clone, Copy, Debug, Pod, Zeroable)]
20+
pub struct Increment {}
21+
22+
instruction!(ProgramDerivedAddressesInstruction, Create);
23+
instruction!(ProgramDerivedAddressesInstruction, Increment);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
pub mod consts;
2+
pub mod instruction;
3+
pub mod sdk;
4+
pub mod state;
5+
6+
pub mod prelude {
7+
pub use crate::consts::*;
8+
pub use crate::instruction::*;
9+
pub use crate::sdk::*;
10+
pub use crate::state::*;
11+
}
12+
13+
use steel::*;
14+
15+
// TODO Set program id
16+
declare_id!("z7msBPQHDJjTvdQRoEcKyENgXDhSRYeHieN1ZMTqo35");
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
use steel::*;
2+
3+
use crate::prelude::*;
4+
5+
pub fn create(signer: Pubkey, user: Pubkey, page_visits: PageVisits) -> Instruction {
6+
let pda = page_visits_pda(&user);
7+
Instruction {
8+
program_id: crate::ID,
9+
accounts: vec![
10+
AccountMeta::new(signer, true),
11+
AccountMeta::new(user, false),
12+
AccountMeta::new(pda.0, false),
13+
AccountMeta::new_readonly(system_program::ID, false),
14+
],
15+
data: Create { page_visits }.to_bytes(),
16+
}
17+
}
18+
19+
pub fn increment(page_visits_pda: Pubkey) -> Instruction {
20+
Instruction {
21+
program_id: crate::ID,
22+
accounts: vec![AccountMeta::new(page_visits_pda, false)],
23+
data: Increment {}.to_bytes(),
24+
}
25+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
use steel::*;
2+
3+
use crate::consts::*;
4+
5+
#[repr(u8)]
6+
#[derive(Clone, Copy, Debug, Eq, PartialEq, IntoPrimitive, TryFromPrimitive)]
7+
pub enum ProgramDerivedAddressesAccount {
8+
PageVisits = 0,
9+
}
10+
11+
#[repr(C)]
12+
#[derive(Clone, Copy, Debug, PartialEq, Pod, Zeroable)]
13+
pub struct PageVisits {
14+
pub page_visits: [u8; 4], // u32
15+
pub bump: [u8; 1],
16+
}
17+
18+
impl PageVisits {
19+
pub fn increment_visits(&mut self) {
20+
let visits = u32::from_le_bytes(self.page_visits);
21+
self.page_visits = (visits + 1).to_le_bytes();
22+
}
23+
24+
pub fn page_visits(&self) -> u32 {
25+
u32::from_le_bytes(self.page_visits)
26+
}
27+
}
28+
29+
account!(ProgramDerivedAddressesAccount, PageVisits);
30+
31+
/// Fetch PDA of the PageVisit account.
32+
pub fn page_visits_pda(user: &Pubkey) -> (Pubkey, u8) {
33+
Pubkey::find_program_address(&[SEED, user.as_ref()], &crate::id())
34+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
{
2+
"name": "program-derived-addresses",
3+
"version": "1.0.0",
4+
"description": "",
5+
"scripts": {
6+
"test": "pnpm ts-mocha -p ./tsconfig.json -t 1000000 ./tests/*.test.ts",
7+
"build-and-test": "cargo build-sbf --manifest-path=./program/Cargo.toml --sbf-out-dir=./tests/fixtures && pnpm test",
8+
"build": "cargo build-sbf --manifest-path=./program/Cargo.toml --sbf-out-dir=./program/target/so",
9+
"deploy": "solana program deploy ./program/target/so/program_derived_addresses_program.so"
10+
},
11+
"keywords": [],
12+
"author": "",
13+
"license": "ISC",
14+
"dependencies": {
15+
"@solana/web3.js": "^1.95.4"
16+
},
17+
"devDependencies": {
18+
"@types/chai": "^4.3.7",
19+
"@types/mocha": "10.0.9",
20+
"@types/node": "^22.7.4",
21+
"borsh": "^2.0.0",
22+
"chai": "^4.3.7",
23+
"mocha": "10.7.3",
24+
"solana-bankrun": "0.4.0",
25+
"ts-mocha": "^10.0.0",
26+
"typescript": "5.6.3"
27+
}
28+
}

0 commit comments

Comments
 (0)