anchor_attribute_program/lib.rs
1extern crate proc_macro;
2
3mod declare_program;
4
5use declare_program::DeclareProgram;
6use quote::ToTokens;
7use syn::parse_macro_input;
8
9/// The `#[program]` attribute defines the module containing all instruction
10/// handlers defining all entries into a Solana program.
11#[proc_macro_attribute]
12pub fn program(
13 _args: proc_macro::TokenStream,
14 input: proc_macro::TokenStream,
15) -> proc_macro::TokenStream {
16 let program = parse_macro_input!(input as anchor_syn::Program);
17 let program_tokens = program.to_token_stream();
18
19 #[cfg(feature = "idl-build")]
20 {
21 use anchor_syn::idl::gen_idl_print_fn_program;
22 let idl_tokens = gen_idl_print_fn_program(&program);
23 return proc_macro::TokenStream::from(quote::quote! {
24 #program_tokens
25 #idl_tokens
26 });
27 }
28
29 #[allow(unreachable_code)]
30 proc_macro::TokenStream::from(program_tokens)
31}
32
33/// Declare an external program based on its IDL.
34///
35/// The IDL of the program must exist in a directory named `idls`. This directory can be at any
36/// depth, e.g. both inside the program's directory (`<PROGRAM_DIR>/idls`) and inside Anchor
37/// workspace root directory (`<PROGRAM_DIR>/../../idls`) are valid.
38///
39/// # Usage
40///
41/// ```rs
42/// declare_program!(program_name);
43/// ```
44///
45/// This generates a module named `program_name` that can be used to interact with the program
46/// without having to add the program's crate as a dependency.
47///
48/// Both on-chain and off-chain usage is supported.
49///
50/// Use `cargo doc --open` to see the generated modules and their documentation.
51///
52/// # Note
53///
54/// Re-defining the same program to use the same definitions should be avoided since this results
55/// in a larger binary size.
56///
57/// A program should only be defined once. If you have multiple programs that depend on the same
58/// definition, you should consider creating a separate crate for the external program definition
59/// and reusing it in your programs.
60///
61/// # Example
62///
63/// A full on-chain CPI usage example can be found [here].
64///
65/// [here]: https://github.com/coral-xyz/anchor/tree/v1.0.0-rc.1/tests/declare-program
66#[proc_macro]
67pub fn declare_program(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
68 parse_macro_input!(input as DeclareProgram)
69 .to_token_stream()
70 .into()
71}
72
73/// The `#[interface]` attribute is used to mark an instruction as belonging
74/// to an interface implementation, thus transforming its discriminator to the
75/// proper bytes for that interface instruction.
76///
77/// # Example
78///
79/// ```rust,ignore
80/// use anchor_lang::prelude::*;
81///
82/// // SPL Transfer Hook Interface: `Execute` instruction.
83/// //
84/// // This instruction is invoked by Token-2022 when a transfer occurs,
85/// // if a mint has specified this program as its transfer hook.
86/// #[interface(spl_transfer_hook_interface::execute)]
87/// pub fn execute_transfer(ctx: Context<Execute>, amount: u64) -> Result<()> {
88/// // Check that all extra accounts were provided
89/// let data = ctx.accounts.extra_metas_account.try_borrow_data()?;
90/// ExtraAccountMetaList::check_account_infos::<ExecuteInstruction>(
91/// &ctx.accounts.to_account_infos(),
92/// &TransferHookInstruction::Execute { amount }.pack(),
93/// &ctx.program_id,
94/// &data,
95/// )?;
96///
97/// // Or maybe perform some custom logic
98/// if ctx.accounts.token_metadata.mint != ctx.accounts.token_account.mint {
99/// return Err(ProgramError::IncorrectAccount);
100/// }
101///
102/// Ok(())
103/// }
104/// ```
105#[cfg(feature = "interface-instructions")]
106#[deprecated(
107 since = "1.0.0-rc.1",
108 note = "Use `#[instruction(discriminator = <EXPR>)]` instead.
109 See examples in https://github.com/coral-xyz/anchor/tree/v1.0.0-rc.1/tests/spl/transfer-hook"
110)]
111#[proc_macro_attribute]
112pub fn interface(
113 _args: proc_macro::TokenStream,
114 input: proc_macro::TokenStream,
115) -> proc_macro::TokenStream {
116 // This macro itself is a no-op, but must be defined as a proc-macro
117 // attribute to be used on a function as the `#[interface]` attribute.
118 //
119 // The `#[program]` macro will detect this attribute and transform the
120 // discriminator.
121 input
122}
123
124/// This attribute is used to override the Anchor defaults of program instructions.
125///
126/// # Arguments
127///
128/// - `discriminator`: Override the default 8-byte discriminator
129///
130/// **Usage:** `discriminator = <CONST_EXPR>`
131///
132/// All constant expressions are supported.
133///
134/// **Examples:**
135///
136/// - `discriminator = 1` (shortcut for `[1]`)
137/// - `discriminator = [1, 2, 3, 4]`
138/// - `discriminator = b"hi"`
139/// - `discriminator = MY_DISC`
140/// - `discriminator = get_disc(...)`
141///
142/// # Example
143///
144/// ```ignore
145/// use anchor_lang::prelude::*;
146///
147/// declare_id!("CustomDiscriminator111111111111111111111111");
148///
149/// #[program]
150/// pub mod custom_discriminator {
151/// use super::*;
152///
153/// #[instruction(discriminator = [1, 2, 3, 4])]
154/// pub fn my_ix(_ctx: Context<MyIx>) -> Result<()> {
155/// Ok(())
156/// }
157/// }
158///
159/// #[derive(Accounts)]
160/// pub struct MyIx<'info> {
161/// pub signer: Signer<'info>,
162/// }
163/// ```
164#[proc_macro_attribute]
165pub fn instruction(
166 _args: proc_macro::TokenStream,
167 input: proc_macro::TokenStream,
168) -> proc_macro::TokenStream {
169 // This macro itself is a no-op, but the `#[program]` macro will detect this attribute and use
170 // the arguments to transform the instruction.
171 input
172}