Skip to main content

typhoon_utility_traits/
create.rs

1use {
2    pinocchio::{cpi, sysvars::rent::Rent, AccountView, Address},
3    typhoon_accounts::{
4        Account, FromRaw, Mut, ReadableAccount, Signer, SignerCheck, SystemAccount,
5        UncheckedAccount, WritableAccount,
6    },
7    typhoon_errors::Error,
8    typhoon_traits::Discriminator,
9    typhoon_utility::create_account_with_minimum_balance_signed,
10};
11
12pub trait CreateAccountCpi<'a, T>
13where
14    Self: Sized + Into<&'a AccountView>,
15    T: ReadableAccount + FromRaw<'a>,
16{
17    type D: Discriminator;
18
19    #[inline(always)]
20    fn create(
21        self,
22        rent: &Rent,
23        payer: &impl WritableAccount,
24        owner: &Address,
25        space: usize,
26        seeds: Option<&[cpi::Signer]>,
27    ) -> Result<Mut<T>, Error> {
28        let info = self.into();
29        create_account_with_minimum_balance_signed(
30            info,
31            space,
32            owner,
33            payer.as_ref(),
34            rent,
35            seeds.unwrap_or_default(),
36        )?;
37
38        {
39            let data = info.data_ptr();
40            unsafe {
41                core::ptr::copy_nonoverlapping(
42                    Self::D::DISCRIMINATOR.as_ptr(),
43                    data,
44                    Self::D::DISCRIMINATOR.len(),
45                );
46            }
47        }
48
49        Ok(Mut::from_raw_info(info))
50    }
51}
52
53macro_rules! impl_trait {
54    ($origin: ty) => {
55        impl<'a, T, C> CreateAccountCpi<'a, Signer<'a, Account<'a, T>, C>> for $origin
56        where
57            T: Discriminator,
58            C: SignerCheck,
59        {
60            type D = T;
61        }
62        impl<'a, T> CreateAccountCpi<'a, Account<'a, T>> for $origin
63        where
64            T: Discriminator,
65        {
66            type D = T;
67        }
68    };
69}
70
71impl_trait!(&'a AccountView);
72impl_trait!(SystemAccount<'a>);
73impl_trait!(UncheckedAccount<'a>);