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