IDL File
An Interface Description Language (IDL) file provides a standardized JSON file describing the program's instructions and accounts. This file simplifies the process of integrating your on-chain program with client applications.
Key Benefits of the IDL:
- Standardization: Provides a consistent format for describing the program's instructions and accounts
- Client Generation: Used to generate client code to interact with the program
The anchor build
command generates an IDL file located at
/target/idl/<program-name>.json
.
The code snippets below highlights how the program, IDL, and client relate to each other.
Program Instructions #
The instructions
array in the IDL corresponds directly to the instructions
defined in your program. It specifies the required accounts and parameters for
each instruction.
The program below includes an initialize
instruction, specifying the accounts
and parameters it requires.
use anchor_lang::prelude::*;
declare_id!("BYFW1vhC1ohxwRbYoLbAWs86STa25i9sD5uEusVjTYNd");
#[program]
mod hello_anchor {
use super::*;
pub fn initialize(ctx: Context<Initialize>, data: u64) -> Result<()> {
ctx.accounts.new_account.data = data;
msg!("Changed data to: {}!", data);
Ok(())
}
}
#[derive(Accounts)]
pub struct Initialize<'info> {
#[account(init, payer = signer, space = 8 + 8)]
pub new_account: Account<'info, NewAccount>,
#[account(mut)]
pub signer: Signer<'info>,
pub system_program: Program<'info, System>,
}
#[account]
pub struct NewAccount {
data: u64,
}
Program Accounts #
The accounts
array in the IDL corresponds to the structs in a program
annotated with the #[account]
macro. These structs define the data stored in
accounts created by the program.
The program below defines a NewAccount
struct with a single data
field of
type u64
.
use anchor_lang::prelude::*;
declare_id!("BYFW1vhC1ohxwRbYoLbAWs86STa25i9sD5uEusVjTYNd");
#[program]
mod hello_anchor {
use super::*;
pub fn initialize(ctx: Context<Initialize>, data: u64) -> Result<()> {
ctx.accounts.new_account.data = data;
msg!("Changed data to: {}!", data);
Ok(())
}
}
#[derive(Accounts)]
pub struct Initialize<'info> {
#[account(init, payer = signer, space = 8 + 8)]
pub new_account: Account<'info, NewAccount>,
#[account(mut)]
pub signer: Signer<'info>,
pub system_program: Program<'info, System>,
}
#[account]
pub struct NewAccount {
data: u64,
}
Discriminators #
Anchor assigns a unique 8 byte discriminator to each instruction and account type in a program. These discriminators serve as identifiers to distinguish between different instructions or account types.
The discriminator is generated using the first 8 bytes of the Sha256 hash of a prefix combined with the instruction or account name. As of Anchor v0.30, these discriminators are included in the IDL file.
Note that when working with Anchor, you typically won't need to interact directly with these discriminators. This section is primarily to provide context on how the discriminator is generated and used.
The instruction discriminator is used by the program to determine which specific instruction to execute when called.
When an Anchor program instruction is invoked, the discriminator is included as the first 8 bytes of the instruction data. This is done automatically by the Anchor client.
"instructions": [
{
"name": "initialize",
"discriminator": [175, 175, 109, 31, 13, 152, 155, 237],
...
}
]
The discriminator for an instruction is the first 8 bytes of the Sha256 hash of
the prefix global
plus the instruction name.
For example:
sha256("global:initialize")
Hexadecimal output:
af af 6d 1f 0d 98 9b ed d4 6a 95 07 32 81 ad c2 1b b5 e0 e1 d7 73 b2 fb bd 7a b5 04 cd d4 aa 30
The first 8 bytes are used as the discriminator for the instruction.
af = 175
af = 175
6d = 109
1f = 31
0d = 13
98 = 152
9b = 155
ed = 237
You can find the implementation of the discriminator generation in the Anchor codebase here, which is used here.