LogoAnchor Docs

TypeScript

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

Anchor provides a Typescript client library (@coral-xyz/anchor) that simplifies the process of interacting with Solana programs from the client in JavaScript or TypeScript.

The @coral-xyz/anchor library is only compatible with the legacy version (v1) of @solana/web3.js and @solana/spl-token. It is not compatible with the new version (v2) of @solana/web3.js.

Client Program

To interact with an Anchor program using @coral-xyz/anchor, you'll need to create a Program instance using the program's IDL file.

Creating an instance of the Program requires the program's IDL and an AnchorProvider. An AnchorProvider is an abstraction that combines two things:

  • Connection - the connection to a Solana cluster (i.e. localhost, devnet, mainnet)
  • Wallet - (optional) a default wallet used to pay for and sign transactions

When integrating with a frontend using the Solana wallet adapter, you'll need to set up the AnchorProvider and Program.

example
import { Program, AnchorProvider, setProvider } from "@coral-xyz/anchor";
import { useAnchorWallet, useConnection } from "@solana/wallet-adapter-react";
import type { HelloAnchor } from "./idlType";
import idl from "./idl.json";
 
const { connection } = useConnection();
const wallet = useAnchorWallet();
 


const provider = new AnchorProvider(connection, wallet, {});
setProvider(provider);
 


export const program = new Program(idl as HelloAnchor, {
  connection,
});

In the code snippet above:

  • idl.json is the IDL file generated by Anchor, found at /target/idl/<program-name>.json in an Anchor project.
  • idlType.ts is the IDL type (for use with TypeScript), found at /target/types/<program-name>.ts in an Anchor project.

Alternatively, you can create an Program instance using only the IDL and the Connection to a Solana cluster. This means there is no default Wallet, but allows you to use the Program to fetch accounts or build instructions without a connected wallet.

import { clusterApiUrl, Connection, PublicKey } from "@solana/web3.js";
import { Program } from "@coral-xyz/anchor";
import type { HelloAnchor } from "./idlType";
import idl from "./idl.json";
 
const connection = new Connection(clusterApiUrl("devnet"), "confirmed");
 


export const program = new Program(idl as HelloAnchor, {
  connection,
});

Invoke Instructions

Once the Program is set up using a program's IDL file, you can use the Anchor MethodsBuilder to:

  • Build individual instructions
  • Build transactions
  • Build and send transactions

The basic format looks like the following:

program.methods - This is the builder API for creating instruction calls from the program's IDL



await program.methods
  .instructionName(instructionData)
  .accounts({})
  .signers([])
  .rpc();

Anchor provides multiple methods for building program instructions:

The rpc() method sends a signed transaction with the specified instruction and returns a TransactionSignature.

When using .rpc, the Wallet from the Provider is automatically included as a signer.

// Generate keypair for the new account
const newAccountKp = new Keypair();
 
const data = new BN(42);
const transactionSignature = await program.methods
  .initialize(data)
  .accounts({
    newAccount: newAccountKp.publicKey,
    signer: wallet.publicKey,
    systemProgram: SystemProgram.programId,
  })
  .signers([newAccountKp])


  .rpc();

Fetch Accounts

The Program client simplifies the process of fetching and deserializing accounts created by your Anchor program.

Use program.account followed by the name of the account type defined in the IDL. Anchor provides multiple methods for fetching accounts.

Use all() to fetch all existing accounts for a specific account type.


const accounts = await program.account.newAccount.all();

Example

The example below demonstrates how to use @coral-xyz/anchor to interact with a simple Anchor program. 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 TypeScript client that interacts with the Anchor program:

example.json
example.ts
example.ts
package.json

The /idl directory in the example includes two files:

  • example.json: The IDL file for the program
  • example.ts: A TypeScript type definition file generated for the IDL

The tabs below include the example.json and example.ts files as a reference of what these files look like.

{
  "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"
          }
        ]
      }
    }
  ]
}

When you run anchor build in an Anchor project, the Anchor CLI automatically generates:

  • The IDL file (.json) in the target/idl folder (ex. target/idl/example.json)

  • The TypeScript type definitions (.ts) in the target/types folder (ex. target/types/example.ts)

The example.ts file below includes the script to interact with the program.

example.ts
import {
  Connection,
  Keypair,
  LAMPORTS_PER_SOL,
  Transaction,
  sendAndConfirmTransaction,
} from "@solana/web3.js";
import { Program } from "@coral-xyz/anchor";
import type { Example } from "./idl/example.ts";
import idl from "./idl/example.json";
 
// Set up a connection to the cluster
const connection = new Connection("http://127.0.0.1:8899", "confirmed");
 
// Create a Program instance using the IDL and connection
const program = new Program(idl as Example, {
  connection,
});
 
// Generate new Keypairs for the payer and the counter account
const payer = Keypair.generate();
const counter = Keypair.generate();
 
// Airdrop SOL to fund the payer's account for transaction fees
const airdropTransactionSignature = await connection.requestAirdrop(
  payer.publicKey,
  LAMPORTS_PER_SOL,
);
await connection.confirmTransaction(airdropTransactionSignature);
 
// Build the initialize instruction
const initializeInstruction = await program.methods
  .initialize()
  .accounts({
    payer: payer.publicKey,
    counter: counter.publicKey,
  })
  .instruction();
 
// Build the increment instruction
const incrementInstruction = await program.methods
  .increment()
  .accounts({
    counter: counter.publicKey,
  })
  .instruction();
 
// Add both instructions to a single transaction
const transaction = new Transaction().add(
  initializeInstruction,
  incrementInstruction,
);
 
// Send the transaction
const transactionSignature = await sendAndConfirmTransaction(
  connection,
  transaction,
  [payer, counter],
);
console.log("Transaction Signature", transactionSignature);
 
// Fetch the counter account
const counterAccount = await program.account.counter.fetch(counter.publicKey);
console.log("Count:", counterAccount.count);

On this page

Edit on GitHub