Accounts
Anchor → Pinocchio
| Anchor | Pinocchio |
|---|---|
AccountInfo<'info> |
AccountView |
#[account(mut)] |
Manual is_writable() check |
#[account(signer)] |
Manual is_signer() check |
#[account(owner = ...)] |
Manual owned_by() check |
#[derive(Accounts)] |
TryFrom<&[AccountView]> |
AccountView API
use pinocchio::{AccountView, Address, ProgramResult, entrypoint, error::ProgramError};
entrypoint!(process_instruction);
pub fn process_instruction(
program_id: &Address,
accounts: &[AccountView],
instruction_data: &[u8],
) -> ProgramResult {
let account = &accounts[0];
let data = account.try_borrow()?;
// Read fields
let addr: &Address = account.address();
let lamports: u64 = account.lamports();
let _bytes: &[u8] = &data;
// Checks
let is_signer: bool = account.is_signer();
let is_writable: bool = account.is_writable();
let owned_by_program: bool = account.owned_by(program_id);
let _ = (addr, lamports, is_signer, is_writable, owned_by_program);
Ok(())
}
Destructuring Accounts
pub fn process_instruction(
program_id: &Address,
accounts: &[AccountView],
instruction_data: &[u8],
) -> ProgramResult {
let [payer, counter, authority, system_program, ..] = accounts else {
return Err(ProgramError::NotEnoughAccountKeys);
};
Ok(())
}
Anchor equivalent:
#[derive(Accounts)]
pub struct Initialize<'info> {
#[account(mut)]
pub payer: Signer<'info>,
#[account(mut)]
pub counter: Account<'info, Counter>,
pub authority: AccountInfo<'info>,
pub system_program: Program<'info, System>,
}
Common Validations
// Signer check (#[account(signer)] in Anchor)
if !authority.is_signer() {
return Err(ProgramError::MissingRequiredSignature);
}
// Owner check (#[account(owner = program)] in Anchor)
if !account.owned_by(program_id) {
return Err(ProgramError::InvalidAccountOwner);
}
// Address check (#[account(address = EXPECTED)] in Anchor)
if account.address() != &expected_address {
return Err(ProgramError::InvalidAccountData);
}
// System account (wallet)
if !account.owned_by(&pinocchio_system::ID) {
return Err(ProgramError::InvalidAccountOwner);
}
// Token account
if !account.owned_by(&pinocchio_token::ID) {
return Err(ProgramError::InvalidAccountOwner);
}
Mutable Data Access
fn update(account: &AccountView) -> ProgramResult {
let mut data = account.try_borrow_mut()?;
data[0..8].copy_from_slice(&42u64.to_le_bytes());
Ok(())
}
TryFrom Pattern
Anchor's #[derive(Accounts)] generates validation logic. In Pinocchio, use TryFrom:
pub struct DepositAccounts<'a> {
pub user: &'a AccountView,
pub vault: &'a AccountView,
}
impl<'a> TryFrom<&'a [AccountView]> for DepositAccounts<'a> {
type Error = ProgramError;
fn try_from(accounts: &'a [AccountView]) -> Result<Self, Self::Error> {
let [user, vault, _system, ..] = accounts else {
return Err(ProgramError::NotEnoughAccountKeys);
};
if !user.is_signer() {
return Err(ProgramError::MissingRequiredSignature);
}
Ok(Self { user, vault })
}
}
// Usage
let accounts = DepositAccounts::try_from(accounts)?;
Anchor equivalent:
#[derive(Accounts)]
pub struct Deposit<'info> {
#[account(mut, signer)]
pub user: AccountInfo<'info>,
#[account(mut)]
pub vault: Account<'info, Vault>,
}