use quote::quote;
pub fn idl_accounts_and_functions() -> proc_macro2::TokenStream {
quote! {
use rialo_sol_lang::idl::ERASED_AUTHORITY;
#[account("internal")]
#[derive(Debug)]
pub struct IdlAccount {
pub authority: Pubkey,
pub data_len: u32,
}
impl IdlAccount {
pub fn address(program_id: &Pubkey) -> Pubkey {
let program_signer = Pubkey::find_program_address(&[], program_id).0;
Pubkey::create_with_seed(&program_signer, IdlAccount::seed(), program_id)
.expect("Seed is always valid")
}
pub fn seed() -> &'static str {
"anchor:idl"
}
}
impl rialo_sol_lang::Owner for IdlAccount {
fn owner() -> Pubkey {
crate::ID
}
}
#[derive(Accounts)]
pub struct IdlCreateAccounts<'info> {
#[account(signer)]
pub from: AccountInfo<'info>,
#[account(mut)]
pub to: AccountInfo<'info>,
#[account(seeds = [], bump)]
pub base: AccountInfo<'info>,
pub system_program: Program<'info, System>,
#[account(executable)]
pub program: AccountInfo<'info>,
}
#[derive(Accounts)]
pub struct IdlAccounts<'info> {
#[account(mut, has_one = authority)]
pub idl: Account<'info, IdlAccount>,
#[account(constraint = authority.key != &ERASED_AUTHORITY)]
pub authority: Signer<'info>,
}
#[derive(Accounts)]
pub struct IdlResizeAccount<'info> {
#[account(mut, has_one = authority)]
pub idl: Account<'info, IdlAccount>,
#[account(mut, constraint = authority.key != &ERASED_AUTHORITY)]
pub authority: Signer<'info>,
pub system_program: Program<'info, System>,
}
#[derive(Accounts)]
pub struct IdlCreateBuffer<'info> {
#[account(zero)]
pub buffer: Account<'info, IdlAccount>,
#[account(constraint = authority.key != &ERASED_AUTHORITY)]
pub authority: Signer<'info>,
}
#[derive(Accounts)]
pub struct IdlSetBuffer<'info> {
#[account(mut, constraint = buffer.authority == idl.authority)]
pub buffer: Account<'info, IdlAccount>,
#[account(mut, has_one = authority)]
pub idl: Account<'info, IdlAccount>,
#[account(constraint = authority.key != &ERASED_AUTHORITY)]
pub authority: Signer<'info>,
}
#[derive(Accounts)]
pub struct IdlCloseAccount<'info> {
#[account(mut, has_one = authority, close = sol_destination)]
pub account: Account<'info, IdlAccount>,
#[account(constraint = authority.key != &ERASED_AUTHORITY)]
pub authority: Signer<'info>,
#[account(mut)]
pub sol_destination: AccountInfo<'info>,
}
use std::cell::{Ref, RefMut};
pub trait IdlTrailingData<'info> {
fn trailing_data(self) -> Ref<'info, [u8]>;
fn trailing_data_mut(self) -> RefMut<'info, [u8]>;
}
impl<'a, 'info: 'a> IdlTrailingData<'a> for &'a Account<'info, IdlAccount> {
fn trailing_data(self) -> Ref<'a, [u8]> {
let info: &AccountInfo<'info> = self.as_ref();
Ref::map(info.try_borrow_data().unwrap(), |d| &d[44..])
}
fn trailing_data_mut(self) -> RefMut<'a, [u8]> {
let info: &AccountInfo<'info> = self.as_ref();
RefMut::map(info.try_borrow_mut_data().unwrap(), |d| &mut d[44..])
}
}
#[inline(never)]
pub fn __idl_create_account(
program_id: &Pubkey,
accounts: &mut IdlCreateAccounts,
data_len: u64,
) -> rialo_sol_lang::Result<()> {
#[cfg(not(feature = "no-log-ix-name"))]
rialo_sol_lang::prelude::msg!("Instruction: IdlCreateAccount");
if program_id != accounts.program.key {
return Err(rialo_sol_lang::error::ErrorCode::IdlInstructionInvalidProgram.into());
}
let from = accounts.from.key;
let (base, nonce) = Pubkey::find_program_address(&[], program_id);
let seed = IdlAccount::seed();
let owner = accounts.program.key;
let to = Pubkey::create_with_seed(&base, seed, owner).unwrap();
let space = std::cmp::min(
IdlAccount::DISCRIMINATOR.len() + 32 + 4 + data_len as usize,
10_000
);
let rent = Rent::get()?;
let kelvins = rent.minimum_balance(space);
let seeds = &[&[nonce][..]];
let ix = rialo_sol_lang::rialo_s_program::system_instruction::create_account_with_seed(
from,
&to,
&base,
seed,
kelvins,
space as u64,
owner,
);
rialo_sol_lang::rialo_s_program::program::invoke_signed(
&ix,
&[
accounts.from.clone(),
accounts.to.clone(),
accounts.base.clone(),
accounts.system_program.to_account_info(),
],
&[seeds],
)?;
let mut idl_account = {
let mut account_data = accounts.to.try_borrow_data()?;
let mut account_data_slice: &[u8] = &account_data;
IdlAccount::try_deserialize_unchecked(
&mut account_data_slice,
)?
};
idl_account.authority = *accounts.from.key;
let mut data = accounts.to.try_borrow_mut_data()?;
let dst: &mut [u8] = &mut data;
let mut cursor = std::io::Cursor::new(dst);
idl_account.try_serialize(&mut cursor)?;
Ok(())
}
#[inline(never)]
pub fn __idl_resize_account(
program_id: &Pubkey,
accounts: &mut IdlResizeAccount,
data_len: u64,
) -> rialo_sol_lang::Result<()> {
#[cfg(not(feature = "no-log-ix-name"))]
rialo_sol_lang::prelude::msg!("Instruction: IdlResizeAccount");
let data_len: usize = data_len as usize;
if accounts.idl.data_len != 0 {
return Err(rialo_sol_lang::error::ErrorCode::IdlAccountNotEmpty.into());
}
let idl_ref = AsRef::<AccountInfo>::as_ref(&accounts.idl);
let new_account_space = idl_ref.data_len().checked_add(std::cmp::min(
data_len
.checked_sub(idl_ref.data_len())
.expect("data_len should always be >= the current account space"),
10_000,
))
.unwrap();
if new_account_space > idl_ref.data_len() {
let sysvar_rent = Rent::get()?;
let new_rent_minimum = sysvar_rent.minimum_balance(new_account_space);
rialo_sol_lang::system_program::transfer(
rialo_sol_lang::context::CpiContext::new(
accounts.system_program.to_account_info(),
rialo_sol_lang::system_program::Transfer {
from: accounts.authority.to_account_info(),
to: accounts.idl.to_account_info(),
},
),
new_rent_minimum
.checked_sub(idl_ref.kelvins())
.unwrap(),
)?;
idl_ref.realloc(new_account_space, false)?;
}
Ok(())
}
#[inline(never)]
pub fn __idl_close_account(
program_id: &Pubkey,
accounts: &mut IdlCloseAccount,
) -> rialo_sol_lang::Result<()> {
#[cfg(not(feature = "no-log-ix-name"))]
rialo_sol_lang::prelude::msg!("Instruction: IdlCloseAccount");
Ok(())
}
#[inline(never)]
pub fn __idl_create_buffer(
program_id: &Pubkey,
accounts: &mut IdlCreateBuffer,
) -> rialo_sol_lang::Result<()> {
#[cfg(not(feature = "no-log-ix-name"))]
rialo_sol_lang::prelude::msg!("Instruction: IdlCreateBuffer");
let mut buffer = &mut accounts.buffer;
buffer.authority = *accounts.authority.key;
Ok(())
}
#[inline(never)]
pub fn __idl_write(
program_id: &Pubkey,
accounts: &mut IdlAccounts,
idl_data: Vec<u8>,
) -> rialo_sol_lang::Result<()> {
#[cfg(not(feature = "no-log-ix-name"))]
rialo_sol_lang::prelude::msg!("Instruction: IdlWrite");
let prev_len: usize = ::std::convert::TryInto::<usize>::try_into(accounts.idl.data_len).unwrap();
let new_len: usize = prev_len.checked_add(idl_data.len()).unwrap() as usize;
accounts.idl.data_len = accounts.idl.data_len.checked_add(::std::convert::TryInto::<u32>::try_into(idl_data.len()).unwrap()).unwrap();
use IdlTrailingData;
let mut idl_bytes = accounts.idl.trailing_data_mut();
let idl_expansion = &mut idl_bytes[prev_len..new_len];
require_eq!(idl_expansion.len(), idl_data.len());
idl_expansion.copy_from_slice(&idl_data[..]);
Ok(())
}
#[inline(never)]
pub fn __idl_set_authority(
program_id: &Pubkey,
accounts: &mut IdlAccounts,
new_authority: Pubkey,
) -> rialo_sol_lang::Result<()> {
#[cfg(not(feature = "no-log-ix-name"))]
rialo_sol_lang::prelude::msg!("Instruction: IdlSetAuthority");
accounts.idl.authority = new_authority;
Ok(())
}
#[inline(never)]
pub fn __idl_set_buffer(
program_id: &Pubkey,
accounts: &mut IdlSetBuffer,
) -> rialo_sol_lang::Result<()> {
#[cfg(not(feature = "no-log-ix-name"))]
rialo_sol_lang::prelude::msg!("Instruction: IdlSetBuffer");
accounts.idl.data_len = accounts.buffer.data_len;
use IdlTrailingData;
let buffer_len = ::std::convert::TryInto::<usize>::try_into(accounts.buffer.data_len).unwrap();
let mut target = accounts.idl.trailing_data_mut();
let source = &accounts.buffer.trailing_data()[..buffer_len];
require_gte!(target.len(), buffer_len);
target[..buffer_len].copy_from_slice(source);
Ok(())
}
}
}