extern crate proc_macro;
#[cfg(feature = "event-cpi")]
use anchor_syn::parser::accounts::event_cpi::{add_event_cpi_accounts, EventAuthority};
use {
anchor_syn::{codegen::program::common::gen_discriminator, Overrides},
quote::quote,
syn::parse_macro_input,
};
#[proc_macro_attribute]
pub fn event(
args: proc_macro::TokenStream,
input: proc_macro::TokenStream,
) -> proc_macro::TokenStream {
let args = parse_macro_input!(args as Overrides);
let event_strct = parse_macro_input!(input as syn::ItemStruct);
let event_name = &event_strct.ident;
let discriminator = args
.discriminator
.unwrap_or_else(|| gen_discriminator("event", event_name));
let ret = quote! {
#[derive(AnchorSerialize, AnchorDeserialize)]
#event_strct
impl anchor_lang::Event for #event_name {
fn data(&self) -> Vec<u8> {
let mut data = Vec::with_capacity(256);
data.extend_from_slice(#event_name::DISCRIMINATOR);
self.serialize(&mut data).unwrap();
data
}
}
impl anchor_lang::Discriminator for #event_name {
const DISCRIMINATOR: &'static [u8] = #discriminator;
}
};
#[cfg(feature = "idl-build")]
{
let idl_build = anchor_syn::idl::gen_idl_print_fn_event(&event_strct);
return proc_macro::TokenStream::from(quote! {
#ret
#idl_build
});
}
#[allow(unreachable_code)]
proc_macro::TokenStream::from(ret)
}
#[proc_macro]
pub fn emit(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let data: proc_macro2::TokenStream = input.into();
proc_macro::TokenStream::from(quote! {
{
anchor_lang::solana_program::log::sol_log_data(&[&anchor_lang::Event::data(&#data)]);
}
})
}
#[cfg(feature = "event-cpi")]
#[proc_macro]
pub fn emit_cpi(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let event_struct = parse_macro_input!(input as syn::Expr);
let authority = EventAuthority::get();
let authority_name = authority.name_token_stream();
let authority_seeds = authority.seeds;
proc_macro::TokenStream::from(quote! {
{
let authority_info = ctx.accounts.#authority_name.to_account_info();
let disc = anchor_lang::event::EVENT_IX_TAG_LE;
let inner_data = anchor_lang::Event::data(&#event_struct);
let ix_data: Vec<u8> = disc
.into_iter()
.map(|b| *b)
.chain(inner_data.into_iter())
.collect();
let ix = anchor_lang::solana_program::instruction::Instruction::new_with_bytes(
crate::ID,
&ix_data,
vec![
anchor_lang::solana_program::instruction::AccountMeta::new_readonly(
*authority_info.key,
true,
),
],
);
anchor_lang::solana_program::program::invoke_signed(
&ix,
&[authority_info],
&[&[#authority_seeds, &[crate::EVENT_AUTHORITY_AND_BUMP.1]]],
)
.map_err(anchor_lang::error::Error::from)?;
}
})
}
#[cfg(feature = "event-cpi")]
#[proc_macro_attribute]
pub fn event_cpi(
_attr: proc_macro::TokenStream,
input: proc_macro::TokenStream,
) -> proc_macro::TokenStream {
let accounts_struct = parse_macro_input!(input as syn::ItemStruct);
let accounts_struct = add_event_cpi_accounts(&accounts_struct).unwrap();
proc_macro::TokenStream::from(quote! {#accounts_struct})
}