anchor_syn/parser/accounts/
event_cpi.rs

1use quote::quote;
2
3/// This struct is used to keep the authority account information in sync.
4pub struct EventAuthority {
5    /// Account name of the event authority
6    pub name: &'static str,
7    /// Seeds expression of the event authority
8    pub seeds: proc_macro2::TokenStream,
9}
10
11impl EventAuthority {
12    /// Returns the account name and the seeds expression of the event authority.
13    pub fn get() -> Self {
14        Self {
15            name: "event_authority",
16            seeds: quote! {b"__event_authority"},
17        }
18    }
19
20    /// Returns the name without surrounding quotes.
21    pub fn name_token_stream(&self) -> proc_macro2::TokenStream {
22        let name_token_stream = syn::parse_str::<syn::Expr>(self.name).unwrap();
23        quote! {#name_token_stream}
24    }
25}
26
27/// Add necessary event CPI accounts to the given accounts struct.
28pub fn add_event_cpi_accounts(
29    accounts_struct: &syn::ItemStruct,
30) -> syn::parse::Result<syn::ItemStruct> {
31    let syn::ItemStruct {
32        attrs,
33        vis,
34        struct_token,
35        ident,
36        generics,
37        fields,
38        ..
39    } = accounts_struct;
40
41    let fields = fields.into_iter().collect::<Vec<_>>();
42
43    let info_lifetime = generics
44        .lifetimes()
45        .next()
46        .map(|lifetime| quote! {#lifetime})
47        .unwrap_or(quote! {'info});
48    let generics = generics
49        .lt_token
50        .map(|_| quote! {#generics})
51        .unwrap_or(quote! {<'info>});
52
53    let authority = EventAuthority::get();
54    let authority_name = authority.name_token_stream();
55    let authority_seeds = authority.seeds;
56
57    let accounts_struct = quote! {
58        #(#attrs)*
59        #vis #struct_token #ident #generics {
60            #(#fields,)*
61
62            /// CHECK: Only the event authority can invoke self-CPI
63            #[account(seeds = [#authority_seeds], bump)]
64            pub #authority_name: AccountInfo<#info_lifetime>,
65            /// CHECK: Self-CPI will fail if the program is not the current program
66            pub program: AccountInfo<#info_lifetime>,
67        }
68    };
69    syn::parse2(accounts_struct)
70}