Skip to main content

typhoon_token/traits/
create_account.rs

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