Skip to content

[2.x] Adapt nodes-from-anchor to Codama v2 - #1180

Merged
lorisleiva merged 1 commit into
mainfrom
09-25-adapt_nodes-from-anchor_to_codama_v2
Sep 30, 2026
Merged

lorisleiva merged 1 commit into
mainfrom
09-25-adapt_nodes-from-anchor_to_codama_v2

Conversation

@lorisleiva

@lorisleiva lorisleiva commented Sep 25, 2026 •

Copy link
Copy Markdown
Member

This PR adapts @codama/nodes-from-anchor to the Codama v2 node model, for both legacy (v00) and current (v01) Anchor IDLs.

Behaviour

  • Identifiers keep the casing of the IDL. Instructions, accounts, events, PDAs, fields, arguments, types, errors and constants are no longer camelCased, so every cross-reference (e.g. definedTypeLinkNodes and PDA seeds) matches the IDL exactly. Accounts flattened from nested groups are prefixed as ${group}_${account}, e.g. token_program_mint.
  • Instruction arguments become instruction data. Arguments are fields of instructionNode.data, a structTypeNode whose first field is the discriminator (with a fieldDiscriminatorNode). PDA seeds referencing arguments use dataValueNodes.
  • Wrapper nodes become transforms. Borsh strings and bytes use a u32 sizePrefixTransformNode, discriminators use fixedSizeTransformNodes and event data uses a hiddenPrefixTransformNode.
  • Numbers map to integerTypeNode or floatTypeNode (f32/f64). Integer constants are kept as lossless strings, so 64- and 128-bit values no longer lose precision, and float constants are canonicalised textually (e.g. 007.50 → 7.5) without losing precision.
  • Enums use enumVariantTypeNodes whose data is absent, a struct or a tuple.
  • Docs are joined into a single string and omitted when empty. Program docs and the docs of account and event types are now carried over.

Removed exports

  • instructionArgumentNodeFromAnchorV00 and instructionArgumentNodeFromAnchorV01: use structFieldTypeNodeFromAnchorV00 and structFieldTypeNodeFromAnchorV01 instead.
  • The per-kind enum variant helpers (enumEmptyVariantTypeNodeFromAnchorV0x, enumStructVariantTypeNodeFromAnchorV0x, enumTupleVariantTypeNodeFromAnchorV0x), replaced by enumVariantTypeNodeFromAnchorV0x.

Bug fixes

  • extractPdasVisitor no longer throws when fingerprinting PDAs.
  • v01 argument seeds are matched by their exact identifier, so snake_case arguments no longer throw ARGUMENT_TYPE_MISSING.
  • Shank instruction discriminators below index 16 are no longer odd-length hex strings.
  • A missing generic type argument throws GENERIC_TYPE_MISSING instead of crashing.
  • v01 errors without a message no longer get "name: " as docs, and empty v00 seed descriptions no longer produce empty docs.

Tests

All tests are ported to v2 nodes and raw casing, with new cases for joined docs, lossless and normalised constants, Shank discriminators, raw PDA collision renames and missing argument seeds.

@changeset-bot

changeset-bot Bot commented Sep 25, 2026 •

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 563892d

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

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

@lorisleiva

Copy link
Copy Markdown
Member Author

@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

Ports @codama/nodes-from-anchor (v00 + v01) to the v2 node model: raw-cased identifiers, instructionNode.data as a structTypeNode with a leading discriminator field, wrapper nodes replaced by transforms (sizePrefixTransformNode, fixedSizeTransformNode, hiddenPrefixTransformNode), numberTypeNode split into integerTypeNode/floatTypeNode with string-backed value nodes, unified enumVariantTypeNode, and docs joined into a single string. Along the way it fixes a handful of latent bugs (extractPdas fingerprint throwing on '', snake_case arg seeds, odd-length Shank discriminators, missing generic crash, empty-docs artifacts).

The refactor is clean and consistent across both IDL versions — the shared helpers in utils.ts (docsFromAnchor, fixedSizeBytesTypeNode, borshSizePrefixedTypeNode, removeBorshSizePrefix) remove a lot of duplication, and the test coverage for the new behaviours (lossless integers, raw-casing collisions, Shank padding, missing arg seeds, joined docs) is solid.

Things worth a look

  • canonicalFloat canonicalises through Number() — see inline. The DecimalString docs say canonicalisation is about spelling, not the f64 the string rounds to, and the current approach both silently mangles high-precision / large-magnitude decimals and downgrades small ones (0.0000001 → 1e-7 → string constant). A purely textual canonicaliser is a few lines and avoids both. Not blocking, but I'd fix it before merge since it's a new helper.
  • camelCase is still imported in both InstructionAccountNode.ts files. That's intentional — hasDuplicateAccountNames uses it to detect collisions under the spec's casing-collision rule (the new token_mint vs tokenMint test covers it). Flagging so nobody treats it as a leftover from the camelCasing removal.
  • origin is dropped from programNode. Correct for v2 (ProgramNode has no origin), but it means the Shank/Anchor distinction is no longer carried anywhere on the output tree. If a renderer ever needs it, a pluginNode is presumably the home — just noting it as a deliberate loss of information.
  • Changeset: none in the PR. Per CONTRIBUTING.md the seeded major changeset on the 2.x line covers all public packages, so this may be intentional — worth confirming that's the convention being followed for this branch given the removed exports (instructionArgumentNodeFromAnchorV0x, per-kind enum variant helpers).

For subsequent reviewers

  • removeBorshSizePrefix requires exactly one transform (transforms?.length === 1). That's fine for what this parser emits, but it's stricter than the v1 logic it replaces conceptually; anything decorating fields with extra transforms before PDA extraction would keep the prefix.
  • Nested account seeds are prefixed with the current group prefix (pdaSeedNodeFromAnchorV01 → ${prefix}_${accountName}), so a nested PDA referencing a top-level account still gets the wrong name. Pre-existing, unchanged here.
  • IdlV01Metadata.description exists and could serve as program-docs fallback — optional nit inline.

Comment thread packages/nodes-from-anchor/src/utils.ts Outdated
Comment thread packages/nodes-from-anchor/src/v01/ProgramNode.ts
@lorisleiva
lorisleiva force-pushed the 09-25-adapt_nodes-from-anchor_to_codama_v2 branch from 146deb5 to 662e982 Compare September 25, 2026 14:09

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

Re-review

Only utils.ts and the two ConstantNode test files changed since my last pass.

canonicalFloat is now textual — the regex-based canonicaliser replaces the String(Number(x)) round-trip, so high-precision, large-magnitude and small-fraction decimals all keep their exact spelling (3.14159265358979323846, 123456789012345678901.5, 0.0000001 are now covered by test.each cases in both v00 and v01). Output still matches DECIMAL_REGEX: leading zeros are stripped down to a single 0, trailing fraction zeros are dropped, and -0.00 → -0 is allowed by the spec since floats have signed zero. Non-decimal spellings like 1e3 still fall back to a string constant, which is the right call given the spec forbids exponent notation.

The optional metadata.description fallback for program docs wasn't taken, which is fine — that was a nit.

Everything else from the previous review stands; nothing new to flag. Good to merge.

@lorisleiva
lorisleiva force-pushed the 09-25-adapt_nodes-from-anchor_to_codama_v2 branch from 662e982 to 3c21987 Compare September 30, 2026 13:54
@lorisleiva
lorisleiva force-pushed the 09-25-adapt_instruction_visitors_to_codama_v2 branch from 566f28f to 621d4b9 Compare September 30, 2026 14:07
@lorisleiva
lorisleiva force-pushed the 09-25-adapt_nodes-from-anchor_to_codama_v2 branch from 3c21987 to 822c4db Compare September 30, 2026 14:07
@lorisleiva
lorisleiva force-pushed the 09-25-adapt_instruction_visitors_to_codama_v2 branch from 621d4b9 to 90e3656 Compare September 30, 2026 14:08
@lorisleiva
lorisleiva force-pushed the 09-25-adapt_nodes-from-anchor_to_codama_v2 branch from 822c4db to 35fe188 Compare September 30, 2026 14:08
@lorisleiva
lorisleiva force-pushed the 09-25-adapt_instruction_visitors_to_codama_v2 branch from 90e3656 to dcf7a0d Compare September 30, 2026 14:09
@lorisleiva
lorisleiva force-pushed the 09-25-adapt_nodes-from-anchor_to_codama_v2 branch 2 times, most recently from 7ada96f to b5a4252 Compare September 30, 2026 14:11
@lorisleiva
lorisleiva force-pushed the 09-25-adapt_instruction_visitors_to_codama_v2 branch from dcf7a0d to 015a2ca Compare September 30, 2026 14:11
@lorisleiva
lorisleiva force-pushed the 09-25-adapt_nodes-from-anchor_to_codama_v2 branch from b5a4252 to d1a13ad Compare September 30, 2026 14:12
@lorisleiva
lorisleiva force-pushed the 09-25-adapt_instruction_visitors_to_codama_v2 branch 2 times, most recently from 6ef73f4 to b8ab0fe Compare September 30, 2026 14:13
@lorisleiva
lorisleiva force-pushed the 09-25-adapt_nodes-from-anchor_to_codama_v2 branch from d1a13ad to 031ad68 Compare September 30, 2026 14:13
@lorisleiva
lorisleiva force-pushed the 09-25-adapt_instruction_visitors_to_codama_v2 branch from 6ef73f4 to b8ab0fe Compare September 30, 2026 14:13
@lorisleiva
lorisleiva force-pushed the 09-25-adapt_nodes-from-anchor_to_codama_v2 branch 2 times, most recently from 031ad68 to e51263e Compare September 30, 2026 14:14
@lorisleiva
lorisleiva force-pushed the 09-25-adapt_instruction_visitors_to_codama_v2 branch 2 times, most recently from 45f5d3f to f8d92f5 Compare September 30, 2026 14:15
@lorisleiva
lorisleiva force-pushed the 09-25-adapt_nodes-from-anchor_to_codama_v2 branch from e51263e to d435238 Compare September 30, 2026 14:15
Base automatically changed from 09-25-adapt_instruction_visitors_to_codama_v2 to main September 30, 2026 14:16
@lorisleiva
lorisleiva force-pushed the 09-25-adapt_nodes-from-anchor_to_codama_v2 branch from d435238 to 563892d Compare September 30, 2026 14:16
@lorisleiva
lorisleiva marked this pull request as ready for review September 30, 2026 14:17
@lorisleiva
lorisleiva merged commit 7391a19 into main Sep 30, 2026
0 of 2 checks passed
@lorisleiva
lorisleiva deleted the 09-25-adapt_nodes-from-anchor_to_codama_v2 branch September 30, 2026 14:17
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.

2 participants