1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
extern crate proc_macro;
use quote::quote;
use syn::parse_macro_input;

#[proc_macro_attribute]
pub fn event(
    _args: proc_macro::TokenStream,
    input: proc_macro::TokenStream,
) -> proc_macro::TokenStream {
    let event_strct = parse_macro_input!(input as syn::ItemEnum);
    let event_name = &event_strct.ident;
    let (impl_gen, type_gen, where_clause) = event_strct.generics.split_for_impl();

    proc_macro::TokenStream::from({
        quote! {
            #[derive(borsh::BorshSerialize, borsh::BorshDeserialize, PartialEq, Eq, Debug, Clone)]
            #event_strct

            #[automatically_derived]
            impl #impl_gen #event_name #type_gen #where_clause {

                pub fn to_instruction(&self) -> Instruction {
                    Instruction {
                        program_id: crate::id(),
                        accounts: vec![],
                        data: vec![
                            crate::id().try_to_vec().unwrap(),
                            self.try_to_vec().unwrap(),
                        ]
                        .concat(),
                    }
                }

                pub fn emit_to<'info>(&self, wrapper_program: AccountInfo<'info>) -> ProgramResult {
                    invoke(&self.to_instruction(), &[wrapper_program.to_account_info()])
                }

                pub fn emit<'info>(&self, hpl_events_program: AccountInfo<'info>) -> ProgramResult {
                    if String::from("EvntXY8sSMZhWLdh26y4aePQWH4VqCk13oCBqydpbdy6")
                        != hpl_events_program.key().to_string()
                    {
                        return Err(ProgramError::IncorrectProgramId);
                    };
                    self.emit_to(hpl_events_program)
                }

                /// Used as backup for old programs
                pub fn wrap<'info>(
                    &self,
                    hpl_events_program: AccountInfo<'info>,
                    emitter_program: Pubkey,
                ) -> ProgramResult {
                    invoke(
                        &Instruction {
                            program_id: crate::id(),
                            accounts: vec![],
                            data: vec![
                                emitter_program.try_to_vec().unwrap(),
                                self.try_to_vec().unwrap(),
                            ]
                            .concat(),
                        },
                        &[hpl_events_program],
                    )
                }

            }
        }
    })
}