Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions courses/anchor-and-programs/workshop/anchor-1h/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -224,9 +224,9 @@ Expected:

Before teaching this workshop, review the **reference implementation** in `/code/final/`:

- 📖 [final/README.md](code/final/README.md) - Teaching notes, troubleshooting, FAQs
- 💻 [final/programs/counter/src/lib.rs](code/final/programs/counter/src/lib.rs) - Deeply commented program
- 🧪 [final/tests/counter.ts](code/final/tests/counter.ts) - Annotated test suite
- [final/README.md](code/final/README.md) - Teaching notes, troubleshooting, FAQs
- [final/programs/counter/src/lib.rs](code/final/programs/counter/src/lib.rs) - Deeply commented program
- [final/tests/counter.ts](code/final/tests/counter.ts) - Annotated test suite

### Official Resources

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
# 3. [provider] sets default cluster and wallet
# 4. [scripts] defines test commands
#
# 🔗 Why separate clusters? Different environments (local vs devnet vs mainnet)
# 🔗 Why same Program ID? Consistency across environments
# Why separate clusters? Different environments (local vs devnet vs mainnet)
# Why same Program ID? Consistency across environments
# 📖 https://www.anchor-lang.com/docs

[toolchain]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
**Audience:** Instructors preparing to teach the 1-hour Anchor workshop.
**Not for students:** Students work in `/code/counter/` with minimal comments.

## ⚠️ Important: This is Reference Only
## Important: This is Reference Only

**Students work in `/code/counter/`** - this directory is for presenter study only.

Expand Down Expand Up @@ -82,7 +82,7 @@ A: No - Rust doesn't have ++ operator. But more importantly, we want checked_add

### Wallet Hygiene

⚠️ **Critical Safety Message**
**Critical Safety Message**

- **Dev wallet only**: Never use production keys in workshops
- **Devnet ≠ Mainnet**: Make this distinction crystal clear
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ use anchor_lang::prelude::*;
// 2. programs/counter/keys/counter-keypair.json
// 3. The deployed program address
//
// 🔗 Why? Solana uses this ID to route transactions to your program.
// 🔗 PDAs (covered in Week 4) derive from this ID.
// Why? Solana uses this ID to route transactions to your program.
// PDAs (covered in Week 4) derive from this ID.
// 📖 https://solana.com/docs/core/programs#program-derived-addresses
declare_id!("FoKCfkWjCJxuHLxHGkzdQ3VXrFgrnGdq4xNsZLnjJLbK");

Expand All @@ -40,8 +40,8 @@ declare_id!("FoKCfkWjCJxuHLxHGkzdQ3VXrFgrnGdq4xNsZLnjJLbK");
// Think of this as your program's "API surface" - what external
// clients can call. Each pub fn becomes an instruction handler.
//
// 🔗 Context<T>: Anchor's account safety system
// 🔗 Result<()>: Rust error handling (vs panics in production)
// Context<T>: Anchor's account safety system
// Result<()>: Rust error handling (vs panics in production)
// 📖 https://www.anchor-lang.com/docs
#[program]
pub mod counter {
Expand All @@ -55,8 +55,8 @@ pub mod counter {
// - Setting count = 0: explicit initialization (vs undefined behavior)
// - Space calculation: 8 (discriminator) + 8 (u64) = 16 bytes
//
// 🔗 Why &mut? Solana enforces exclusive access for data integrity
// 🔗 Why explicit init? Prevents reading uninitialized memory
// Why &mut? Solana enforces exclusive access for data integrity
// Why explicit init? Prevents reading uninitialized memory
// 📖 https://www.anchor-lang.com/docs
pub fn initialize(ctx: Context<Initialize>) -> Result<()> {
let counter = &mut ctx.accounts.counter;
Expand All @@ -72,8 +72,8 @@ pub mod counter {
// - unwrap(): safe here because we're adding 1 to a u64
// - State persists: Solana stores account data on-chain
//
// 🔗 Why checked_add? Prevents integer overflow attacks
// 🔗 Why unwrap? In production, handle Result properly
// Why checked_add? Prevents integer overflow attacks
// Why unwrap? In production, handle Result properly
// 📖 https://doc.rust-lang.org/std/primitive.u64.html#method.checked_add
pub fn increment(ctx: Context<Increment>) -> Result<()> {
let counter = &mut ctx.accounts.counter;
Expand All @@ -93,8 +93,8 @@ pub mod counter {
// - Why not Vec or String? Complexity vs learning goals
// - Discriminator: hash of "account:Counter" for type safety
//
// 🔗 Borsh: Binary Object Representation Serializer for Hashing
// 🔗 Discriminator: prevents account type confusion
// Borsh: Binary Object Representation Serializer for Hashing
// Discriminator: prevents account type confusion
// 📖 https://www.anchor-lang.com/docs
#[account]
pub struct Counter {
Expand All @@ -111,9 +111,9 @@ pub struct Counter {
// - System program: Solana's "account factory" (creates accounts)
// - Lifetimes ('info): Rust memory safety (brief note)
//
// 🔗 init constraint: creates account if it doesn't exist
// 🔗 space = 8 + 8: discriminator (8) + u64 (8) = 16 bytes
// 🔗 Signer: proves caller owns the private key
// init constraint: creates account if it doesn't exist
// space = 8 + 8: discriminator (8) + u64 (8) = 16 bytes
// Signer: proves caller owns the private key
// 📖 https://www.anchor-lang.com/docs
// 📖 https://solana.com/docs/core/transactions#signatures
#[derive(Accounts)]
Expand All @@ -134,8 +134,8 @@ pub struct Initialize<'info> {
// - Minimal constraints: show evolution to complex checks
// - Preview: add ownership checks, PDAs in advanced lessons
//
// 🔗 mut constraint: account must be mutable for writes
// 🔗 No init: account must already exist
// mut constraint: account must be mutable for writes
// No init: account must already exist
// 📖 https://www.anchor-lang.com/docs
#[derive(Accounts)]
pub struct Increment<'info> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ describe("counter", () => {
// This is the "connection + wallet" bundle that Anchor needs
// to send transactions and sign them.
//
// 🔗 Why .env()? Consistent environment across team members
// 🔗 Why not manual setup? Reduces boilerplate and errors
// Why .env()? Consistent environment across team members
// Why not manual setup? Reduces boilerplate and errors
// 📖 https://www.anchor-lang.com/docs/testing#provider
anchor.setProvider(anchor.AnchorProvider.env());

Expand All @@ -45,8 +45,8 @@ describe("counter", () => {
// - workspace: Anchor's program registry
// - .methods.*: instruction handlers become method calls
//
// 🔗 IDL: JSON schema of your program's interface
// 🔗 Type safety: TypeScript knows your program's shape
// IDL: JSON schema of your program's interface
// Type safety: TypeScript knows your program's shape
// 📖 https://www.anchor-lang.com/docs/testing#program
const program = anchor.workspace.counter as Program<Counter>;

Expand All @@ -57,8 +57,8 @@ describe("counter", () => {
// 1. Sign transactions (cryptographic authorization)
// 2. Pay for account creation (rent-exempt minimum balance)
//
// 🔗 Signer: proves ownership of private key
// 🔗 Payer: pays transaction fees + account creation costs
// Signer: proves ownership of private key
// Payer: pays transaction fees + account creation costs
// 📖 https://solana.com/docs/core/transactions#signatures
const provider = program.provider as anchor.AnchorProvider;
const payer = provider.wallet as anchor.Wallet;
Expand All @@ -72,8 +72,8 @@ describe("counter", () => {
// Alternative: reuse a PDA (Program Derived Address)
// but that's advanced and requires seeds.
//
// 🔗 Keypair: public key + private key pair
// 🔗 .generate(): cryptographically secure random generation
// Keypair: public key + private key pair
// .generate(): cryptographically secure random generation
// 📖 https://solana-labs.github.io/solana-web3.js/classes/Keypair.html
const counterKeypair = anchor.web3.Keypair.generate();

Expand All @@ -86,8 +86,8 @@ describe("counter", () => {
// - .signers(): who authorizes this transaction
// - .rpc(): send transaction + wait for confirmation
//
// 🔗 Transaction = instruction + accounts + signers
// 🔗 systemProgram: Solana's account creation program
// Transaction = instruction + accounts + signers
// systemProgram: Solana's account creation program
// 📖 https://www.anchor-lang.com/docs/testing#calling-instructions
await program.methods
.initialize()
Expand All @@ -107,8 +107,8 @@ describe("counter", () => {
// - No systemProgram: no account creation
// - Just the counter account: matches Increment<'info> struct
//
// 🔗 State persistence: Solana stores account data on-chain
// 🔗 Multiple calls: prove state survives across transactions
// State persistence: Solana stores account data on-chain
// Multiple calls: prove state survives across transactions
await program.methods
.increment()
.accounts({ counter: counterKeypair.publicKey })
Expand All @@ -121,8 +121,8 @@ describe("counter", () => {
// 2. The increment worked (count = 1)
// 3. State persists between transactions
//
// 🔗 .fetch(): deserialize on-chain data to TypeScript
// 🔗 .toString(): convert BigNum to readable string
// .fetch(): deserialize on-chain data to TypeScript
// .toString(): convert BigNum to readable string
// 📖 https://www.anchor-lang.com/docs/testing#fetching-accounts
let counterAcc = await program.account.counter.fetch(
counterKeypair.publicKey
Expand Down
35 changes: 35 additions & 0 deletions courses/anchor-and-programs/workshop/anchor-3h/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Rust build artifacts
**/target/
**/Cargo.lock

# Node.js dependencies
**/node_modules/
**/yarn.lock
**/package-lock.json

# IDE files
**/.vscode/
**/.idea/
**/*.swp
**/*.swo

# OS files
**/.DS_Store
**/Thumbs.db

# Solana/Anchor specific
**/.anchor/
**/test-ledger/
**/keypairs/

# Environment files
**/.env
**/.env.local

# Logs
**/*.log
**/logs/

# Temporary files
**/tmp/
**/temp/
Loading