Skip to main content

typhoon_token/traits/
create_account.rs

1use {
2    crate::{TokenAccount, TokenProgram},
3    pinocchio::{cpi::Signer as CpiSigner, sysvars::rent::Rent, AccountView, Address},
4    pinocchio_associated_token_account::instructions::{Create, CreateIdempotent},
5    pinocchio_token::instructions::InitializeAccount3,
6    typhoon_accounts::{
7        Account, FromAccountInfo, FromRaw, InterfaceAccount, Mut, ReadableAccount, Signer,
8        SignerCheck, SystemAccount, UncheckedAccount, WritableAccount,
9    },
10    typhoon_errors::Error,
11    typhoon_traits::ProgramId,
12    typhoon_utility::create_account_with_minimum_balance_signed,
13};
14
15pub trait SplCreateToken<'a, T>
16where
17    Self: Sized + Into<&'a AccountView>,
18    T: ReadableAccount + FromAccountInfo<'a> + FromRaw<'a>,
19{
20    fn create_token_account(
21        self,
22        rent: &Rent,
23        payer: &impl WritableAccount,
24        mint: &impl ReadableAccount,
25        owner: &Address,
26        seeds: Option<&[CpiSigner]>,
27    ) -> Result<Mut<T>, Error> {
28        let info = self.into();
29        create_account_with_minimum_balance_signed(
30            info,
31            TokenAccount::LEN,
32            &TokenProgram::ID,
33            payer.as_ref(),
34            rent,
35            seeds.unwrap_or_default(),
36        )?;
37
38        InitializeAccount3 {
39            account: info,
40            mint: mint.as_ref(),
41            owner,
42        }
43        .invoke()?;
44
45        Ok(Mut::from_raw_info(info))
46    }
47
48    fn create_associated_token_account(
49        self,
50        payer: &impl WritableAccount,
51        mint: &impl ReadableAccount,
52        owner: &impl ReadableAccount,
53        system_program: &impl ReadableAccount,
54        token_program: &impl ReadableAccount,
55    ) -> Result<Mut<T>, Error> {
56        let info = self.into();
57        Create {
58            funding_account: payer.as_ref(),
59            account: info,
60            wallet: owner.as_ref(),
61            mint: mint.as_ref(),
62            system_program: system_program.as_ref(),
63            token_program: token_program.as_ref(),
64        }
65        .invoke()?;
66
67        Ok(Mut::from_raw_info(info))
68    }
69
70    fn create_idempotent_associated_token_account(
71        self,
72        payer: &impl WritableAccount,
73        mint: &impl ReadableAccount,
74        owner: &impl ReadableAccount,
75        system_program: &impl ReadableAccount,
76        token_program: &impl ReadableAccount,
77    ) -> Result<Mut<T>, Error> {
78        let info = self.into();
79        CreateIdempotent {
80            funding_account: payer.as_ref(),
81            account: info,
82            wallet: owner.as_ref(),
83            mint: mint.as_ref(),
84            system_program: system_program.as_ref(),
85            token_program: token_program.as_ref(),
86        }
87        .invoke()?;
88
89        Ok(Mut::from_raw_info(info))
90    }
91}
92
93macro_rules! impl_trait {
94    ($origin: ty) => {
95        impl<'a> SplCreateToken<'a, Account<'a, TokenAccount>> for $origin {}
96        impl<'a, C> SplCreateToken<'a, Signer<'a, Account<'a, TokenAccount>, C>> for $origin where
97            C: SignerCheck
98        {
99        }
100        impl<'a> SplCreateToken<'a, InterfaceAccount<'a, TokenAccount>> for $origin {}
101        impl<'a, C> SplCreateToken<'a, Signer<'a, InterfaceAccount<'a, TokenAccount>, C>>
102            for $origin
103        where
104            C: SignerCheck,
105        {
106        }
107    };
108}
109
110impl_trait!(&'a AccountView);
111impl_trait!(SystemAccount<'a>);
112impl_trait!(UncheckedAccount<'a>);