typhoon_token/traits/
create_account.rs

1use {
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>);