Skip to main content

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/// # Off-chain usage
62///
63/// When using in off-chain environments, for example via `anchor_client`, you must have
64/// `anchor_lang` in scope:
65///
66/// ```ignore
67/// use anchor_client::anchor_lang;
68/// ```
69///
70/// # Example
71///
72/// A full on-chain CPI usage example can be found [here].
73///
74/// [here]: https://github.com/solana-foundation/anchor/tree/v1.0.0-rc.5/tests/declare-program
75#[proc_macro]
76pub fn declare_program(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
77    parse_macro_input!(input as DeclareProgram)
78        .to_token_stream()
79        .into()
80}
81
82/// This attribute is used to override the Anchor defaults of program instructions.
83///
84/// # Arguments
85///
86/// - `discriminator`: Override the default 8-byte discriminator
87///
88///     **Usage:** `discriminator = <CONST_EXPR>`
89///
90///     All constant expressions are supported.
91///
92///     **Examples:**
93///
94///     - `discriminator = 1` (shortcut for `[1]`)
95///     - `discriminator = [1, 2, 3, 4]`
96///     - `discriminator = b"hi"`
97///     - `discriminator = MY_DISC`
98///     - `discriminator = get_disc(...)`
99///
100/// # Example
101///
102/// ```ignore
103/// use anchor_lang::prelude::*;
104///
105/// declare_id!("CustomDiscriminator111111111111111111111111");
106///
107/// #[program]
108/// pub mod custom_discriminator {
109///     use super::*;
110///
111///     #[instruction(discriminator = [1, 2, 3, 4])]
112///     pub fn my_ix(_ctx: Context<MyIx>) -> Result<()> {
113///         Ok(())
114///     }
115/// }
116///
117/// #[derive(Accounts)]
118/// pub struct MyIx<'info> {
119///     pub signer: Signer<'info>,
120/// }
121/// ```
122#[proc_macro_attribute]
123pub fn instruction(
124    _args: proc_macro::TokenStream,
125    input: proc_macro::TokenStream,
126) -> proc_macro::TokenStream {
127    // This macro itself is a no-op, but the `#[program]` macro will detect this attribute and use
128    // the arguments to transform the instruction.
129    input
130}