Full lesson
anchor
⚓ Solana Program Framework
What it does
From the project README:
Anchor is a framework providing several convenient developer tools for writing Solana programs (sometimes called 'smart contracts').
- Original
- otter-sec/anchor
- SuperStack fork
- Blockchains/anchor @
541295d - Stars
- 5,166
- Last push (original)
- 2026-11-02
- Languages
- Rust, TypeScript, JavaScript, Astro, Shell, CSS
- Detected stack
- AnchorNext.jsweb3.js
- Categories
- Infrastructure & Tooling
- Licence
- Apache-2.0
- Homepage
- https://anchor-lang.com
Architecture
749 source files. By extension: .ts ×353, .rs ×348, .js ×33, .tsx ×15.
| Top-level directory | Source files |
|---|---|
tests | 204 |
ts | 201 |
lang | 113 |
docs-v2 | 109 |
cli | 42 |
spl | 31 |
docs | 15 |
examples | 14 |
On-chain programs: examples/tutorial/basic-0/programs/basic-0, examples/tutorial/basic-1/programs/basic-1, examples/tutorial/basic-2/programs/basic-2, examples/tutorial/basic-3/programs/puppet, examples/tutorial/basic-3/programs/puppet-master, examples/tutorial/basic-4/programs/basic-4, examples/tutorial/basic-5/programs/basic-5, tests/account-generation-test/programs/account-generation-test
Dapp: deploying
This fork is queued for its own live dapp on Sol.College, with a Devnet/Mainnet switch. It appears here, at /dapps/anchor/, once it is deployed and checked on devnet. Until then, run it locally with the commands below.
Key code, explained
Excerpts chosen automatically where the code uses the most Solana concepts, pinned to the fork's commit.
docs-v2/src/content/docs/v1/tokens/spl-token-basics/_transfer-tokens/lib_pda.rs L37–60 @ 541295d · Apache-2.0 · original authority: ctx.accounts.sender_token_account.to_account_info(), }; let cpi_program = ctx.accounts.token_program.to_account_info(); let cpi_context = CpiContext::new(cpi_program, cpi_accounts).with_signer(signer_seeds); token_interface::transfer_checked(cpi_context, amount, decimals)?; Ok(()) }} #[derive(Accounts)]pub struct CreateAndMintTokens<'info> { #[account(mut)] pub signer: Signer<'info>, #[account( init, payer = signer, mint::decimals = 6, mint::authority = mint, mint::freeze_authority = mint, seeds = [b"mint"], bump )] pub mint: InterfaceAccount<'info, Mint>, #[account(- Line 40
let cpi_context = CpiContext::new(cpi_program, cpi_accounts).with_signer(signer_seeds);: Makes a cross-program invocation into another program. - Line 41
token_interface::transfer_checked(cpi_context, amount, decimals)?;: A checked token transfer, which also verifies the mint and decimals. - Line 47
pub struct CreateAndMintTokens<'info> {: Mints new tokens. The mint authority must sign. - Line 49
pub signer: Signer<'info>,: Requires this account to have signed the transaction. - Line 51
init,: Creates and pays for a new account. Space and payer must be specified. - Line 56
seeds = [b"mint"],: Declares the PDA seeds. Anchor re-derives the address and rejects the account if it doesn't match. - Line 57
bump: Uses the bump seed, the extra byte that pushes the derived address off the ed25519 curve.
cli/src/template.rs L157–180 @ 541295d · Apache-2.0 · original ctx.accounts.counter.count += 1; msg!("Hello, world! Counter is now {{}}", ctx.accounts.counter.count); Ok(()) }}}} #[derive(Accounts)]pub struct Initialize<'info> {{ #[account(mut)] pub payer: Signer<'info>, #[account( init, payer = payer, space = 8 + Counter::INIT_SPACE, seeds = [COUNTER_SEED], bump )] pub counter: Account<'info, Counter>, pub system_program: Program<'info, System>,}} #[derive(Accounts)]pub struct Increment<'info> {{- Line 159
msg!("Hello, world! Counter is now {{}}", ctx.accounts.counter.count);: Logs to the program log, which is visible in explorers and the test output. - Line 167
pub payer: Signer<'info>,: Requires this account to have signed the transaction. - Line 169
init,: Creates and pays for a new account. Space and payer must be specified. - Line 172
seeds = [COUNTER_SEED],: Declares the PDA seeds. Anchor re-derives the address and rejects the account if it doesn't match. - Line 173
bump: Uses the bump seed, the extra byte that pushes the derived address off the ed25519 curve.
examples/tutorial/basic-5/programs/basic-5/src/lib.rs L49–72 @ 541295d · Apache-2.0 · original }} #[derive(Accounts)]pub struct Create<'info> { // init means to create action_state account // bump to use unique address for action_state account #[account( init, payer = user, space = 8 + ActionState::INIT_SPACE, seeds = [b"action-state", user.key().as_ref()], bump )] pub action_state: Account<'info, ActionState>, // mut makes it changeable (mutable) #[account(mut)] pub user: Signer<'info>, pub system_program: Program<'info, System>,} #[derive(Accounts)]pub struct Walk<'info> { // Only the user on account action_state, should be able to change state- Line 55
// bump to use unique address for action_state account: Uses the bump seed, the extra byte that pushes the derived address off the ed25519 curve. - Line 57
init,: Creates and pays for a new account. Space and payer must be specified. - Line 60
seeds = [b"action-state", user.key().as_ref()],: Declares the PDA seeds. Anchor re-derives the address and rejects the account if it doesn't match. - Line 66
pub user: Signer<'info>,: Requires this account to have signed the transaction.
examples/tutorial/basic-4/programs/basic-4/src/lib.rs L25–48 @ 541295d · Apache-2.0 · original ctx.accounts.authority.key(), ctx.accounts.counter.authority, ErrorCode::Unauthorized ); ctx.accounts.counter.count += 1; Ok(()) }} #[derive(Accounts)]pub struct Initialize<'info> { #[account( init, payer = authority, space = Counter::SIZE, seeds = [b"counter"], bump )] counter: Account<'info, Counter>, #[account(mut)] authority: Signer<'info>, system_program: Program<'info, System>,}- Line 38
init,: Creates and pays for a new account. Space and payer must be specified. - Line 41
seeds = [b"counter"],: Declares the PDA seeds. Anchor re-derives the address and rejects the account if it doesn't match. - Line 42
bump: Uses the bump seed, the extra byte that pushes the derived address off the ed25519 curve. - Line 46
authority: Signer<'info>,: Requires this account to have signed the transaction.
How to run, build and test
These commands come from the repo's own manifests (package.json scripts, Anchor.toml, Cargo, go.mod, Makefile). Check the README for prerequisites and environment variables.
| Directory | Command | Runs |
|---|---|---|
docs | npm run dev | next dev |
docs | npm run start | next start |
docs | npm run build | next build |
examples/tutorial | npm run lint | prettier */*.js "*/**/*{.js,.ts}" --check |
ts/tests | npm run test | rimraf dist && tsc -p . && ts-node dist |
docs-v2 | npm run dev | astro dev |
docs-v2 | npm run start | astro dev |
docs-v2 | npm run build | astro check && astro build |
tests | npm run lint | prettier */*.js "*/**/*{.js,.ts}" --check |
tests/relations-derivation | npm run test | anchor test |
tests/accountloader-realloc | npm run test | anchor test |
tests/realloc | npm run test | anchor test |
tests/pda-derivation | npm run test | anchor test |
tests/custom-program | npm run test | anchor test |
tests/typescript | npm run test | anchor test |
tests/lockup | npm run test | anchor test |
What you could build from it
- Fork the SuperStack copy and extend it within the Infrastructure & Tooling gaps listed on the idea page.
- Learn the pattern first: Building and sending transactions from a client
- Learn the pattern first: Anchor account constraints