diff --git a/docs/.env.example b/docs/.env.example
deleted file mode 100644
index 71d53c5c13..0000000000
--- a/docs/.env.example
+++ /dev/null
@@ -1,3 +0,0 @@
-NEXT_PUBLIC_DOCSEARCH_APP_ID=
-NEXT_PUBLIC_DOCSEARCH_API_KEY=
-NEXT_PUBLIC_DOCSEARCH_INDEX_NAME=
diff --git a/docs/.eslintrc.json b/docs/.eslintrc.json
deleted file mode 100644
index bffb357a71..0000000000
--- a/docs/.eslintrc.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- "extends": "next/core-web-vitals"
-}
diff --git a/docs/.gitignore b/docs/.gitignore
index 4db8cdcd07..55a12ae71d 100644
--- a/docs/.gitignore
+++ b/docs/.gitignore
@@ -1,35 +1,28 @@
-# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
-
-# dependencies
+# deps
/node_modules
-/.pnp
-.pnp.js
-# testing
-/coverage
+# generated content
+.contentlayer
+.content-collections
+.source
-# next.js
+# test & build
+/coverage
/.next/
/out/
-
-# production
/build
+*.tsbuildinfo
# misc
.DS_Store
*.pem
-
-# debug
+/.pnp
+.pnp.js
npm-debug.log*
yarn-debug.log*
yarn-error.log*
-.pnpm-debug.log*
-# local env files
+# others
.env*.local
-
-# vercel
.vercel
-
-.vscode/
-.idea
\ No newline at end of file
+next-env.d.ts
\ No newline at end of file
diff --git a/docs/.prettierrc b/docs/.prettierrc
new file mode 100644
index 0000000000..d2f009f9d5
--- /dev/null
+++ b/docs/.prettierrc
@@ -0,0 +1,10 @@
+{
+ "tabWidth": 2,
+ "useTabs": false,
+ "singleQuote": false,
+ "printWidth": 80,
+ "trailingComma": "all",
+ "arrowParens": "avoid",
+ "endOfLine": "auto",
+ "proseWrap": "always"
+}
diff --git a/docs/README.md b/docs/README.md
index 351378f663..0566d41e7d 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -1,20 +1,16 @@
# Anchor Docs
-## Getting started
+Created with [Fumadocs](https://fumadocs.vercel.app). Page contents located in
+[`docs/content/docs`](/docs/content/docs).
-```bash
-npm install
-cp .env.example .env.local
-```
-
-Next, run the development server:
+Run development server:
```bash
npm run dev
+# or
+pnpm dev
+# or
+yarn dev
```
-Finally, open [http://localhost:3000](http://localhost:3000) in your browser to view the website.
-
-## Customizing
-
-You can start editing this template by modifying the files in the `/src` folder. The site will auto-update as you edit these files.
+Open http://localhost:3000 with your browser to see the result.
diff --git a/docs/app/(home)/layout.tsx b/docs/app/(home)/layout.tsx
new file mode 100644
index 0000000000..608a58b1d4
--- /dev/null
+++ b/docs/app/(home)/layout.tsx
@@ -0,0 +1,11 @@
+import type { ReactNode } from 'react';
+import { HomeLayout } from 'fumadocs-ui/layouts/home';
+import { baseOptions } from '@/app/layout.config';
+
+export default function Layout({
+ children,
+}: {
+ children: ReactNode;
+}): React.ReactElement {
+ return {children};
+}
diff --git a/docs/app/(home)/page.tsx b/docs/app/(home)/page.tsx
new file mode 100644
index 0000000000..f58825d8d9
--- /dev/null
+++ b/docs/app/(home)/page.tsx
@@ -0,0 +1,19 @@
+import Link from "next/link";
+
+export default function HomePage() {
+ return (
+
+
Hello World
+
+ You can open{" "}
+
+ /docs
+ {" "}
+ and see the documentation.
+
+
+ );
+}
diff --git a/docs/app/api/search/route.ts b/docs/app/api/search/route.ts
new file mode 100644
index 0000000000..6818340f7c
--- /dev/null
+++ b/docs/app/api/search/route.ts
@@ -0,0 +1,4 @@
+import { docsSource } from '@/app/source';
+import { createFromSource } from 'fumadocs-core/search/server';
+
+export const { GET } = createFromSource(docsSource);
diff --git a/docs/app/docs/[[...slug]]/page.tsx b/docs/app/docs/[[...slug]]/page.tsx
new file mode 100644
index 0000000000..81b4b202a1
--- /dev/null
+++ b/docs/app/docs/[[...slug]]/page.tsx
@@ -0,0 +1,93 @@
+import { docsSource as source } from "@/app/source";
+import {
+ DocsPage,
+ DocsBody,
+ DocsDescription,
+ DocsTitle,
+ DocsCategory,
+} from "fumadocs-ui/page";
+import { notFound } from "next/navigation";
+import defaultMdxComponents from "fumadocs-ui/mdx";
+import { ImageZoom } from "fumadocs-ui/components/image-zoom";
+import { Accordion, Accordions } from "fumadocs-ui/components/accordion";
+import { Step, Steps } from "fumadocs-ui/components/steps";
+import { Tab, Tabs } from "fumadocs-ui/components/tabs";
+import { Callout } from "fumadocs-ui/components/callout";
+import { TypeTable } from "fumadocs-ui/components/type-table";
+import { Files, Folder, File } from "fumadocs-ui/components/files";
+import GithubIcon from "@/public/icons/github.svg";
+
+export default async function Page(props: {
+ params: Promise<{ slug?: string[] }>;
+}) {
+ const params = await props.params;
+ const page = source.getPage(params.slug);
+ if (!page) notFound();
+
+ const MDX = page.data.body;
+
+ return (
+ item.depth <= 3)}
+ full={page.data.full}
+ tableOfContent={{ footer: }}
+ >
+ {page.data.title}
+ {page.data.description}
+
+ ,
+ Accordion,
+ Accordions,
+ Step,
+ Steps,
+ Tab,
+ Tabs,
+ Callout,
+ TypeTable,
+ Files,
+ Folder,
+ File,
+ }}
+ />
+ {page.data.index ? : null}
+
+
+ );
+}
+
+function EditOnGithub({ path }: { path: string }) {
+ // placeholder
+ const href = `https://github.com/coral-xyz/anchor/blob/master/docs/content/docs/${path.startsWith("/") ? path.slice(1) : path}`;
+ return (
+
+
+ Edit on GitHub
+
+ );
+}
+
+export async function generateStaticParams() {
+ return source.generateParams();
+}
+
+export async function generateMetadata(props: {
+ params: Promise<{ slug?: string[] }>;
+}) {
+ const params = await props.params;
+ const page = source.getPage(params.slug);
+ if (!page) notFound();
+
+ return {
+ title: page.data.title,
+ description: page.data.description,
+ };
+}
diff --git a/docs/app/docs/layout.tsx b/docs/app/docs/layout.tsx
new file mode 100644
index 0000000000..33f3444a70
--- /dev/null
+++ b/docs/app/docs/layout.tsx
@@ -0,0 +1,7 @@
+import { DocsLayout } from "fumadocs-ui/layouts/notebook";
+import type { ReactNode } from "react";
+import { docsOptions } from "../layout.config";
+
+export default function Layout({ children }: { children: ReactNode }) {
+ return {children};
+}
diff --git a/docs/app/global.css b/docs/app/global.css
new file mode 100644
index 0000000000..b5c61c9567
--- /dev/null
+++ b/docs/app/global.css
@@ -0,0 +1,3 @@
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
diff --git a/docs/public/favicon.ico b/docs/app/icon.ico
similarity index 100%
rename from docs/public/favicon.ico
rename to docs/app/icon.ico
diff --git a/docs/app/layout.config.tsx b/docs/app/layout.config.tsx
new file mode 100644
index 0000000000..197330c7c3
--- /dev/null
+++ b/docs/app/layout.config.tsx
@@ -0,0 +1,54 @@
+import { type DocsLayoutProps } from "fumadocs-ui/layouts/notebook";
+import { type HomeLayoutProps } from "fumadocs-ui/layouts/home";
+import { docsSource } from "./source";
+import StackExchangeIcon from "@/public/icons/stackexchange.svg";
+import GithubIcon from "@/public/icons/github.svg";
+import DiscordIcon from "@/public/icons/discord.svg";
+import Image from "next/image";
+
+/**
+ * Shared layout configurations
+ *
+ * you can configure layouts individually from:
+ * Home Layout: app/(home)/layout.tsx
+ * Docs Layout: app/docs/layout.tsx
+ */
+export const baseOptions: HomeLayoutProps = {
+ nav: {
+ title: (
+
+
+ Anchor Docs
+
+ ),
+ url: "/docs",
+ },
+ links: [
+ {
+ icon: ,
+ text: "Github",
+ url: "https://github.com/coral-xyz/anchor",
+ active: "none",
+ },
+ {
+ icon: ,
+ text: "Discord",
+ url: "https://discord.com/invite/NHHGSXAnXk",
+ active: "none",
+ },
+ {
+ icon: ,
+ text: "Stack Exchange",
+ url: "https://solana.stackexchange.com/",
+ active: "none",
+ },
+ ],
+};
+
+export const docsOptions: DocsLayoutProps = {
+ ...baseOptions,
+ sidebar: {
+ defaultOpenLevel: 1,
+ },
+ tree: docsSource.pageTree,
+};
diff --git a/docs/app/layout.tsx b/docs/app/layout.tsx
new file mode 100644
index 0000000000..934fe2f21e
--- /dev/null
+++ b/docs/app/layout.tsx
@@ -0,0 +1,19 @@
+import "./global.css";
+import { RootProvider } from "fumadocs-ui/provider";
+import { Inter } from "next/font/google";
+import type { ReactNode } from "react";
+import { GoogleAnalytics } from "@next/third-parties/google";
+const inter = Inter({
+ subsets: ["latin"],
+});
+
+export default function Layout({ children }: { children: ReactNode }) {
+ return (
+
+
+ {children}
+
+
+
+ );
+}
diff --git a/docs/app/source.ts b/docs/app/source.ts
new file mode 100644
index 0000000000..882708be6b
--- /dev/null
+++ b/docs/app/source.ts
@@ -0,0 +1,8 @@
+import { docs, meta } from "@/.source";
+import { createMDXSource } from "fumadocs-mdx";
+import { loader } from "fumadocs-core/source";
+
+export const docsSource = loader({
+ baseUrl: "/docs",
+ source: createMDXSource(docs, meta),
+});
diff --git a/docs/content/docs/basics/cpi.mdx b/docs/content/docs/basics/cpi.mdx
new file mode 100644
index 0000000000..fbb8e374af
--- /dev/null
+++ b/docs/content/docs/basics/cpi.mdx
@@ -0,0 +1,586 @@
+---
+title: Cross Program Invocation
+description:
+ Learn how to implement Cross Program Invocations (CPIs) in Anchor programs to
+ enable composability between different Solana programs.
+---
+
+Cross Program Invocations (CPI) refer to the process of one program invoking
+instructions of another program, which enables the composibility of Solana
+programs.
+
+This section will cover the basics of implementing CPIs in an Anchor program,
+using a simple SOL transfer instruction as a practical example. Once you
+understand the basics of how to implement a CPI, you can apply the same concepts
+for any instruction.
+
+## Cross Program Invocations
+
+Let's examine a program that implements a CPI to the System Program's transfer
+instruction. Here is the example program on
+[Solana Playground](https://beta.solpg.io/66df2751cffcf4b13384d35a).
+
+The `lib.rs` file includes a single `sol_transfer` instruction. When the
+`sol_transfer` instruction on the Anchor program is invoked, the program
+internally invokes the transfer instruction of the System Program.
+
+```rust title="lib.rs"
+use anchor_lang::prelude::*;
+use anchor_lang::system_program::{transfer, Transfer};
+
+declare_id!("9AvUNHjxscdkiKQ8tUn12QCMXtcnbR9BVGq3ULNzFMRi");
+
+#[program]
+pub mod cpi {
+ use super::*;
+
+ // [!code word:sol_transfer]
+ // [!code highlight]
+ pub fn sol_transfer(ctx: Context, amount: u64) -> Result<()> {
+ let from_pubkey = ctx.accounts.sender.to_account_info();
+ let to_pubkey = ctx.accounts.recipient.to_account_info();
+ let program_id = ctx.accounts.system_program.to_account_info();
+
+ let cpi_context = CpiContext::new(
+ program_id,
+ Transfer {
+ from: from_pubkey,
+ to: to_pubkey,
+ },
+ );
+ // [!code word:transfer]
+ // [!code highlight]
+ transfer(cpi_context, amount)?;
+ Ok(())
+ }
+}
+
+#[derive(Accounts)]
+pub struct SolTransfer<'info> {
+ #[account(mut)]
+ sender: Signer<'info>,
+ #[account(mut)]
+ recipient: SystemAccount<'info>,
+ system_program: Program<'info, System>,
+}
+```
+
+The `cpi.test.ts` file shows how to invoke the Anchor program's `sol_transfer`
+instruction and logs a link to the transaction details on SolanaFM.
+
+```ts title="cpi.test.ts"
+it("SOL Transfer Anchor", async () => {
+ const transactionSignature = await program.methods
+ .solTransfer(new BN(transferAmount))
+ .accounts({
+ sender: sender.publicKey,
+ recipient: recipient.publicKey,
+ })
+ .rpc();
+
+ console.log(
+ `\nTransaction Signature:` +
+ `https://solana.fm/tx/${transactionSignature}?cluster=devnet-solana`,
+ );
+});
+```
+
+You can build, deploy, and run the test for this example on Playground to view
+the transaction details on the [SolanaFM explorer](https://solana.fm/).
+
+The transaction details will show that the Anchor program was first invoked
+(instruction 1), which then invokes the System Program (instruction 1.1),
+resulting in a successful SOL transfer.
+
+
+
+### Example Explanation
+
+Cross Program Invocations (CPIs) allow one program to invoke instructions on
+another program. The process of implementing a CPI is the same as that of
+creating a instruction where you must specify:
+
+1. The program ID of the program being called
+2. The accounts required by the instruction
+3. Any instruction data required as arguments
+
+This pattern ensures the CPI has all the information needed to invoke the target
+program's instruction.
+
+The System Program's transfer instruction requires two accounts:
+
+- `from`: The account sending SOL.
+- `to`: The account receiving SOL.
+
+In the example program, the `SolTransfer` struct specifies the accounts required
+by the transfer instruction. The System Program is also included because the CPI
+invokes the System Program.
+
+```rust
+// [!code word:sender]
+// [!code word:recipient]
+// [!code word:system_program]
+#[derive(Accounts)]
+pub struct SolTransfer<'info> {
+ #[account(mut)]
+ sender: Signer<'info>, // from account
+ #[account(mut)]
+ recipient: SystemAccount<'info>, // to account
+ system_program: Program<'info, System>, // program ID
+}
+```
+
+The following tabs present three approaches to implementing Cross Program
+Invocations (CPIs), each at a different level of abstraction. All examples are
+functionally equivalent. The main purpose is to illustrate the implementation
+details of a CPI.
+
+
+
+
+The `sol_transfer` instruction included in the example code shows a typical
+approach for constructing CPIs using the Anchor framework.
+
+This approach involves creating a
+[`CpiContext`](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/src/context.rs#L171),
+which includes the `program_id` and accounts required for the instruction being
+called. The `CpiContext` is then passed to an Anchor helper function
+([`transfer`](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/src/system_program.rs#L298))
+to invoke a specific instruction.
+
+```rust
+use anchor_lang::system_program::{transfer, Transfer};
+```
+
+```rust
+pub fn sol_transfer(ctx: Context, amount: u64) -> Result<()> {
+ let from_pubkey = ctx.accounts.sender.to_account_info();
+ let to_pubkey = ctx.accounts.recipient.to_account_info();
+ let program_id = ctx.accounts.system_program.to_account_info();
+
+ // [!code word:cpi_context]
+ let cpi_context = CpiContext::new(
+ program_id,
+ Transfer {
+ from: from_pubkey,
+ to: to_pubkey,
+ },
+ );
+
+ // [!code highlight]
+ transfer(cpi_context, amount)?;
+ Ok(())
+}
+```
+
+The `cpi_context` variable specifies the program ID (System Program) and
+accounts (sender and recipient) required by the transfer instruction.
+
+```rust /program_id/ /from_pubkey/ /to_pubkey/
+let cpi_context = CpiContext::new(
+ program_id,
+ Transfer {
+ from: from_pubkey,
+ to: to_pubkey,
+ },
+);
+```
+
+The `cpi_context` and `amount` are then passed into the `transfer` function to
+execute the CPI invoking the transfer instruction of the System Program.
+
+```rust
+transfer(cpi_context, amount)?;
+```
+
+
+
+
+This example shows a different approach to implementing a CPI using the `invoke`
+function and
+[`system_instruction::transfer`](https://github.com/anza-xyz/agave/blob/v1.18.26/sdk/program/src/system_instruction.rs#L881-L891),
+which is generally seen in native Rust programs.
+
+Under the hood, the previous example is an abstraction of this implementation.
+The example below is functionally equivalent to the previous example.
+
+```rust
+use anchor_lang::solana_program::{program::invoke, system_instruction};
+```
+
+```rust
+pub fn sol_transfer(ctx: Context, amount: u64) -> Result<()> {
+ let from_pubkey = ctx.accounts.sender.to_account_info();
+ let to_pubkey = ctx.accounts.recipient.to_account_info();
+ let program_id = ctx.accounts.system_program.to_account_info();
+
+ // [!code word:instruction:1]
+ let instruction =
+ &system_instruction::transfer(&from_pubkey.key(), &to_pubkey.key(), amount);
+
+ // [!code highlight]
+ // [!code word:instruction:1]
+ invoke(instruction, &[from_pubkey, to_pubkey, program_id])?;
+ Ok(())
+}
+```
+
+
+
+
+You can also manually build the instruction to pass into the `invoke()`
+function. This is useful when there is no crate available to help build the
+instruction you want to invoke. This approach requires you to specify the
+`AccountMeta`s for the instruction and correctly create the instruction data
+buffer.
+
+The `sol_transfer` instruction below is a manual implementation of a CPI to the
+System Program's transfer instruction.
+
+```rust
+pub fn sol_transfer(ctx: Context, amount: u64) -> Result<()> {
+ let from_pubkey = ctx.accounts.sender.to_account_info();
+ let to_pubkey = ctx.accounts.recipient.to_account_info();
+ let program_id = ctx.accounts.system_program.to_account_info();
+
+ // Prepare instruction AccountMetas
+ let account_metas = vec![
+ AccountMeta::new(from_pubkey.key(), true),
+ AccountMeta::new(to_pubkey.key(), false),
+ ];
+
+ // SOL transfer instruction discriminator
+ let instruction_discriminator: u32 = 2;
+
+ // Prepare instruction data
+ let mut instruction_data = Vec::with_capacity(4 + 8);
+ instruction_data.extend_from_slice(&instruction_discriminator.to_le_bytes());
+ instruction_data.extend_from_slice(&amount.to_le_bytes());
+
+ // Create instruction
+ // [!code word:instruction:1]
+ let instruction = Instruction {
+ program_id: program_id.key(),
+ accounts: account_metas,
+ data: instruction_data,
+ };
+
+ // Invoke instruction
+ // [!code word:instruction:1]
+ // [!code highlight]
+ invoke(&instruction, &[from_pubkey, to_pubkey, program_id])?;
+ Ok(())
+}
+```
+
+When building an instruction in Rust, use the following syntax to specify the
+`AccountMeta` for each account:
+
+```rust
+AccountMeta::new(account1_pubkey, true), // writable, signer
+AccountMeta::new(account2_pubkey, false), // writable, not signer
+AccountMeta::new_readonly(account3_pubkey, false), // not writable, not signer
+AccountMeta::new_readonly(account4_pubkey, true), // writable, signer
+```
+
+
+
+
+Here is a reference program on
+[Solana Playground](https://beta.solpg.io/github.com/ZYJLiu/doc-examples/tree/main/cpi)
+which includes all 3 examples.
+
+## Cross Program Invocations with PDA Signers
+
+Next, let's examine a program that implements a CPI to the System Program's
+transfer instruction where the sender is a Program Derived Address (PDA) that
+must be "signed" for by the program. Here is the example program on
+[Solana Playground](https://beta.solpg.io/66df2bd2cffcf4b13384d35b).
+
+The `lib.rs` file includes the following program with a single `sol_transfer`
+instruction.
+
+```rust title="lib.rs"
+use anchor_lang::prelude::*;
+use anchor_lang::system_program::{transfer, Transfer};
+
+declare_id!("3455LkCS85a4aYmSeNbRrJsduNQfYRY82A7eCD3yQfyR");
+
+#[program]
+pub mod cpi {
+ use super::*;
+
+ // [!code word:sol_transfer]
+ // [!code highlight]
+ pub fn sol_transfer(ctx: Context, amount: u64) -> Result<()> {
+ let from_pubkey = ctx.accounts.pda_account.to_account_info();
+ let to_pubkey = ctx.accounts.recipient.to_account_info();
+ let program_id = ctx.accounts.system_program.to_account_info();
+
+ let seed = to_pubkey.key();
+ let bump_seed = ctx.bumps.pda_account;
+ let signer_seeds: &[&[&[u8]]] = &[&[b"pda", seed.as_ref(), &[bump_seed]]];
+
+ let cpi_context = CpiContext::new(
+ program_id,
+ Transfer {
+ from: from_pubkey,
+ to: to_pubkey,
+ },
+ )
+ .with_signer(signer_seeds);
+
+ transfer(cpi_context, amount)?;
+ Ok(())
+ }
+}
+
+#[derive(Accounts)]
+pub struct SolTransfer<'info> {
+ #[account(
+ mut,
+ seeds = [b"pda", recipient.key().as_ref()],
+ bump,
+ )]
+ pda_account: SystemAccount<'info>,
+ #[account(mut)]
+ recipient: SystemAccount<'info>,
+ system_program: Program<'info, System>,
+}
+```
+
+The `cpi.test.ts` file shows how to invoke the Anchor program's `sol_transfer`
+instruction and logs a link to the transaction details on SolanaFM.
+
+It shows how to derive the PDA using the seeds specified in the program:
+
+```ts
+// [!code word:pda]
+// [!code word:wallet.publicKey]
+const [PDA] = PublicKey.findProgramAddressSync(
+ // [!code highlight]
+ [Buffer.from("pda"), wallet.publicKey.toBuffer()],
+ program.programId,
+);
+```
+
+The first step in this example is to fund the PDA account with a basic SOL
+transfer from the Playground wallet.
+
+```ts title="cpi.test.ts"
+it("Fund PDA with SOL", async () => {
+ const transferInstruction = SystemProgram.transfer({
+ fromPubkey: wallet.publicKey,
+ toPubkey: PDA,
+ lamports: transferAmount,
+ });
+
+ const transaction = new Transaction().add(transferInstruction);
+
+ const transactionSignature = await sendAndConfirmTransaction(
+ connection,
+ transaction,
+ [wallet.payer], // signer
+ );
+
+ console.log(
+ `\nTransaction Signature:` +
+ `https://solana.fm/tx/${transactionSignature}?cluster=devnet-solana`,
+ );
+});
+```
+
+Once the PDA is funded with SOL, invoke the `sol_transfer` instruction. This
+instruction transfers SOL from the PDA account back to the `wallet` account via
+a CPI to the System Program, which is "signed" for by the program.
+
+```ts
+it("SOL Transfer with PDA signer", async () => {
+ const transactionSignature = await program.methods
+ .solTransfer(new BN(transferAmount))
+ .accounts({
+ pdaAccount: PDA,
+ recipient: wallet.publicKey,
+ })
+ .rpc();
+
+ console.log(
+ `\nTransaction Signature: https://solana.fm/tx/${transactionSignature}?cluster=devnet-solana`,
+ );
+});
+```
+
+You can build, deploy, and run the test to view the transaction details on the
+[SolanaFM explorer](https://solana.fm/).
+
+The transaction details will show that the custom program was first invoked
+(instruction 1), which then invokes the System Program (instruction 1.1),
+resulting in a successful SOL transfer.
+
+
+
+### Example Explanation
+
+In the example code, the `SolTransfer` struct specifies the accounts required by
+the transfer instruction.
+
+The sender is a PDA that the program must sign for. The `seeds` to derive the
+address for the `pda_account` include the hardcoded string "pda" and the address
+of the `recipient` account. This means the address for the `pda_account` is
+unique for each `recipient`.
+
+```rust
+#[derive(Accounts)]
+pub struct SolTransfer<'info> {
+ #[account(
+ mut,
+ // [!code highlight]
+ seeds = [b"pda", recipient.key().as_ref()],
+ bump,
+ )]
+ // [!code word:pda_account]
+ pda_account: SystemAccount<'info>,
+ #[account(mut)]
+ // [!code word:recipient]
+ recipient: SystemAccount<'info>,
+ // [!code word:system_program]
+ system_program: Program<'info, System>,
+}
+```
+
+The Javascript equivalent to derive the PDA is included in the test file.
+
+```ts
+// [!code word:pda]
+// [!code word:wallet.publicKey]
+const [PDA] = PublicKey.findProgramAddressSync(
+ // [!code highlight]
+ [Buffer.from("pda"), wallet.publicKey.toBuffer()],
+ program.programId,
+);
+```
+
+The following tabs present two approaches to implementing Cross Program
+Invocations (CPIs), each at a different level of abstraction. Both examples are
+functionally equivalent. The main purpose is to illustrate the implementation
+details of the CPI.
+
+
+
+
+The `sol_transfer` instruction included in the example code shows a typical
+approach for constructing CPIs using the Anchor framework.
+
+This approach involves creating a
+[`CpiContext`](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/src/context.rs#L171),
+which includes the `program_id` and accounts required for the instruction being
+called, followed by a helper function (`transfer`) to invoke a specific
+instruction.
+
+```rust
+pub fn sol_transfer(ctx: Context, amount: u64) -> Result<()> {
+ let from_pubkey = ctx.accounts.pda_account.to_account_info();
+ let to_pubkey = ctx.accounts.recipient.to_account_info();
+ let program_id = ctx.accounts.system_program.to_account_info();
+
+ let seed = to_pubkey.key();
+ let bump_seed = ctx.bumps.pda_account;
+ let signer_seeds: &[&[&[u8]]] = &[&[b"pda", seed.as_ref(), &[bump_seed]]];
+
+ // [!code word:cpi_context]
+ let cpi_context = CpiContext::new(
+ program_id,
+ Transfer {
+ from: from_pubkey,
+ to: to_pubkey,
+ },
+ )
+ .with_signer(signer_seeds);
+
+ // [!code highlight]
+ transfer(cpi_context, amount)?;
+ Ok(())
+}
+```
+
+When signing with PDAs, the seeds and bump seed are included in the
+`cpi_context` as `signer_seeds` using `with_signer()`. The bump seed for a PDA
+can be accessed using `ctx.bumps` followed by the name of the PDA account.
+
+```rust /signer_seeds/ /bump_seed/ {3}
+let seed = to_pubkey.key();
+let bump_seed = ctx.bumps.pda_account;
+// [!code word:signer_seeds]
+// [!code highlight]
+let signer_seeds: &[&[&[u8]]] = &[&[b"pda", seed.as_ref(), &[bump_seed]]];
+
+let cpi_context = CpiContext::new(
+ program_id,
+ Transfer {
+ from: from_pubkey,
+ to: to_pubkey,
+ },
+)
+// [!code highlight]
+.with_signer(signer_seeds);
+```
+
+The `cpi_context` and `amount` are then passed into the `transfer` function to
+execute the CPI.
+
+```rust
+transfer(cpi_context, amount)?;
+```
+
+When the CPI is processed, the Solana runtime will validate that the provided
+seeds and caller program ID derive a valid PDA. The PDA is then added as a
+signer on the invocation. This mechanism allows for programs to sign for PDAs
+that are derived from their program ID.
+
+
+
+
+Under the hood, the previous example is a wrapper around the `invoke_signed()`
+function which uses
+[`system_instruction::transfer`](https://github.com/anza-xyz/agave/blob/v1.18.26/sdk/program/src/system_instruction.rs#L881-L891)
+to build the instruction.
+
+This example shows how to use the `invoke_signed()` function to make a CPI
+signed for by a PDA.
+
+```rust
+use anchor_lang::solana_program::{program::invoke_signed, system_instruction};
+```
+
+```rust
+pub fn sol_transfer(ctx: Context, amount: u64) -> Result<()> {
+ let from_pubkey = ctx.accounts.pda_account.to_account_info();
+ let to_pubkey = ctx.accounts.recipient.to_account_info();
+ let program_id = ctx.accounts.system_program.to_account_info();
+
+ let seed = to_pubkey.key();
+ let bump_seed = ctx.bumps.pda_account;
+
+ // [!code word:signer_seeds]
+ let signer_seeds: &[&[&[u8]]] = &[&[b"pda", seed.as_ref(), &[bump_seed]]];
+
+ // [!code word:instruction:1]
+ let instruction =
+ &system_instruction::transfer(&from_pubkey.key(), &to_pubkey.key(), amount);
+
+ // [!code word:instruction:1]
+ // [!code highlight]
+ invoke_signed(instruction, &[from_pubkey, to_pubkey, program_id], signer_seeds)?;
+ Ok(())
+}
+```
+
+This implementation is functionally equivalent to the previous example. The
+`signer_seeds` are passed into the `invoke_signed` function.
+
+
+
+
+Here is a reference program on
+[Solana Playground](https://beta.solpg.io/github.com/ZYJLiu/doc-examples/tree/main/cpi-pda)
+which includes both examples.
diff --git a/docs/content/docs/basics/idl.mdx b/docs/content/docs/basics/idl.mdx
new file mode 100644
index 0000000000..f90d346f10
--- /dev/null
+++ b/docs/content/docs/basics/idl.mdx
@@ -0,0 +1,492 @@
+---
+title: Program IDL File
+description:
+ Learn about the Interface Description Language (IDL) file in Anchor, its
+ purpose, benefits, and how it simplifies program-client interactions
+---
+
+An Interface Description Language (IDL) file for an Anchor program provides a
+standardized JSON file describing the program's instructions and accounts. This
+file simplifies the process of integrating your on-chain program with client
+applications.
+
+Key Benefits of the IDL:
+
+- Standardization: Provides a consistent format for describing the program's
+ instructions and accounts
+- Client Generation: Used to generate client code to interact with the program
+
+
+The `anchor build` command generates an IDL file located at
+`/target/idl/.json`.
+
+
+The code snippets in the sections below highlight how the program, IDL, and
+client relate to each other.
+
+## Program Instructions
+
+The `instructions` array in the IDL corresponds directly to the instructions
+defined in your program. It specifies the required accounts and parameters for
+each instruction.
+
+
+
+
+The program below includes an `initialize` instruction, specifying the accounts
+and parameters it requires.
+
+```rust title="lib.rs"
+use anchor_lang::prelude::*;
+
+declare_id!("BYFW1vhC1ohxwRbYoLbAWs86STa25i9sD5uEusVjTYNd");
+
+#[program]
+mod hello_anchor {
+ use super::*;
+ // [!code word:initialize]
+ // [!code word:Initialize]
+ // [!code highlight:5]
+ pub fn initialize(ctx: Context, data: u64) -> Result<()> {
+ ctx.accounts.new_account.data = data;
+ msg!("Changed data to: {}!", data);
+ Ok(())
+ }
+}
+
+ // [!code highlight:8]
+#[derive(Accounts)]
+pub struct Initialize<'info> {
+ #[account(init, payer = signer, space = 8 + 8)]
+ pub new_account: Account<'info, NewAccount>,
+ #[account(mut)]
+ pub signer: Signer<'info>,
+ pub system_program: Program<'info, System>,
+}
+
+#[account]
+pub struct NewAccount {
+ data: u64,
+}
+```
+
+
+
+
+The generated IDL file includes the instruction in a standardized JSON format,
+including its name, discriminator, accounts, and arguments.
+
+```json title="JSON"
+{
+ "address": "BYFW1vhC1ohxwRbYoLbAWs86STa25i9sD5uEusVjTYNd",
+ "metadata": {
+ "name": "hello_anchor",
+ "version": "0.1.0",
+ "spec": "0.1.0",
+ "description": "Created with Anchor"
+ },
+ "instructions": [
+ {
+ // [!code word:initialize]
+ // [!code highlight]
+ "name": "initialize",
+ // [!code word:discriminator:1]
+ // [!code highlight]
+ "discriminator": [175, 175, 109, 31, 13, 152, 155, 237],
+ // [!code word:accounts:1]
+ "accounts": [
+ // [!code highlight:14]
+ {
+ "name": "new_account",
+ "writable": true,
+ "signer": true
+ },
+ {
+ "name": "signer",
+ "writable": true,
+ "signer": true
+ },
+ {
+ "name": "system_program",
+ "address": "11111111111111111111111111111111"
+ }
+ ],
+ // [!code word:args:1]
+ "args": [
+ // [!code highlight:4]
+ {
+ "name": "data",
+ "type": "u64"
+ }
+ ]
+ }
+ ],
+ "accounts": [
+ {
+ "name": "NewAccount",
+ "discriminator": [176, 95, 4, 118, 91, 177, 125, 232]
+ }
+ ],
+ "types": [
+ {
+ "name": "NewAccount",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "data",
+ "type": "u64"
+ }
+ ]
+ }
+ }
+ ]
+}
+```
+
+
+
+
+The IDL file is then used to generate a client for interacting with the program,
+simplifying the process of invoking the program instruction.
+
+```ts title="test.ts"
+import * as anchor from "@coral-xyz/anchor";
+import { Program, BN } from "@coral-xyz/anchor";
+import { HelloAnchor } from "../target/types/hello_anchor";
+import { Keypair } from "@solana/web3.js";
+import assert from "assert";
+
+describe("hello_anchor", () => {
+ const provider = anchor.AnchorProvider.env();
+ anchor.setProvider(provider);
+ const wallet = provider.wallet as anchor.Wallet;
+ const program = anchor.workspace.HelloAnchor as Program;
+
+ it("initialize", async () => {
+ // Generate keypair for the new account
+ const newAccountKp = new Keypair();
+
+ // Send transaction
+ const data = new BN(42);
+ // [!code word:initialize]
+ // [!code highlight:8]
+ const transactionSignature = await program.methods
+ .initialize(data)
+ .accounts({
+ newAccount: newAccountKp.publicKey,
+ signer: wallet.publicKey,
+ })
+ .signers([newAccountKp])
+ .rpc();
+
+ // Fetch the created account
+ const newAccount = await program.account.newAccount.fetch(
+ newAccountKp.publicKey,
+ );
+
+ console.log("Transaction signature: ", transactionSignature);
+ console.log("On-chain data is:", newAccount.data.toString());
+ assert(data.eq(newAccount.data));
+ });
+});
+```
+
+
+
+
+## Program Accounts
+
+The `accounts` array in the IDL corresponds to the structs in a program
+annotated with the `#[account]` attribute. These structs define the data stored
+on accounts created by the program.
+
+
+
+
+The program below defines a `NewAccount` struct with a single `data` field of
+type `u64`.
+
+```rust title="lib.rs"
+use anchor_lang::prelude::*;
+
+declare_id!("BYFW1vhC1ohxwRbYoLbAWs86STa25i9sD5uEusVjTYNd");
+
+#[program]
+mod hello_anchor {
+ use super::*;
+ pub fn initialize(ctx: Context, data: u64) -> Result<()> {
+ ctx.accounts.new_account.data = data;
+ msg!("Changed data to: {}!", data);
+ Ok(())
+ }
+}
+
+#[derive(Accounts)]
+pub struct Initialize<'info> {
+ #[account(init, payer = signer, space = 8 + 8)]
+ pub new_account: Account<'info, NewAccount>,
+ #[account(mut)]
+ pub signer: Signer<'info>,
+ pub system_program: Program<'info, System>,
+}
+
+// [!code word:NewAccount]
+// [!code highlight:4]
+#[account]
+pub struct NewAccount {
+ data: u64,
+}
+```
+
+
+
+
+The generated IDL file includes the account in a standardized JSON format,
+including its name, discriminator, and fields.
+
+```json title="JSON"
+{
+ "address": "BYFW1vhC1ohxwRbYoLbAWs86STa25i9sD5uEusVjTYNd",
+ "metadata": {
+ "name": "hello_anchor",
+ "version": "0.1.0",
+ "spec": "0.1.0",
+ "description": "Created with Anchor"
+ },
+ "instructions": [
+ {
+ "name": "initialize",
+ "discriminator": [175, 175, 109, 31, 13, 152, 155, 237],
+ "accounts": [
+ {
+ "name": "new_account",
+ "writable": true,
+ "signer": true
+ },
+ {
+ "name": "signer",
+ "writable": true,
+ "signer": true
+ },
+ {
+ "name": "system_program",
+ "address": "11111111111111111111111111111111"
+ }
+ ],
+ "args": [
+ {
+ "name": "data",
+ "type": "u64"
+ }
+ ]
+ }
+ ],
+ "accounts": [
+ {
+ // [!code word:discriminator]
+ // [!code word:NewAccount]
+ // [!code highlight:2]
+ "name": "NewAccount",
+ "discriminator": [176, 95, 4, 118, 91, 177, 125, 232]
+ }
+ ],
+ "types": [
+ // [!code highlight:12]
+ {
+ "name": "NewAccount",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "data",
+ "type": "u64"
+ }
+ ]
+ }
+ }
+ ]
+}
+```
+
+
+
+
+The IDL file is then used to generate a client for interacting with the program,
+simplifying the process of fetching and deserializing account data.
+
+```ts title="test.ts"
+import * as anchor from "@coral-xyz/anchor";
+import { Program, BN } from "@coral-xyz/anchor";
+import { HelloAnchor } from "../target/types/hello_anchor";
+import { Keypair } from "@solana/web3.js";
+import assert from "assert";
+
+describe("hello_anchor", () => {
+ const provider = anchor.AnchorProvider.env();
+ anchor.setProvider(provider);
+ const wallet = provider.wallet as anchor.Wallet;
+ const program = anchor.workspace.HelloAnchor as Program;
+
+ it("initialize", async () => {
+ // Generate keypair for the new account
+ const newAccountKp = new Keypair();
+
+ // Send transaction
+ const data = new BN(42);
+ const transactionSignature = await program.methods
+ .initialize(data)
+ .accounts({
+ newAccount: newAccountKp.publicKey,
+ signer: wallet.publicKey,
+ })
+ .signers([newAccountKp])
+ .rpc();
+
+ // Fetch the created account
+ // [!code word:.newAccount.:1]
+ // [!code highlight:3]
+ const newAccount = await program.account.newAccount.fetch(
+ newAccountKp.publicKey,
+ );
+
+ console.log("Transaction signature: ", transactionSignature);
+ console.log("On-chain data is:", newAccount.data.toString());
+ assert(data.eq(newAccount.data));
+ });
+});
+```
+
+
+
+
+## Discriminators
+
+Anchor assigns a unique 8 byte discriminator to each instruction and account
+type in a program. These discriminators serve as identifiers to distinguish
+between different instructions or account types.
+
+The discriminator is generated using the first 8 bytes of the Sha256 hash of a
+prefix combined with the instruction or account name. As of Anchor v0.30, these
+discriminators are included in the IDL file.
+
+
+ Note that when working with Anchor, you typically won't need to interact
+ directly with these discriminators. This section is primarily to provide
+ context on how the discriminator is generated and used.
+
+
+
+
+
+The instruction discriminator is used by the program to determine which specific
+instruction to execute when called.
+
+When an Anchor program instruction is invoked, the discriminator is included as
+the first 8 bytes of the instruction data. This is done automatically by the
+Anchor client.
+
+```json title="IDL"
+ "instructions": [
+ {
+ "name": "initialize",
+ // [!code word:discriminator]
+ // [!code highlight]
+ "discriminator": [175, 175, 109, 31, 13, 152, 155, 237],
+ ...
+ }
+ ]
+```
+
+The discriminator for an instruction is the first 8 bytes of the Sha256 hash of
+the prefix `global` plus the instruction name.
+
+For example:
+
+```
+sha256("global:initialize")
+```
+
+Hexadecimal output:
+
+```
+af af 6d 1f 0d 98 9b ed d4 6a 95 07 32 81 ad c2 1b b5 e0 e1 d7 73 b2 fb bd 7a b5 04 cd d4 aa 30
+```
+
+The first 8 bytes are used as the discriminator for the instruction.
+
+```
+af = 175
+af = 175
+6d = 109
+1f = 31
+0d = 13
+98 = 152
+9b = 155
+ed = 237
+```
+
+You can find the implementation of the discriminator generation in the Anchor
+codebase
+[here](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/syn/src/codegen/program/common.rs#L5-L19),
+which is used
+[here](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/syn/src/codegen/program/instruction.rs#L27).
+
+
+
+
+The account discriminator is used to identify the specific account type when
+deserializing on-chain data and is set when the account is created.
+
+```json title="IDL"
+ "accounts": [
+ {
+ "name": "NewAccount",
+ // [!code word:discriminator]
+ // [!code highlight]
+ "discriminator": [176, 95, 4, 118, 91, 177, 125, 232]
+ }
+ ]
+```
+
+The discriminator for an account is the first 8 bytes of the Sha256 hash of the
+prefix `account` plus the account name.
+
+For example:
+
+```
+sha256("account:NewAccount")
+```
+
+Hexadecimal output:
+
+```
+b0 5f 04 76 5b b1 7d e8 a1 93 57 2a d3 5e b1 ae e5 f0 69 e2 09 7e 5c d2 64 56 55 2a cb 4a e9 57
+```
+
+The first 8 bytes are used as the discriminator for the account.
+
+```
+b0 = 176
+5f = 95
+04 = 4
+76 = 118
+5b = 91
+b1 = 177
+7d = 125
+e8 = 232
+```
+
+You can find the implementation of the discriminator generation in the Anchor
+codebase
+[here](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/attribute/account/src/lib.rs#L101-L117).
+
+
+ Note that different programs using identical account names will generate the
+ same discriminator. When deserializing account data, Anchor programs will also
+ check an account is owned by the expected program for a specified account
+ type.
+
+
+
+
diff --git a/docs/content/docs/basics/index.mdx b/docs/content/docs/basics/index.mdx
new file mode 100644
index 0000000000..bd0f53c3d0
--- /dev/null
+++ b/docs/content/docs/basics/index.mdx
@@ -0,0 +1,9 @@
+---
+title: Anchor Framework Basics
+description:
+ Learn how to use the Anchor framework to build secure Solana programs.
+index: true
+---
+
+Before diving into Anchor, it's recommended to have a basic understanding of
+[Solana's core concepts](https://solana.com/docs/core).
diff --git a/docs/content/docs/basics/meta.json b/docs/content/docs/basics/meta.json
new file mode 100644
index 0000000000..018ef1ba6c
--- /dev/null
+++ b/docs/content/docs/basics/meta.json
@@ -0,0 +1,4 @@
+{
+ "title": "The Basics",
+ "pages": ["program-structure", "idl", "client", "pda", "cpi"]
+}
diff --git a/docs/content/docs/basics/pda.mdx b/docs/content/docs/basics/pda.mdx
new file mode 100644
index 0000000000..89271df26a
--- /dev/null
+++ b/docs/content/docs/basics/pda.mdx
@@ -0,0 +1,346 @@
+---
+title: Program Derived Address
+description:
+ Learn how to use Program Derived Addresses (PDAs) in Anchor programs to create
+ deterministic account addresses.
+---
+
+Program Derived Addresses (PDA) refer to a feature of Solana development that
+allows you to create a unique address derived deterministically from pre-defined
+inputs (seeds) and a program ID.
+
+This section will cover basic examples of how to use PDAs in an Anchor program.
+
+## Anchor PDA Constraints
+
+When using PDAs in an Anchor program, you generally use Anchor's account
+constraints to define the seeds to derive the PDA. These constraints serve as
+security checks to ensure that the correct address is derived.
+
+The constraints used to define the PDA seeds include:
+
+- `seeds`: An array of optional seeds used to derive the PDA. Seeds can be
+ static values or dynamic references to account data.
+- `bump`: The bump seed used to derive the PDA. Used to ensure the address falls
+ off the Ed25519 curve and is a valid PDA.
+- `seeds::program` - (Optional) The program ID used to derive the PDA address.
+ This constraint is only used to derive a PDA where the program ID is not the
+ current program.
+
+
+ The `seeds` and `bump` constraints are required to be used together.
+
+
+### Usage Examples
+
+Below are examples demonstrating how to use PDA constraints in an Anchor
+program.
+
+
+
+
+The `seeds` constraint specifies the optional values used to derive the PDA.
+
+#### No Optional Seeds
+
+- Use an empty array `[]` to define a PDA without optional seeds.
+
+```rust
+#[derive(Accounts)]
+pub struct InstructionAccounts<'info> {
+ #[account(
+ // [!code highlight]
+ seeds = [],
+ bump,
+ )]
+ pub pda_account: SystemAccount<'info>,
+}
+```
+
+#### Single Static Seed
+
+- Specify optional seeds in the `seeds` constraint.
+
+```rust
+#[derive(Accounts)]
+pub struct InstructionAccounts<'info> {
+ #[account(
+ // [!code word:b"hello_world"]
+ // [!code highlight]
+ seeds = [b"hello_world"],
+ bump,
+ )]
+ pub pda_account: SystemAccount<'info>,
+}
+```
+
+#### Multiple Seeds and Account References
+
+- Multiple seeds can be specified in the `seeds` constraint. The `seeds`
+ constraint can also reference other account addresses or account data.
+
+```rust
+#[derive(Accounts)]
+pub struct InstructionAccounts<'info> {
+ pub signer: Signer<'info>,
+ #[account(
+ // [!code highlight]
+ seeds = [b"hello_world", signer.key().as_ref()],
+ bump,
+ )]
+ pub pda_account: SystemAccount<'info>,
+}
+```
+
+The example above uses both a static seed (`b"hello_world"`) and a dynamic seed
+(the signer's public key).
+
+
+
+
+The `bump` constraint specifies the bump seed used to derive the PDA.
+
+#### Automatic Bump Calculation
+
+When using the `bump` constraint without a value, the bump is automatically
+calculated each time the instruction is invoked.
+
+```rust
+#[derive(Accounts)]
+pub struct InstructionAccounts<'info> {
+ #[account(
+ seeds = [b"hello_world"],
+ // [!code highlight]
+ bump,
+ )]
+ pub pda_account: SystemAccount<'info>,
+}
+```
+
+#### Specify Bump Value
+
+You can explicitly provide the bump value, which is useful for optimizing
+compute unit usage. This assumes that the PDA account has been created and the
+bump seed is stored as a field on an existing account.
+
+```rust
+#[derive(Accounts)]
+pub struct InstructionAccounts<'info> {
+ #[account(
+ seeds = [b"hello_world"],
+ // [!code highlight]
+ bump = pda_account.bump_seed,
+ )]
+ pub pda_account: Account<'info, CustomAccount>,
+}
+
+#[account]
+pub struct CustomAccount {
+ pub bump_seed: u8,
+}
+```
+
+By storing the bump value in the account's data, the program doesn't need to
+recalculate it, saving compute units. The saved bump value can be stored on the
+account itself or another account.
+
+
+
+
+The `seeds::program` constraint specifies the program ID used to derive the PDA.
+This constraint is only used when deriving a PDA from a different program.
+
+Use this constraint when your instruction needs to interact with PDA accounts
+created by another program.
+
+```rust
+#[derive(Accounts)]
+pub struct InstructionAccounts<'info> {
+ #[account(
+ seeds = [b"hello_world"],
+ bump,
+ // [!code word:other_program]
+ // [!code highlight]
+ seeds::program = other_program.key(),
+ )]
+ pub pda_account: SystemAccount<'info>,
+ pub other_program: Program<'info, OtherProgram>,
+}
+```
+
+
+
+
+The `init` constraint is commonly used with `seeds` and `bump` to create a new
+account with an address that is a PDA. Under the hood, the `init` constraint
+invokes the System Program to create the account.
+
+```rust
+#[derive(Accounts)]
+pub struct InstructionAccounts<'info> {
+ #[account(mut)]
+ pub signer: Signer<'info>,
+ #[account(
+ // [!code word:init]
+ // [!code highlight:3]
+ init,
+ payer = signer,
+ space = 8 + 1,
+ seeds = [b"hello_world", signer.key().as_ref()],
+ bump,
+ )]
+ pub pda_account: Account<'info, CustomAccount>,
+ pub system_program: Program<'info, System>,
+}
+
+#[account]
+pub struct CustomAccount {
+ pub bump_seed: u8,
+}
+```
+
+
+ The `init` constraint must be used with `payer` and `space`. The `payer`
+ specifies the account that will pay for the account creation. The `space`
+ specifies the bytes to allocate for the account (including the 8-byte
+ discriminator).
+
+
+
+
+
+## PDA seeds in the IDL
+
+Program Derived Address (PDA) seeds defined in the `seeds` constraint are
+included in the program's IDL file. This allows the Anchor client to
+automatically resolve account addresses using these seeds when constructing
+instructions.
+
+This example below shows the relationship between the program, IDL, and client.
+
+
+
+
+The program below defines a `pda_account` using a static seed (`b"hello_world"`)
+and the signer's public key as a dynamic seed.
+
+```rust
+use anchor_lang::prelude::*;
+
+declare_id!("BZLiJ62bzRryYp9mRobz47uA66WDgtfTXhhgM25tJyx5");
+
+#[program]
+mod hello_anchor {
+ use super::*;
+ pub fn test_instruction(ctx: Context) -> Result<()> {
+ msg!("PDA: {}", ctx.accounts.pda_account.key());
+ Ok(())
+ }
+}
+
+#[derive(Accounts)]
+pub struct InstructionAccounts<'info> {
+ // [!code word:signer]
+ pub signer: Signer<'info>,
+ #[account(
+ // [!code highlight]
+ seeds = [b"hello_world", signer.key().as_ref()],
+ bump,
+ )]
+ pub pda_account: SystemAccount<'info>,
+}
+```
+
+
+
+
+The program's IDL file includes the PDA seeds defined in the `seeds` constraint.
+
+- The static seed `b"hello_world"` is converted to byte values.
+- The dynamic seed is included as reference to the signer account.
+
+```json
+{
+ "address": "BZLiJ62bzRryYp9mRobz47uA66WDgtfTXhhgM25tJyx5",
+ "metadata": {
+ "name": "hello_anchor",
+ "version": "0.1.0",
+ "spec": "0.1.0",
+ "description": "Created with Anchor"
+ },
+ "instructions": [
+ {
+ "name": "test_instruction",
+ "discriminator": [33, 223, 61, 208, 32, 193, 201, 79],
+ "accounts": [
+ {
+ "name": "signer",
+ "signer": true
+ },
+ {
+ "name": "pda_account",
+ "pda": {
+ // [!code word:seeds]
+ "seeds": [
+ {
+ // [!code highlight:2]
+ "kind": "const",
+ "value": [104, 101, 108, 108, 111, 95, 119, 111, 114, 108, 100]
+ },
+ {
+ // [!code highlight:2]
+ "kind": "account",
+ "path": "signer"
+ }
+ ]
+ }
+ }
+ ],
+ "args": []
+ }
+ ]
+}
+```
+
+
+
+
+The Anchor client can automatically resolve the PDA address using the IDL file.
+
+In the example below, Anchor automatically resolves the PDA address using the
+provider wallet as the signer, and its public key as the dynamic seed for PDA
+derivation. This removes the need to explicitly derive the PDA when building the
+instruction.
+
+```ts {13}
+import * as anchor from "@coral-xyz/anchor";
+import { Program } from "@coral-xyz/anchor";
+import { HelloAnchor } from "../target/types/hello_anchor";
+
+describe("hello_anchor", () => {
+ // Configure the client to use the local cluster.
+ anchor.setProvider(anchor.AnchorProvider.env());
+
+ const program = anchor.workspace.HelloAnchor as Program;
+
+ it("Is initialized!", async () => {
+ // Account address is automatically resolved using the IDL
+ const tx = await program.methods.testInstruction().rpc();
+ console.log("Your transaction signature", tx);
+ });
+});
+```
+
+When the instruction is invoked, the PDA is printed to program logs as defined
+in the program instruction.
+
+```{3}
+Program BZLiJ62bzRryYp9mRobz47uA66WDgtfTXhhgM25tJyx5 invoke [1]
+Program log: Instruction: TestInstruction
+Program log: PDA: 3Hikt5mpKaSS4UNA5Du1TZJ8tp4o8VC8YWW6X9vtfVnJ
+Program BZLiJ62bzRryYp9mRobz47uA66WDgtfTXhhgM25tJyx5 consumed 18505 of 200000 compute units
+Program BZLiJ62bzRryYp9mRobz47uA66WDgtfTXhhgM25tJyx5 success
+```
+
+
+
diff --git a/docs/content/docs/basics/program-structure.mdx b/docs/content/docs/basics/program-structure.mdx
new file mode 100644
index 0000000000..e0a03fb698
--- /dev/null
+++ b/docs/content/docs/basics/program-structure.mdx
@@ -0,0 +1,438 @@
+---
+title: Program Structure
+description:
+ Learn about the structure of Anchor programs, including key macros and their
+ roles in simplifying Solana program development
+---
+
+The Anchor framework uses
+[Rust macros](https://rust-book.cs.brown.edu/ch20-06-macros.html) to reduce
+boilerplate code and simplify the implementation of common security checks
+required for writing Solana programs.
+
+The main macros found in an Anchor program include:
+
+- [`declare_id`](#declare_id-macro): Specifies the program's on-chain address
+- [`#[program]`](#program-attribute): Specifies the module containing the
+ program’s instruction logic
+- [`#[derive(Accounts)]`](#deriveaccounts-macro): Applied to structs to indicate
+ a list of accounts required by an instruction
+- [`#[account]`](#account-attribute): Applied to structs to create custom
+ account types for the program
+
+## Example Program
+
+Let's examine a simple program that demonstrates the usage of the macros
+mentioned above to understand the basic structure of an Anchor program.
+
+The program below includes a single instruction called `initialize` that creates
+a new account (`NewAccount`) and initializes it with a `u64` value.
+
+```rust title="lib.rs"
+use anchor_lang::prelude::*;
+
+declare_id!("11111111111111111111111111111111");
+
+#[program]
+mod hello_anchor {
+ use super::*;
+ pub fn initialize(ctx: Context, data: u64) -> Result<()> {
+ ctx.accounts.new_account.data = data;
+ msg!("Changed data to: {}!", data);
+ Ok(())
+ }
+}
+
+#[derive(Accounts)]
+pub struct Initialize<'info> {
+ #[account(init, payer = signer, space = 8 + 8)]
+ pub new_account: Account<'info, NewAccount>,
+ #[account(mut)]
+ pub signer: Signer<'info>,
+ pub system_program: Program<'info, System>,
+}
+
+#[account]
+pub struct NewAccount {
+ data: u64,
+}
+```
+
+## declare_id! macro
+
+The
+[`declare_id`](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/attribute/account/src/lib.rs#L439)
+macro specifies the on-chain address of the program, known as the program ID.
+You can find the implementation of the code generated by the `declare_id!` macro
+[here](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/attribute/account/src/id.rs#L40-L73).
+
+```rust title="lib.rs"
+use anchor_lang::prelude::*;
+
+// [!code highlight]
+declare_id!("11111111111111111111111111111111");
+```
+
+By default, the program ID is the public key of the keypair generated at
+`/target/deploy/your_program_name.json`.
+
+To update the value of the program ID in the `declare_id` macro with the public
+key of the keypair in the `/target/deploy/your_program_name.json` file, run the
+following command:
+
+```shell title="Terminal"
+anchor keys sync
+```
+
+The `anchor keys sync` command is useful to run when cloning a repository where
+the value of the program ID in a cloned repo's `declare_id` macro won't match
+the one generated when you run `anchor build` locally.
+
+## #[program] attribute
+
+The
+[`#[program]`](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/attribute/program/src/lib.rs#L12)
+attribute annotates the module containing all the instruction handlers for your
+program. Each public function within this module corresponds to an instruction
+that can be invoked.
+
+You can find the implementation of the code generated by the `#[program]`
+attribute
+[here](https://github.com/coral-xyz/anchor/tree/v0.30.1/lang/syn/src/codegen/program).
+
+```rust title="lib.rs"
+use anchor_lang::prelude::*;
+
+declare_id!("11111111111111111111111111111111");
+
+// [!code highlight]
+#[program]
+mod hello_anchor {
+ use super::*;
+ // [!code highlight:5]
+ pub fn initialize(ctx: Context, data: u64) -> Result<()> {
+ ctx.accounts.new_account.data = data;
+ msg!("Changed data to: {}!", data);
+ Ok(())
+ }
+}
+
+#[derive(Accounts)]
+pub struct Initialize<'info> {
+ #[account(init, payer = signer, space = 8 + 8)]
+ pub new_account: Account<'info, NewAccount>,
+ #[account(mut)]
+ pub signer: Signer<'info>,
+ pub system_program: Program<'info, System>,
+}
+
+#[account]
+pub struct NewAccount {
+ data: u64,
+}
+```
+
+### Instruction Context
+
+Instruction handlers are functions that define the logic executed when an
+instruction is invoked. The first parameter of each handler is a `Context`
+type, where `T` is a struct implementing the
+[`Accounts`](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/src/lib.rs#L105)
+trait and specifies the accounts the instruction requires.
+
+The
+[`Context`](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/src/context.rs#L24)
+type provides the instruction with access to the following non-argument inputs:
+
+```rust
+pub struct Context<'a, 'b, 'c, 'info, T> {
+ /// Currently executing program id.
+ pub program_id: &'a Pubkey,
+ /// Deserialized accounts.
+ pub accounts: &'b mut T,
+ /// Remaining accounts given but not deserialized or validated.
+ /// Be very careful when using this directly.
+ pub remaining_accounts: &'c [AccountInfo<'info>],
+ /// Bump seeds found during constraint validation. This is provided as a
+ /// convenience so that handlers don't have to recalculate bump seeds or
+ /// pass them in as arguments.
+ pub bumps: BTreeMap,
+}
+```
+
+The `Context` fields can be accessed in an instruction using dot notation:
+
+- `ctx.accounts`: The accounts required for the instruction
+- `ctx.program_id`: The program's public key (address)
+- `ctx.remaining_accounts`: Additional accounts not specified in the `Accounts`
+ struct.
+- `ctx.bumps`: Bump seeds for any Program Derived Address (PDA) accounts
+ specified in the `Accounts` struct
+
+Additional parameters are optional and can be included to specify arguments that
+must be provided when the instruction is invoked.
+
+```rust title="lib.rs"
+// [!code word:Context]
+// [!code word:data:1]
+pub fn initialize(ctx: Context, data: u64) -> Result<()> {
+ ctx.accounts.new_account.data = data;
+ msg!("Changed data to: {}!", data);
+ Ok(())
+}
+```
+
+In this example, the `Initialize` struct implements the `Accounts` trait where
+each field in the struct represents an account required by the `initialize`
+instruction.
+
+```rust title="lib.rs"
+// [!code word:Initialize]
+// [!code word:Accounts]
+#[program]
+mod hello_anchor {
+ use super::*;
+ pub fn initialize(ctx: Context, data: u64) -> Result<()> {
+ ctx.accounts.new_account.data = data;
+ msg!("Changed data to: {}!", data);
+ Ok(())
+ }
+}
+
+#[derive(Accounts)]
+pub struct Initialize<'info> {
+ #[account(init, payer = signer, space = 8 + 8)]
+ pub new_account: Account<'info, NewAccount>,
+ #[account(mut)]
+ pub signer: Signer<'info>,
+ pub system_program: Program<'info, System>,
+}
+```
+
+## #[derive(Accounts)] macro
+
+The
+[`#[derive(Accounts)]`](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/derive/accounts/src/lib.rs#L630)
+macro is applied to a struct to specify the accounts that must be provided when
+an instruction is invoked. This macro implements the
+[`Accounts`](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/src/lib.rs#L105)
+trait, which simplifies account validation and serialization and deserialization
+of account data.
+
+You can find the implementation of the code generated by the
+`#[derive(Accounts)]` macro
+[here](https://github.com/coral-xyz/anchor/tree/v0.30.1/lang/syn/src/codegen/accounts).
+
+```rust
+// [!code word:Accounts]
+#[derive(Accounts)]
+// [!code highlight]
+pub struct Initialize<'info> {
+ #[account(init, payer = signer, space = 8 + 8)]
+ pub new_account: Account<'info, NewAccount>,
+ #[account(mut)]
+ pub signer: Signer<'info>,
+ pub system_program: Program<'info, System>,
+}
+```
+
+Each field in the struct represents an account required by an instruction. The
+naming of each field is arbitrary, but it is recommended to use a descriptive
+name that indicates the purpose of the account.
+
+```rust
+#[derive(Accounts)]
+pub struct Initialize<'info> {
+ #[account(init, payer = signer, space = 8 + 8)]
+ // [!code word:new_account]
+ pub new_account: Account<'info, NewAccount>,
+ #[account(mut)]
+ // [!code word:signer]
+ pub signer: Signer<'info>,
+ // [!code word:system_program]
+ pub system_program: Program<'info, System>,
+}
+```
+
+### Account Validation
+
+To prevent security vulnerabilities, it's important to verify that accounts
+provided to an instruction are the expected accounts. Accounts are validated in
+Anchor programs in two ways that are generally used together:
+
+- [Account Constraints](/docs/references/account-constraints): Constraints
+ define additional conditions that an account must satisfy to be considered
+ valid for the instruction. Constraints are applied using the `#[account(..)]`
+ attribute, which is placed above a field in a struct that implements the
+ `Accounts` trait.
+
+ You can find a full list of the constraints
+ [here](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/syn/src/parser/accounts/constraints.rs)
+ and implementation
+ [here](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/syn/src/codegen/accounts/constraints.rs).
+
+ ```rust
+ #[derive(Accounts)]
+ pub struct Initialize<'info> {
+ // [!code highlight]
+ #[account(init, payer = signer, space = 8 + 8)]
+ pub new_account: Account<'info, NewAccount>,
+ // [!code highlight]
+ #[account(mut)]
+ pub signer: Signer<'info>,
+ pub system_program: Program<'info, System>,
+ }
+ ```
+
+- [Account Types](/docs/references/account-types): Anchor provides various
+ account types to help ensure that the account provided by the client matches
+ what the program expects.
+
+ You can find the implementation of the account types
+ [here](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/src/accounts).
+
+ ```rust
+ #[derive(Accounts)]
+ pub struct Initialize<'info> {
+ #[account(init, payer = signer, space = 8 + 8)]
+ // [!code word: Account]
+ pub new_account: Account<'info, NewAccount>,
+ #[account(mut)]
+ // [!code word:Signer]
+ pub signer: Signer<'info>,
+ // [!code word:Program]
+ pub system_program: Program<'info, System>,
+ }
+ ```
+
+When an instruction in an Anchor program is invoked, the program first validates
+the accounts provided before executing the instruction's logic. After
+validation, these accounts can be accessed within the instruction using the
+`ctx.accounts` syntax.
+
+```rust title="lib.rs"
+// [!code word:new_account]
+// [!code word:Initialize]
+use anchor_lang::prelude::*;
+
+declare_id!("11111111111111111111111111111111");
+
+#[program]
+mod hello_anchor {
+ use super::*;
+ pub fn initialize(ctx: Context, data: u64) -> Result<()> {
+ ctx.accounts.new_account.data = data;
+ msg!("Changed data to: {}!", data);
+ Ok(())
+ }
+}
+
+#[derive(Accounts)]
+pub struct Initialize<'info> {
+ #[account(init, payer = signer, space = 8 + 8)]
+ pub new_account: Account<'info, NewAccount>,
+ #[account(mut)]
+ pub signer: Signer<'info>,
+ pub system_program: Program<'info, System>,
+}
+
+#[account]
+pub struct NewAccount {
+ data: u64,
+}
+```
+
+## #[account] attribute
+
+The
+[`#[account]`](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/attribute/account/src/lib.rs#L66)
+attribute is applied to structs that define the structure of the data stored in
+custom accounts created by your program.
+
+```rust
+// [!code highlight]
+#[account]
+pub struct NewAccount {
+ data: u64,
+}
+```
+
+This macro implements various traits
+[detailed here](https://docs.rs/anchor-lang/latest/anchor_lang/attr.account.html).
+The key functionalities of the `#[account]` macro include:
+
+- [Assign Program Owner](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/attribute/account/src/lib.rs#L119-L132):
+ When creating an account, the program owner of the account is automatically
+ set to the program specified in `declare_id`.
+- [Set Discriminator](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/attribute/account/src/lib.rs#L101-L117):
+ A unique 8 byte discriminator, specific to the account type, is added as the
+ first 8 bytes of account data during its initialization. This helps in
+ differentiating account types and is used for account validation.
+- [Data Serialization and Deserialization](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/attribute/account/src/lib.rs#L202-L246):
+ Account data is automatically serialized and deserialized as the account type.
+
+```rust title="lib.rs"
+// [!code word:NewAccount]
+use anchor_lang::prelude::*;
+
+declare_id!("11111111111111111111111111111111");
+
+#[program]
+mod hello_anchor {
+ use super::*;
+ pub fn initialize(ctx: Context, data: u64) -> Result<()> {
+ // [!code word:data :1]
+ ctx.accounts.new_account.data = data;
+ msg!("Changed data to: {}!", data);
+ Ok(())
+ }
+}
+
+#[derive(Accounts)]
+pub struct Initialize<'info> {
+ #[account(init, payer = signer, space = 8 + 8)]
+ pub new_account: Account<'info, NewAccount>,
+ #[account(mut)]
+ pub signer: Signer<'info>,
+ pub system_program: Program<'info, System>,
+}
+
+// [!code word:data]
+// [!code highlight:4]
+#[account]
+pub struct NewAccount {
+ data: u64,
+}
+```
+
+### Account Discriminator
+
+An account discriminator in an Anchor program refers to an 8 byte identifier
+unique to each account type. You can find the implementation of the account
+discriminator
+[here](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/attribute/account/src/lib.rs#L101-L117).
+
+The discriminator is the first 8 bytes of the SHA256 hash of the string
+`account:`. This discriminator is stored as the first 8 bytes of
+account data when an account is created.
+
+When creating an account in an Anchor program, 8 bytes must be allocated for the
+discriminator.
+
+```rust
+// [!code word:8 ]
+#[account(init, payer = signer, space = 8 + 8)]
+pub new_account: Account<'info, NewAccount>,
+```
+
+The discriminator is used during the following two scenarios:
+
+- Initialization: When an account is created, the discriminator is set as the
+ first 8 bytes of the account's data.
+- Deserialization: When account data is deserialized, the first 8 bytes of
+ account data is checked against the discriminator of the expected account
+ type.
+
+If there's a mismatch, it indicates that the client has provided an unexpected
+account. This mechanism serves as an account validation check in Anchor
+programs.
diff --git a/docs/content/docs/clients/index.mdx b/docs/content/docs/clients/index.mdx
new file mode 100644
index 0000000000..e38c2cb0ab
--- /dev/null
+++ b/docs/content/docs/clients/index.mdx
@@ -0,0 +1,7 @@
+---
+title: Clients
+description:
+ Learn how to interact with Anchor programs using client libraries in
+ TypeScript and Rust.
+index: true
+---
diff --git a/docs/content/docs/clients/meta.json b/docs/content/docs/clients/meta.json
new file mode 100644
index 0000000000..be9a9e31b0
--- /dev/null
+++ b/docs/content/docs/clients/meta.json
@@ -0,0 +1,4 @@
+{
+ "title": "Client Libraries",
+ "pages": ["typescript", "rust"]
+}
diff --git a/docs/content/docs/clients/rust.mdx b/docs/content/docs/clients/rust.mdx
new file mode 100644
index 0000000000..d9b957126d
--- /dev/null
+++ b/docs/content/docs/clients/rust.mdx
@@ -0,0 +1,268 @@
+---
+title: Rust
+description:
+ Learn how to use Anchor's Rust client library to interact with Solana programs
+---
+
+The [`anchor-client`](https://docs.rs/anchor-client/latest/anchor_client/) crate
+is the Rust client library for interacting with Anchor programs. You can find
+the source code [here](https://github.com/coral-xyz/anchor/tree/v0.30.1/client).
+
+## 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
+
+```rust title="lib.rs"
+use anchor_lang::prelude::*;
+
+declare_id!("6khKp4BeJpCjBY1Eh39ybiqbfRnrn2UzWeUARjQLXYRC");
+
+#[program]
+pub mod example {
+ use super::*;
+
+ pub fn initialize(ctx: Context) -> Result<()> {
+ let counter = &ctx.accounts.counter;
+ msg!("Counter account created! Current count: {}", counter.count);
+ Ok(())
+ }
+
+ pub fn increment(ctx: Context) -> 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:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+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.
+
+```json title="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
+
+```rust title="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.pubkey()).await?;
+ println!(" Counter value: {}", counter_account.count);
+ Ok(())
+}
+```
+
+Below are the dependencies for the `Cargo.toml` file:
+
+```toml title="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"] }
+```
diff --git a/docs/content/docs/clients/typescript.mdx b/docs/content/docs/clients/typescript.mdx
new file mode 100644
index 0000000000..cb5557d84e
--- /dev/null
+++ b/docs/content/docs/clients/typescript.mdx
@@ -0,0 +1,690 @@
+---
+title: TypeScript
+description:
+ Learn how to use Anchor's TypeScript client library to interact with Solana
+ programs
+---
+
+Anchor provides a Typescript client library
+([@coral-xyz/anchor](https://github.com/coral-xyz/anchor/tree/v0.30.1/ts/packages/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`](https://github.com/coral-xyz/anchor/blob/v0.30.1/ts/packages/anchor/src/program/index.ts#L58)
+instance using the program's [IDL file](/docs/basics/idl).
+
+Creating an instance of the `Program` requires the program's IDL and an
+[`AnchorProvider`](https://github.com/coral-xyz/anchor/blob/v0.30.1/ts/packages/anchor/src/provider.ts#L55).
+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](https://github.com/anza-xyz/wallet-adapter), you'll need
+to set up the `AnchorProvider` and `Program`.
+
+```ts title="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();
+
+// [!code word:AnchorProvider]
+// [!code highlight:2]
+const provider = new AnchorProvider(connection, wallet, {});
+setProvider(provider);
+
+// [!code word:Program]
+// [!code highlight:3]
+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/.json` in an Anchor project.
+- `idlType.ts` is the IDL type (for use with TypeScript), found at
+ `/target/types/.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.
+
+```ts
+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");
+
+// [!code word:Program]
+// [!code highlight:3]
+export const program = new Program(idl as HelloAnchor, {
+ connection,
+});
+```
+
+
+
+
+When creating a new Anchor project, a default test file is generated that
+includes a `Program` instance. This setup differs from applications outside the
+Anchor workspace (like React or Node.js) where you'll need to manually create
+the `Program` instance.
+
+```ts
+import * as anchor from "@coral-xyz/anchor";
+import { Program } from "@coral-xyz/anchor";
+import { HelloAnchor } from "../target/types/hello_anchor";
+
+describe("hello_anchor", () => {
+ // Configure the client to use the local cluster.
+ anchor.setProvider(anchor.AnchorProvider.env());
+
+ // [!code highlight]
+ const program = anchor.workspace.HelloAnchor as Program;
+
+ it("Is initialized!", async () => {
+ // Add your test here.
+ const tx = await program.methods.initialize().rpc();
+ console.log("Your transaction signature", tx);
+ });
+});
+```
+
+
+
+
+## Invoke Instructions
+
+Once the `Program` is set up using a program's IDL file, you can use the Anchor
+[`MethodsBuilder`](https://github.com/coral-xyz/anchor/blob/v0.30.1/ts/packages/anchor/src/program/namespace/methods.ts#L155)
+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
+
+```ts
+// [!code word:methods]
+// [!code highlight]
+await program.methods
+ .instructionName(instructionData)
+ .accounts({})
+ .signers([])
+ .rpc();
+```
+
+
+
+
+Following `.methods`, specify the name of an instruction from the program IDL,
+passing in any required arguments as comma-separated values.
+
+```ts
+// [!code word:instructionName]
+await program.methods
+ // [!code highlight]
+ .instructionName(instructionData1, instructionData2)
+ .accounts({})
+ .signers([])
+ .rpc();
+```
+
+
+
+
+`.accounts` - Pass in the address of the accounts required by the instruction as
+specified in the IDL
+
+```ts
+// [!code word:accounts]
+await program.methods
+ .instructionName(instructionData)
+ // [!code highlight]
+ .accounts({})
+ .signers([])
+ .rpc();
+```
+
+Note that certain account addresses don't need to be explicitly provided, as
+they can automatically resolve using information included in the IDL. These
+typically include:
+
+- Common accounts (ex. the System Program)
+- Accounts where the address is a PDA (Program Derived Address)
+
+
+
+
+`.signers` - Optionally pass in an array of keypairs required as additional
+signers by the instruction. This is commonly used when creating new accounts
+where the account address is the public key of a newly generated keypair.
+
+```ts
+// [!code word:signers]
+await program.methods
+ .instructionName(instructionData)
+ .accounts({})
+ // [!code highlight]
+ .signers([])
+ .rpc();
+```
+
+
+ Note that `.signers` should only be used when also using `.rpc()`. When using
+ `.transaction()` or `.instruction()`, signers should be added to the
+ transaction before sending.
+
+
+
+
+
+Anchor provides multiple methods for building program instructions:
+
+
+
+
+The
+[`rpc()`](https://github.com/coral-xyz/anchor/blob/v0.30.1/ts/packages/anchor/src/program/namespace/methods.ts#L283)
+method
+[sends a signed transaction](https://github.com/coral-xyz/anchor/blob/v0.30.1/ts/packages/anchor/src/program/namespace/rpc.ts#L29)
+with the specified instruction and returns a `TransactionSignature`.
+
+When using `.rpc`, the `Wallet` from the `Provider` is automatically included as
+a signer.
+
+```ts
+// 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])
+ // [!code word:rpc]
+ // [!code highlight]
+ .rpc();
+```
+
+
+
+
+The
+[`transaction()`](https://github.com/coral-xyz/anchor/blob/v0.30.1/ts/packages/anchor/src/program/namespace/methods.ts#L382)
+method
+[builds a `Transaction`](https://github.com/coral-xyz/anchor/blob/v0.30.1/ts/packages/anchor/src/program/namespace/transaction.ts#L18-L26)
+with the specified instruction without sending the transaction.
+
+```ts
+// Generate keypair for the new account
+const newAccountKp = new Keypair();
+
+const data = new BN(42);
+const transaction = await program.methods
+ .initialize(data)
+ .accounts({
+ newAccount: newAccountKp.publicKey,
+ signer: wallet.publicKey,
+ systemProgram: SystemProgram.programId,
+ })
+ // [!code word:transaction:1]
+ // [!code highlight]
+ .transaction();
+
+const transactionSignature = await connection.sendTransaction(transaction, [
+ wallet.payer,
+ newAccountKp,
+]);
+```
+
+
+
+
+The
+[`instruction()`](https://github.com/coral-xyz/anchor/blob/v0.30.1/ts/packages/anchor/src/program/namespace/methods.ts#L348)
+method
+[builds a `TransactionInstruction`](https://github.com/coral-xyz/anchor/blob/v0.30.1/ts/packages/anchor/src/program/namespace/instruction.ts#L57-L61)
+using the specified instruction. This is useful if you want to manually add the
+instruction to a transaction and combine it with other instructions.
+
+```ts
+// Generate keypair for the new account
+const newAccountKp = new Keypair();
+
+const data = new BN(42);
+const instruction = await program.methods
+ .initialize(data)
+ .accounts({
+ newAccount: newAccountKp.publicKey,
+ signer: wallet.publicKey,
+ systemProgram: SystemProgram.programId,
+ })
+ // [!code word:instruction:1]
+ // [!code highlight]
+ .instruction();
+
+const transaction = new Transaction().add(instruction);
+
+const transactionSignature = await connection.sendTransaction(transaction, [
+ wallet.payer,
+ newAccountKp,
+]);
+```
+
+
+
+
+## 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()`](https://github.com/coral-xyz/anchor/blob/v0.30.1/ts/packages/anchor/src/program/namespace/account.ts#L251)
+to fetch all existing accounts for a specific account type.
+
+```ts
+// [!code word:all]
+const accounts = await program.account.newAccount.all();
+```
+
+
+
+
+Use `memcmp` (memory compare) to filter for account data that matches a specific
+value at a specific offset. Using `memcmp` requires you to understand the byte
+layout of the data field for the account type you are fetching.
+
+When calculating the offset, remember that the first 8 bytes in accounts created
+by an Anchor program are reserved for the account discriminator.
+
+```ts
+// [!code word:memcmp]
+const accounts = await program.account.newAccount.all([
+ {
+ // [!code highlight:4]
+ memcmp: {
+ offset: 8,
+ bytes: "",
+ },
+ },
+]);
+```
+
+
+
+
+Use
+[`fetch()`](https://github.com/coral-xyz/anchor/blob/v0.30.1/ts/packages/anchor/src/program/namespace/account.ts#L165)
+to fetch the account data for a single account
+
+```ts
+// [!code word:fetch]
+const account = await program.account.newAccount.fetch(ACCOUNT_ADDRESS);
+```
+
+
+
+
+Use
+[`fetchMultiple()`](https://github.com/coral-xyz/anchor/blob/v0.30.1/ts/packages/anchor/src/program/namespace/account.ts#L200)
+to fetch the account data for multiple accounts by passing in an array of
+account addresses
+
+```ts
+// [!code word:fetchMultiple]
+const accounts = await program.account.newAccount.fetchMultiple([
+ ACCOUNT_ADDRESS_ONE,
+ ACCOUNT_ADDRESS_TWO,
+]);
+```
+
+
+
+
+## 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
+
+```rust title="lib.rs"
+use anchor_lang::prelude::*;
+
+declare_id!("6khKp4BeJpCjBY1Eh39ybiqbfRnrn2UzWeUARjQLXYRC");
+
+#[program]
+pub mod example {
+ use super::*;
+
+ pub fn initialize(ctx: Context) -> Result<()> {
+ let counter = &ctx.accounts.counter;
+ msg!("Counter account created! Current count: {}", counter.count);
+ Ok(())
+ }
+
+ pub fn increment(ctx: Context) -> 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:
+
+
+
+
+
+
+
+
+
+
+
+
+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.
+
+
+
+```json tab="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"
+ }
+ ]
+ }
+ }
+ ]
+}
+```
+
+```ts tab="example.ts"
+/**
+ * Program IDL in camelCase format in order to be used in JS/TS.
+ *
+ * Note that this is only a type helper and is not the actual IDL. The original
+ * IDL can be found at `target/idl/example.json`.
+ */
+export type Example = {
+ 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: "systemProgram";
+ 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.
+
+```ts title="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);
+```
diff --git a/docs/content/docs/features/declare-program.mdx b/docs/content/docs/features/declare-program.mdx
new file mode 100644
index 0000000000..13809aa334
--- /dev/null
+++ b/docs/content/docs/features/declare-program.mdx
@@ -0,0 +1,778 @@
+---
+title: Dependency Free Composability
+description:
+ Learn how to use Anchor's declare_program macro to interact with programs
+ without additional dependencies.
+---
+
+The
+[`declare_program!()`](https://github.com/coral-xyz/anchor/tree/v0.30.1/lang/attribute/program/src/declare_program)
+macro simplifies the process of interacting with Anchor programs by generating
+Rust modules (from a program's IDL) that can be used in both on-chain and
+off-chain code. You can find an example program
+[here](https://github.com/coral-xyz/anchor/tree/master/tests/declare-program).
+
+The following modules are generated by the `declare_program!()` macro:
+
+| Module | Description |
+| ---------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- |
+| [`cpi`](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/attribute/program/src/declare_program/mods/cpi.rs) | Helper functions for making cross-program invocations (CPIs) to the program from other on-chain programs |
+| [`client`](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/attribute/program/src/declare_program/mods/client.rs) | Accounts and arguments required to build program instructions to add to client-side transactions |
+| [`account`](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/attribute/program/src/declare_program/mods/accounts.rs) | Account data types (program state) defined in the program |
+| [`program`](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/attribute/program/src/declare_program/mods/program.rs) | Program ID constant used to identify the program |
+| [`constants`](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/attribute/program/src/declare_program/mods/constants.rs) | Program constants defined in the program |
+| [`events`](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/attribute/program/src/declare_program/mods/events.rs) | Program events defined in the program |
+| [`types`](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/attribute/program/src/declare_program/mods/types.rs) | Program types defined in the program |
+
+## Examples
+
+The following examples demonstrate how to use the `declare_program!()` macro in
+two scenarios:
+
+1. Making Cross Program Invocations (CPIs) from one program to another program
+2. Building client-side transactions to invoke a program's instructions
+
+Both examples show how the modules generated by the `declare_program!()` macro
+simplify program interactions, whether you're writing on-chain or off-chain
+code.
+
+### On-chain CPI
+
+To use the `declare_program!()` macro, you need the IDL file for the target
+program. The IDL file must be placed in a directory named `/idls` in your
+project. The `/idls` directory can be located at any level in your project
+structure. For example, your project could have this layout:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Below is the source code (`lib.rs`) for the target (callee) program that
+generates the `example.json` IDL file shown above.
+
+Using the program's IDL file, another program can use the `declare_program!()`
+macro to generate a CPI module, enabling it to make CPIs to this program's
+instructions.
+
+
+
+```rust tab="Callee Program"
+use anchor_lang::prelude::*;
+
+declare_id!("8HupNBr7SBhBLcBsLhbtes3tCarBm6Bvpqp5AfVjHuj8");
+
+#[program]
+pub mod example {
+ use super::*;
+
+ pub fn initialize(ctx: Context) -> Result<()> {
+ let counter = &ctx.accounts.counter;
+ msg!("Counter account created! Current count: {}", counter.count);
+ Ok(())
+ }
+
+ pub fn increment(ctx: Context) -> 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,
+}
+```
+
+```ts tab="IDL"
+{
+ "address": "8HupNBr7SBhBLcBsLhbtes3tCarBm6Bvpqp5AfVjHuj8",
+ "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 source code (`lib.rs`) for the caller program (example-cpi) that
+uses the `declare_program!()` macro to generate a CPI module to invoke the
+instructions defined in the callee program above.
+
+
+
+```rust tab="Caller Program"
+use anchor_lang::prelude::*;
+
+declare_id!("GENmb1D59wqCKRwujq4PJ8461EccQ5srLHrXyXp4HMTH");
+
+// [!code word:declare_program]
+// [!code highlight:9]
+declare_program!(example);
+use example::{
+ accounts::Counter,
+ cpi::{
+ self,
+ accounts::{Increment, Initialize},
+ },
+ program::Example,
+};
+
+#[program]
+pub mod example_cpi {
+
+ use super::*;
+
+ pub fn initialize_cpi(ctx: Context) -> Result<()> {
+ // Create CPI context for initialize
+ let cpi_ctx = CpiContext::new(
+ ctx.accounts.example_program.to_account_info(),
+ Initialize {
+ payer: ctx.accounts.payer.to_account_info(),
+ counter: ctx.accounts.counter.to_account_info(),
+ system_program: ctx.accounts.system_program.to_account_info(),
+ },
+ );
+
+ // Invoke the initialize instruction
+ cpi::initialize(cpi_ctx)?;
+ Ok(())
+ }
+
+ pub fn increment_cpi(ctx: Context) -> Result<()> {
+ // Create CPI context for increment
+ let cpi_ctx = CpiContext::new(
+ ctx.accounts.example_program.to_account_info(),
+ Increment {
+ counter: ctx.accounts.counter.to_account_info(),
+ },
+ );
+
+ // Invoke the increment instruction
+ cpi::increment(cpi_ctx)?;
+ Ok(())
+ }
+}
+
+#[derive(Accounts)]
+pub struct InitializeCpi<'info> {
+ #[account(mut)]
+ pub payer: Signer<'info>,
+ #[account(mut)]
+ pub counter: Signer<'info>,
+ pub system_program: Program<'info, System>,
+ pub example_program: Program<'info, Example>,
+}
+
+#[derive(Accounts)]
+pub struct IncrementCpi<'info> {
+ #[account(mut)]
+ pub counter: Account<'info, Counter>,
+ pub example_program: Program<'info, Example>,
+}
+```
+
+```ts tab="Test"
+import * as anchor from "@coral-xyz/anchor";
+import { Program } from "@coral-xyz/anchor";
+import { Example } from "../target/types/example";
+import { ExampleCpi } from "../target/types/example_cpi";
+import { Keypair } from "@solana/web3.js";
+
+describe("example", () => {
+ anchor.setProvider(anchor.AnchorProvider.env());
+
+ const program = anchor.workspace.Example as Program;
+ const cpiProgram = anchor.workspace.ExampleCpi as Program;
+
+ const counterAccount = Keypair.generate();
+
+ it("Is initialized!", async () => {
+ const transactionSignature = await cpiProgram.methods
+ .initializeCpi()
+ .accounts({
+ counter: counterAccount.publicKey,
+ })
+ .signers([counterAccount])
+ .rpc({ skipPreflight: true });
+
+ const accountData = await program.account.counter.fetch(
+ counterAccount.publicKey,
+ );
+
+ console.log(`Transaction Signature: ${transactionSignature}`);
+ console.log(`Count: ${accountData.count}`);
+ });
+
+ it("Increment", async () => {
+ const transactionSignature = await cpiProgram.methods
+ .incrementCpi()
+ .accounts({
+ counter: counterAccount.publicKey,
+ })
+ .rpc();
+
+ const accountData = await program.account.counter.fetch(
+ counterAccount.publicKey,
+ );
+
+ console.log(`Transaction Signature: ${transactionSignature}`);
+ console.log(`Count: ${accountData.count}`);
+ });
+});
+```
+
+
+
+#### Explanation
+
+
+
+
+
+The `declare_program!()` macro takes a single argument - the name of the
+program's IDL file (e.g. `example.json`):
+
+```rust
+declare_program!(example); // Looks for /idls/example.json
+```
+
+
+
+
+
+Bring into scope the generated modules:
+
+```rust
+use example::{
+ accounts::Counter, // Account types
+ cpi::{ // Cross program invocation helpers
+ self,
+ accounts::{Increment, Initialize},
+ },
+ program::Example, // Program type
+};
+```
+
+
+
+
+
+Use the imported types in the account validation structs:
+
+```rust
+#[derive(Accounts)]
+pub struct IncrementCpi<'info> {
+ // Counter type from accounts module
+ #[account(mut)]
+ // [!code word:Counter]
+ // [!code highlight]
+ pub counter: Account<'info, Counter>,
+
+ // Example type from program module
+ // [!code word:Example]
+ // [!code highlight]
+ pub example_program: Program<'info, Example>,
+}
+```
+
+
+
+
+
+Use the CPI module to invoke the program's instructions:
+
+```rust
+pub fn initialize_cpi(ctx: Context) -> Result<()> {
+ // Create CPI context for initialize
+ let cpi_ctx = CpiContext::new(
+ ctx.accounts.example_program.to_account_info(),
+ Initialize {
+ payer: ctx.accounts.payer.to_account_info(),
+ counter: ctx.accounts.counter.to_account_info(),
+ system_program: ctx.accounts.system_program.to_account_info(),
+ },
+ );
+
+ // Invoke the initialize instruction
+ // [!code highlight]
+ cpi::initialize(cpi_ctx)?;
+ Ok(())
+}
+```
+
+```rust
+pub fn increment_cpi(ctx: Context) -> Result<()> {
+ // Create CPI context for increment
+ let cpi_ctx = CpiContext::new(
+ ctx.accounts.example_program.to_account_info(),
+ Increment {
+ counter: ctx.accounts.counter.to_account_info(),
+ },
+ );
+
+ // Invoke the increment instruction
+ // [!code highlight]
+ cpi::increment(cpi_ctx)?;
+ Ok(())
+}
+```
+
+
+
+
+
+### Off-chain Client
+
+To use the `declare_program!()` macro, you need the IDL file for the target
+program. The IDL file must be placed in a directory named `/idls` in your
+project. The `/idls` directory can be located at any level in your project
+structure. For example, your project could have this layout:
+
+
+
+
+
+
+
+
+
+
+
+Below is the source code (`lib.rs`) for the target program that generates the
+`example.json` IDL file shown above. The program's IDL can then be used in a
+client script along with the `declare_program!()` macro to generate a Client
+module to build the program's instructions.
+
+
+
+```rust tab="Callee Program"
+use anchor_lang::prelude::*;
+
+declare_id!("6khKp4BeJpCjBY1Eh39ybiqbfRnrn2UzWeUARjQLXYRC");
+
+#[program]
+pub mod example {
+ use super::*;
+
+ pub fn initialize(ctx: Context) -> Result<()> {
+ let counter = &ctx.accounts.counter;
+ msg!("Counter account created! Current count: {}", counter.count);
+ Ok(())
+ }
+
+ pub fn increment(ctx: Context) -> 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,
+}
+```
+
+```ts tab="IDL"
+{
+ "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 client script (main.rs) that uses the `declare_program!()` macro to
+generate a Client module to build the program's instructions.
+
+
+
+```rust tab="Client Script"
+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.pubkey()).await?;
+ println!(" Counter value: {}", counter_account.count);
+ Ok(())
+}
+```
+
+```toml tab="Dependencies"
+[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"] }
+```
+
+
+
+
+
+
+
+The `declare_program!()` macro takes a single argument - the name of the
+program's IDL file (e.g. `example.json`):
+
+```rust
+declare_program!(example); // Looks for /idls/example.json
+```
+
+
+
+
+
+Bring into scope the generated modules:
+
+```rust
+use example::{
+ accounts::Counter, // Program Account types
+ client::accounts, // Accounts for program instructions
+ client::args, // Arguments for program instructions
+};
+```
+
+
+
+
+
+Use the Client module to build the program's instructions:
+
+```rust
+// Build initialize instruction
+let initialize_ix = program
+ .request()
+ // Accounts required for initialize instruction
+ .accounts(accounts::Initialize {
+ counter: counter.pubkey(),
+ payer: program.payer(),
+ system_program: system_program::ID,
+ })
+ // Arguments for initialize instruction (discriminator)
+ .args(args::Initialize)
+ .instructions()?
+ .remove(0);
+```
+
+```rust
+// Build increment instruction
+let increment_ix = program
+ .request()
+ // Accounts required for increment instruction
+ .accounts(accounts::Increment {
+ counter: counter.pubkey(),
+ })
+ // Arguments for increment instruction (discriminator)
+ .args(args::Increment)
+ .instructions()?
+ .remove(0);
+```
+
+
+
+
+Add the program's instructions to a transaction and send the transaction:
+
+```rust
+let signature = program
+ .request()
+ .instruction(initialize_ix)
+ .instruction(increment_ix)
+ .signer(&counter)
+ .send()
+ .await?;
+```
+
+
+
+
+
+Use the Account module to fetch and deserialize the program's account types:
+
+```rust
+// Counter type from accounts module
+let counter_account: Counter = program.account::(counter.pubkey()).await?;
+```
+
+
+
+
diff --git a/docs/content/docs/features/errors.mdx b/docs/content/docs/features/errors.mdx
new file mode 100644
index 0000000000..e0a8e87c01
--- /dev/null
+++ b/docs/content/docs/features/errors.mdx
@@ -0,0 +1,321 @@
+---
+title: Custom Errors
+description: Learn how to implement custom error handling in Anchor programs.
+---
+
+All instruction handlers in Anchor programs return a custom `Result` type
+that allows you to handle successful execution with `Ok(T)` and error cases with
+`Err(Error)`.
+
+```rust
+// [!code word:Result]
+pub fn custom_instruction(ctx: Context) -> Result<()> {
+ // --snip--
+ Ok(())
+}
+```
+
+The
+[`Result`](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/src/lib.rs#L74)
+type in Anchor programs is a type alias that wraps the standard Rust
+`Result`. In this case, `T` represents the successful return type, while
+`E` is Anchor's custom `Error` type.
+
+```rust
+pub type Result = std::result::Result;
+```
+
+## Anchor Error
+
+When an error occurs in an Anchor program, it returns a custom
+[`Error`](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/src/error.rs#L277-L281)
+type defined as:
+
+```rust
+#[derive(Debug, PartialEq, Eq)]
+pub enum Error {
+ AnchorError(Box),
+ ProgramError(Box),
+}
+```
+
+The `Error` type in Anchor programs can be one of two variants:
+
+1. [`ProgramErrorWithOrigin`](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/src/error.rs#L389-L394):
+ Custom type that wraps a standard Solana
+ [`ProgramError`](https://github.com/anza-xyz/agave/blob/v1.18.26/sdk/program/src/program_error.rs#L12-L66)
+ type. These errors come from the `solana_program` crate.
+
+```rust
+#[derive(Debug)]
+pub struct ProgramErrorWithOrigin {
+ pub program_error: ProgramError,
+ pub error_origin: Option,
+ pub compared_values: Option,
+}
+```
+
+2. [`AnchorError`](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/src/error.rs#L490-L497):
+ Errors defined by the Anchor framework.
+
+```rust
+#[derive(Debug)]
+pub struct AnchorError {
+ pub error_name: String,
+ pub error_code_number: u32,
+ pub error_msg: String,
+ pub error_origin: Option,
+ pub compared_values: Option,
+}
+```
+
+An `AnchorError` can be thought of as having two categories:
+
+1. Internal Anchor Errors - These are built-in errors included with the Anchor
+ framework. They are defined in the
+ [`ErrorCode`](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/src/error.rs#L10-L275)
+ enum.
+
+2. Custom Program Errors - These are program specific errors that developers
+ define to handle custom error cases.
+
+The `error_code_number` from an `AnchorError` has the following numbering
+scheme:
+
+| Error Code | Description |
+| ---------- | ------------------------------------- |
+| >= 100 | Instruction error codes |
+| >= 1000 | IDL error codes |
+| >= 2000 | Constraint error codes |
+| >= 3000 | Account error codes |
+| >= 4100 | Misc error codes |
+| = 5000 | Deprecated error code |
+| >= 6000 | Starting point for custom user errors |
+
+## Usage
+
+Anchor provides a convenient way to define custom errors through the
+`error_code` attribute. The implementation details can be found
+[here](https://github.com/coral-xyz/anchor/blob/master/lang/syn/src/codegen/error.rs).
+
+When you define an enum with the `error_code` attribute, Anchor automatically:
+
+- Assigns an error code starting from 6000
+- Generates the necessary boilerplate for error handling
+- Enables the use of custom error messages via the `msg` attribute
+
+```rust
+#[error_code]
+pub enum MyError {
+ #[msg("My custom error message")]
+ MyCustomError,
+ #[msg("My second custom error message")]
+ MySecondCustomError,
+}
+```
+
+### err!
+
+To throw an error, use the
+[`err!`](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/src/lib.rs#L720-L728)
+macro. The `err!` macro provides a convenient way to return custom errors from
+your program. Under the hood, `err!` uses the `error!` macro to construct
+`AnchorError`. The implementation can be found
+[here](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/attribute/error/src/lib.rs#L84-L116).
+
+```rust
+#[program]
+mod hello_anchor {
+ use super::*;
+ pub fn set_data(ctx: Context
+
+
+```rust title="lib.rs"
+use anchor_lang::prelude::*;
+
+declare_id!("9oECKMeeyf1fWNPKzyrB2x1AbLjHDFjs139kEyFwBpoV");
+
+#[program]
+pub mod custom_error {
+ use super::*;
+
+ pub fn validate_amount(_ctx: Context
+
+
+```ts title="test.ts"
+import * as anchor from "@coral-xyz/anchor";
+import { Program } from "@coral-xyz/anchor";
+import { CustomError } from "../target/types/custom_error";
+import assert from "assert";
+
+describe("custom-error", () = {
+ anchor.setProvider(anchor.AnchorProvider.env());
+ const program = anchor.workspace.CustomError as Program
+
+
+When a program error occurs, Anchor's TypeScript Client SDK returns a detailed
+[error response](https://github.com/coral-xyz/anchor/blob/v0.30.1/ts/packages/anchor/src/error.ts#L51-L71)
+containing information about the error. Here's an example error response showing
+the structure and available fields:
+
+```shell title="Error Response"
+{
+ errorLogs: [
+ 'Program log: AnchorError thrown in programs/custom-error/src/lib.rs:11. Error Code: AmountTooLarge. Error Number: 6001. Error Message: Amount must be less than or equal to 100.'
+ ],
+ logs: [
+ 'Program 9oECKMeeyf1fWNPKzyrB2x1AbLjHDFjs139kEyFwBpoV invoke [1]',
+ 'Program log: Instruction: ValidateAmount',
+ 'Program log: AnchorError thrown in programs/custom-error/src/lib.rs:11. Error Code: AmountTooLarge. Error Number: 6001. Error Message: Amount must be less than or equal to 100.',
+ 'Program 9oECKMeeyf1fWNPKzyrB2x1AbLjHDFjs139kEyFwBpoV consumed 2153 of 200000 compute units',
+ 'Program 9oECKMeeyf1fWNPKzyrB2x1AbLjHDFjs139kEyFwBpoV failed: custom program error: 0x1771'
+ ],
+ error: {
+ errorCode: { code: 'AmountTooLarge', number: 6001 },
+ errorMessage: 'Amount must be less than or equal to 100',
+ comparedValues: undefined,
+ origin: { file: 'programs/custom-error/src/lib.rs', line: 11 }
+ },
+ _programErrorStack: ProgramErrorStack {
+ stack: [
+ [PublicKey [PublicKey(9oECKMeeyf1fWNPKzyrB2x1AbLjHDFjs139kEyFwBpoV)]]
+ ]
+ }
+}
+```
+
+For a more comprehensive example, you can also reference the
+[errors test program](https://github.com/coral-xyz/anchor/blob/master/tests/errors/programs/errors/src/lib.rs)
+in the Anchor repository.
diff --git a/docs/content/docs/features/events.mdx b/docs/content/docs/features/events.mdx
new file mode 100644
index 0000000000..64cf3ce3ce
--- /dev/null
+++ b/docs/content/docs/features/events.mdx
@@ -0,0 +1,367 @@
+---
+title: Emit Events
+description:
+ Learn how to emit events in Anchor programs using emit! and emit_cpi! macros.
+---
+
+## Examples
+
+Anchor provides two macros for emitting events in your programs:
+
+1. `emit!()` - Emits events directly to program logs. This is the simpler,
+ though program logs may be truncated by data providers in some cases
+2. `emit_cpi!()` - Emits events through a Cross Program Invocation (CPI) by
+ including the event data in the instruction data.
+
+
+
+The `emit_cpi()` approach was introduced an alternative to program logs, which
+can sometimes be truncated by data providers. While CPI instruction data is less
+likely to be truncated, this approach does incur additional compute costs from
+the Cross Program Invocation.
+
+
+
+
+
+For more robust solutions for events, consider geyser gRPC services by
+[Triton](https://docs.triton.one/project-yellowstone/dragons-mouth-grpc-subscriptions)
+or [Helius](https://docs.helius.dev/data-streaming/geyser-yellowstone).
+
+
+
+### `emit`
+
+The
+[`emit!()`](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/attribute/event/src/lib.rs#L94-L102)
+macro provides a way to emit events through program logs. When called, it:
+
+1. Uses the
+ [`sol_log_data()`](https://github.com/anza-xyz/agave/blob/v1.18.26/sdk/program/src/log.rs#L115-L124)
+ syscall to write the data to program logs
+2. Encodes the event data as a
+ [base64 string](https://github.com/anza-xyz/agave/blob/v1.18.26/program-runtime/src/stable_log.rs#L46-L61)
+ prefixed with `Program Data:`
+
+To receive emitted events in your client application, use the
+[`addEventListener()`](https://github.com/coral-xyz/anchor/blob/v0.30.1/ts/packages/anchor/src/program/event.ts#L74-L123)
+method. This method automatically
+[parses and decodes](https://github.com/coral-xyz/anchor/blob/v0.30.1/ts/packages/anchor/src/program/event.ts#L230-L251)
+event data from the program logs.
+
+Example usage:
+
+
+
+
+```rust title="lib.rs"
+use anchor_lang::prelude::*;
+
+declare_id!("8T7MsCZyzxboviPJg5Rc7d8iqEcDReYR2pkQKrmbg7dy");
+
+#[program]
+pub mod event {
+ use super::*;
+
+ pub fn emit_event(_ctx: Context, input: String) -> Result<()> {
+ // [!code word:emit!]
+ // [!code highlight]
+ emit!(CustomEvent { message: input });
+ Ok(())
+ }
+}
+
+#[derive(Accounts)]
+pub struct EmitEvent {}
+
+// [!code highlight:4]
+#[event]
+pub struct CustomEvent {
+ pub message: String,
+}
+```
+
+
+
+
+```ts title="test.ts"
+import * as anchor from "@coral-xyz/anchor";
+import { Program } from "@coral-xyz/anchor";
+import { Event } from "../target/types/event";
+
+describe("event", () => {
+ // Configure the client to use the local cluster.
+ anchor.setProvider(anchor.AnchorProvider.env());
+
+ const program = anchor.workspace.Event as Program;
+
+ it("Emits custom event", async () => {
+ // Set up listener before sending transaction
+ // [!code word:addEventListener]
+ // [!code highlight:4]
+ const listenerId = program.addEventListener("customEvent", event => {
+ // Do something with the event data
+ console.log("Event Data:", event);
+ });
+
+ // Message to be emitted in the event
+ const message = "Hello, Solana!";
+ // Send transaction
+ await program.methods.emitEvent(message).rpc();
+
+ // Remove listener
+ await program.removeEventListener(listenerId);
+ });
+});
+```
+
+
+
+
+The following is the output of the program logs. The event data is base64
+encoded as `Zb1eU3aiYdwOAAAASGVsbG8sIFNvbGFuYSE=`.
+
+```shell title="Program Logs"
+Log Messages:
+ Program 8T7MsCZyzxboviPJg5Rc7d8iqEcDReYR2pkQKrmbg7dy invoke [1]
+ Program log: Instruction: EmitEvent
+ Program data: Zb1eU3aiYdwOAAAASGVsbG8sIFNvbGFuYSE=
+ Program 8T7MsCZyzxboviPJg5Rc7d8iqEcDReYR2pkQKrmbg7dy consumed 1012 of 200000 compute units
+ Program 8T7MsCZyzxboviPJg5Rc7d8iqEcDReYR2pkQKrmbg7dy success
+```
+
+
+ Ensure the RPC provider you use does not truncate the program logs from the
+ transaction data.
+
+
+### `emit_cpi`
+
+The
+[`emit_cpi!()`](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/attribute/event/src/lib.rs#L148-L184)
+macro emits events through Cross Program Invocations (CPIs) to the program
+itself. The event data is encoded and included in the CPI's instruction data
+(instead of program logs).
+
+To emit events through CPIs, you need to enable the `event-cpi` feature in your
+program's `Cargo.toml`:
+
+```toml title="Cargo.toml"
+[dependencies]
+anchor-lang = { version = "0.30.1", features = ["event-cpi"] }
+```
+
+Example usage:
+
+
+
+
+```rust title="lib.rs"
+use anchor_lang::prelude::*;
+
+declare_id!("2cDQ2LxKwQ8fnFUz4LLrZ157QzBnhPNeQrTSmWcpVin1");
+
+#[program]
+pub mod event_cpi {
+ use super::*;
+
+ pub fn emit_event(ctx: Context, input: String) -> Result<()> {
+ // [!code word:emit_cpi!]
+ // [!code highlight]
+ emit_cpi!(CustomEvent { message: input });
+ Ok(())
+ }
+}
+
+// [!code highlight]
+#[event_cpi]
+#[derive(Accounts)]
+pub struct EmitEvent {}
+
+// [!code highlight:4]
+#[event]
+pub struct CustomEvent {
+ pub message: String,
+}
+```
+
+
+
+
+```ts title="test.ts"
+import * as anchor from "@coral-xyz/anchor";
+import { Program } from "@coral-xyz/anchor";
+import { EventCpi } from "../target/types/event_cpi";
+
+describe("event-cpi", () => {
+ // Configure the client to use the local cluster.
+ anchor.setProvider(anchor.AnchorProvider.env());
+ const program = anchor.workspace.EventCpi as Program;
+
+ it("Emits custom event", async () => {
+ const message = "Hello, Solana!";
+ const transactionSignature = await program.methods.emitEvent(message).rpc();
+
+ // Wait for the transaction to be confirmed
+ await program.provider.connection.confirmTransaction(
+ transactionSignature,
+ "confirmed",
+ );
+
+ // Fetch the transaction data
+ // [!code highlight:4]
+ const transactionData = await program.provider.connection.getTransaction(
+ transactionSignature,
+ { commitment: "confirmed" },
+ );
+
+ // Decode the event data from the CPI instruction data
+ // [!code highlight:4]
+ const eventIx = transactionData.meta.innerInstructions[0].instructions[0];
+ const rawData = anchor.utils.bytes.bs58.decode(eventIx.data);
+ const base64Data = anchor.utils.bytes.base64.encode(rawData.subarray(8));
+ const event = program.coder.events.decode(base64Data);
+ console.log(event);
+ });
+});
+```
+
+
+
+
+The
+[`event_cpi`](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/attribute/event/src/lib.rs#L217-L226)
+attribute must be added to the `#[derive(Accounts)]` struct for the instruction
+instruction that emits events using the `emit_cpi!()` macro. This attribute
+[automatically includes additional accounts](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/syn/src/parser/accounts/event_cpi.rs#L28-L70)
+that are required for the self CPI.
+
+```rust title="lib.rs"
+// [!code highlight]
+#[event_cpi]
+#[derive(Accounts)]
+pub struct RequiredAccounts {
+ // --snip--
+}
+```
+
+To get the emitted event data in your client application, you need to fetch the
+transaction using the transaction signature and parse the event data from the
+CPI instruction data.
+
+```ts title="test.ts"
+// 1. Fetch the full transaction data using the transaction signature
+const transactionData = await program.provider.connection.getTransaction(
+ transactionSignature,
+ { commitment: "confirmed" },
+);
+
+// 2. Extract the CPI (inner instruction) that contains the event data
+const eventIx = transactionData.meta.innerInstructions[0].instructions[0];
+
+// 3. Decode the event data
+const rawData = anchor.utils.bytes.bs58.decode(eventIx.data);
+const base64Data = anchor.utils.bytes.base64.encode(rawData.subarray(8));
+const event = program.coder.events.decode(base64Data);
+console.log(event);
+```
+
+Below is an example transaction showing how event data appears in the
+transaction details. When using `emit_cpi!()`, the event data is encoded and
+included in the `data` field of an inner instruction (CPI).
+
+In the example transaction below, the encoded event data is
+`"data": "6AJcBqZP8afBKheoif1oA6UAiLAcqYr2RaR33pFnEY1taQp"` in the
+`innerInstructions` array.
+
+```shell title="Transaction Data"
+{
+ "blockTime": 1735854530,
+ "meta": {
+ "computeUnitsConsumed": 13018,
+ "err": null,
+ "fee": 5000,
+ "innerInstructions": [
+ {
+ "index": 0,
+ "instructions": [
+ {
+ "accounts": [
+ 1
+ ],
+ "data": "6AJcBqZP8afBKheoif1oA6UAiLAcqYr2RaR33pFnEY1taQp",
+ "programIdIndex": 2,
+ "stackHeight": 2
+ }
+ ]
+ }
+ ],
+ "loadedAddresses": {
+ "readonly": [],
+ "writable": []
+ },
+ "logMessages": [
+ "Program 2cDQ2LxKwQ8fnFUz4LLrZ157QzBnhPNeQrTSmWcpVin1 invoke [1]",
+ "Program log: Instruction: EmitEvent",
+ "Program 2cDQ2LxKwQ8fnFUz4LLrZ157QzBnhPNeQrTSmWcpVin1 invoke [2]",
+ "Program 2cDQ2LxKwQ8fnFUz4LLrZ157QzBnhPNeQrTSmWcpVin1 consumed 5000 of 192103 compute units",
+ "Program 2cDQ2LxKwQ8fnFUz4LLrZ157QzBnhPNeQrTSmWcpVin1 success",
+ "Program 2cDQ2LxKwQ8fnFUz4LLrZ157QzBnhPNeQrTSmWcpVin1 consumed 13018 of 200000 compute units",
+ "Program 2cDQ2LxKwQ8fnFUz4LLrZ157QzBnhPNeQrTSmWcpVin1 success"
+ ],
+ "postBalances": [
+ 499999999999995000,
+ 0,
+ 1141440
+ ],
+ "postTokenBalances": [],
+ "preBalances": [
+ 500000000000000000,
+ 0,
+ 1141440
+ ],
+ "preTokenBalances": [],
+ "rewards": [],
+ "status": {
+ "Ok": null
+ }
+ },
+ "slot": 3,
+ "transaction": {
+ "message": {
+ "header": {
+ "numReadonlySignedAccounts": 0,
+ "numReadonlyUnsignedAccounts": 2,
+ "numRequiredSignatures": 1
+ },
+ "accountKeys": [
+ "4kh6HxYZiAebF8HWLsUWod2EaQQ6iWHpHYCz8UcmFbM1",
+ "2brZf9PQqEvv17xtbj5WNhZJULgVZuLZT6FgH1Cqpro2",
+ "2cDQ2LxKwQ8fnFUz4LLrZ157QzBnhPNeQrTSmWcpVin1"
+ ],
+ "recentBlockhash": "2QtnU35RXTo7uuQEVARYJgWYRYtbqUxWQkK8WywUnVdY",
+ "instructions": [
+ {
+ "accounts": [
+ 1,
+ 2
+ ],
+ "data": "3XZZ984toC4WXCLkxBsLimpEGgH75TKXRJnk",
+ "programIdIndex": 2,
+ "stackHeight": null
+ }
+ ],
+ "indexToProgramIds": {}
+ },
+ "signatures": [
+ "3gFbKahSSbitRSos4MH3cqeVv2FiTNaLCuWaLPo6R98FEbHnTshoYxopGcx74nFLqt1pbZK9i8dnr4NFXayrMndZ"
+ ]
+ }
+}
+```
+
+
+ Currently, event data emitted through CPIs cannot be directly subscribed to.
+ To access this data, you must fetch the complete transaction data and manually
+ decode the event information from the instruction data of the CPI.
+
diff --git a/docs/content/docs/features/index.mdx b/docs/content/docs/features/index.mdx
new file mode 100644
index 0000000000..25a8abac54
--- /dev/null
+++ b/docs/content/docs/features/index.mdx
@@ -0,0 +1,5 @@
+---
+title: Features
+description: Learn how to use additional features of the Anchor framework
+index: true
+---
diff --git a/docs/content/docs/features/meta.json b/docs/content/docs/features/meta.json
new file mode 100644
index 0000000000..a4b2f5be20
--- /dev/null
+++ b/docs/content/docs/features/meta.json
@@ -0,0 +1,4 @@
+{
+ "title": "Additional Features",
+ "pages": ["declare-program", "errors", "events", "zero-copy"]
+}
diff --git a/docs/content/docs/features/zero-copy.mdx b/docs/content/docs/features/zero-copy.mdx
new file mode 100644
index 0000000000..a01c7cb1ba
--- /dev/null
+++ b/docs/content/docs/features/zero-copy.mdx
@@ -0,0 +1,404 @@
+---
+title: Zero Copy
+description:
+ Learn how to use Anchor's zero-copy deserialization feature to handle large
+ account data in Solana programs.
+---
+
+## Usage
+
+Zero copy is a deserialization feature that allows programs to read account data
+directly from memory without copying it. This is particularly useful when
+working with large accounts.
+
+To use zero-copy add the `bytemuck` crate to your dependencies. Add the
+`min_const_generics` feature to allow working with arrays of any size in your
+zero-copy types.
+
+```toml title="Cargo.toml"
+[dependencies]
+bytemuck = { version = "1.20.0", features = ["min_const_generics"] }
+anchor-lang = "0.30.1"
+```
+
+### Define a Zero Copy Account
+
+To define an account type that uses zero-copy, annotate the struct with
+[`#[account(zero_copy)]`](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/attribute/account/src/lib.rs#L319).
+
+```rust
+// [!code highlight]
+#[account(zero_copy)]
+pub struct Data {
+ // 10240 bytes - 8 bytes account discriminator
+ pub data: [u8; 10232],
+}
+```
+
+The `#[account(zero_copy)]` attribute automatically implements several traits
+required for zero-copy deserialization:
+
+```rust
+// [!code highlight:4]
+#[derive(Copy, Clone)]
+#[derive(bytemuck::Zeroable)]
+#[derive(bytemuck::Pod)]
+#[repr(C)]
+struct Data {
+ // --snip--
+}
+```
+
+### Use AccountLoader for Zero Copy Accounts
+
+To deserialize a zero-copy account, use
+[`AccountLoader<'info, T>`](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/src/accounts/account_loader.rs#L96-L100),
+where `T` is the zero-copy account type defined with the `#[account(zero_copy)]`
+attribute.
+
+For example:
+
+```rust
+#[derive(Accounts)]
+pub struct InstructionAccounts<'info> {
+ // [!code word:AccountLoader]
+ // [!code highlight]
+ pub zero_copy_account: AccountLoader<'info, Data>,
+}
+```
+
+#### Initialize a Zero Copy Account
+
+The `init` constraint can be used with the `AccountLoader` type to create a
+zero-copy account.
+
+```rust
+#[derive(Accounts)]
+pub struct Initialize<'info> {
+ #[account(
+ // [!code word:init:1]
+ // [!code highlight:4]
+ init,
+ // 10240 bytes is max space to allocate with init constraint
+ space = 8 + 10232,
+ payer = payer,
+ )]
+ pub data_account: AccountLoader<'info, Data>,
+ #[account(mut)]
+ pub payer: Signer<'info>,
+ pub system_program: Program<'info, System>,
+}
+```
+
+
+ The `init` constraint is limited to allocating a maximum of 10240 bytes due to
+ CPI limitations. Under the hood, the `init` constraint makes a CPI call to the
+ SystemProgram to create the account.
+
+
+When initializing a zero-copy account for the first time, use
+[`load_init`](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/src/accounts/account_loader.rs#L194-L214)
+to get a mutable reference to the account data. The `load_init` method also sets
+the account discriminator.
+
+```rust
+pub fn initialize(ctx: Context) -> Result<()> {
+ // [!code word:load_init]
+ // [!code highlight]
+ let account = &mut ctx.accounts.data_account.load_init()?;
+ account.data = [1; 10232];
+ Ok(())
+}
+```
+
+For accounts that require more than 10240 bytes, use the
+[`zero`](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/syn/src/codegen/accounts/constraints.rs#L200-L217)
+constraint instead of `init`. The `zero` constraint verifies the account has not
+been initialized by checking that its discriminator has not been set.
+
+```rust
+#[derive(Accounts)]
+pub struct Initialize<'info> {
+ // [!code word:zero]
+ // [!code highlight]
+ #[account(zero)]
+ pub data_account: AccountLoader<'info, Data>,
+}
+```
+
+With the `zero` constraint, you'll need to first create the account in a
+separate instruction by directly calling the System Program. This allows you to
+create accounts up to Solana's maximum account size of 10MB (10_485_760 bytes),
+bypassing the CPI limitation.
+
+Just as before, use `load_init` to get a mutable reference to the account data
+and set the account discriminator. Since 8 bytes are reserved for the account
+discriminator, the maximum data size is 10_485_752 bytes (10MB - 8 bytes).
+
+```rust
+pub fn initialize(ctx: Context) -> Result<()> {
+ // [!code word:load_init]
+ // [!code highlight]
+ let account = &mut ctx.accounts.data_account.load_init()?;
+ account.data = [1; 10_485_752];
+ Ok(())
+}
+```
+
+#### Update a Zero Copy Account
+
+Use
+[`load_mut`](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/src/accounts/account_loader.rs#L170-L190)
+when you need mutable access to update an existing zero-copy account:
+
+```rust
+#[derive(Accounts)]
+pub struct Update<'info> {
+ // [!code highlight]
+ #[account(mut)]
+ pub data_account: AccountLoader<'info, Data>,
+}
+```
+
+```rust
+pub fn update(ctx: Context) -> Result<()> {
+ // [!code word:load_mut]
+ // [!code highlight]
+ let account = &mut ctx.accounts.data_account.load_mut()?;
+ account.data = [2; 10232];
+ Ok(())
+}
+```
+
+#### Read a Zero Copy Account
+
+Use
+[`load`](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/src/accounts/account_loader.rs#L153-L167)
+to only read the account data.
+
+```rust
+#[derive(Accounts)]
+pub struct ReadOnly<'info> {
+ pub data_account: AccountLoader<'info, Data>,
+}
+```
+
+```rust
+pub fn read_only(ctx: Context) -> Result<()> {
+ // [!code word:load]
+ // [!code highlight]
+ let account = &ctx.accounts.data_account.load()?;
+ msg!("First 10 bytes: {:?}", &account.data[..10]);
+ Ok(())
+}
+```
+
+## Examples
+
+The examples below demonstrate two approaches for initializing zero-copy
+accounts in Anchor:
+
+1. Using the `init` constraint to initialize the account in a single instruction
+2. Using the `zero` constraint to initialize an account with data greater than
+ 10240 bytes
+
+### Zero Copy
+
+
+
+
+```rust title="lib.rs"
+use anchor_lang::prelude::*;
+
+declare_id!("8B7XpDXjPWodpDUWDSzv4q9k73jB5WdNQXZxNBj1hqw1");
+
+#[program]
+pub mod zero_copy {
+ use super::*;
+ pub fn initialize(ctx: Context) -> Result<()> {
+ let account = &mut ctx.accounts.data_account.load_init()?;
+ account.data = [1; 10232];
+ Ok(())
+ }
+
+ pub fn update(ctx: Context) -> Result<()> {
+ let account = &mut ctx.accounts.data_account.load_mut()?;
+ account.data = [2; 10232];
+ Ok(())
+ }
+}
+
+#[derive(Accounts)]
+pub struct Initialize<'info> {
+ #[account(
+ init,
+ // 10240 bytes is max space to allocate with init constraint
+ space = 8 + 10232,
+ payer = payer,
+ )]
+ pub data_account: AccountLoader<'info, Data>,
+ #[account(mut)]
+ pub payer: Signer<'info>,
+ pub system_program: Program<'info, System>,
+}
+
+#[derive(Accounts)]
+pub struct Update<'info> {
+ #[account(mut)]
+ pub data_account: AccountLoader<'info, Data>,
+}
+
+#[account(zero_copy)]
+pub struct Data {
+ // 10240 bytes - 8 bytes account discriminator
+ pub data: [u8; 10232],
+}
+```
+
+
+
+
+```ts title="test.ts"
+import * as anchor from "@coral-xyz/anchor";
+import { Program } from "@coral-xyz/anchor";
+import { ZeroCopy } from "../target/types/zero_copy";
+
+describe("zero-copy", () => {
+ // Configure the client to use the local cluster.
+ anchor.setProvider(anchor.AnchorProvider.env());
+
+ const program = anchor.workspace.ZeroCopy as Program;
+ const dataAccount = anchor.web3.Keypair.generate();
+
+ it("Is initialized!", async () => {
+ const tx = await program.methods
+ .initialize()
+ .accounts({
+ dataAccount: dataAccount.publicKey,
+ })
+ .signers([dataAccount])
+ .rpc();
+ console.log("Your transaction signature", tx);
+
+ const account = await program.account.data.fetch(dataAccount.publicKey);
+ console.log("Account", account);
+ });
+
+ it("Update!", async () => {
+ const tx = await program.methods
+ .update()
+ .accounts({
+ dataAccount: dataAccount.publicKey,
+ })
+ .rpc();
+ console.log("Your transaction signature", tx);
+
+ const account = await program.account.data.fetch(dataAccount.publicKey);
+ console.log("Account", account);
+ });
+});
+```
+
+
+
+
+### Initialize Large Account
+
+When initializing an account that requires more than 10,240 bytes of space, you
+must split the initialization into two steps:
+
+1. Create the account in a separate instruction invoking the System Program
+2. Initialize the account data in your program instruction
+
+Note that the maximum Solana account size is 10MB (10_485_760 bytes), 8 bytes
+are reserved for the account discriminator.
+
+
+
+
+```rust title="lib.rs"
+use anchor_lang::prelude::*;
+
+declare_id!("CZgWhy3FYPFgKE5v9atSGaiQzbSB7cM38ofwX1XxeCFH");
+
+#[program]
+pub mod zero_copy_two {
+ use super::*;
+ pub fn initialize(ctx: Context) -> Result<()> {
+ let account = &mut ctx.accounts.data_account.load_init()?;
+ account.data = [1; 10_485_752];
+ Ok(())
+ }
+}
+
+#[derive(Accounts)]
+pub struct Initialize<'info> {
+ #[account(zero)]
+ pub data_account: AccountLoader<'info, Data>,
+}
+
+#[account(zero_copy)]
+pub struct Data {
+ // 10240 bytes - 8 bytes account discriminator
+ pub data: [u8; 10_485_752],
+}
+```
+
+
+
+
+```ts title="test.ts"
+import * as anchor from "@coral-xyz/anchor";
+import { Program } from "@coral-xyz/anchor";
+import { ZeroCopyTwo } from "../target/types/zero_copy_two";
+
+describe("zero-copy-two", () => {
+ // Configure the client to use the local cluster.
+ anchor.setProvider(anchor.AnchorProvider.env());
+
+ const program = anchor.workspace.ZeroCopyTwo as Program;
+ const dataAccount = anchor.web3.Keypair.generate();
+
+ it("Is initialized!", async () => {
+ const space = 10_485_760; // 10MB max account size
+ const lamports =
+ await program.provider.connection.getMinimumBalanceForRentExemption(
+ space,
+ );
+
+ // [!code highlight:7]
+ const createAccountInstruction = anchor.web3.SystemProgram.createAccount({
+ fromPubkey: program.provider.publicKey,
+ newAccountPubkey: dataAccount.publicKey,
+ space,
+ lamports,
+ programId: program.programId,
+ });
+
+ // [!code highlight:6]
+ const initializeInstruction = await program.methods
+ .initialize()
+ .accounts({
+ dataAccount: dataAccount.publicKey,
+ })
+ .instruction();
+
+ const transaction = new anchor.web3.Transaction().add(
+ createAccountInstruction,
+ initializeInstruction,
+ );
+
+ const tx = await program.provider.sendAndConfirm(transaction, [
+ dataAccount,
+ ]);
+
+ console.log("Your transaction signature", tx);
+
+ const account = await program.account.data.fetch(dataAccount.publicKey);
+ console.log("Account", account);
+ });
+});
+```
+
+
+
diff --git a/docs/content/docs/index.mdx b/docs/content/docs/index.mdx
new file mode 100644
index 0000000000..c09636b55f
--- /dev/null
+++ b/docs/content/docs/index.mdx
@@ -0,0 +1,35 @@
+---
+title: Introduction
+description:
+ Anchor is a development framework for building secure Solana programs (smart
+ contracts)
+---
+
+import { Download, PanelsTopLeft, Database, Terminal } from "lucide-react";
+
+Anchor is the leading development framework for building Solana programs (smart
+contracts) and simplifies the process of writing, testing, deploying, and
+interacting with Solana programs.
+
+The Anchor framework helps developers build production-ready applications faster
+while reducing potential vulnerabilities through built-in security features.
+
+## Where to start?
+
+
+
+} title='Installation' href='/docs/installation'>
+
+Step-by-step guide to install Anchor framework. Set up your local development
+environment.
+
+
+
+} title='Quickstart' href='/docs/quickstart/solpg'>
+
+Quickstart guide to start building Solana programs with Anchor. Start building
+directly in your browser. No installation required.
+
+
+
+
diff --git a/docs/content/docs/installation.mdx b/docs/content/docs/installation.mdx
new file mode 100644
index 0000000000..cce96f8268
--- /dev/null
+++ b/docs/content/docs/installation.mdx
@@ -0,0 +1,641 @@
+---
+title: Installation
+description:
+ Learn how to install Rust, the Solana CLI, and Anchor Framework on Windows
+ (WSL), Linux, or Mac.
+---
+
+import { Accordion, Accordions } from 'fumadocs-ui/components/accordion';
+
+This section covers the steps to set up your local environment for Solana
+development.
+
+## Install Dependencies
+
+- Windows users must first install WSL (Windows subsystem for Linux) and then
+ install the dependencies specified in the Linux section below.
+- Linux users should first install the dependencies specified in the Linux
+ section below.
+- Mac users should start with the Rust installation instructions below.
+
+
+
+ To develop Solana programs on Windows **you must use
+ [WSL](https://learn.microsoft.com/en-us/windows/wsl/install)** (Windows
+ subsystem for Linux). All additional dependencies must be installed through the
+ Linux terminal.
+
+ Once WSL is installed, install the dependencies specified in the Linux section
+ below before proceeding to install Rust, Solana CLI, and Anchor CLI.
+
+ To install WSL, run the following command in Windows PowerShell:
+
+ ```shell
+ wsl --install
+ ```
+
+ The install process will prompt you to create a default user account.
+
+ 
+
+ By default, WSL installs Ubuntu. You can open a Linux terminal by searching
+ "Ubuntu" in the Search bar.
+
+ 
+
+ If your Ubuntu terminal looks like the image below, you may encounter an issue
+ where `ctrl + v` (paste keyboard shortcut) doesn't work in the terminal.
+
+ 
+
+ If you encounter this issue, open Windows Terminal by searching for "Terminal"
+ in the Search bar.
+
+ 
+
+ Next, close the Windows Terminal and reopen a Linux terminal by searching for
+ Ubuntu again. The terminal should now look like the image below, where
+ `ctrl + v` (paste keyboard shortcut) works.
+
+ 
+
+ If you are using VS Code, the
+ [WSL extension](https://code.visualstudio.com/docs/remote/wsl-tutorial) enables
+ you to use WSL and VS Code together.
+
+ 
+
+ You should then see the following in the VS Code status bar:
+
+ 
+
+ Once you have WSL set up, all additional dependencies must be installed through
+ the Linux terminal. Install the dependencies specified in the Linux section
+ below before proceeding to install Rust, Solana CLI, and Anchor CLI.
+
+
+
+ The following dependencies are required for the Anchor CLI installation.
+
+ First, run the following command:
+
+ ```shell
+ sudo apt-get update
+ ```
+
+ Next, install the following dependencies:
+
+ ```shell
+ sudo apt-get install -y \
+ build-essential \
+ pkg-config \
+ libudev-dev llvm libclang-dev \
+ protobuf-compiler libssl-dev
+ ```
+
+ If you encounter the following error when installing `protobuf-compiler`, make
+ sure you first run `sudo apt-get update`:
+
+ ```
+ Package protobuf-compiler is not available, but is referred to by another package.
+ This may mean that the package is missing, has been obsoleted, or
+ is only available from another source
+ ```
+
+
+
+
+
+
+
+### Install Rust
+
+Solana programs are written in the
+[Rust programming language](https://www.rust-lang.org/).
+
+The recommended installation method for Rust is
+[rustup](https://www.rust-lang.org/tools/install).
+
+Run the following command to install Rust:
+
+```shell
+curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
+```
+
+You should see the following message after the installation completes:
+
+
+
+
+```
+Rust is installed now. Great!
+
+To get started you may need to restart your current shell.
+This would reload your PATH environment variable to include
+Cargo's bin directory ($HOME/.cargo/bin).
+
+To configure your current shell, you need to source
+the corresponding env file under $HOME/.cargo.
+
+This is usually done by running one of the following (note the leading DOT):
+. "$HOME/.cargo/env" # For sh/bash/zsh/ash/dash/pdksh
+source "$HOME/.cargo/env.fish" # For fish
+```
+
+
+
+
+Run the following command to reload your PATH environment variable to include
+Cargo's bin directory:
+
+```shell
+. "$HOME/.cargo/env"
+```
+
+To verify that the installation was successful, check the Rust version:
+
+```shell
+rustc --version
+```
+
+You should see output similar to the following:
+
+```
+rustc 1.80.1 (3f5fd8dd4 2024-08-06)
+```
+
+
+
+
+### Install the Solana CLI
+
+The Solana CLI provides all the tools required to build and deploy Solana
+programs.
+
+Install the Solana CLI tool suite using the official install command:
+
+```shell
+sh -c "$(curl -sSfL https://release.anza.xyz/stable/install)"
+```
+
+You can replace `stable` with the release tag matching the software version of
+your desired release (i.e. `v2.0.3`), or use one of the three symbolic channel
+names: `stable`, `beta`, or `edge`.
+
+If it is your first time installing the Solana CLI, you may see the following
+message prompting you to add a PATH environment variable:
+
+```
+Close and reopen your terminal to apply the PATH changes or run the following in your existing shell:
+
+export PATH="/Users/test/.local/share/solana/install/active_release/bin:$PATH"
+```
+
+
+
+
+If you are using a Linux or WSL terminal, you can add the PATH environment
+variable to your shell configuration file by running the command logged from the
+installation or by restarting your terminal.
+
+```shell
+export PATH="$HOME/.local/share/solana/install/active_release/bin:$PATH"
+```
+
+
+
+
+If you're on Mac using `zsh`, running the default `export PATH` command logged
+from the installation does not persist once you close your terminal.
+
+Instead, you can add the PATH to your shell configuration file by running the
+following command:
+
+```shell
+echo 'export PATH="$HOME/.local/share/solana/install/active_release/bin:$PATH"' >> ~/.zshrc
+```
+
+Then run the following command to refresh the terminal session or restart your
+terminal.
+
+```shell
+source ~/.zshrc
+```
+
+
+
+
+To verify that the installation was successful, check the Solana CLI version:
+
+```shell
+solana --version
+```
+
+You should see output similar to the following:
+
+```
+solana-cli 1.18.22 (src:9efdd74b; feat:4215500110, client:Agave)
+```
+
+You can view all available versions on the
+[Agave Github repo](https://github.com/anza-xyz/agave/releases).
+
+
+
+Agave is the validator client from [Anza](https://www.anza.xyz/), formerly known
+as Solana Labs validator client.
+
+
+
+To later update the Solana CLI to the latest version, you can use the following
+command:
+
+```shell
+agave-install update
+```
+
+
+
+
+### Install Anchor CLI
+
+Anchor is a framework for developing Solana
+programs. The Anchor framework leverages Rust macros to simplify the process of
+writing Solana programs.
+
+There are two ways to install the Anchor CLI and tooling:
+
+1. Using Anchor Version Manager (AVM) - is the **recommended installation**
+ method since it simplifies updating Anchor versions in the future
+2. Without AVM - this requires more a manual process to update Anchor versions
+ later
+
+
+
+
+The Anchor version manager (AVM) allows you to install and manage different
+Anchor versions on your system, including more easily updating Anchor versions
+in the future.
+
+Install AVM with the following command:
+
+```shell
+cargo install --git https://github.com/coral-xyz/anchor avm --force
+```
+
+Test to ensure AVM was installed and is accessible:
+
+```shell
+avm --version
+```
+
+Install the latest version of Anchor CLI using AVM:
+
+```shell
+avm install latest
+avm use latest
+```
+
+Or install a specific version of the Anchor CLI by declaring which version you
+want to install:
+
+```shell
+avm install 0.30.1
+avm use 0.30.1
+```
+
+> Don't forget to run the `avm use` command to declare which Anchor CLI version
+> should be used on your system.
+>
+> - If you installed the `latest` version, run `avm use latest`.
+> - If you installed the version `0.30.1`, run `avm use 0.30.1`.
+
+
+
+
+
+Install a specific version of the Anchor CLI with the following command:
+
+```shell
+cargo install --git https://github.com/coral-xyz/anchor --tag v0.30.1 anchor-cli
+```
+
+
+
+
+You may see the following warning during installation. However, it does not
+affect the installation process.
+
+
+
+
+```
+warning: unexpected `cfg` condition name: `nightly`
+ --> cli/src/lib.rs:1:13
+ |
+1 | #![cfg_attr(nightly, feature(proc_macro_span))]
+ | ^^^^^^^
+ |
+ = help: expected names are: `clippy`, `debug_assertions`, `doc`, `docsrs`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows`
+ = help: consider using a Cargo feature instead
+ = help: or consider adding in `Cargo.toml` the `check-cfg` lint config for the lint:
+ [lints.rust]
+ unexpected_cfgs = { level = "warn", check-cfg = ['cfg(nightly)'] }
+ = help: or consider adding `println!("cargo::rustc-check-cfg=cfg(nightly)");` to the top of the `build.rs`
+ = note: see for more information about checking conditional configuration
+ = note: `#[warn(unexpected_cfgs)]` on by default
+
+warning: `anchor-cli` (lib) generated 1 warning
+```
+
+
+
+
+To verify that the installation was successful, check the Anchor CLI version:
+
+```shell
+anchor --version
+```
+
+You should see output similar to the following:
+
+```
+anchor-cli 0.30.1
+```
+
+When installing the Anchor CLI on Linux or WSL, you may encounter this error:
+
+```
+error: could not exec the linker cc = note: Permission denied (os error 13)
+```
+
+If you see this error message, follow these steps:
+
+1. Install the dependencies listed in the Linux section at the top of this page.
+2. Retry installing the Anchor CLI.
+
+#### Node.js and Yarn
+
+Node.js and Yarn are required to run the default Anchor project test file
+(TypeScript) created with the `anchor init` command. (Rust test template is also
+available using `anchor init --test-template rust`)
+
+
+
+
+The recommended way to install node is using
+[Node Version Manager (nvm)](https://github.com/nvm-sh/nvm).
+
+Install nvm using the following command:
+
+```shell
+curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/master/install.sh | bash
+```
+
+Restart your terminal and verify that nvm is installed:
+
+```shell
+command -v nvm
+```
+
+Next, use `nvm` to install node:
+
+```shell
+nvm install node
+```
+
+To verify that the installation was successful, check the Node version:
+
+```
+node --version
+```
+
+You should see output similar to the following:
+
+```
+v22.7.0
+```
+
+
+
+
+Install Yarn:
+
+```shell
+npm install --global yarn
+```
+
+To verify that the installation was successful, check the Yarn version:
+
+```
+yarn --version
+```
+
+You should the following output:
+
+```
+1.22.1
+```
+
+
+
+
+When running `anchor build`, if you encounter `error: not a directory` similar
+following:
+
+```
+error: not a directory: '.../solana-release/bin/sdk/sbf/dependencies/platform-tools/rust/lib'
+```
+
+Try these solutions:
+
+1. Force install using the following command:
+
+```shell
+cargo build-sbf --force-tools-install
+```
+
+2. If the above doesn't work, clear the Solana cache:
+
+```shell
+rm -rf ~/.cache/solana/*
+```
+
+After applying either solution, attempt to run `anchor build` again.
+
+If you are on Linux or WSL and encounter the following errors when running
+`anchor test` after creating a new Anchor project, it's may be due to missing
+Node.js or Yarn:
+
+```
+Permission denied (os error 13)
+```
+
+```
+No such file or directory (os error 2)
+```
+
+
+
+
+## Solana CLI Basics
+
+This section will walk through some common Solana CLI commands to get you
+started.
+
+
+
+
+### Solana Config
+
+To see your current config:
+
+```shell
+solana config get
+```
+
+You should see output similar to the following:
+
+```
+Config File: /Users/test/.config/solana/cli/config.yml
+RPC URL: https://api.mainnet-beta.solana.com
+WebSocket URL: wss://api.mainnet-beta.solana.com/ (computed)
+Keypair Path: /Users/test/.config/solana/id.json
+Commitment: confirmed
+```
+
+The RPC URL and Websocket URL specific the Solana cluster the CLI will make
+requests to. By default this will be mainnet-beta.
+
+You can update the Solana CLI cluster using the following commands:
+
+```
+solana config set --url mainnet-beta
+solana config set --url devnet
+solana config set --url localhost
+solana config set --url testnet
+```
+
+You can also use the following short options:
+
+```
+solana config set -um # For mainnet-beta
+solana config set -ud # For devnet
+solana config set -ul # For localhost
+solana config set -ut # For testnet
+```
+
+The Keypair Path specifies the location of the default wallet used by the Solana
+CLI (to pay transaction fees and deploy programs). The default path is
+`~/.config/solana/id.json`. The next step walks through how to generate a
+keypair at the default location.
+
+
+
+
+### Create Wallet
+
+To interact with the Solana network using the Solana CLI, you need a Solana
+wallet funded with SOL.
+
+To generate a keypair at the default Keypair Path, run the following command:
+
+```shell
+solana-keygen new
+```
+
+You should see output similar to the following:
+
+```
+Generating a new keypair
+
+For added security, enter a BIP39 passphrase
+
+NOTE! This passphrase improves security of the recovery seed phrae NOT the
+keypair file itself, which is stored as insecure plain text
+
+BIP39 Passphrase (empty for none):
+
+Wrote new keypair to /Users/test/.config/solana/id.json
+===========================================================================
+pubkey: 8dBTPrjnkXyuQK3KDt9wrZBfizEZijmmUQXVHpFbVwGT
+===========================================================================
+Save this seed phrase and your BIP39 passphrase to recover your new keypair:
+cream bleak tortoise ocean nasty game gift forget fancy salon mimic amazing
+===========================================================================
+```
+
+
+
+If you already have a file system wallet saved at the default location, this
+command will **NOT** override it unless you explicitly force override using the
+`--force` flag.
+
+
+
+Once a keypair is generated, you can get the address (public key) of the keypair
+with the following command:
+
+```shell
+solana address
+```
+
+
+
+
+### Airdrop SOL
+
+Once you've set up your local wallet, request an airdrop of SOL to fund your
+wallet. You need SOL to pay for transaction fees and to deploy programs.
+
+Set your cluster to the devnet:
+
+```shell
+solana config set -ud
+```
+
+Then request an airdrop of devnet SOL:
+
+```shell
+solana airdrop 2
+```
+
+To check your wallet's SOL balance, run the following command:
+
+```shell
+solana balance
+```
+
+
+
+The `solana airdrop` command is currently limited to 5 SOL per request on
+devnet. Errors are likely due to rate limits.
+
+Alternatively, you can get devnet SOL using the
+[Solana Web Faucet](https://faucet.solana.com).
+
+
+
+
+
+### Run Local Validator
+
+The Solana CLI comes with the
+[test validator](https://docs.solanalabs.com/cli/examples/test-validator)
+built-in. Running a local validator will allow you to deploy and test your
+programs locally.
+
+In a separate terminal, run the following command to start a local validator:
+
+```shell
+solana-test-validator
+```
+
+Make sure to update the Solana CLI config to localhost before commands.
+
+```shell
+solana config set -ul
+```
+
+
+
diff --git a/docs/content/docs/meta.json b/docs/content/docs/meta.json
new file mode 100644
index 0000000000..76e6143359
--- /dev/null
+++ b/docs/content/docs/meta.json
@@ -0,0 +1,22 @@
+{
+ "title": "docs",
+ "description": "The description of root folder",
+ "pages": [
+ "---Getting Started---",
+ "installation",
+ "quickstart",
+
+ "---Core Concepts---",
+ "basics",
+ "clients",
+ "features",
+
+ "---SPL Tokens---",
+ "tokens",
+
+ "---References---",
+ "references",
+ "updates",
+ "contribution"
+ ]
+}
diff --git a/docs/content/docs/quickstart/index.mdx b/docs/content/docs/quickstart/index.mdx
new file mode 100644
index 0000000000..cefe81ed07
--- /dev/null
+++ b/docs/content/docs/quickstart/index.mdx
@@ -0,0 +1,7 @@
+---
+title: Quickstart
+description:
+ Learn how to quickly get started with Anchor, the leading Solana smart
+ contract development framework.
+index: true
+---
diff --git a/docs/content/docs/quickstart/local.mdx b/docs/content/docs/quickstart/local.mdx
new file mode 100644
index 0000000000..6a9b857ac1
--- /dev/null
+++ b/docs/content/docs/quickstart/local.mdx
@@ -0,0 +1,410 @@
+---
+title: Local Development
+description:
+ Learn how to build Solana programs using the Anchor framework on your local
+ machine.
+---
+
+The Anchor framework is a tool that simplifies the process of building Solana
+programs. Whether you're new to blockchain development or an experienced
+programmer, Anchor simplifies the process of writing, testing, and deploying
+Solana programs.
+
+In this section, we'll walk through:
+
+- Creating a new Anchor project
+- Building and testing your program
+- Deploying to Solana clusters
+- Understanding the project file structure
+
+## Prerequisites
+
+For detailed installation instructions, visit the
+[installation](/docs/installation) page.
+
+Before you begin, ensure you have the following installed:
+
+- Rust: The programming language for building Solana programs.
+- Solana CLI: Command-line tool for Solana development.
+- Anchor CLI: Command-line tool for the Anchor framework.
+
+To verify Anchor CLI installation, open your terminal and run:
+
+```shell filename="Terminal"
+anchor --version
+```
+
+Expected output:
+
+```shell filename="Terminal"
+anchor-cli 0.30.1
+```
+
+## Getting Started
+
+This section covers the basic steps to create, build, and test your first local
+Anchor program.
+
+
+
+
+
+### Create a new Project
+
+To start a new project, use the `anchor init` command followed by your project's
+name. This command creates a new directory with the specified name and sets up a
+default program and test file.
+
+```shell filename="Terminal"
+anchor init my-program
+```
+
+Navigate to the new project directory and open it in your code editor.
+
+```shell filename="Terminal" copy
+cd my-project
+```
+
+The default Anchor program is located at `/programs/my-project/src/lib.rs`.
+
+
+
+
+The value in the `declare_id!` macro is the program ID, a unique identifier for
+your program.
+
+By default, it is the public key of the keypair generated in
+`/target/deploy/my_project-keypair.json`.
+
+```rust filename="lib.rs"
+use anchor_lang::prelude::*;
+
+declare_id!("3ynNB373Q3VAzKp7m4x238po36hjAGFXFJB4ybN2iTyg");
+
+#[program]
+pub mod my_project {
+ use super::*;
+
+ pub fn initialize(ctx: Context) -> Result<()> {
+ msg!("Greetings from: {:?}", ctx.program_id);
+ Ok(())
+ }
+}
+
+#[derive(Accounts)]
+pub struct Initialize {}
+```
+
+
+
+
+The default Typescript test file is located at `/tests/my-project.ts`.
+
+
+
+
+This file demonstrates how to invoke the default program's `initialize`
+instruction in Typescript.
+
+```ts filename="my-project.ts"
+import * as anchor from "@coral-xyz/anchor";
+import { Program } from "@coral-xyz/anchor";
+import { MyProject } from "../target/types/my_project";
+
+describe("my-project", () => {
+ // Configure the client to use the local cluster.
+ anchor.setProvider(anchor.AnchorProvider.env());
+
+ const program = anchor.workspace.MyProject as Program;
+
+ it("Is initialized!", async () => {
+ // Add your test here.
+ const tx = await program.methods.initialize().rpc();
+ console.log("Your transaction signature", tx);
+ });
+});
+```
+
+
+
+
+If you prefer Rust for testing, initialize your project with the
+`--test-template rust` flag.
+
+```shell
+anchor init --test-template rust my-program
+```
+
+The Rust test file will be at `/tests/src/test_initialize.rs`.
+
+
+
+
+```rust filename="test_initialize.rs"
+use std::str::FromStr;
+
+use anchor_client::{
+ solana_sdk::{
+ commitment_config::CommitmentConfig, pubkey::Pubkey, signature::read_keypair_file,
+ },
+ Client, Cluster,
+};
+
+#[test]
+fn test_initialize() {
+ let program_id = "3ynNB373Q3VAzKp7m4x238po36hjAGFXFJB4ybN2iTyg";
+ let anchor_wallet = std::env::var("ANCHOR_WALLET").unwrap();
+ let payer = read_keypair_file(&anchor_wallet).unwrap();
+
+ let client = Client::new_with_options(Cluster::Localnet, &payer, CommitmentConfig::confirmed());
+ let program_id = Pubkey::from_str(program_id).unwrap();
+ let program = client.program(program_id).unwrap();
+
+ let tx = program
+ .request()
+ .accounts(my_program::accounts::Initialize {})
+ .args(my_program::instruction::Initialize {})
+ .send()
+ .expect("");
+
+ println!("Your transaction signature {}", tx);
+}
+```
+
+
+
+
+
+
+
+### Build the Program
+
+Build the program by running `anchor build`.
+
+```shell filename="Terminal" copy
+anchor build
+```
+
+The compiled program will be at `/target/deploy/my_project.so`. The content of
+this file is what gets stored on the Solana network (as an executable account)
+when you deploy your program.
+
+
+
+
+### Test the Program
+
+To test the program, run `anchor test`.
+
+```shell filename="Terminal" copy
+anchor test
+```
+
+By default, the `Anchor.toml` config file specifies the `localnet` cluster. When
+developing on `localnet`, `anchor test` will automatically:
+
+1. Start a local Solana validator
+2. Build and deploy your program to the local cluster
+3. Run the tests in the `tests` folder
+4. Stop the local Solana validator
+
+Alternatively, you can manually start a local Solana validator and run tests
+against it. This is useful if you want to keep the validator running while you
+iterate on your program. It allows you to inspect accounts and transaction logs
+on the [Solana Explorer](https://explorer.solana.com/?cluster=custom) while
+developing locally.
+
+Open a new terminal and start a local Solana validator by running the
+`solana-test-validator` command.
+
+```shell filename="Terminal" copy
+solana-test-validator
+```
+
+In a separate terminal, run the tests against the local cluster. Use the
+`--skip-local-validator` flag to skip starting the local validator since it's
+already running.
+
+```shell filename="Terminal" copy
+anchor test --skip-local-validator
+```
+
+
+
+
+### Deploy to Devnet
+
+By default, the `Anchor.toml` config file in an Anchor project specifies the
+localnet cluster.
+
+```toml filename="Anchor.toml" {14}
+[toolchain]
+
+[features]
+resolution = true
+skip-lint = false
+
+[programs.localnet]
+my_program = "3ynNB373Q3VAzKp7m4x238po36hjAGFXFJB4ybN2iTyg"
+
+[registry]
+url = "https://api.apr.dev"
+
+[provider]
+cluster = "Localnet"
+wallet = "~/.config/solana/id.json"
+
+[scripts]
+test = "yarn run ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts"
+```
+
+To deploy your program to devnet, change the `cluster` value to `Devnet`.
+
+
+
+Note that deploying to devnet requires your wallet to have enough SOL to cover
+deployment cost. You can get devnet SOL using the
+[Web Faucet](https://faucet.solana.com/).
+
+
+
+```diff
+-cluster = "Localnet"
++cluster = "Devnet"
+```
+
+```toml filename="Anchor.toml"
+[provider]
+cluster = "Devnet"
+wallet = "~/.config/solana/id.json"
+```
+
+Now when you run `anchor deploy`, your program will be deployed to the devnet
+cluster. The `anchor test` command will also use the cluster specified in the
+`Anchor.toml` file.
+
+```shell
+anchor deploy
+```
+
+To deploy to mainnet, simply update the `Anchor.toml` file to specify the
+mainnet cluster.
+
+```toml filename="Anchor.toml"
+[provider]
+cluster = "Mainnet"
+wallet = "~/.config/solana/id.json"
+```
+
+
+
+
+### Update the Program
+
+Solana programs can be updated by redeploying the program to the same program
+ID.
+
+To update a program, simply make changes to your program's code and run the
+`anchor build` command to generated an updated `.so` file.
+
+```shell
+anchor build
+```
+
+Then run the `anchor deploy` command to redeploy the updated program.
+
+```shell
+anchor deploy
+```
+
+
+
+
+### Close the Program
+
+To reclaim the SOL allocated to a program account, you can close your Solana
+program.
+
+To close a program, use the `solana program close ` command. For
+example:
+
+```shell
+solana program close 3ynNB373Q3VAzKp7m4x238po36hjAGFXFJB4ybN2iTyg --bypass-warning
+```
+
+Note that once a program is closed, the program ID cannot be reused to deploy a
+new program.
+
+
+
+
+
+## Project File Structure
+
+Below is an overview of default file structure in an Anchor workspace:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+### Programs Folder
+
+The `/programs` directory contains your project's Anchor programs. A single
+workspace can contain multiple programs.
+
+### Tests Folder
+
+The `/tests` directory contains test files for your project. A default test file
+is created for you when you create your project.
+
+### Target Folder
+
+The `/target` directory contains build outputs. The main subfolders include:
+
+- `/deploy`: Contains the keypair and program binary for your programs.
+- `/idl`: Contains the JSON IDL for your programs.
+- `/types`: Contains the TypeScript type for the IDL.
+
+### Anchor.toml File
+
+The `Anchor.toml` file configures workspace settings for your project.
+
+### .anchor Folder
+
+Includes a `program-logs` file that contains transaction logs from the last run
+of test files.
+
+### App Folder
+
+The `/app` folder is an empty folder that can be optionally used for your
+frontend code.
diff --git a/docs/content/docs/quickstart/meta.json b/docs/content/docs/quickstart/meta.json
new file mode 100644
index 0000000000..74e1fd3149
--- /dev/null
+++ b/docs/content/docs/quickstart/meta.json
@@ -0,0 +1,4 @@
+{
+ "title": "Quickstart",
+ "pages": ["solpg", "local"]
+}
diff --git a/docs/content/docs/quickstart/solpg.mdx b/docs/content/docs/quickstart/solpg.mdx
new file mode 100644
index 0000000000..de16677b9d
--- /dev/null
+++ b/docs/content/docs/quickstart/solpg.mdx
@@ -0,0 +1,462 @@
+---
+title: Solana Playground
+description:
+ Learn how to build your first Solana program using the Anchor framework
+ directly in your browser.
+---
+
+In this section, we'll build, deploy, and test a simple Solana program using the
+Anchor framework. By the end, you'll have deployed your first program to the
+Solana blockchain!
+
+Solana Playground (Solpg) is a browser-based development environment that allows
+you to quickly develop, deploy, and test Solana programs!
+
+## Getting Started
+
+Open a new tab in your web browser and navigate to https://beta.solpg.io/.
+
+
+
+
+### Create Playground Wallet
+
+If you're new to Solana Playground, the first step is to create your Playground
+Wallet. This wallet will allow you to interact with the Solana network right
+from your browser.
+
+#### Step 1. Connect to Playground
+
+Click the "Not connected" button at the bottom left of the screen.
+
+
+
+#### Step 2. Create Your Wallet
+
+You'll see an option to save your wallet's keypair. Optionally, save your
+wallet's keypair for backup and then click "Continue".
+
+
+
+You should now see your wallet's address, SOL balance, and connected cluster
+(devnet by default) at the bottom of the window.
+
+
+
+
+ Your Playground Wallet will be saved in your browser's local storage. Clearing
+ your browser cache will remove your saved wallet.
+
+
+Some definitions you may find helpful:
+
+- _wallet address_: a public key that serves as your unique identity on the
+ Solana blockchain. Just like an email address is used to receive emails, your
+ wallet address is used to receive SOL.
+- _connection cluster_: a network of Solana nodes (computers running Solana
+ validator client). Devnet is the cluster for developer testing.
+
+
+
+
+### Get Devnet SOL
+
+Before we start building, we first need some devnet SOL.
+
+From a developer's perspective, SOL is required for two main use cases:
+
+- To create accounts on the network where we store data or deploy programs
+- To pay for transaction fees when we interact with the network
+
+Below are two methods to fund your wallet with devnet SOL:
+
+#### Option 1: Using the Playground Terminal
+
+To fund your Playground wallet with devnet SOL. In the Playground terminal, run:
+
+```shell filename="Terminal"
+solana airdrop 5
+```
+
+#### Option 2: Using the Devnet Faucet
+
+If the airdrop command doesn't work (due to rate limits or errors), you can use
+the [Web Faucet](https://faucet.solana.com/).
+
+- Enter your wallet address (found at the bottom of the Playground screen) and
+ select an amount
+- Click "Confirm Airdrop" to receive your devnet SOL
+
+
+
+
+
+
+
+### Create Anchor Project
+
+First, open https://beta.solpg.io in a new browser tab.
+
+- Click the "Create a new project" button on the left-side panel.
+
+- Enter a project name, select Anchor as the framework, then click the "Create"
+ button.
+
+
+
+You'll see a new project created with the program code in the `src/lib.rs` file.
+
+```rust filename="lib.rs"
+use anchor_lang::prelude::*;
+
+// This is your program's public key and it will update
+// automatically when you build the project.
+declare_id!("11111111111111111111111111111111");
+
+#[program]
+mod hello_anchor {
+ use super::*;
+ pub fn initialize(ctx: Context, data: u64) -> Result<()> {
+ ctx.accounts.new_account.data = data;
+ msg!("Changed data to: {}!", data); // Message will show up in the tx logs
+ Ok(())
+ }
+}
+
+#[derive(Accounts)]
+pub struct Initialize<'info> {
+ // We must specify the space in order to initialize an account.
+ // First 8 bytes are default account discriminator,
+ // next 8 bytes come from NewAccount.data being type u64.
+ // (u64 = 64 bits unsigned integer = 8 bytes)
+ #[account(init, payer = signer, space = 8 + 8)]
+ pub new_account: Account<'info, NewAccount>,
+ #[account(mut)]
+ pub signer: Signer<'info>,
+ pub system_program: Program<'info, System>,
+}
+
+#[account]
+pub struct NewAccount {
+ data: u64
+}
+```
+
+
+
+
+For now, we'll only cover the high-level overview of the program code:
+
+- The `declare_id!` macro specifies the on-chain address of your program. It
+ will be automatically updated when we build the program in the next step.
+
+ ```rust
+ declare_id!("11111111111111111111111111111111");
+ ```
+
+- The `#[program]` attribute annotates a module containing functions that
+ represent the program's instructions.
+
+ ```rust
+ #[program]
+ mod hello_anchor {
+ use super::*;
+ pub fn initialize(ctx: Context, data: u64) -> Result<()> {
+ ctx.accounts.new_account.data = data;
+ msg!("Changed data to: {}!", data); // Message will show up in the tx logs
+ Ok(())
+ }
+ }
+ ```
+
+ In this example, the `initialize` instruction takes two parameters:
+
+ 1. `ctx: Context` - Provides access to the accounts required for
+ this instruction, as specified in the `Initialize` struct.
+ 2. `data: u64` - An instruction parameter that will be passed in when the
+ instruction is invoked.
+
+ The function body sets the `data` field of `new_account` to the provided
+ `data` argument and then prints a message to the program logs.
+
+- The `#[derive(Accounts)]` macro is used to annotate a struct that specifies
+ the accounts required for a particular instruction, where each field
+ represents a separate account.
+
+ The field types (ex. `Signer<'info>`) and constraints (ex. `#[account(mut)]`)
+ are used by Anchor to automatically handle common security checks related to
+ account validation.
+
+ ```rust
+ #[derive(Accounts)]
+ pub struct Initialize<'info> {
+ #[account(init, payer = signer, space = 8 + 8)]
+ pub new_account: Account<'info, NewAccount>,
+ #[account(mut)]
+ pub signer: Signer<'info>,
+ pub system_program: Program<'info, System>,
+ }
+ ```
+
+- The `#[account]` attribute is used to annotate a struct that represents the
+ data structure of an account created and owned by the program.
+
+ ```rust
+ #[account]
+ pub struct NewAccount {
+ data: u64
+ }
+ ```
+
+
+
+
+
+
+### Build and Deploy Program
+
+To build the program, simply run `build` in the terminal.
+
+```shell filename="Terminal"
+build
+```
+
+Notice that the address in `declare_id!()` has been updated. This is your
+program's on-chain address.
+
+
+
+
+```shell filename="Terminal"
+$ build
+Building...
+Build successful. Completed in 1.46s.
+```
+
+
+
+
+Once the program is built, run `deploy` in the terminal to deploy the program to
+the network (devnet by default). To deploy a program, SOL must be allocated to
+the on-chain account that stores the program.
+
+Before deployment, ensure you have enough SOL. You can get devnet SOL by either
+running `solana airdrop 5` in the Playground terminal or using the
+[Web Faucet](https://faucet.solana.com/).
+
+```shell filename="Terminal"
+deploy
+```
+
+
+
+
+```shell filename="Terminal"
+$ deploy
+Deploying... This could take a while depending on the program size and network conditions.
+Warning: 1 transaction not confirmed, retrying...
+Deployment successful. Completed in 19s.
+```
+
+
+
+
+Alternatively, you can also use the `Build` and `Deploy` buttons on the
+left-side panel.
+
+
+
+Once the program is deployed, you can now invoke its instructions.
+
+
+
+### Test Program
+
+Included with the starter code is a test file found in `tests/anchor.test.ts`.
+This file demonstrates how to invoke the `initialize` instruction on the starter
+program from the client.
+
+```ts filename="anchor.test.ts"
+// No imports needed: web3, anchor, pg and more are globally available
+
+describe("Test", () => {
+ it("initialize", async () => {
+ // Generate keypair for the new account
+ const newAccountKp = new web3.Keypair();
+
+ // Send transaction
+ const data = new BN(42);
+ const txHash = await pg.program.methods
+ .initialize(data)
+ .accounts({
+ newAccount: newAccountKp.publicKey,
+ signer: pg.wallet.publicKey,
+ systemProgram: web3.SystemProgram.programId,
+ })
+ .signers([newAccountKp])
+ .rpc();
+ console.log(`Use 'solana confirm -v ${txHash}' to see the logs`);
+
+ // Confirm transaction
+ await pg.connection.confirmTransaction(txHash);
+
+ // Fetch the created account
+ const newAccount = await pg.program.account.newAccount.fetch(
+ newAccountKp.publicKey,
+ );
+
+ console.log("On-chain data is:", newAccount.data.toString());
+
+ // Check whether the data on-chain is equal to local 'data'
+ assert(data.eq(newAccount.data));
+ });
+});
+```
+
+To run the test file once the program is deployed, run `test` in the terminal.
+
+```shell filename="Terminal"
+test
+```
+
+You should see an output indicating that the test passed successfully.
+
+
+
+
+```shell filename="Terminal"
+$ test
+Running tests...
+ hello_anchor.test.ts:
+ hello_anchor
+ Use 'solana confirm -v 3TewJtiUz1EgtT88pLJHvKFzqrzDNuHVi8CfD2mWmHEBAaMfC5NAaHdmr19qQYfTiBace6XUmADvR4Qrhe8gH5uc' to see the logs
+ On-chain data is: 42
+ ✔ initialize (961ms)
+ 1 passing (963ms)
+```
+
+
+
+
+You can also use the `Test` button on the left-side panel.
+
+
+
+You can then view the transaction logs by running the `solana confirm -v`
+command and specifying the transaction hash (signature) from the test output:
+
+```shell filename="Terminal"
+solana confirm -v [TxHash]
+```
+
+For example:
+
+```shell filename="Terminal"
+solana confirm -v 3TewJtiUz1EgtT88pLJHvKFzqrzDNuHVi8CfD2mWmHEBAaMfC5NAaHdmr19qQYfTiBace6XUmADvR4Qrhe8gH5uc
+```
+
+
+
+
+```shell filename="Terminal" {29-35}
+$ solana confirm -v 3TewJtiUz1EgtT88pLJHvKFzqrzDNuHVi8CfD2mWmHEBAaMfC5NAaHdmr19qQYfTiBace6XUmADvR4Qrhe8gH5uc
+RPC URL: https://api.devnet.solana.com
+Default Signer: Playground Wallet
+Commitment: confirmed
+
+Transaction executed in slot 308150984:
+ Block Time: 2024-06-25T12:52:05-05:00
+ Version: legacy
+ Recent Blockhash: 7AnZvY37nMhCybTyVXJ1umcfHSZGbngnm4GZx6jNRTNH
+ Signature 0: 3TewJtiUz1EgtT88pLJHvKFzqrzDNuHVi8CfD2mWmHEBAaMfC5NAaHdmr19qQYfTiBace6XUmADvR4Qrhe8gH5uc
+ Signature 1: 3TrRbqeMYFCkjsxdPExxBkLAi9SB2pNUyg87ryBaTHzzYtGjbsAz9udfT9AkrjSo1ZjByJgJHBAdRVVTZv6B87PQ
+ Account 0: srw- 3z9vL1zjN6qyAFHhHQdWYRTFAcy69pJydkZmSFBKHg1R (fee payer)
+ Account 1: srw- c7yy8zdP8oeZ2ewbSb8WWY2yWjDpg3B43jk3478Nv7J
+ Account 2: -r-- 11111111111111111111111111111111
+ Account 3: -r-x 2VvQ11q8xrn5tkPNyeraRsPaATdiPx8weLAD8aD4dn2r
+ Instruction 0
+ Program: 2VvQ11q8xrn5tkPNyeraRsPaATdiPx8weLAD8aD4dn2r (3)
+ Account 0: c7yy8zdP8oeZ2ewbSb8WWY2yWjDpg3B43jk3478Nv7J (1)
+ Account 1: 3z9vL1zjN6qyAFHhHQdWYRTFAcy69pJydkZmSFBKHg1R (0)
+ Account 2: 11111111111111111111111111111111 (2)
+ Data: [175, 175, 109, 31, 13, 152, 155, 237, 42, 0, 0, 0, 0, 0, 0, 0]
+ Status: Ok
+ Fee: ◎0.00001
+ Account 0 balance: ◎5.47001376 -> ◎5.46900152
+ Account 1 balance: ◎0 -> ◎0.00100224
+ Account 2 balance: ◎0.000000001
+ Account 3 balance: ◎0.00139896
+ Log Messages:
+ Program 2VvQ11q8xrn5tkPNyeraRsPaATdiPx8weLAD8aD4dn2r invoke [1]
+ Program log: Instruction: Initialize
+ Program 11111111111111111111111111111111 invoke [2]
+ Program 11111111111111111111111111111111 success
+ Program log: Changed data to: 42!
+ Program 2VvQ11q8xrn5tkPNyeraRsPaATdiPx8weLAD8aD4dn2r consumed 5661 of 200000 compute units
+ Program 2VvQ11q8xrn5tkPNyeraRsPaATdiPx8weLAD8aD4dn2r success
+
+Confirmed
+```
+
+
+
+
+Alternatively, you can view the transaction details on
+[SolanaFM](https://solana.fm/) or
+[Solana Explorer](https://explorer.solana.com/?cluster=devnet) by searching for
+the transaction signature (hash).
+
+
+ Reminder to update the cluster (network) connection on the Explorer you are
+ using to match Solana Playground. Solana Playground's default cluster is
+ devnet.
+
+
+### Close Program
+
+Lastly, the SOL allocated to the on-chain program can be fully recovered by
+closing the program.
+
+You can close a program by running the following command and specifying the
+program address found in `declare_id!()`:
+
+```shell filename="Terminal"
+solana program close [ProgramID]
+```
+
+For example:
+
+```shell filename="Terminal"
+solana program close 2VvQ11q8xrn5tkPNyeraRsPaATdiPx8weLAD8aD4dn2r
+```
+
+
+
+
+```shell filename="Terminal"
+$ solana program close 2VvQ11q8xrn5tkPNyeraRsPaATdiPx8weLAD8aD4dn2r
+Closed Program Id 2VvQ11q8xrn5tkPNyeraRsPaATdiPx8weLAD8aD4dn2r, 2.79511512 SOL reclaimed
+```
+
+
+
+
+
+
+
+Only the upgrade authority of the program can close it. The upgrade authority is
+set when the program is deployed, and it's the only account with permission to
+modify or close the program. If the upgrade authority is revoked, then the
+program becomes immutable and can never be closed or upgraded.
+
+When deploying programs on Solana Playground, your Playground wallet is the
+upgrade authority for all your programs.
+
+
+
+
+Congratulations! You've just built and deployed your first Solana program using
+the Anchor framework!
+
+
+
diff --git a/docs/content/docs/references/account-constraints.mdx b/docs/content/docs/references/account-constraints.mdx
new file mode 100644
index 0000000000..8717f5b737
--- /dev/null
+++ b/docs/content/docs/references/account-constraints.mdx
@@ -0,0 +1,396 @@
+---
+title: Account Constraints
+description: Anchor Account Constraints Examples
+---
+
+Minimal reference examples for Anchor account
+[constraints](https://docs.rs/anchor-lang/latest/anchor_lang/derive.Accounts.html).
+
+See the account constraints
+[source code](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/syn/src/codegen/accounts/constraints.rs)
+for implementation details.
+
+## Normal Constraints
+
+### `#[account(signer)]`
+
+```rust title="attribute"
+#[account(signer)]
+#[account(signer @ )]
+```
+
+Description: Checks the given account signed the transaction. Consider using the
+Signer type if you would only have this constraint on the account.
+Examples: [Github](https://github.com/solana-developers/anchor-examples/tree/main/account-constraints/signer)
+|
+[Solpg](https://beta.solpg.io/https://github.com/solana-developers/anchor-examples/tree/main/account-constraints/signer)
+
+```rust title="attribute"
+#[account(signer)]
+#[account(signer @ )]
+```
+
+### `#[account(mut)]`
+
+Description: Checks the given account is mutable. Makes anchor persist any state
+changes.
+Examples: [Github](https://github.com/solana-developers/anchor-examples/tree/main/account-constraints/mut)
+|
+[Solpg](https://beta.solpg.io/https://github.com/solana-developers/anchor-examples/tree/main/account-constraints/mut)
+
+```rust title="attribute"
+#[account(mut)]
+#[account(mut @ )]
+```
+
+### `#[account(init)]`
+
+Description: Creates the account via a CPI to the system program and initializes
+it (sets its account discriminator).
+Examples: [Github](https://github.com/solana-developers/anchor-examples/tree/main/account-constraints/init)
+|
+[Solpg](https://beta.solpg.io/https://github.com/solana-developers/anchor-examples/tree/main/account-constraints/init)
+
+```rust title="attribute"
+#[account(
+ init,
+ payer = ,
+ space =
+)]
+```
+
+### `#[account(init_if_needed)]`
+
+Description: Same as init but only runs if the account does not exist yet.
+Requires init-if-needed cargo feature.
+Examples: [Github](https://github.com/solana-developers/anchor-examples/tree/main/account-constraints/init_if_needed)
+|
+[Solpg](https://beta.solpg.io/https://github.com/solana-developers/anchor-examples/tree/main/account-constraints/init_if_needed)
+
+```rust title="attribute"
+#[account(
+ init_if_needed,
+ payer =
+)]
+
+#[account(
+ init_if_needed,
+ payer = ,
+ space =
+)]
+```
+
+### `#[account(seeds, bump)]`
+
+Description: Checks that given account is a PDA derived from the currently
+executing program, the seeds, and if provided, the bump.
+Examples: [Github](https://github.com/solana-developers/anchor-examples/tree/main/account-constraints/seed-bump)
+|
+[Solpg](https://beta.solpg.io/https://github.com/solana-developers/anchor-examples/tree/main/account-constraints/seed-bump)
+
+```rust title="attribute"
+#[account(
+ seeds = ,
+ bump
+)]
+
+#[account(
+ seeds = ,
+ bump,
+ seeds::program =
+)]
+
+#[account(
+ seeds = ,
+ bump =
+)]
+
+#[account(
+ seeds = ,
+ bump = ,
+ seeds::program =
+)]
+```
+
+### `#[account(has_one = target)]`
+
+Description: Checks the target field on the account matches the key of the
+target field in the Accounts struct.
+Examples: [Github](https://github.com/solana-developers/anchor-examples/tree/main/account-constraints/has_one)
+|
+[Solpg](https://beta.solpg.io/https://github.com/solana-developers/anchor-examples/tree/main/account-constraints/has_one)
+
+```rust title="attribute"
+#[account(
+ has_one =
+)]
+
+#[account(
+ has_one = @
+)]
+```
+
+### `#[account(address = expr)]`
+
+Description: Checks the account key matches the pubkey.
+Examples: [Github](https://github.com/solana-developers/anchor-examples/tree/main/account-constraints/address)
+|
+[Solpg](https://beta.solpg.io/https://github.com/solana-developers/anchor-examples/tree/main/account-constraints/address)
+
+```rust title="attribute"
+#[account(address = )]
+#[account(address = @ )]
+```
+
+### `#[account(owner = expr)]`
+
+Description: Checks the account owner matches expr.
+Examples: [Github](https://github.com/solana-developers/anchor-examples/tree/main/account-constraints/owner)
+|
+[Solpg](https://beta.solpg.io/https://github.com/solana-developers/anchor-examples/tree/main/account-constraints/owner)
+
+```rust title="attribute"
+#[account(owner = )]
+#[account(owner = @ )]
+```
+
+### `#[account(executable)]`
+
+Description: Checks the account is executable (i.e. the account is a program).
+Examples: [Github](https://github.com/solana-developers/anchor-examples/tree/main/account-constraints/executable)
+|
+[Solpg](https://beta.solpg.io/https://github.com/solana-developers/anchor-examples/tree/main/account-constraints/executable)
+
+```rust title="attribute"
+#[account(executable)]
+```
+
+### `#[account(zero)]`
+
+Description: Checks the account discriminator is zero. Use for accounts larger
+than 10 Kibibyte.
+Examples: [Github](https://github.com/solana-developers/anchor-examples/tree/main/account-constraints/zero)
+|
+[Solpg](https://beta.solpg.io/https://github.com/solana-developers/anchor-examples/tree/main/account-constraints/zero)
+
+```rust title="attribute"
+#[account(zero)]
+```
+
+### `#[account(close = target)]`
+
+Description: Closes the account by sending lamports to target and resetting
+data.
+Examples: [Github](https://github.com/solana-developers/anchor-examples/tree/main/account-constraints/close)
+|
+[Solpg](https://beta.solpg.io/https://github.com/solana-developers/anchor-examples/tree/main/account-constraints/close)
+
+```rust title="attribute"
+#[account(close = )]
+```
+
+### `#[account(constraint = expr)]`
+
+Description: Custom constraint that checks whether the given expression
+evaluates to true.
+Examples: [Github](https://github.com/solana-developers/anchor-examples/tree/main/account-constraints/constraint)
+|
+[Solpg](https://beta.solpg.io/https://github.com/solana-developers/anchor-examples/tree/main/account-constraints/constraint)
+
+```rust title="attribute"
+#[account(constraint = )]
+#[account(
+ constraint = @
+)]
+```
+
+### `#[account(realloc)]`
+
+Description: Used to realloc program account space at the beginning of an
+instruction.
+Examples: [Github](https://github.com/solana-developers/anchor-examples/tree/main/account-constraints/realloc)
+|
+[Solpg](https://beta.solpg.io/https://github.com/solana-developers/anchor-examples/tree/main/account-constraints/realloc)
+
+```rust title="attribute"
+#[account(
+ realloc = ,
+ realloc::payer = ,
+ realloc::zero =
+)]
+```
+
+## SPL Constraints
+
+### `#[account(token::*)]`
+
+Description: Create or validate token accounts with specified mint and
+authority.
+Examples: [Github](https://github.com/solana-developers/anchor-examples/tree/main/account-constraints/token)
+|
+[Solpg](https://beta.solpg.io/https://github.com/solana-developers/anchor-examples/tree/main/account-constraints/token)
+
+```rust title="attribute"
+#[account(
+ token::mint = ,
+ token::authority =
+)]
+
+#[account(
+ token::mint = ,
+ token::authority = ,
+ token::token_program =
+)]
+```
+
+### `#[account(mint::*)]`
+
+Description: Create or validate mint accounts with specified parameters.
+Examples: [Github](https://github.com/solana-developers/anchor-examples/tree/main/account-constraints/mint)
+|
+[Solpg](https://beta.solpg.io/https://github.com/solana-developers/anchor-examples/tree/main/account-constraints/mint)
+
+```rust title="attribute"
+#[account(
+ mint::authority = ,
+ mint::decimals =
+)]
+
+#[account(
+ mint::authority = ,
+ mint::decimals = ,
+ mint::freeze_authority =
+)]
+```
+
+### `#[account(associated_token::*)]`
+
+Description: Create or validate associated token accounts.
+Examples: [Github](https://github.com/solana-developers/anchor-examples/tree/main/account-constraints/associated_token)
+|
+[Solpg](https://beta.solpg.io/https://github.com/solana-developers/anchor-examples/tree/main/account-constraints/associated_token)
+
+```rust title="attribute"
+#[account(
+ associated_token::mint = ,
+ associated_token::authority =
+)]
+
+#[account(
+ associated_token::mint = ,
+ associated_token::authority = ,
+ associated_token::token_program =
+)]
+```
+
+### `#[account(*::token_program = expr)]`
+
+Description: The token_program can optionally be overridden.
+Examples: [Github](https://github.com/solana-developers/anchor-examples/tree/main/account-constraints/token_program)
+|
+[Solpg](https://beta.solpg.io/https://github.com/solana-developers/anchor-examples/tree/main/account-constraints/token_program)
+
+```rust title="attribute"
+#[account(*::token_program = )]
+```
+
+## Instruction Attribute
+
+### `#[instruction(...)]`
+
+Description: You can access the instruction's arguments with the
+`#[instruction(..)]` attribute. You must list them in the same order as in the
+instruction handler but you can omit all arguments after the last one you need.
+Skipping arguments will result in an error.
+
+Examples:
+[Github](https://github.com/solana-developers/anchor-examples/tree/main/account-constraints/instruction)
+|
+[Solpg](https://beta.solpg.io/https://github.com/solana-developers/anchor-examples/tree/main/account-constraints/instruction)
+
+```rust title="snippet"
+// [!code word:input]
+#[program]
+pub mod example {
+ use super::*;
+
+ pub fn initialize(ctx: Context, input: String) -> Result<()> {
+ // --snip--
+ }
+}
+
+#[derive(Accounts)]
+// [!code highlight]
+#[instruction(input: String)]
+pub struct Initialize<'info> {
+ #[account(
+ init,
+ payer = signer,
+ space = 8 + 4 + input.len(),
+ )]
+ pub new_account: Account<'info, DataAccount>,
+ // --snip--
+}
+```
+
+Valid Usage:
+
+```rust title="snippet"
+// [!code word:input_one]
+// [!code word:input_two]
+#[program]
+pub mod example {
+ use super::*;
+
+ pub fn initialize(ctx: Context, input_one: String, input_two: String) -> Result<()> {
+ // --snip--
+ }
+}
+
+#[derive(Accounts)]
+// [!code highlight]
+#[instruction(input_one: String, input_two: String)]
+pub struct Initialize<'info> {
+ // --snip--
+}
+```
+
+```rust title="snippet"
+// [!code word:input_one]
+#[program]
+pub mod example {
+ use super::*;
+
+ pub fn initialize(ctx: Context, input_one: String, input_two: String) -> Result<()> {
+ // --snip--
+ }
+}
+
+#[derive(Accounts)]
+// [!code highlight]
+#[instruction(input_one: String)]
+pub struct Initialize<'info> {
+ // --snip--
+}
+```
+
+Invalid Usage, will result in an error:
+
+```rust title="snippet"
+// [!code word:input_two]
+#[program]
+pub mod example {
+ use super::*;
+
+ pub fn initialize(ctx: Context, input_one: String, input_two: String) -> Result<()> {
+ // --snip--
+ }
+}
+
+#[derive(Accounts)]
+// [!code highlight]
+#[instruction(input_two: String)]
+pub struct Initialize<'info> {
+ // --snip--
+}
+```
diff --git a/docs/content/docs/references/account-types.mdx b/docs/content/docs/references/account-types.mdx
new file mode 100644
index 0000000000..3e668b0aca
--- /dev/null
+++ b/docs/content/docs/references/account-types.mdx
@@ -0,0 +1,232 @@
+---
+title: Account Types
+description: Anchor Account Type Examples
+---
+
+Minimal reference examples for Anchor
+[account types](https://docs.rs/anchor-lang/latest/anchor_lang/accounts/index.html).
+
+See the account types
+[source code](https://github.com/coral-xyz/anchor/tree/v0.30.1/lang/src/accounts)
+for implementation details.
+
+## Account Types
+
+### `Account<'info, T>`
+
+Description: Account container that checks ownership on deserialization
+Examples: [Github](https://github.com/solana-developers/anchor-examples/tree/main/account-types/Account)
+|
+[Solpg](https://beta.solpg.io/https://github.com/solana-developers/anchor-examples/tree/main/account-types/Account)
+
+```rust title="snippet"
+#[derive(Accounts)]
+pub struct InstructionAccounts<'info> {
+ // [!code word: Account]
+ // [!code highlight]
+ pub account: Account<'info, CustomAccountType>,
+}
+
+#[account]
+pub struct CustomAccountType {
+ data: u64,
+}
+```
+
+### `AccountInfo<'info>`
+
+Description: AccountInfo can be used as a type but Unchecked Account should be
+used instead
+Examples: [Github](https://github.com/solana-developers/anchor-examples/tree/main/account-types/AccountInfo)
+|
+[Solpg](https://beta.solpg.io/https://github.com/solana-developers/anchor-examples/tree/main/account-types/AccountInfo)
+
+```rust title="snippet"
+#[derive(Accounts)]
+pub struct InstructionAccounts<'info> {
+ /// CHECK: AccountInfo is an unchecked account
+ // [!code word:AccountInfo]
+ // [!code highlight]
+ pub unchecked_account: AccountInfo<'info>,
+}
+```
+
+### `AccountLoader<'info, T>`
+
+Description: Type facilitating on demand zero copy deserialization
+Examples: [Github](https://github.com/solana-developers/anchor-examples/tree/main/account-types/AccountLoader)
+|
+[Solpg](https://beta.solpg.io/https://github.com/solana-developers/anchor-examples/tree/main/account-types/AccountLoader)
+
+```rust title="snippet"
+#[derive(Accounts)]
+pub struct InstructionAccounts<'info> {
+ // [!code word:AccountLoader]
+ // [!code highlight]
+ pub account: AccountLoader<'info, ZeroCopyAccountType>,
+}
+
+#[account(zero_copy)]
+pub struct ZeroCopyAccountType {
+ data: u64,
+}
+```
+
+### `Box>`
+
+Description: Box type to save stack space
+Examples: [Github](https://github.com/solana-developers/anchor-examples/tree/main/account-types/Box)
+|
+[Solpg](https://beta.solpg.io/https://github.com/solana-developers/anchor-examples/tree/main/account-types/Box)
+
+```rust title="snippet"
+#[derive(Accounts)]
+pub struct InstructionAccounts<'info> {
+ // [!code word:Box]
+ // [!code highlight]
+ pub account: Box>,
+}
+```
+
+### `Interface<'info, T>`
+
+Description: Type validating that the account is one of a set of given
+Programs
+Examples: [Github](https://github.com/solana-developers/anchor-examples/tree/main/account-types/Interface)
+|
+[Solpg](https://beta.solpg.io/https://github.com/solana-developers/anchor-examples/tree/main/account-types/Interface)
+
+```rust title="snippet"
+// Token program or Token2022 program
+use anchor_spl::token_interface::TokenInterface;
+
+#[derive(Accounts)]
+pub struct InstructionAccounts<'info> {
+ // [!code word: Interface]
+ // [!code highlight]
+ pub program: Interface<'info, TokenInterface>,
+}
+```
+
+### `InterfaceAccount<'info, T>`
+
+Description: Account container that checks ownership on deserialization
+Examples: [Github](https://github.com/solana-developers/anchor-examples/tree/main/account-types/InterfaceAccount)
+|
+[Solpg](https://beta.solpg.io/https://github.com/solana-developers/anchor-examples/tree/main/account-types/InterfaceAccount)
+
+```rust title="snippet"
+// Token program or Token2022 program Mint/TokenAccount
+use anchor_spl::token_interface::{Mint, TokenAccount, TokenInterface};
+
+#[derive(Accounts)]
+pub struct InstructionAccounts<'info> {
+ // [!code word:InterfaceAccount]
+ // [!code highlight:2]
+ pub mint: InterfaceAccount<'info, Mint>,
+ pub token: InterfaceAccount<'info, TokenAccount>,
+ pub program: Interface<'info, TokenInterface>,
+}
+```
+
+### `Option>`
+
+Description: Option type for optional accounts
+Examples: [Github](https://github.com/solana-developers/anchor-examples/tree/main/account-types/Option)
+|
+[Solpg](https://beta.solpg.io/https://github.com/solana-developers/anchor-examples/tree/main/account-types/Option)
+
+```rust title="snippet"
+#[derive(Accounts)]
+pub struct InstructionAccounts<'info> {
+ // [!code word:Option]
+ // [!code highlight]
+ pub account: Option>,
+}
+```
+
+### `Program<'info, T>`
+
+Description: Type validating that the account is the given Program
+Examples: [Github](https://github.com/solana-developers/anchor-examples/tree/main/account-types/Program)
+|
+[Solpg](https://beta.solpg.io/https://github.com/solana-developers/anchor-examples/tree/main/account-types/Program)
+
+```rust title="snippet"
+use anchor_spl::token::Token;
+
+#[derive(Accounts)]
+pub struct InstructionAccounts<'info> {
+ // [!code word:Program]
+ // [!code highlight:2]
+ pub system_program: Program<'info, System>,
+ pub token_program: Program<'info, Token>,
+}
+```
+
+### `Signer<'info>`
+
+Description: Type validating that the account signed the transaction
+Examples: [Github](https://github.com/solana-developers/anchor-examples/tree/main/account-types/Signer)
+|
+[Solpg](https://beta.solpg.io/https://github.com/solana-developers/anchor-examples/tree/main/account-types/Signer)
+
+```rust title="snippet"
+#[derive(Accounts)]
+pub struct InstructionAccounts<'info> {
+ // [!code word:Signer]
+ // [!code highlight]
+ pub signer: Signer<'info>,
+}
+```
+
+### `SystemAccount<'info>`
+
+Description: Type validating that the account is owned by the system program
+Examples: [Github](https://github.com/solana-developers/anchor-examples/tree/main/account-types/SystemAccount)
+|
+[Solpg](https://beta.solpg.io/https://github.com/solana-developers/anchor-examples/tree/main/account-types/SystemAccount)
+
+```rust title="snippet"
+#[derive(Accounts)]
+pub struct InstructionAccounts<'info> {
+ // [!code word:SystemAccount]
+ // [!code highlight]
+ pub account: SystemAccount<'info>,
+}
+```
+
+### `Sysvar<'info, T>`
+
+Description: Type validating that the account is a sysvar and deserializing it
+Examples: [Github](https://github.com/solana-developers/anchor-examples/tree/main/account-types/Sysvar)
+|
+[Solpg](https://beta.solpg.io/https://github.com/solana-developers/anchor-examples/tree/main/account-types/Sysvar)
+
+```rust title="snippet"
+#[derive(Accounts)]
+pub struct InstructionAccounts<'info> {
+ // [!code word:Sysvar]
+ // [!code highlight:2]
+ pub rent: Sysvar<'info, Rent>,
+ pub clock: Sysvar<'info, Clock>,
+}
+```
+
+### `UncheckedAccount<'info>`
+
+Description: Explicit wrapper for AccountInfo types to emphasize that no checks
+are performed
+Examples: [Github](https://github.com/solana-developers/anchor-examples/tree/main/account-types/UncheckedAccount)
+|
+[Solpg](https://beta.solpg.io/https://github.com/solana-developers/anchor-examples/tree/main/account-types/UncheckedAccount)
+
+```rust title="snippet"
+#[derive(Accounts)]
+pub struct InstructionAccounts<'info> {
+ // CHECK: No checks are performed
+ // [!code word:UncheckedAccount]
+ // [!code highlight]
+ pub account: UncheckedAccount<'info>,
+}
+```
diff --git a/docs/src/pages/docs/manifest.md b/docs/content/docs/references/anchor-toml.mdx
similarity index 68%
rename from docs/src/pages/docs/manifest.md
rename to docs/content/docs/references/anchor-toml.mdx
index 4285bfb597..d8c54d60a5 100644
--- a/docs/src/pages/docs/manifest.md
+++ b/docs/content/docs/references/anchor-toml.mdx
@@ -1,6 +1,6 @@
---
-title: Anchor.toml Reference
-description: Anchor - Anchor.toml Reference
+title: Anchor.toml Configuration
+description: Anchor workspace config reference documentation
---
## provider (required)
@@ -17,7 +17,8 @@ wallet = "~/.config/solana/id.json" # The keypair used for all commands.
## scripts (required for testing)
-Scripts that can be run with `anchor run