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