Skip to content

Commit a46d611

Browse files
committed
docs: Enhance Anchor integration guide with positioning and patterns
- Add "LUMOS + Anchor: Better Together" section explaining the relationship - Add "When to Use LUMOS vs Anchor Alone" decision guide table - Add Common Patterns section (PDA, one-to-many, token integration, state machines) - Expand Troubleshooting from 3 to 10 Q&As with code examples Addresses #89
1 parent 663b547 commit a46d611

File tree

1 file changed

+234
-0
lines changed

1 file changed

+234
-0
lines changed

src/content/docs/frameworks/anchor.md

Lines changed: 234 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,45 @@ description: Generate complete Anchor programs from LUMOS schemas
55

66
LUMOS provides deep integration with the [Anchor framework](https://www.anchor-lang.com/), allowing you to generate complete Solana programs with account contexts, IDL, and TypeScript clients.
77

8+
## LUMOS + Anchor: Better Together
9+
10+
:::tip[Key Point]
11+
**LUMOS complements Anchor, it doesn't replace it.** LUMOS generates Anchor-compatible code from a schema, giving you a single source of truth for your data structures.
12+
:::
13+
14+
Think of it this way:
15+
- **Anchor** = The framework that runs your Solana program
16+
- **LUMOS** = The tool that generates Anchor code from a schema
17+
18+
**Why use both?**
19+
20+
| Without LUMOS | With LUMOS |
21+
|---------------|------------|
22+
| Manually write Rust structs | Define once in `.lumos` schema |
23+
| Manually write TypeScript types | Auto-generate TypeScript |
24+
| Hope Rust ↔ TS stay in sync | Guaranteed sync (same source) |
25+
| Calculate account space by hand | Auto-calculated `LEN` constants |
26+
| Write IDL manually or extract | Auto-generate IDL from schema |
27+
28+
**LUMOS generates standard Anchor code** - your program still uses `anchor_lang`, `#[account]`, `#[program]`, and everything else you know. The difference is you define your types once and generate the rest.
29+
30+
---
31+
32+
## When to Use LUMOS vs Anchor Alone
33+
34+
| Scenario | Recommendation |
35+
|----------|----------------|
36+
| Starting a new Anchor project | ✅ Use LUMOS - define schema first, generate code |
37+
| Existing Anchor project, want type sync | ✅ Use LUMOS - adopt gradually for new types |
38+
| Simple program, few account types | ⚠️ Either works - Anchor alone is fine |
39+
| Complex program, many shared types | ✅ Use LUMOS - prevents drift between Rust/TS |
40+
| Need custom IDL modifications | ⚠️ Start with LUMOS, customize after |
41+
| Team with mixed Rust/TS developers | ✅ Use LUMOS - schema is readable by all |
42+
43+
**Bottom line:** If you're writing TypeScript clients that interact with your Anchor program, LUMOS saves you from maintaining duplicate type definitions.
44+
45+
---
46+
847
## Overview
948

1049
When your schema uses `#[account]` attributes, LUMOS automatically generates Anchor-compatible code:
@@ -477,12 +516,148 @@ struct Stake {
477516

478517
---
479518

519+
## Common Patterns
520+
521+
### PDA (Program Derived Address) Accounts
522+
523+
PDAs are accounts whose address is derived from seeds. Define the account structure in LUMOS, derive the PDA in your Anchor code:
524+
525+
```rust
526+
// schema.lumos
527+
#[solana]
528+
#[account]
529+
struct UserProfile {
530+
authority: PublicKey,
531+
username: String,
532+
reputation: u64,
533+
created_at: i64,
534+
}
535+
```
536+
537+
```rust
538+
// In your Anchor program
539+
#[derive(Accounts)]
540+
#[instruction(username: String)]
541+
pub struct CreateProfile<'info> {
542+
#[account(
543+
init,
544+
payer = authority,
545+
space = 8 + UserProfile::LEN,
546+
seeds = [b"profile", authority.key().as_ref()],
547+
bump
548+
)]
549+
pub profile: Account<'info, UserProfile>,
550+
#[account(mut)]
551+
pub authority: Signer<'info>,
552+
pub system_program: Program<'info, System>,
553+
}
554+
```
555+
556+
### One-to-Many Relationships
557+
558+
Model relationships using PublicKey references:
559+
560+
```rust
561+
// schema.lumos
562+
#[solana]
563+
#[account]
564+
struct Collection {
565+
authority: PublicKey,
566+
name: String,
567+
item_count: u32,
568+
}
569+
570+
#[solana]
571+
#[account]
572+
struct Item {
573+
collection: PublicKey, // Reference to parent
574+
owner: PublicKey,
575+
name: String,
576+
attributes: Vec<u8>,
577+
}
578+
```
579+
580+
### Token Account Integration
581+
582+
When working with SPL tokens alongside LUMOS-generated accounts:
583+
584+
```rust
585+
// schema.lumos
586+
#[solana]
587+
#[account]
588+
struct Vault {
589+
authority: PublicKey,
590+
token_mint: PublicKey, // SPL token mint
591+
token_account: PublicKey, // Associated token account
592+
total_deposited: u64,
593+
is_locked: bool,
594+
}
595+
```
596+
597+
```rust
598+
// Anchor context
599+
#[derive(Accounts)]
600+
pub struct Deposit<'info> {
601+
#[account(mut)]
602+
pub vault: Account<'info, Vault>,
603+
#[account(mut)]
604+
pub vault_token_account: Account<'info, TokenAccount>,
605+
#[account(mut)]
606+
pub user_token_account: Account<'info, TokenAccount>,
607+
pub token_program: Program<'info, Token>,
608+
pub authority: Signer<'info>,
609+
}
610+
```
611+
612+
### Enum-Based State Machines
613+
614+
Use LUMOS enums for program state:
615+
616+
```rust
617+
// schema.lumos
618+
#[solana]
619+
enum AuctionState {
620+
Created,
621+
Active { start_time: i64 },
622+
Ended { winner: PublicKey, final_bid: u64 },
623+
Cancelled,
624+
}
625+
626+
#[solana]
627+
#[account]
628+
struct Auction {
629+
authority: PublicKey,
630+
item_mint: PublicKey,
631+
state: AuctionState,
632+
min_bid: u64,
633+
current_bid: u64,
634+
}
635+
```
636+
637+
---
638+
480639
## Troubleshooting
481640

482641
### "Cannot find type" error
483642

484643
Ensure all referenced types are defined in the schema or imported.
485644

645+
```rust
646+
// Bad - UndefinedType not in schema
647+
struct MyAccount {
648+
data: UndefinedType, // Error!
649+
}
650+
651+
// Good - all types defined
652+
struct MyData {
653+
value: u64,
654+
}
655+
656+
struct MyAccount {
657+
data: MyData, // Works
658+
}
659+
```
660+
486661
### IDL mismatch
487662

488663
Regenerate IDL after schema changes:
@@ -499,6 +674,65 @@ Use `lumos anchor space` to verify:
499674
lumos anchor space schema.lumos --format rust
500675
```
501676

677+
### "Discriminator mismatch" at runtime
678+
679+
This happens when the account struct definition changed but the on-chain account wasn't migrated. Solutions:
680+
681+
1. **Development:** Close and recreate the account
682+
2. **Production:** Implement account migration logic
683+
684+
### Generated code has compile errors
685+
686+
Check your schema for:
687+
- Reserved Rust keywords used as field names (`type`, `move`, `ref`)
688+
- Circular type references
689+
- Missing `#[solana]` attribute
690+
691+
```rust
692+
// Bad - 'type' is reserved
693+
struct Token {
694+
type: u8, // Error!
695+
}
696+
697+
// Good - use different name
698+
struct Token {
699+
token_type: u8,
700+
}
701+
```
702+
703+
### TypeScript types don't match runtime values
704+
705+
Ensure you regenerated TypeScript after schema changes:
706+
707+
```bash
708+
lumos generate schema.lumos --lang ts -o client/types.ts
709+
```
710+
711+
### Anchor test fails with "Account not found"
712+
713+
The account might not be initialized. Check:
714+
1. Account is created before being accessed
715+
2. PDA seeds match between init and access
716+
3. Program ID is correct
717+
718+
### "Program failed to complete" without details
719+
720+
Enable Anchor's verbose logging:
721+
722+
```bash
723+
RUST_LOG=solana_runtime::system_instruction_processor=trace anchor test
724+
```
725+
726+
### How to update schema without breaking existing accounts?
727+
728+
Follow these rules for backward compatibility:
729+
- ✅ Add new optional fields at the end
730+
- ✅ Add new enum variants at the end
731+
- ❌ Don't remove or reorder fields
732+
- ❌ Don't change field types
733+
734+
See [Schema Migrations](/guides/schema-migrations) for detailed guidance.
735+
502736
---
503737

504738
## See Also

0 commit comments

Comments
 (0)