use solana_program::{
account_info::AccountInfo,
entrypoint::ProgramResult,
instruction::{AccountMeta, Instruction},
program::invoke_signed,
program_error::ProgramError,
pubkey::Pubkey,
};
use crate::Interface;
#[macro_export]
macro_rules! fetch_proxy_data {
( $data:expr, $signer:ident, $authority:ident ) => {
let __proxy = $crate::state::Asset::get::<$crate::extensions::Proxy>($data)
.ok_or(solana_program::program_error::ProgramError::InvalidAccountData)?;
let __seeds = *__proxy.seeds;
let $signer = [__seeds.as_ref(), &[*__proxy.bump]];
let $authority = if let Some(authority) = __proxy.authority.value() {
Some(*authority)
} else {
None
};
};
( $data:expr, $signer:ident, $authority:ident, $program:ident, $remaining:expr ) => {
fetch_proxy_data!($data, $signer, $authority);
let $program = $remaining
.iter()
.find(|account| {
account.key
== &solana_program::pubkey!("AssetGtQBTSgm5s91d1RAQod5JmaZiJDxqsgtqrZud73")
})
.ok_or(solana_program::program_error::ProgramError::NotEnoughAccountKeys)?;
};
}
macro_rules! log_instruction_name {
( $instruction_data:expr ) => {{
if $instruction_data.is_empty() {
return Err(solana_program::program_error::ProgramError::InvalidInstructionData);
}
let name = match $instruction_data[0] {
0 => "Close",
1 => "Burn",
2 => "Create",
3 => "Approve",
4 => "Allocate",
5 => "Lock",
6 => "Revoke",
7 => "Transfer",
8 => "Unlock",
9 => "Unverify",
10 => "Update",
11 => "Verify",
12 => "Write",
13 => "Group",
14 => "Ungroup",
15 => "Handover",
16 => "Remove",
_ => return Err(solana_program::program_error::ProgramError::InvalidInstructionData),
};
solana_program::msg!("Interface: {}", name);
}};
}
impl Interface {
pub fn process_instruction<'a>(
_program_id: &'a Pubkey,
accounts: &'a [AccountInfo<'a>],
instruction_data: &[u8],
) -> ProgramResult {
log_instruction_name!(instruction_data);
let asset = accounts.first().ok_or(ProgramError::NotEnoughAccountKeys)?;
let data = (*asset.data).borrow();
fetch_proxy_data!(&data, signer, _authority);
drop(data);
let mut account_metas = Vec::with_capacity(accounts.len());
accounts.iter().for_each(|account| {
account_metas.push(AccountMeta {
pubkey: *account.key,
is_signer: account.is_signer,
is_writable: account.is_writable,
});
});
account_metas.first_mut().unwrap().is_signer = true;
invoke_signed(
&Instruction {
accounts: account_metas,
data: instruction_data.to_vec(),
program_id: solana_program::pubkey!("AssetGtQBTSgm5s91d1RAQod5JmaZiJDxqsgtqrZud73"),
},
accounts,
&[&signer],
)
}
}