Summary
SPEL has two ways to produce an IDL, and they disagree about `#[account_type]`:
| Path |
How it's invoked |
Picks up `#[account_type]` markers? |
| CLI subcommand |
`spel generate-idl methods/guest/src/bin/prog.rs` (→ `spel_framework_core::idl_gen::generate_idl_from_file`) |
✅ yes, via `collect_account_types(&file.items)` |
| Proc macro |
`spel_framework::generate_idl!("…/prog.rs")` inside `examples/src/bin/generate_idl.rs`, invoked by `make idl` (→ `spel_framework_macros::expand_generate_idl` / `generate_idl_json`) |
❌ no |
The scaffold's `Makefile` wires `make idl` to the proc-macro path. So a user who follows the tutorial, writes `#[account_type] pub struct CounterState { … }` in the guest file, and runs `make idl`, gets an IDL with `"accounts": []`. Then `spel inspect --type CounterState` silently can't find the type. Nothing in the output tells them why.
The CLI path produces the correct IDL (I confirmed this during the PR #138 tutorial walk):
```bash
spel generate-idl methods/guest/src/bin/my_counter.rs | jq .accounts
[ { "name": "CounterState", "type": { "kind": "struct", "fields": [ … ] } } ]
```
Why this happens
`spel_framework_core/src/idl_gen.rs` (CLI path) calls `collect_account_types(&file.items)` after parsing the program source. `spel_framework_macros/src/lib.rs::generate_idl_json` (proc-macro path) walks `instructions` but never iterates `file.items` looking for `#[account_type]` markers — so the top-level structs/enums annotated with it are silently dropped when emitting `PROGRAM_IDL_JSON`.
Proposed fix
Two options:
-
Unify on one path. Have `generate_idl_fn` / `generate_idl_json` in `spel-framework-macros` delegate to the same `collect_account_types` logic (or to `idl_gen::generate_idl_from_str` directly). Both produce an `SpelIdl`; the proc-macro path just needs to serialize it.
-
Port the collection. Copy the `collect_account_types` logic into `generate_idl_json` so it builds the `accounts`/`types` entries from the file's top-level items. Less invasive but duplicates code.
Option 1 is the clean fix.
Workaround (until fixed)
Replace `make idl` with `spel generate-idl methods/guest/src/bin/.rs > -idl.json`. The tutorial in PR #138 tells users to do this and explains why.
Impact
`spel inspect --type …` is the primary way to read account data off-chain, and it's prominently advertised in the README ("inspect subcommand to extract ProgramId from binaries and decode account data"). Any user who defines state via `#[account_type]` and generates the IDL via `make idl` will hit this.
Found during the tutorial walk that produced #138.
cc @fryorcraken
Summary
SPEL has two ways to produce an IDL, and they disagree about `#[account_type]`:
The scaffold's `Makefile` wires `make idl` to the proc-macro path. So a user who follows the tutorial, writes `#[account_type] pub struct CounterState { … }` in the guest file, and runs `make idl`, gets an IDL with `"accounts": []`. Then `spel inspect --type CounterState` silently can't find the type. Nothing in the output tells them why.
The CLI path produces the correct IDL (I confirmed this during the PR #138 tutorial walk):
```bash
spel generate-idl methods/guest/src/bin/my_counter.rs | jq .accounts
[ { "name": "CounterState", "type": { "kind": "struct", "fields": [ … ] } } ]
```
Why this happens
`spel_framework_core/src/idl_gen.rs` (CLI path) calls `collect_account_types(&file.items)` after parsing the program source. `spel_framework_macros/src/lib.rs::generate_idl_json` (proc-macro path) walks `instructions` but never iterates `file.items` looking for `#[account_type]` markers — so the top-level structs/enums annotated with it are silently dropped when emitting `PROGRAM_IDL_JSON`.
Proposed fix
Two options:
Unify on one path. Have `generate_idl_fn` / `generate_idl_json` in `spel-framework-macros` delegate to the same `collect_account_types` logic (or to `idl_gen::generate_idl_from_str` directly). Both produce an `SpelIdl`; the proc-macro path just needs to serialize it.
Port the collection. Copy the `collect_account_types` logic into `generate_idl_json` so it builds the `accounts`/`types` entries from the file's top-level items. Less invasive but duplicates code.
Option 1 is the clean fix.
Workaround (until fixed)
Replace `make idl` with `spel generate-idl methods/guest/src/bin/.rs > -idl.json`. The tutorial in PR #138 tells users to do this and explains why.
Impact
`spel inspect --type …` is the primary way to read account data off-chain, and it's prominently advertised in the README ("inspect subcommand to extract ProgramId from binaries and decode account data"). Any user who defines state via `#[account_type]` and generates the IDL via `make idl` will hit this.
Found during the tutorial walk that produced #138.
cc @fryorcraken