5 min read
Overview
In Solana programming, an Interface Definition Language (IDL) specifies a program's public interface. It defines a Solana program's account structures, instructions, and error codes. IDLs are .json
files used to generate client-side code, allowing users to easily interact with a Solana program. IDL's are not a new concept created by Solana--in fact they are used in many applications and programming languages. Since Anchor, introduced IDLs to Solana, they have become an essential part of building and interacting with Solana programs. Though you can interact with Solana programs without IDLs, they make the process much easier.
The most optimal way to generate an IDL for a Solana program is by using Anchor. Anchor is a framework that accelerates building secure Rust programs on Solana, and with its automatic generation of IDLs, it enables developers to quickly build programs and communicate with them via a front end. In this guide, you will learn the purpose of IDLs and how to generate them using Anchor.
Why are IDLs important?
IDLs are essential because they provide a standardized way for dApps to communicate with Solana programs. By defining the program's public interface, an IDL ensures that other programs and services can interact with the program in a consistent way. For example, Solana Explorer is able to use IDLs to parse transaction instruction data based on a Program ID. Here's an example of a parsed transaction instruction on Solana Explorer:
Marinade Finance, a popular liquid staking token, for instance, has a public IDL, Solana Explorer is able to parse the transaction on load to provide relevant information about the transaction to users. Here's an example of how Solana Explorer displays public IDLs:
IDLs also simplify client-side code generation, making deploying a front end for a Solana program easier. Below is an example of two Hello World front ends that create a greeting account to say "hello"--one using native Solana and the other using Anchor:
- Native Solana
- Anchor
const GREETING_SEED = 'hello'
const greetedPubkey = await PublicKey.createWithSeed(
payer.publicKey,
GREETING_SEED,
programId
)
// Check if the greeting account has already been created
const greetedAccount = await connection.getAccountInfo(greetedPubkey)
if (greetedAccount === null) {
console.log('Creating account', greetedPubkey.toBase58(), 'to say hello to')
const lamports = await connection.getMinimumBalanceForRentExemption(
GREETING_SIZE
)
const transaction = new Transaction().add(
SystemProgram.createAccountWithSeed({
fromPubkey: payer.publicKey,
basePubkey: payer.publicKey,
seed: GREETING_SEED,
newAccountPubkey: greetedPubkey,
lamports,
space: GREETING_SIZE,
programId,
})
)
await sendAndConfirmTransaction(connection, transaction, [payer])
}
// ...
export async function sayHello(): Promise<void> {
console.log('Saying hello to', greetedPubkey.toBase58())
const instruction = new TransactionInstruction({
keys: [{ pubkey: greetedPubkey, isSigner: false, isWritable: true }],
programId,
data: Buffer.alloc(0), // All instructions are hellos
})
await sendAndConfirmTransaction(
connection,
new Transaction().add(instruction),
[payer]
)
}
// Src: https://github.com/solana-labs/example-helloworld/blob/master/src/client/hello_world.ts
const anchor = require('@project-serum/anchor')
async function greet(message: string) {
anchor.setProvider(anchor.Provider.local())
// Here we load the HelloAnchor example IDL
const program = anchor.workspace.HelloAnchor
let greetKey = Keypair.generate()
await program.methods
.initialize(message)
.accounts({
newAccount: greetKey.publicKey,
signer: wallet.publicKey,
systemProgram: web3.SystemProgram.programId,
})
.signers([wallet, greetKey])
.rpc()
}
greet('Hello World')
A lot cleaner, right? Anchor uses the IDL to abstract this process into one that is much easier to read and quicker to deploy. Additionaly, it improves composability by making it easier for you to interface between other programs.
How to Create IDLs using Anchor
Generate IDLs
Because IDLs are so integral to programming with Anchor, IDLs are automatically generated when you build your program. From any Anchor project directory, enter the following in your terminal:
anchor build --idl <IDL_OUTPUT_DIRECTORY>
Check out our Guide: How to Write Your First Anchor Program
By default, idl.json
will be saved to your ./target/idl
folder:
Publish IDLs
Anchor also makes it easy to publish your IDLs on-chain. To do this, you simply need to enter the following in your terminal:
anchor idl init --filepath <FILEPATH> <PROGRAM_ID> --provider.cluster <CLUSTER> --provider.wallet <WALLET>
Make sure the wallet you use is the program authority and has SOL for the on-chain transaction! After your IDL is loaded, you should be able to see your IDL on Solana Explorer at https://explorer.solana.com/address/YOUR_PROGRAM_ID/anchor-program.
The anchor idl
command has several other handy tools that allow you to fetch, update, or freeze an IDL. For information on each of those commands, you can enter the following in your terminal:
anchor idl -h
Use IDLs in Your Front End
Import the generated TypeScript module into your front-end application, and use it to interact with your program. The module provides functions that correspond to the functions defined in your IDL.
import { Program, AnchorProvider, setProvider } from '@project-serum/anchor'
import { Connection, KeyPair } from '@solana/web3.js'
import { PROGRAM_ID, IDL } from './your-program-dir'
// where IDL is the .json created by anchor build
// and PROGRAM_ID is your on-chain program ID
export const yourFunction = async () => {
const wallet = KeyPair.generate()
const connection = new Connection(QN_ENDPOINT)
const provider = new AnchorProvider(connection, wallet, {})
setProvider(provider)
const program = new Program(IDL, PROGRAM_ID)
// ... your code
// e.g. await program.methods.yourMethod(YOUR_PARAMETERS).accounts({YOUR_ACCOUNTS}).rpc();
}
Because your program instructions and accounts are embedded in your IDL (now stored in your program
variable), your code editor should automatically detect your callable program methods via program.methods...
. Your type guards should ensure you pass all the necessary accounts into the instruction. If you are looking for a specific demo on how to build a small anchor app and simple client-side code, check out our Guide: How to Use Program Derived Addresses.
Wrap Up
IDLs are an excellent way to connect your dApp to many Programs and can help your Program gain exposure to many dApps.
If you're stuck, have questions, or just want to talk about what you're building, drop us a line on Discord or Twitter!
We <3 Feedback!
If you have any feedback on this guide, let us know. We'd love to hear from you.
Resources
- Anchor CLI IDL Documentation
- Metaplex Shank - for generating IDLs from Rust programs
- Native to Anchor - for generating IDLs from native Solana programs
- Address for Program's Public IDL (if available):
https://explorer.solana.com/address/<PROGRAM-ID>/anchor-program