#![no_std]
#![deny(unsafe_op_in_unsafe_fn)]
use core::mem::MaybeUninit;
use hopper_runtime::account::AccountView;
use hopper_runtime::address::Address;
use hopper_runtime::error::ProgramError;
use hopper_runtime::instruction::{InstructionAccount, InstructionView, Signer};
use hopper_runtime::ProgramResult;
pub const MEMO_PROGRAM_ID: Address =
hopper_runtime::address!("MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr");
pub const MAX_MEMO_SIGNERS: usize = 16;
pub mod v1 {
use hopper_runtime::address::Address;
pub const MEMO_V1_PROGRAM_ID: Address =
hopper_runtime::address!("Memo1UhkJRfHyvLMcVucJwxXeuD728EqVDDwQDxFMNo");
}
pub struct Memo<'a, 'b, 'c> {
pub signers: &'a [&'a AccountView],
pub memo: &'b [u8],
pub program_id: Option<&'c Address>,
}
impl Memo<'_, '_, '_> {
#[inline]
pub fn invoke(&self) -> ProgramResult {
self.invoke_signed(&[])
}
pub fn invoke_signed(&self, signers_seeds: &[Signer]) -> ProgramResult {
let n = self.signers.len();
if n > MAX_MEMO_SIGNERS {
return Err(ProgramError::InvalidArgument);
}
let mut accounts: [MaybeUninit<InstructionAccount>; MAX_MEMO_SIGNERS] =
[const { MaybeUninit::uninit() }; MAX_MEMO_SIGNERS];
let mut i = 0;
while i < n {
accounts[i].write(InstructionAccount::readonly_signer(
self.signers[i].address(),
));
i += 1;
}
let accounts_slice: &[InstructionAccount] = unsafe {
core::slice::from_raw_parts(accounts.as_ptr() as *const InstructionAccount, n)
};
let pid = self.program_id.unwrap_or(&MEMO_PROGRAM_ID);
let instruction = InstructionView {
program_id: pid,
data: self.memo,
accounts: accounts_slice,
};
macro_rules! invoke_with_signers {
($n:literal, [$($idx:literal),*]) => {{
let account_views: [&AccountView; $n] = [$(self.signers[$idx]),*];
hopper_runtime::cpi::invoke_signed::<$n>(&instruction, &account_views, signers_seeds)
}};
}
match n {
0 => invoke_with_signers!(0, []),
1 => invoke_with_signers!(1, [0]),
2 => invoke_with_signers!(2, [0, 1]),
3 => invoke_with_signers!(3, [0, 1, 2]),
4 => invoke_with_signers!(4, [0, 1, 2, 3]),
5 => invoke_with_signers!(5, [0, 1, 2, 3, 4]),
6 => invoke_with_signers!(6, [0, 1, 2, 3, 4, 5]),
7 => invoke_with_signers!(7, [0, 1, 2, 3, 4, 5, 6]),
8 => invoke_with_signers!(8, [0, 1, 2, 3, 4, 5, 6, 7]),
9 => invoke_with_signers!(9, [0, 1, 2, 3, 4, 5, 6, 7, 8]),
10 => invoke_with_signers!(10, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]),
11 => invoke_with_signers!(11, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]),
12 => invoke_with_signers!(12, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]),
13 => invoke_with_signers!(13, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]),
14 => invoke_with_signers!(14, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]),
15 => invoke_with_signers!(15, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]),
16 => invoke_with_signers!(16, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]),
_ => Err(ProgramError::InvalidArgument),
}
}
}