1#![no_std]
5
6use hayabusa_errors::Result;
7use hayabusa_utility::fail_with_ctx;
8use pinocchio::{
9 account_info::AccountInfo, hint::unlikely, instruction::Signer, program_error::ProgramError, pubkey::Pubkey
10};
11
12pub trait CheckProgramId {
13 const ID: Pubkey;
14
15 #[inline(always)]
16 fn check_program_id(id: &Pubkey) -> Result<()> {
17 if unlikely(id != &Self::ID) {
18 fail_with_ctx!(
19 "HAYABUSA_CPI_INCORRECT_PROGRAM_ID",
20 ProgramError::IncorrectProgramId,
21 id,
22 &Self::ID,
23 );
24 }
25
26 Ok(())
27 }
28}
29
30pub struct CpiCtx<'a, 'b, 'c, 'd, T: CheckProgramId> {
31 pub program_info: &'a AccountInfo,
32 pub accounts: T,
33 pub signers: Option<&'b [Signer<'c, 'd>]>,
34}
35
36impl<'a, 'b, 'c, 'd, T: CheckProgramId> CpiCtx<'a, 'b, 'c, 'd, T> {
37 #[inline(always)]
38 pub fn try_new(
39 program_info: &'a AccountInfo,
40 accounts: T,
41 signers: Option<&'b [Signer<'c, 'd>]>,
42 ) -> Result<Self> {
43 T::check_program_id(program_info.key())?;
44
45 Ok(Self {
46 program_info,
47 accounts,
48 signers,
49 })
50 }
51
52 #[inline(always)]
53 pub fn try_new_without_signer(
54 program_info: &'a AccountInfo,
55 accounts: T,
56 ) -> Result<Self> {
57 T::check_program_id(program_info.key())?;
58
59 Ok(Self {
60 program_info,
61 accounts,
62 signers: None,
63 })
64 }
65
66 #[inline(always)]
67 pub fn try_new_with_signer(
68 program_info: &'a AccountInfo,
69 accounts: T,
70 signers: &'b [Signer<'c, 'd>],
71 ) -> Result<Self> {
72 T::check_program_id(program_info.key())?;
73
74 Ok(Self {
75 program_info,
76 accounts,
77 signers: Some(signers),
78 })
79 }
80}
81
82impl<T: CheckProgramId> core::ops::Deref for CpiCtx<'_, '_, '_, '_, T> {
83 type Target = T;
84
85 #[inline(always)]
86 fn deref(&self) -> &Self::Target {
87 &self.accounts
88 }
89}