use crate::account_view::AccountView;
use crate::address::Address;
use crate::instruction::{CpiAccount, Signer};
use crate::ProgramResult;
pub const SYSTEM_PROGRAM_ID: Address = Address::new_from_array([
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
]);
pub struct CreateAccount<'a, 'b> {
pub from: &'a AccountView,
pub to: &'a AccountView,
pub lamports: u64,
pub space: u64,
pub owner: &'b Address,
}
impl CreateAccount<'_, '_> {
#[inline]
pub fn invoke(&self) -> ProgramResult {
self.invoke_signed(&[])
}
#[inline]
pub fn invoke_signed(&self, signers: &[Signer]) -> ProgramResult {
let mut data = [0u8; 52];
data[4..12].copy_from_slice(&self.lamports.to_le_bytes());
data[12..20].copy_from_slice(&self.space.to_le_bytes());
data[20..52].copy_from_slice(self.owner.as_array());
let accounts = [CpiAccount::from(self.from), CpiAccount::from(self.to)];
invoke_system(&data, &accounts, signers)
}
}
pub struct Transfer<'a> {
pub from: &'a AccountView,
pub to: &'a AccountView,
pub lamports: u64,
}
impl Transfer<'_> {
#[inline]
pub fn invoke(&self) -> ProgramResult {
self.invoke_signed(&[])
}
#[inline]
pub fn invoke_signed(&self, signers: &[Signer]) -> ProgramResult {
let mut data = [0u8; 12];
data[0] = 2;
data[4..12].copy_from_slice(&self.lamports.to_le_bytes());
let accounts = [CpiAccount::from(self.from), CpiAccount::from(self.to)];
invoke_system(&data, &accounts, signers)
}
}
pub struct Assign<'a, 'b> {
pub account: &'a AccountView,
pub owner: &'b Address,
}
impl Assign<'_, '_> {
#[inline]
pub fn invoke(&self) -> ProgramResult {
self.invoke_signed(&[])
}
#[inline]
pub fn invoke_signed(&self, signers: &[Signer]) -> ProgramResult {
let mut data = [0u8; 36];
data[0] = 1;
data[4..36].copy_from_slice(self.owner.as_array());
let accounts = [CpiAccount::from(self.account)];
invoke_system(&data, &accounts, signers)
}
}
pub struct Allocate<'a> {
pub account: &'a AccountView,
pub space: u64,
}
impl Allocate<'_> {
#[inline]
pub fn invoke(&self) -> ProgramResult {
self.invoke_signed(&[])
}
#[inline]
pub fn invoke_signed(&self, signers: &[Signer]) -> ProgramResult {
let mut data = [0u8; 12];
data[0] = 8;
data[4..12].copy_from_slice(&self.space.to_le_bytes());
let accounts = [CpiAccount::from(self.account)];
invoke_system(&data, &accounts, signers)
}
}
#[inline]
fn invoke_system(data: &[u8], accounts: &[CpiAccount], signers: &[Signer]) -> ProgramResult {
#[cfg(target_os = "solana")]
{
let ix = crate::instruction::InstructionView {
program_id: &SYSTEM_PROGRAM_ID,
data,
accounts: &[], };
let result = unsafe {
crate::syscalls::sol_invoke_signed_c(
&ix as *const _ as *const u8,
accounts.as_ptr() as *const u8,
accounts.len() as u64,
signers.as_ptr() as *const u8,
signers.len() as u64,
)
};
if result == 0 {
Ok(())
} else {
Err(crate::ProgramError::from(result))
}
}
#[cfg(not(target_os = "solana"))]
{
let _ = (data, accounts, signers);
Ok(())
}
}
pub mod instructions {
pub use super::{Allocate, Assign, CreateAccount, Transfer};
}