Skip to content

IDL generation paths diverge: make idl drops #[account_type] that spel generate-idl picks up #141

@vpavlin

Description

@vpavlin

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:

  1. 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.

  2. 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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions