Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions basics/checking-accounts/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/checking-accounts/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 = ""
respository = ""
readme = "./README.md"
keywords = ["solana"]

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

**Steel** 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
- [`Hello`](program/src/hello.rs) – Hello ...

## State
- [`User`](api/src/state/user.rs) – User ...

## Tests

To run the test suit, use the Solana toolchain:
```
cargo test-sbf
```
11 changes: 11 additions & 0 deletions basics/checking-accounts/steel/api/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[package]
name = "steel-api"
version = "0.1.0"
edition = "2021"

[dependencies]
bytemuck.workspace = true
num_enum.workspace = true
solana-program.workspace = true
steel.workspace = true
thiserror.workspace = true
2 changes: 2 additions & 0 deletions basics/checking-accounts/steel/api/src/consts.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/// Seed of the account_to_change account PDA.
pub const ACCOUNT_TO_CHANGE: &[u8] = b"account_to_change";
13 changes: 13 additions & 0 deletions basics/checking-accounts/steel/api/src/instruction.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
use steel::*;

#[repr(u8)]
#[derive(Clone, Copy, Debug, Eq, PartialEq, TryFromPrimitive)]
pub enum SteelInstruction {
CheckAccounts = 0,
}

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

instruction!(SteelInstruction, CheckAccounts);
16 changes: 16 additions & 0 deletions basics/checking-accounts/steel/api/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
pub mod consts;
pub mod instruction;
pub mod sdk;
pub mod state;

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

use steel::*;

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

use crate::prelude::*;

pub fn check_accounts(
signer: Pubkey,
account_to_create: Pubkey,
account_to_change: Pubkey,
) -> Instruction {
Instruction {
program_id: crate::ID,
accounts: vec![
AccountMeta::new(signer, true),
AccountMeta::new(account_to_create, false),
AccountMeta::new(account_to_change, false),
AccountMeta::new_readonly(system_program::ID, false),
],
data: CheckAccounts {}.to_bytes(),
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
use steel::*;

use super::SteelAccount;

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

account!(SteelAccount, AccountToChange);
18 changes: 18 additions & 0 deletions basics/checking-accounts/steel/api/src/state/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
mod account_to_change;

pub use account_to_change::*;

use steel::*;

use crate::consts::*;

#[repr(u8)]
#[derive(Clone, Copy, Debug, Eq, PartialEq, IntoPrimitive, TryFromPrimitive)]
pub enum SteelAccount {
AccountToChange = 0,
}

/// Fetch PDA of the account_to_change account.
pub fn account_to_change_pda() -> (Pubkey, u8) {
Pubkey::find_program_address(&[ACCOUNT_TO_CHANGE], &crate::id())
}
19 changes: 19 additions & 0 deletions basics/checking-accounts/steel/program/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
[package]
name = "steel-program"
version = "0.1.0"
edition = "2021"

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

[dependencies]
steel-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"] }
49 changes: 49 additions & 0 deletions basics/checking-accounts/steel/program/src/check_accounts.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
use solana_program::msg;
use steel::*;

pub fn process_check_accounts(accounts: &[AccountInfo<'_>], _data: &[u8]) -> ProgramResult {
// Load accounts.
// You can verify the list has the correct number of accounts.
let [signer_info, account_to_create_info, account_to_change_info, system_program] = accounts
else {
return Err(ProgramError::NotEnoughAccountKeys);
};

// You can verify if an account is a signer
signer_info.is_signer()?;

// You can verify the program ID from the instruction is in fact
// the program ID of your program.
if system_program.is_program(&system_program::ID).is_err() {
return Err(ProgramError::IncorrectProgramId);
};

// You can make sure an account has NOT been initialized.

msg!("New account: {}", account_to_create_info.key);
if account_to_create_info.lamports() != 0 {
msg!("The program expected the account to create to not yet be initialized.");
return Err(ProgramError::AccountAlreadyInitialized);
};
// (Create account...)

// You can also make sure an account has been initialized.
msg!("Account to change: {}", account_to_change_info.key);
if account_to_change_info.lamports() == 0 {
msg!("The program expected the account to change to be initialized.");
return Err(ProgramError::UninitializedAccount);
};

// If we want to modify an account's data, it must be owned by our program.
if account_to_change_info.owner != &steel_api::ID {
msg!("Account to change does not have the correct program id.");
return Err(ProgramError::IncorrectProgramId);
};

// You can also check pubkeys against constants.
if system_program.key != &system_program::ID {
return Err(ProgramError::IncorrectProgramId);
};

Ok(())
}
22 changes: 22 additions & 0 deletions basics/checking-accounts/steel/program/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
mod check_accounts;

use check_accounts::*;

use steel::*;
use steel_api::prelude::*;

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

match ix {
SteelInstruction::CheckAccounts => process_check_accounts(accounts, data)?,
}

Ok(())
}

entrypoint!(process_instruction);
51 changes: 51 additions & 0 deletions basics/checking-accounts/steel/program/tests/test.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
use solana_program::hash::Hash;
use solana_program_test::{processor, BanksClient, ProgramTest};
use solana_sdk::{signature::Keypair, signer::Signer, transaction::Transaction};
use steel_api::prelude::*;

async fn setup() -> (BanksClient, Keypair, Hash) {
let mut program_test = ProgramTest::new(
"steel_program",
steel_api::ID,
processor!(steel_program::process_instruction),
);
program_test.prefer_bpf(true);
program_test.start().await
}

#[tokio::test]
async fn run_test() {
// Setup test
let (mut banks, payer, blockhash) = setup().await;

let account_to_create = Keypair::new();
let account_to_change = Keypair::new();

let account_to_change_ix = solana_sdk::system_instruction::create_account(
&payer.pubkey(),
&account_to_change.pubkey(),
solana_sdk::native_token::LAMPORTS_PER_SOL,
0,
&steel_api::ID,
);

let tx = Transaction::new_signed_with_payer(
&[account_to_change_ix],
Some(&payer.pubkey()),
&[&payer, &account_to_change],
blockhash,
);

let res = banks.process_transaction(tx).await;
assert!(res.is_ok());

// Submit check_accounts transaction.
let ix = check_accounts(
payer.pubkey(),
account_to_create.pubkey(),
account_to_change.pubkey(),
);
let tx = Transaction::new_signed_with_payer(&[ix], Some(&payer.pubkey()), &[&payer], blockhash);
let res = banks.process_transaction(tx).await;
assert!(res.is_ok());
}