Skip to content

Search additional programs when identifying and parsing data - #1024

Open
plutohan wants to merge 1 commit into
codama-idl:mainfrom
plutohan:plutohan/issue-553-parse-additional-programs
Open

Search additional programs when identifying and parsing data#1024
plutohan wants to merge 1 commit into
codama-idl:mainfrom
plutohan:plutohan/issue-553-parse-additional-programs

Conversation

@plutohan

Copy link
Copy Markdown
Contributor

Fixes #553.

identifyData only visited the root node's main program, so instructions living in additionalPrograms (e.g. the ATA program embedded in the token IDLs) could never be identified and were misparsed against the main program's discriminators.

  • The identification visitor now searches the main program first, then each additional program.
  • parseInstruction passes the instruction's programAddress down, restricting the search to programs matching that address. When no program matches, all programs are searched, which keeps the existing behavior for roots whose program IDs are placeholders.
  • The single-non-discriminated-node fallback applies the same program selection.
  • All identify*/parse* functions accept an optional programAddress option.

With this, an ATA createAssociatedTokenIdempotent carried in a token IDL's additional programs parses through the ATA program instead of colliding with the token program's initializeAccount on the shared one-byte discriminator.

@changeset-bot

changeset-bot Bot commented Jul 17, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 06941f4

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 3 packages
Name Type
@codama/dynamic-parsers Minor
@codama/dynamic-instructions Patch
@codama/dynamic-client Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@lorisleiva

Copy link
Copy Markdown
Member

@trevor-cortex

@trevor-cortex trevor-cortex left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Summary

Fixes the long-standing gap where identifyData / parseInstruction only ever searched root.program, causing instructions from additionalPrograms (e.g. ATA embedded in a token IDL) to be misidentified against the main program's discriminators. The change:

  • Introduces IdentifyDataOptions with a programAddress field, threaded through every identify* / parse* entry point.
  • getByteIdentificationVisitor now iterates all candidate programs via a new getCandidatePrograms helper — main program first (via getAllPrograms), then additional programs.
  • parseInstruction automatically passes instruction.programAddress down, so callers get correct routing for free.
  • When programAddress is provided but no program in the IDL matches, all programs are searched — this preserves behavior for IDLs whose publicKey fields are placeholders rather than real on-chain addresses.
  • The single-non-discriminated-node fallback now applies per candidate program with the same selection logic.

Things to watch

  • Fallback behavior is subtly broader. Previously the "single non-discriminated instruction" fallback only inspected root.program. It now inspects every candidate program (main first). For most IDLs this is a strict improvement, but any IDL that relied on the fallback returning undefined when the main program had multiple candidates — while an additional program happened to have exactly one non-discriminated node — would now get a match. Almost certainly desirable, worth being aware of.
  • Program-address matching is exact string equality on publicKey. No normalization / case handling — fine given publicKey is a base58 address, just noting it in case future IDLs ever carry non-canonical strings.
  • Ordering guarantee (main program wins over additional programs on ambiguous discriminators) is enforced by getAllPrograms returning main first. There's a test covering this, so the contract is pinned.

Notes for subsequent reviewers

  • The changeset is minor on @codama/dynamic-parsers, which matches: new optional option + expanded (non-breaking) identification surface.
  • getByteIdentificationVisitor is exported; its options type widened from { stack?: NodeStack } to IdentifyDataOptions & { stack?: NodeStack }. Backwards compatible for existing callers.
  • Test coverage is thorough: main-first ordering, address-restricted search, no-match-falls-back-to-all, and the additional-program single-non-discriminated fallback all have dedicated cases. The new parsers.test.ts case realistically models the ATA-vs-token discriminator collision from the linked issue.

Nice, tight fix.

@lorisleiva
lorisleiva requested a review from mikhd July 29, 2026 10:14
@lorisleiva

Copy link
Copy Markdown
Member

Thanks! Looks good to me. @mikhd Let me know if that's good on your side as well since that touches the dynamic packages.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[dynamic-parsers] Use additional programs when parsing data

3 participants