typhoon_token/traits/
create_account.rs1use {
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>);