Dependency Free Composability
Learn how to use Anchor's declare_program macro to interact with programs without additional dependencies.
The
declare_program!()
macro simplifies the process of interacting with Anchor programs by generating
Rust modules (from a program's IDL) that can be used in both on-chain and
off-chain code. You can find an example program
here.
The following modules are generated by the declare_program!()
macro:
Module | Description |
---|---|
cpi | Helper functions for making cross-program invocations (CPIs) to the program from other on-chain programs |
client | Accounts and arguments required to build program instructions to add to client-side transactions |
account | Account data types (program state) defined in the program |
program | Program ID constant used to identify the program |
constants | Program constants defined in the program |
events | Program events defined in the program |
types | Program types defined in the program |
Examples
The following examples demonstrate how to use the declare_program!()
macro in
two scenarios:
- Making Cross Program Invocations (CPIs) from one program to another program
- Building client-side transactions to invoke a program's instructions
Both examples show how the modules generated by the declare_program!()
macro
simplify program interactions, whether you're writing on-chain or off-chain
code.
On-chain CPI
To use the declare_program!()
macro, you need the IDL file for the target
program. The IDL file must be placed in a directory named /idls
in your
project. The /idls
directory can be located at any level in your project
structure. For example, your project could have this layout:
Below is the source code (lib.rs
) for the target (callee) program that
generates the example.json
IDL file shown above.
Using the program's IDL file, another program can use the declare_program!()
macro to generate a CPI module, enabling it to make CPIs to this program's
instructions.
Below is the source code (lib.rs
) for the caller program (example-cpi) that
uses the declare_program!()
macro to generate a CPI module to invoke the
instructions defined in the callee program above.
Explanation
The declare_program!()
macro takes a single argument - the name of the
program's IDL file (e.g. example.json
):
Bring into scope the generated modules:
Use the imported types in the account validation structs:
Use the CPI module to invoke the program's instructions:
Off-chain Client
To use the declare_program!()
macro, you need the IDL file for the target
program. The IDL file must be placed in a directory named /idls
in your
project. The /idls
directory can be located at any level in your project
structure. For example, your project could have this layout:
Below is the source code (lib.rs
) for the target program that generates the
example.json
IDL file shown above. The program's IDL can then be used in a
client script along with the declare_program!()
macro to generate a Client
module to build the program's instructions.
Below is the client script (main.rs) that uses the declare_program!()
macro to
generate a Client module to build the program's instructions.
The declare_program!()
macro takes a single argument - the name of the
program's IDL file (e.g. example.json
):
Bring into scope the generated modules:
Use the Client module to build the program's instructions:
Add the program's instructions to a transaction and send the transaction:
Use the Account module to fetch and deserialize the program's account types: