Skip to main content

Overview

The workspace object provides a convenient way to automatically load and access Anchor programs defined in your workspace. It searches for compiled IDLs in the target/idl directory and creates Program instances on demand.
The workspace API is only available in Node.js environments, not in browsers.

Usage

import * as anchor from "@anchor-lang/anchor";
import { Program } from "@anchor-lang/anchor";
import { MyProgram } from "./target/types/my_program";

// Access program from workspace
const program = anchor.workspace.MyProgram as Program<MyProgram>;

// TypeScript types are automatically inferred
const tx = await program.methods.initialize().rpc();

How It Works

The workspace object uses a JavaScript Proxy to dynamically load programs when accessed:
  1. IDL Discovery: Searches the target/idl directory for matching IDL files
  2. Name Matching: Converts the property name to camelCase and matches against IDL filenames
  3. Program Creation: Automatically creates a Program instance with the loaded IDL
  4. Caching: Caches loaded programs for subsequent access

Workspace Type

type Workspace = {
  [programName: string]: Program;
};
The workspace acts as a dictionary where keys are program names (in any case format) and values are Program instances.

Program Name Resolution

The workspace converts program names to camelCase for flexible access:
// All of these access the same program:
anchor.workspace.myProgram
anchor.workspace.MyProgram
anchor.workspace["my-program"]
anchor.workspace["my_program"]

Configuration

Anchor.toml Override

You can override workspace program locations in Anchor.toml:
[provider]
cluster = "localnet"

[programs.localnet]
my_program = "Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS"

# Override IDL location
[programs.localnet.my_program]
idl = "./custom/path/to/idl.json"
address = "Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS"

Default Behavior

Without configuration overrides, the workspace:
  • Reads IDL files from target/idl/
  • Matches filenames against the requested program name (after converting both to camelCase)
  • Uses the program address specified in the IDL’s address field

Properties

[programName]
Program
Access a program by name. The name is case-insensitive and can use any format.
const program = anchor.workspace.MyProgram;

Error Handling

Browser Environment

Attempting to use workspace in a browser throws an error:
// Error: Workspaces aren't available in the browser
const program = anchor.workspace.MyProgram;

IDL Not Found

If no matching IDL file is found:
// Error: Failed to find IDL of program `myProgram`
const program = anchor.workspace.NonExistent;

IDL File Missing

If the IDL path doesn’t exist:
// Error: target/idl/my_program.json doesn't exist. 
// Did you run `anchor build`?
const program = anchor.workspace.MyProgram;

Usage Examples

Basic Test Setup

import * as anchor from "@anchor-lang/anchor";
import { Program } from "@anchor-lang/anchor";
import { MyProgram } from "../target/types/my_program";
import { assert } from "chai";

describe("my-program", () => {
  // Configure the client to use the local cluster
  anchor.setProvider(anchor.AnchorProvider.env());

  const program = anchor.workspace.MyProgram as Program<MyProgram>;

  it("initializes", async () => {
    const tx = await program.methods.initialize().rpc();
    console.log("Transaction signature:", tx);
  });
});

Multiple Programs

import * as anchor from "@anchor-lang/anchor";

const tokenProgram = anchor.workspace.TokenProgram;
const nftProgram = anchor.workspace.NftProgram;
const stakingProgram = anchor.workspace.StakingProgram;

// All programs share the same provider
const provider = anchor.getProvider();

Type-Safe Access

import { Program } from "@anchor-lang/anchor";
import { MyProgram } from "../target/types/my_program";

// TypeScript knows all available methods and accounts
const program = anchor.workspace.MyProgram as Program<MyProgram>;

// Autocomplete works for instruction names
const tx = await program.methods
  .initialize()
  .accounts({
    // Autocomplete works for account names
    myAccount: myAccountPubkey,
  })
  .rpc();

// Autocomplete works for account types
const account = await program.account.myAccount.fetch(address);
console.log(account.balance); // Type-safe access to fields

Testing with Multiple Clusters

import * as anchor from "@anchor-lang/anchor";
import { Program } from "@anchor-lang/anchor";
import { MyProgram } from "../target/types/my_program";

describe("my-program", () => {
  let program: Program<MyProgram>;

  before(async () => {
    // Set up provider for desired cluster
    const provider = anchor.AnchorProvider.local();
    anchor.setProvider(provider);

    // Load program from workspace
    program = anchor.workspace.MyProgram;
  });

  it("works on localnet", async () => {
    const tx = await program.methods.initialize().rpc();
    assert.ok(tx);
  });
});

Custom IDL Path

For programs with custom IDL locations specified in Anchor.toml:
# Anchor.toml
[programs.localnet.my_program]
idl = "./idls/custom_location.json"
address = "YourProgramAddress"
// Still access the same way
const program = anchor.workspace.MyProgram;

// The workspace automatically uses the custom IDL path

Accessing Program Properties

const program = anchor.workspace.MyProgram;

// Program ID from IDL
console.log("Program ID:", program.programId.toString());

// Provider connection
console.log("Cluster:", program.provider.connection.rpcEndpoint);

// IDL metadata
console.log("Instructions:", program.idl.instructions.map(i => i.name));
console.log("Accounts:", program.idl.accounts?.map(a => a.name));

Integration with Anchor CLI

The workspace object is designed to work seamlessly with the Anchor CLI workflow:
# Build programs and generate IDLs
anchor build

# IDLs are output to target/idl/
# TypeScript types are output to target/types/

# Run tests that use workspace
anchor test

Best Practices

Use the generated TypeScript types for type safety:
// Good - type-safe
const program = anchor.workspace.MyProgram as Program<MyProgram>;

// Bad - no type checking
const program = anchor.workspace.MyProgram;
Ensure your programs are built before accessing the workspace:
anchor build
anchor test
The workspace is ideal for testing but shouldn’t be used in production clients:
// Good - test environment
describe("tests", () => {
  const program = anchor.workspace.MyProgram;
});

// Bad - production app
// Use explicit Program constructor instead
const program = new Program(idl, provider);
Check if a program exists before using it:
try {
  const program = anchor.workspace.MyProgram;
  // Use program...
} catch (error) {
  console.error("Program not found. Run 'anchor build' first.");
}

Build docs developers (and LLMs) love