Skip to main content

anchor_attribute_program/
lib.rs

1extern crate proc_macro;
2
3mod declare_program;
4
5use {declare_program::DeclareProgram, quote::ToTokens, syn::parse_macro_input};
6
7/// The `#[program]` attribute defines the module containing all instruction
8/// handlers defining all entries into a Solana program.
9#[proc_macro_attribute]
10pub fn program(
11    args: proc_macro::TokenStream,
12    input: proc_macro::TokenStream,
13) -> proc_macro::TokenStream {
14    let args = parse_macro_input!(args as anchor_syn::ProgramArgs);
15    let mut program = parse_macro_input!(input as anchor_syn::Program);
16    program.program_args.replace(args);
17
18    let program_tokens = program.to_token_stream();
19
20    #[cfg(feature = "idl-build")]
21    {
22        use anchor_syn::idl::gen_idl_print_fn_program;
23        let idl_tokens = gen_idl_print_fn_program(&program);
24        return proc_macro::TokenStream::from(quote::quote! {
25            #program_tokens
26            #idl_tokens
27        });
28    }
29
30    #[allow(unreachable_code)]
31    proc_macro::TokenStream::from(program_tokens)
32}
33
34/// Declare an external program based on its IDL.
35///
36/// The IDL of the program must exist in a directory named `idls`. This directory can be at any
37/// depth, e.g. both inside the program's directory (`<PROGRAM_DIR>/idls`) and inside Anchor
38/// workspace root directory (`<PROGRAM_DIR>/../../idls`) are valid.
39///
40/// # Usage
41///
42/// ```rs
43/// declare_program!(program_name);
44/// ```
45///
46/// This generates a module named `program_name` that can be used to interact with the program
47/// without having to add the program's crate as a dependency.
48///
49/// Both on-chain and off-chain usage is supported.
50///
51/// Use `cargo doc --open` to see the generated modules and their documentation.
52///
53/// # Note
54///
55/// Re-defining the same program to use the same definitions should be avoided since this results
56/// in a larger binary size.
57///
58/// A program should only be defined once. If you have multiple programs that depend on the same
59/// definition, you should consider creating a separate crate for the external program definition
60/// and reusing it in your programs.
61///
62/// # Off-chain usage
63///
64/// When using in off-chain environments, for example via `anchor_client`, you must have
65/// `anchor_lang` in scope:
66///
67/// ```ignore
68/// use anchor_client::anchor_lang;
69/// ```
70///
71/// # Example
72///
73/// A full on-chain CPI usage example can be found [here].
74///
75/// [here]: https://github.com/otter-sec/anchor/tree/v1.1.1/tests/declare-program
76#[proc_macro]
77pub fn declare_program(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
78    parse_macro_input!(input as DeclareProgram)
79        .to_token_stream()
80        .into()
81}
82
83/// This attribute is used to override the Anchor defaults of program instructions.
84///
85/// # Arguments
86///
87/// - `discriminator`: Override the default 8-byte discriminator
88///
89///     **Usage:** `discriminator = <CONST_EXPR>`
90///
91///     All constant expressions are supported.
92///
93///     **Examples:**
94///
95///     - `discriminator = 1` (shortcut for `[1]`)
96///     - `discriminator = [1, 2, 3, 4]`
97///     - `discriminator = b"hi"`
98///     - `discriminator = MY_DISC`
99///     - `discriminator = get_disc(...)`
100///
101/// # Example
102///
103/// ```ignore
104/// use anchor_lang::prelude::*;
105///
106/// declare_id!("CustomDiscriminator111111111111111111111111");
107///
108/// #[program]
109/// pub mod custom_discriminator {
110///     use super::*;
111///
112///     #[instruction(discriminator = [1, 2, 3, 4])]
113///     pub fn my_ix(_ctx: Context<MyIx>) -> Result<()> {
114///         Ok(())
115///     }
116/// }
117///
118/// #[derive(Accounts)]
119/// pub struct MyIx<'info> {
120///     pub signer: Signer<'info>,
121/// }
122/// ```
123#[proc_macro_attribute]
124pub fn instruction(
125    _args: proc_macro::TokenStream,
126    input: proc_macro::TokenStream,
127) -> proc_macro::TokenStream {
128    // This macro itself is a no-op, but the `#[program]` macro will detect this attribute and use
129    // the arguments to transform the instruction.
130    input
131}