Skip to content

Commit

Permalink
add basics/realloc/steel (#241)
Browse files Browse the repository at this point in the history
Co-authored-by: Ayush <[email protected]>
  • Loading branch information
Perelyn-sama and heyAyushh authored Jan 2, 2025
1 parent cd7eb23 commit 30d45c7
Show file tree
Hide file tree
Showing 19 changed files with 427 additions and 0 deletions.
2 changes: 2 additions & 0 deletions basics/realloc/steel/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
target
test-ledger
21 changes: 21 additions & 0 deletions basics/realloc/steel/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
[workspace]
resolver = "2"
members = ["api", "program"]

[workspace.package]
version = "0.1.0"
edition = "2021"
license = "Apache-2.0"
homepage = ""
documentation = ""
repository = ""
readme = "./README.md"
keywords = ["solana"]

[workspace.dependencies]
realloc-api = { path = "./api", version = "0.1.0" }
bytemuck = "1.14"
num_enum = "0.7"
solana-program = "1.18"
steel = "2.0"
thiserror = "1.0"
28 changes: 28 additions & 0 deletions basics/realloc/steel/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Realloc

**Realloc** is a ...

## API
- [`Consts`](api/src/consts.rs) – Program constants.
- [`Error`](api/src/error.rs) – Custom program errors.
- [`Event`](api/src/event.rs) – Custom program events.
- [`Instruction`](api/src/instruction.rs) – Declared instructions.

## Instructions
- [`Add`](program/src/add.rs) – Add ...
- [`Initialize`](program/src/initialize.rs) – Initialize ...

## State
- [`Counter`](api/src/state/counter.rs) – Counter ...

## Get started

Compile your program:
```sh
steel build
```

Run unit and integration tests:
```sh
steel test
```
18 changes: 18 additions & 0 deletions basics/realloc/steel/api/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[package]
name = "realloc-api"
description = "API for interacting with the Realloc program"
version.workspace = true
edition.workspace = true
license.workspace = true
homepage.workspace = true
documentation.workspace = true
repository.workspace = true
readme.workspace = true
keywords.workspace = true

[dependencies]
bytemuck.workspace = true
num_enum.workspace = true
solana-program.workspace = true
steel.workspace = true
thiserror.workspace = true
4 changes: 4 additions & 0 deletions basics/realloc/steel/api/src/consts.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
/// Seed of the address_info account PDA.
pub const ADDRESS_INFO: &[u8] = b"address_info";

pub const MAX_STR_LEN: usize = 32;
10 changes: 10 additions & 0 deletions basics/realloc/steel/api/src/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
use steel::*;

#[derive(Debug, Error, Clone, Copy, PartialEq, Eq, IntoPrimitive)]
#[repr(u32)]
pub enum ReallocError {
#[error("This is a dummy error")]
Dummy = 0,
}

error!(ReallocError);
21 changes: 21 additions & 0 deletions basics/realloc/steel/api/src/instruction.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
use steel::*;

#[repr(u8)]
#[derive(Clone, Copy, Debug, Eq, PartialEq, TryFromPrimitive)]
pub enum ReallocInstruction {
Initialize = 0,
Add = 1
}

#[repr(C)]
#[derive(Clone, Copy, Debug, Pod, Zeroable)]
pub struct Initialize {}

#[repr(C)]
#[derive(Clone, Copy, Debug, Pod, Zeroable)]
pub struct Add {
pub amount: [u8; 8]
}

instruction!(ReallocInstruction, Initialize);
instruction!(ReallocInstruction, Add);
20 changes: 20 additions & 0 deletions basics/realloc/steel/api/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
pub mod consts;
pub mod error;
pub mod instruction;
pub mod sdk;
pub mod state;
pub mod utils;

pub mod prelude {
pub use crate::consts::*;
pub use crate::error::*;
pub use crate::instruction::*;
pub use crate::sdk::*;
pub use crate::state::*;
pub use crate::utils::*;
}

use steel::*;

// TODO Set program id
declare_id!("z7msBPQHDJjTvdQRoEcKyENgXDhSRYeHieN1ZMTqo35");
29 changes: 29 additions & 0 deletions basics/realloc/steel/api/src/sdk.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
use steel::*;

use crate::prelude::*;

pub fn initialize(signer: Pubkey) -> Instruction {
Instruction {
program_id: crate::ID,
accounts: vec![
AccountMeta::new(signer, true),
AccountMeta::new(counter_pda().0, false),
AccountMeta::new_readonly(system_program::ID, false),
],
data: Initialize {}.to_bytes()
}
}

pub fn add(signer: Pubkey, amount: u64) -> Instruction {
Instruction {
program_id: crate::ID,
accounts: vec![
AccountMeta::new(signer, true),
AccountMeta::new(counter_pda().0, false),
],
data: Add {
amount: amount.to_le_bytes(),
}
.to_bytes(),
}
}
27 changes: 27 additions & 0 deletions basics/realloc/steel/api/src/state/address_info.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
use crate::consts::*;
use crate::utils::*;
use steel::*;

use super::ReallocAccount;

#[repr(C)]
#[derive(Clone, Copy, Debug, PartialEq, Pod, Zeroable)]
pub struct AddressInfo {
pub name: [u8; MAX_STR_LEN],
pub house_number: u8,
pub street: [u8; MAX_STR_LEN],
pub city: [u8; MAX_STR_LEN],
}

impl AddressInfo {
pub fn new(name: &str, house_number: u8, street: &str, city: &str) -> Self {
AddressInfo {
name: str_to_bytes(name),
house_number,
street: str_to_bytes(street),
city: str_to_bytes(city),
}
}
}

account!(ReallocAccount, AddressInfo);
43 changes: 43 additions & 0 deletions basics/realloc/steel/api/src/state/enchanced_address_info.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
use crate::consts::*;
use crate::state::AddressInfo;
use crate::utils::*;
use steel::*;

use super::ReallocAccount;

#[repr(C)]
#[derive(Clone, Copy, Debug, PartialEq, Pod, Zeroable)]
pub struct EnhancedAddressInfoExtender {
pub state: [u8; MAX_STR_LEN],
pub zip: u32,
}

#[repr(C)]
#[derive(Clone, Copy, Debug, PartialEq, Pod, Zeroable)]
pub struct EnhancedAddressInfo {
pub zip: u32,
pub house_number: u8,

pub name: [u8; MAX_STR_LEN],
pub street: [u8; MAX_STR_LEN],
pub city: [u8; MAX_STR_LEN],
pub state: [u8; MAX_STR_LEN],

pub _padding: [u8; 3],
}

impl EnhancedAddressInfo {
pub fn from_address_info(address_info: AddressInfo, state: &str, zip: u32) -> Self {
EnhancedAddressInfo {
name: address_info.name,
house_number: address_info.house_number,
street: address_info.street,
city: address_info.city,
state: str_to_bytes(state),
zip,
_padding: [0u8; 3],
}
}
}

account!(ReallocAccount, EnhancedAddressInfo);
25 changes: 25 additions & 0 deletions basics/realloc/steel/api/src/state/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
mod address_info;
mod enchanced_address_info;
mod work_info;

pub use address_info::*;
pub use enchanced_address_info::*;
pub use work_info::*;

use steel::*;

use crate::consts::*;

#[repr(u8)]
#[derive(Clone, Copy, Debug, Eq, PartialEq, IntoPrimitive, TryFromPrimitive)]
pub enum ReallocAccount {
AddressInfo = 0,
EnhancedAddressInfo = 1,
EnhancedAddressInfoExtender = 2,
WorkInfo = 3,
}

/// Fetch PDA of the counter account.
pub fn counter_pda() -> (Pubkey, u8) {
Pubkey::find_program_address(&[COUNTER], &crate::id())
}
27 changes: 27 additions & 0 deletions basics/realloc/steel/api/src/state/work_info.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
use crate::consts::*;
use crate::utils::*;
use steel::*;

use super::ReallocAccount;

#[repr(C)]
#[derive(Clone, Copy, Debug, PartialEq, Pod, Zeroable)]
pub struct WorkInfo {
pub name: [u8; MAX_STR_LEN],
pub position: [u8; MAX_STR_LEN],
pub company: [u8; MAX_STR_LEN],
pub years_employed: u8,
}

impl WorkInfo {
pub fn new(name: &str, position: &str, company: &str, years_employed: u8) -> Self {
WorkInfo {
name: str_to_bytes(name),
position: str_to_bytes(position),
company: str_to_bytes(company),
years_employed,
}
}
}

account!(ReallocAccount, WorkInfo);
5 changes: 5 additions & 0 deletions basics/realloc/steel/api/src/utils.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
pub fn str_to_bytes(name: &str) -> [u8; MAX_STR_LEN] {
let mut name_bytes = [0u8; MAX_STR_LEN];
name_bytes[..name.len()].copy_from_slice(name.as_bytes());
name_bytes
}
26 changes: 26 additions & 0 deletions basics/realloc/steel/program/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
[package]
name = "realloc-program"
description = ""
version.workspace = true
edition.workspace = true
license.workspace = true
homepage.workspace = true
documentation.workspace = true
repository.workspace = true
readme.workspace = true
keywords.workspace = true

[lib]
crate-type = ["cdylib", "lib"]

[dependencies]
realloc-api.workspace = true
solana-program.workspace = true
steel.workspace = true

[dev-dependencies]
base64 = "0.21"
rand = "0.8.5"
solana-program-test = "1.18"
solana-sdk = "1.18"
tokio = { version = "1.35", features = ["full"] }
22 changes: 22 additions & 0 deletions basics/realloc/steel/program/src/add.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
use realloc_api::prelude::*;
use steel::*;

pub fn process_add(accounts: &[AccountInfo<'_>], data: &[u8]) -> ProgramResult {
// Parse args.
let args = Add::try_from_bytes(data)?;
let amount = u64::from_le_bytes(args.amount);

// Load accounts.
let [signer_info, counter_info] = accounts else {
return Err(ProgramError::NotEnoughAccountKeys);
};
signer_info.is_signer()?;
let counter = counter_info
.as_account_mut::<Counter>(&realloc_api::ID)?
.assert_mut(|c| c.value < 100)?;

// Update state
counter.value += amount;

Ok(())
}
28 changes: 28 additions & 0 deletions basics/realloc/steel/program/src/initialize.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
use realloc_api::prelude::*;
use steel::*;

pub fn process_initialize(accounts: &[AccountInfo<'_>], _data: &[u8]) -> ProgramResult {
// Load accounts.
let [signer_info, counter_info, system_program] = accounts else {
return Err(ProgramError::NotEnoughAccountKeys);
};
signer_info.is_signer()?;
counter_info.is_empty()?.is_writable()?.has_seeds(
&[COUNTER],
&realloc_api::ID
)?;
system_program.is_program(&system_program::ID)?;

// Initialize counter.
create_account::<Counter>(
counter_info,
system_program,
signer_info,
&realloc_api::ID,
&[COUNTER],
)?;
let counter = counter_info.as_account_mut::<Counter>(&realloc_api::ID)?;
counter.value = 0;

Ok(())
}
25 changes: 25 additions & 0 deletions basics/realloc/steel/program/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
mod add;
mod initialize;

use add::*;
use initialize::*;

use realloc_api::prelude::*;
use steel::*;

pub fn process_instruction(
program_id: &Pubkey,
accounts: &[AccountInfo],
data: &[u8],
) -> ProgramResult {
let (ix, data) = parse_instruction(&realloc_api::ID, program_id, data)?;

match ix {
ReallocInstruction::Initialize => process_initialize(accounts, data)?,
ReallocInstruction::Add => process_add(accounts, data)?,
}

Ok(())
}

entrypoint!(process_instruction);
Loading

0 comments on commit 30d45c7

Please sign in to comment.