LogoAnchor Docs

Rust

Learn how to use Anchor's Rust client library to interact with Solana programs

The anchor-client crate is the Rust client library for interacting with Anchor programs. You can find the source code here.

Example

The example below demonstrates how to use the anchor-client crate to interact with a simple Anchor program. The program client can be automatically generated from the program's IDL using the declare_program! macro. This macro generates dependency free modules that enable you to interact with the program's instructions and accounts.

The program has two instructions:

  • initialize – Creates and initializes a counter account to store a value
  • increment – Increments the value stored on the counter account
lib.rs
use anchor_lang::prelude::*;
 
declare_id!("6khKp4BeJpCjBY1Eh39ybiqbfRnrn2UzWeUARjQLXYRC");
 
#[program]
pub mod example {
    use super::*;
 
    pub fn initialize(ctx: Context<Initialize>) -> Result<()> {
        let counter = &ctx.accounts.counter;
        msg!("Counter account created! Current count: {}", counter.count);
        Ok(())
    }
 
    pub fn increment(ctx: Context<Increment>) -> Result<()> {
        let counter = &mut ctx.accounts.counter;
        msg!("Previous counter: {}", counter.count);
 
        counter.count += 1;
        msg!("Counter incremented! Current count: {}", counter.count);
        Ok(())
    }
}
 
#[derive(Accounts)]
pub struct Initialize<'info> {
    #[account(mut)]
    pub payer: Signer<'info>,
 
    #[account(
        init,
        payer = payer,
        space = 8 + 8
    )]
    pub counter: Account<'info, Counter>,
    pub system_program: Program<'info, System>,
}
 
#[derive(Accounts)]
pub struct Increment<'info> {
    #[account(mut)]
    pub counter: Account<'info, Counter>,
}
 
#[account]
pub struct Counter {
    pub count: u64,
}

Below is an example folder structure for a Rust client that interacts with the Anchor program:

example.json
main.rs
Cargo.toml

The program IDL must be in a /idls folder. The declare_program! macro searches for the IDL in the /idls folder to generate the client modules.

idls/example.json
{
  "address": "6khKp4BeJpCjBY1Eh39ybiqbfRnrn2UzWeUARjQLXYRC",
  "metadata": {
    "name": "example",
    "version": "0.1.0",
    "spec": "0.1.0",
    "description": "Created with Anchor"
  },
  "instructions": [
    {
      "name": "increment",
      "discriminator": [11, 18, 104, 9, 104, 174, 59, 33],
      "accounts": [
        {
          "name": "counter",
          "writable": true
        }
      ],
      "args": []
    },
    {
      "name": "initialize",
      "discriminator": [175, 175, 109, 31, 13, 152, 155, 237],
      "accounts": [
        {
          "name": "payer",
          "writable": true,
          "signer": true
        },
        {
          "name": "counter",
          "writable": true,
          "signer": true
        },
        {
          "name": "system_program",
          "address": "11111111111111111111111111111111"
        }
      ],
      "args": []
    }
  ],
  "accounts": [
    {
      "name": "Counter",
      "discriminator": [255, 176, 4, 245, 188, 253, 124, 25]
    }
  ],
  "types": [
    {
      "name": "Counter",
      "type": {
        "kind": "struct",
        "fields": [
          {
            "name": "count",
            "type": "u64"
          }
        ]
      }
    }
  ]
}

Below is the src/main.rs file for interacting with the program:

  1. The declare_program! macro - Generates client modules for the program using the IDL file

  2. The anchor_client crate - Provides utilities for interacting with the program, including:

    • Building program instructions
    • Sending transactions
    • Fetching program accounts
src/main.rs
use anchor_client::{
    solana_client::rpc_client::RpcClient,
    solana_sdk::{
        commitment_config::CommitmentConfig, native_token::LAMPORTS_PER_SOL, signature::Keypair,
        signer::Signer, system_program,
    },
    Client, Cluster,
};
use anchor_lang::prelude::*;
use std::rc::Rc;
 
declare_program!(example);
use example::{accounts::Counter, client::accounts, client::args};
 
#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let connection = RpcClient::new_with_commitment(
        "http://127.0.0.1:8899", // Local validator URL
        CommitmentConfig::confirmed(),
    );
 
    // Generate Keypairs and request airdrop
    let payer = Keypair::new();
    let counter = Keypair::new();
    println!("Generated Keypairs:");
    println!("   Payer: {}", payer.pubkey());
    println!("   Counter: {}", counter.pubkey());
 
    println!("\nRequesting 1 SOL airdrop to payer");
    let airdrop_signature = connection.request_airdrop(&payer.pubkey(), LAMPORTS_PER_SOL)?;
 
    // Wait for airdrop confirmation
    while !connection.confirm_transaction(&airdrop_signature)? {
        std::thread::sleep(std::time::Duration::from_millis(100));
    }
    println!("   Airdrop confirmed!");
 
    // Create program client
    let provider = Client::new_with_options(
        Cluster::Localnet,
        Rc::new(payer),
        CommitmentConfig::confirmed(),
    );
    let program = provider.program(example::ID)?;
 
    // Build and send instructions
    println!("\nSend transaction with initialize and increment instructions");
    let initialize_ix = program
        .request()
        .accounts(accounts::Initialize {
            counter: counter.pubkey(),
            payer: program.payer(),
            system_program: system_program::ID,
        })
        .args(args::Initialize)
        .instructions()?
        .remove(0);
 
    let increment_ix = program
        .request()
        .accounts(accounts::Increment {
            counter: counter.pubkey(),
        })
        .args(args::Increment)
        .instructions()?
        .remove(0);
 
    let signature = program
        .request()
        .instruction(initialize_ix)
        .instruction(increment_ix)
        .signer(&counter)
        .send()
        .await?;
    println!("   Transaction confirmed: {}", signature);
 
    println!("\nFetch counter account data");
    let counter_account: Counter = program.account::<Counter>(counter.pubkey()).await?;
    println!("   Counter value: {}", counter_account.count);
    Ok(())
}

Below are the dependencies for the Cargo.toml file:

Cargo.toml
[package]
name = "rs"
version = "0.1.0"
edition = "2021"
 
[dependencies]
anchor-client = { version = "0.30.1", features = ["async"] }
anchor-lang = "0.30.1"
anyhow = "1.0.93"
tokio = { version = "1.0", features = ["full"] }

On this page

Edit on GitHub