> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/solana-foundation/anchor/llms.txt
> Use this file to discover all available pages before exploring further.

# Rust Client

> Learn how to use Anchor's Rust client library (anchor-client) to interact with Solana programs from Rust applications

The `anchor-client` crate provides a Rust client library for interacting with Anchor programs. It offers a type-safe, ergonomic API for building transactions, sending them to the cluster, and fetching program accounts.

## Installation

Add `anchor-client` to your `Cargo.toml`:

<CodeGroup>
  ```toml Cargo.toml (Blocking) theme={null}
  [dependencies]
  anchor-client = "0.32.1"
  anchor-lang = "0.32.1"
  ```

  ```toml Cargo.toml (Async) theme={null}
  [dependencies]
  anchor-client = { version = "0.32.1", features = ["async"] }
  anchor-lang = "0.32.1"
  tokio = { version = "1.0", features = ["full"] }
  ```
</CodeGroup>

<Note>
  The client is blocking by default. Enable the `async` feature for asynchronous operations.
</Note>

## Core Concepts

The Anchor Rust client is built around these key components:

<CardGroup cols={3}>
  <Card title="Client" icon="plug">
    Configures cluster connection and payer for transactions
  </Card>

  <Card title="Program" icon="code">
    Provides methods to interact with a specific on-chain program
  </Card>

  <Card title="RequestBuilder" icon="wrench">
    Builder pattern for constructing and sending transactions
  </Card>
</CardGroup>

## Client Setup

Create a `Client` to manage your cluster connection and transaction payer.

### API Signature

```rust theme={null}
impl<C: Deref<Target = impl Signer> + Clone> Client<C> {
    pub fn new(cluster: Cluster, payer: C) -> Self
    
    pub fn new_with_options(
        cluster: Cluster, 
        payer: C, 
        options: CommitmentConfig
    ) -> Self
    
    pub fn program(&self, program_id: Pubkey) -> Result<Program<C>, ClientError>
}
```

### Basic Example

```rust theme={null}
use anchor_client::{
    Client, Cluster,
    solana_sdk::{
        signature::{read_keypair_file, Keypair},
        signer::Signer,
    },
};
use std::rc::Rc;

// Read keypair from file
let payer = read_keypair_file("~/.config/solana/id.json")
    .expect("Failed to read keypair");

// Create client for localnet
let client = Client::new(Cluster::Localnet, Rc::new(payer));

// Or with custom commitment
let client = Client::new_with_options(
    Cluster::Devnet,
    Rc::new(payer),
    CommitmentConfig::confirmed(),
);
```

### Using Dynamic Signers

If you need to work with `Box<dyn Signer>`, use the `DynSigner` wrapper:

```rust theme={null}
use anchor_client::{Client, DynSigner};
use std::sync::Arc;

let signer: Box<dyn Signer> = /* ... */;
let payer = DynSigner(Arc::from(signer));
let client = Client::new(Cluster::Devnet, payer);
```

## Cluster Configuration

The `Cluster` enum defines which Solana cluster to connect to:

```rust theme={null}
pub enum Cluster {
    Localnet,   // http://127.0.0.1:8899
    Devnet,     // https://api.devnet.solana.com
    Testnet,    // https://api.testnet.solana.com
    Mainnet,    // https://api.mainnet-beta.solana.com
    Custom(String, String), // (http_url, ws_url)
}
```

### Usage Examples

```rust theme={null}
use anchor_client::Cluster;
use std::str::FromStr;

// Built-in clusters
let cluster = Cluster::Devnet;
let cluster = Cluster::Mainnet;

// Parse from string
let cluster = Cluster::from_str("devnet")?;
let cluster = Cluster::from_str("https://api.devnet.solana.com")?;

// Custom RPC endpoint
let cluster = Cluster::Custom(
    "https://my-rpc.com".to_string(),
    "wss://my-rpc.com".to_string(),
);

// Get URLs
println!("HTTP URL: {}", cluster.url());
println!("WebSocket URL: {}", cluster.ws_url());
```

## Program Instance

Create a `Program` instance to interact with a specific on-chain program.

### API

```rust theme={null}
impl<C: Deref<Target = impl Signer> + Clone> Program<C> {
    pub fn payer(&self) -> Pubkey
    pub fn id(&self) -> Pubkey
    pub fn request(&self) -> RequestBuilder<'_, C, Box<dyn Signer>>
    pub fn account<T: AccountDeserialize>(&self, address: Pubkey) -> Result<T>
    pub fn accounts<T: AccountDeserialize + Discriminator>(
        &self,
        filters: Vec<RpcFilterType>,
    ) -> Result<ProgramAccountsIterator<T>>
}
```

### Creating a Program

```rust theme={null}
use anchor_client::Client;
use solana_sdk::pubkey::Pubkey;
use std::str::FromStr;

let client = Client::new(Cluster::Devnet, Rc::new(payer));

// Create program instance
let program_id = Pubkey::from_str("YourProgramID...").unwrap();
let program = client.program(program_id)?;

// Access program properties
println!("Program ID: {}", program.id());
println!("Payer: {}", program.payer());
```

## Using declare\_program!

The `declare_program!` macro generates type-safe client code from your program's IDL.

<Steps>
  <Step title="Place IDL in idls/ directory">
    Create an `idls/` folder in your client project root and place your program's IDL JSON file there:

    ```
    my-client/
    ├── idls/
    │   └── my_program.json
    ├── src/
    │   └── main.rs
    └── Cargo.toml
    ```
  </Step>

  <Step title="Declare the program">
    Use the macro in your code:

    ```rust theme={null}
    use anchor_lang::prelude::*;

    declare_program!(my_program);
    ```
  </Step>

  <Step title="Import generated modules">
    The macro generates `client::accounts` and `client::args` modules:

    ```rust theme={null}
    use my_program::{
        accounts::Counter,          // Account types
        client::accounts,           // Account structs for instructions  
        client::args,               // Argument structs for instructions
    };
    ```
  </Step>
</Steps>

### Generated Modules

The `declare_program!` macro generates:

* **`client::accounts`** - Structs matching instruction account requirements
* **`client::args`** - Structs for instruction arguments
* **Account types** - Deserializable account data structures
* **`ID`** - The program's public key constant

## Building Transactions

Use the `RequestBuilder` to construct transactions with the builder pattern.

### RequestBuilder API

```rust theme={null}
impl<C, S> RequestBuilder<'_, C, S> {
    pub fn accounts(self, accounts: impl ToAccountMetas) -> Self
    pub fn args(self, args: impl InstructionData) -> Self
    pub fn signer(self, signer: &S) -> Self
    pub fn instruction(self, ix: Instruction) -> Self
    pub fn instructions(&self) -> Vec<Instruction>
    pub fn transaction(&self) -> Transaction
    pub fn send(self) -> Result<Signature>
    pub fn signed_transaction(self) -> Result<Transaction>
}
```

### Single Instruction

```rust theme={null}
use anchor_client::solana_sdk::system_program;

declare_program!(counter_program);
use counter_program::client::{accounts, args};

let counter_keypair = Keypair::new();

// Build and send transaction
let signature = program
    .request()
    .accounts(accounts::Initialize {
        counter: counter_keypair.pubkey(),
        payer: program.payer(),
        system_program: system_program::ID,
    })
    .args(args::Initialize)
    .signer(&counter_keypair)
    .send()
    .await?;

println!("Transaction signature: {}", signature);
```

### Multiple Instructions

Combine multiple instructions into a single transaction:

```rust theme={null}
// Build individual instructions
let init_ix = program
    .request()
    .accounts(accounts::Initialize { /* ... */ })
    .args(args::Initialize)
    .instructions()?
    .remove(0);

let increment_ix = program
    .request()
    .accounts(accounts::Increment { /* ... */ })
    .args(args::Increment)
    .instructions()?
    .remove(0);

// Combine and send
let signature = program
    .request()
    .instruction(init_ix)
    .instruction(increment_ix)
    .signer(&counter_keypair)
    .send()
    .await?;
```

### Remaining Accounts

For instructions that accept remaining accounts:

```rust theme={null}
use solana_instruction::AccountMeta;

let remaining = vec![
    AccountMeta {
        pubkey: additional_account,
        is_signer: false,
        is_writable: true,
    },
];

let signature = program
    .request()
    .accounts(accounts::MyInstruction { /* ... */ })
    .accounts(remaining)  // Add remaining accounts
    .args(args::MyInstruction { /* ... */ })
    .send()
    .await?;
```

## Fetching Accounts

Fetch and deserialize program accounts using type-safe methods.

### Single Account

```rust theme={null}
use my_program::accounts::Counter;

// Fetch and deserialize account
let counter: Counter = program.account(counter_address).await?;
println!("Count: {}", counter.count);
```

### Multiple Accounts with Filters

```rust theme={null}
use anchor_client::solana_rpc_client_api::filter::{Memcmp, RpcFilterType};

// Filter accounts where bytes 8-16 match a specific value
let filters = vec![
    RpcFilterType::Memcmp(Memcmp::new_base58_encoded(
        8,  // offset (skip 8-byte discriminator)
        &expected_value,
    )),
];

let accounts_iter = program.accounts::<Counter>(filters).await?;

// Iterate over matching accounts
for result in accounts_iter {
    let (pubkey, account) = result?;
    println!("Account {}: count = {}", pubkey, account.count);
}
```

## Event Listeners

Subscribe to program events emitted via logs:

<Tabs>
  <Tab title="Async">
    ```rust theme={null}
    use my_program::events::CounterUpdated;

    let unsubscriber = program
        .on::<CounterUpdated>(|ctx, event| {
            println!("Event received!");
            println!("  Slot: {}", ctx.slot);
            println!("  Signature: {}", ctx.signature);
            println!("  Counter: {}", event.count);
        })
        .await?;

    // Later, unsubscribe
    unsubscriber.unsubscribe().await;
    ```
  </Tab>

  <Tab title="Blocking">
    ```rust theme={null}
    use my_program::events::CounterUpdated;

    let unsubscriber = program.on::<CounterUpdated>(|ctx, event| {
        println!("Event received!");
        println!("  Slot: {}", ctx.slot);
        println!("  Signature: {}", ctx.signature);
        println!("  Counter: {}", event.count);
    })?;

    // Later, unsubscribe  
    unsubscriber.unsubscribe();
    ```
  </Tab>
</Tabs>

## Complete Example

Here's a full example demonstrating the Rust client in action:

<CodeGroup>
  ```rust main.rs (Async) theme={null}
  use anchor_client::{
      solana_client::rpc_client::RpcClient,
      solana_sdk::{
          commitment_config::CommitmentConfig,
          native_token::LAMPORTS_PER_SOL,
          signature::Keypair,
          system_program,
      },
      solana_signer::Signer,
      Client, Cluster,
  };
  use anchor_lang::prelude::*;
  use std::rc::Rc;

  // Generate client code from IDL
  declare_program!(counter);
  use counter::{accounts::Counter, client::accounts, client::args};

  #[tokio::main]
  async fn main() -> anyhow::Result<()> {
      // Setup
      let connection = RpcClient::new_with_commitment(
          "http://127.0.0.1:8899",
          CommitmentConfig::confirmed(),
      );

      let payer = Keypair::new();
      let counter_kp = Keypair::new();

      // Airdrop SOL
      println!("Requesting airdrop...");
      let sig = connection.request_airdrop(&payer.pubkey(), LAMPORTS_PER_SOL)?;
      loop {
          if connection.confirm_transaction(&sig)? {
              break;
          }
          std::thread::sleep(std::time::Duration::from_millis(100));
      }
      println!("Airdrop confirmed");

      // Create client and program
      let client = Client::new_with_options(
          Cluster::Localnet,
          Rc::new(payer),
          CommitmentConfig::confirmed(),
      );
      let program = client.program(counter::ID)?;

      // Initialize counter
      println!("\nInitializing counter...");
      let init_sig = program
          .request()
          .accounts(accounts::Initialize {
              counter: counter_kp.pubkey(),
              payer: program.payer(),
              system_program: system_program::ID,
          })
          .args(args::Initialize)
          .signer(&counter_kp)
          .send()
          .await?;
      println!("Initialize tx: {}", init_sig);

      // Increment counter
      println!("\nIncrementing counter...");
      let increment_sig = program
          .request()
          .accounts(accounts::Increment {
              counter: counter_kp.pubkey(),
          })
          .args(args::Increment)
          .send()
          .await?;
      println!("Increment tx: {}", increment_sig);

      // Fetch account
      println!("\nFetching counter account...");
      let counter_account: Counter = program
          .account(counter_kp.pubkey())
          .await?;
      println!("Counter value: {}", counter_account.count);

      Ok(())
  }
  ```

  ```rust main.rs (Blocking) theme={null}
  use anchor_client::{
      solana_client::rpc_client::RpcClient,
      solana_sdk::{
          commitment_config::CommitmentConfig,
          native_token::LAMPORTS_PER_SOL,
          signature::Keypair,
          system_program,
      },
      solana_signer::Signer,
      Client, Cluster,
  };
  use anchor_lang::prelude::*;
  use std::rc::Rc;

  // Generate client code from IDL
  declare_program!(counter);
  use counter::{accounts::Counter, client::accounts, client::args};

  fn main() -> anyhow::Result<()> {
      // Setup
      let connection = RpcClient::new_with_commitment(
          "http://127.0.0.1:8899",
          CommitmentConfig::confirmed(),
      );

      let payer = Keypair::new();
      let counter_kp = Keypair::new();

      // Airdrop SOL
      println!("Requesting airdrop...");
      let sig = connection.request_airdrop(&payer.pubkey(), LAMPORTS_PER_SOL)?;
      loop {
          if connection.confirm_transaction(&sig)? {
              break;
          }
          std::thread::sleep(std::time::Duration::from_millis(100));
      }
      println!("Airdrop confirmed");

      // Create client and program
      let client = Client::new_with_options(
          Cluster::Localnet,
          Rc::new(payer),
          CommitmentConfig::confirmed(),
      );
      let program = client.program(counter::ID)?;

      // Initialize counter
      println!("\nInitializing counter...");
      let init_sig = program
          .request()
          .accounts(accounts::Initialize {
              counter: counter_kp.pubkey(),
              payer: program.payer(),
              system_program: system_program::ID,
          })
          .args(args::Initialize)
          .signer(&counter_kp)
          .send()?;
      println!("Initialize tx: {}", init_sig);

      // Increment counter
      println!("\nIncrementing counter...");
      let increment_sig = program
          .request()
          .accounts(accounts::Increment {
              counter: counter_kp.pubkey(),
          })
          .args(args::Increment)
          .send()?;
      println!("Increment tx: {}", increment_sig);

      // Fetch account
      println!("\nFetching counter account...");
      let counter_account: Counter = program.account(counter_kp.pubkey())?;
      println!("Counter value: {}", counter_account.count);

      Ok(())
  }
  ```

  ```toml Cargo.toml theme={null}
  [package]
  name = "counter-client"
  version = "0.1.0"
  edition = "2021"

  [dependencies]
  anchor-client = { version = "0.32.1", features = ["async"] }
  anchor-lang = "0.32.1"
  anyhow = "1.0"
  tokio = { version = "1.0", features = ["full"] }
  ```
</CodeGroup>

## Error Handling

The client uses the `ClientError` enum for error handling:

```rust theme={null}
use anchor_client::ClientError;

match program.account::<Counter>(address).await {
    Ok(account) => println!("Count: {}", account.count),
    Err(ClientError::AccountNotFound) => {
        println!("Account doesn't exist");
    }
    Err(ClientError::AnchorError(e)) => {
        println!("Anchor error: {:?}", e);
    }
    Err(ClientError::SolanaClientError(e)) => {
        println!("RPC error: {:?}", e);
    }
    Err(e) => println!("Error: {:?}", e),
}
```

## Features

The `anchor-client` crate supports optional features:

### async

Enables asynchronous client operations:

```toml theme={null}
anchor-client = { version = "0.32.1", features = ["async"] }
```

With async enabled, all I/O operations return `Future`s and require an async runtime like Tokio.

### mock

Allows passing custom RPC clients for testing:

```toml theme={null}
anchor-client = { version = "0.32.1", features = ["mock"] }
```

Useful for mocking RPC responses in tests using [`RpcClient::new_mock`](https://docs.rs/solana-rpc-client/latest/solana_rpc_client/rpc_client/struct.RpcClient.html#method.new_mock).

## API Reference

### Client

| Method                                      | Description                          |
| ------------------------------------------- | ------------------------------------ |
| `new(cluster, payer)`                       | Create new client                    |
| `new_with_options(cluster, payer, options)` | Create client with custom commitment |
| `program(program_id)`                       | Create program instance              |

### Program

| Method                 | Description                          |
| ---------------------- | ------------------------------------ |
| `request()`            | Create new request builder           |
| `account<T>(address)`  | Fetch and deserialize account        |
| `accounts<T>(filters)` | Fetch multiple accounts with filters |
| `payer()`              | Get payer public key                 |
| `id()`                 | Get program ID                       |

### RequestBuilder

| Method               | Description                       |
| -------------------- | --------------------------------- |
| `accounts(accounts)` | Set instruction accounts          |
| `args(args)`         | Set instruction arguments         |
| `signer(signer)`     | Add signer                        |
| `instruction(ix)`    | Add instruction                   |
| `send()`             | Build, sign, and send transaction |
| `transaction()`      | Build transaction without sending |
| `instructions()`     | Get list of instructions          |

## Next Steps

<CardGroup cols={2}>
  <Card title="TypeScript Client" icon="js" href="/clients/typescript">
    Learn about the TypeScript client library
  </Card>

  <Card title="Testing Programs" icon="vial" href="/testing/overview">
    Write tests for your Anchor programs
  </Card>
</CardGroup>
