Skip to content

[2.x] Return decoded nodes from dynamic parsers - #1216

Merged
lorisleiva merged 1 commit into
mainfrom
10-07-return_decoded_nodes_from_dynamic_parsers
Oct 9, 2026
Merged

lorisleiva merged 1 commit into
mainfrom
10-07-return_decoded_nodes_from_dynamic_parsers

Conversation

@lorisleiva

@lorisleiva lorisleiva commented Oct 7, 2026 •

Copy link
Copy Markdown
Member

This PR makes the parsers of @codama/dynamic-parsers return the decoded nodes of @codama/dynamic-codecs, so parsed accounts, events and instructions keep the node of every decoded value, e.g. to format it.

// Before
const parsed = parseAccountData(root, bytes);
parsed.data; // { amount: 42n }
parsed.path; // [root, program, account]

// After
const parsed = parseAccountData(root, bytes); // DecodedAccountNode
parsed.value; // { amount: 42n }
parsed.data; // the decoded struct, with its `fields`
parsed.path; // [root, program, account]
parsed.preOffset; // 0
parsed.postOffset; // 9
  • Decoded nodes: parseAccountData, parseEventData, parseInstructionData and parseData return DecodedAccountNode, DecodedEventNode and DecodedInstructionNode. ParsedData is removed, and the plain value moves from data to value.
  • ParsedInstruction: a DecodedInstructionNode with its named accounts and its remainingAccounts, which is now always present. Named accounts carry their identifier instead of a name.
  • Options: the new ParseDataOptions adds bytesEncoding to programAddress, and parseInstruction accepts bytesEncoding too.
  • Unparsable bytes: unchanged, parsers return undefined when nothing is identified or when the identified node cannot decode the bytes.

@changeset-bot

changeset-bot Bot commented Oct 7, 2026 •

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 9e05227

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

Swaps getNodeValueCodec for getNodeCodec in parseData, so every parser now returns the DecodedAccountNode / DecodedEventNode / DecodedInstructionNode of @codama/dynamic-codecs instead of the local ParsedData<TNode> wrapper. ParsedInstruction becomes DecodedInstructionNode & { accounts, remainingAccounts }, with remainingAccounts now required and named accounts carrying identifier rather than name. A new ParseDataOptions = CodecVisitorOptions & IdentifyDataOptions threads bytesEncoding through, and parseInstruction takes CodecVisitorOptions directly (its programAddress still comes from the instruction). README and tests are updated accordingly.

The implementation is a thin, correct delegation. Things I checked:

  • Option splitting in parseData is explicit ({ programAddress } → identifyData, { bytesEncoding } → getNodeCodec) rather than forwarding the merged object, so neither side sees keys it doesn't own. Identification only encodes discriminator constants, so it genuinely doesn't need bytesEncoding — nothing is lost there.
  • The as GetDecodedNodeFromKind<TKind> cast is the same shape of erasure as the previous path as NodePath<ParsableNode> and is sound: getNodeCodec on a ParsableNode path yields the union of the three decoded node types, and the kind filter already narrowed the path.
  • Unparsable bytes keep the same try/catch → undefined contract; the "truncated data" and "unknown program" tests still cover it.
  • parseInstruction options type is CodecVisitorOptions, not ParseDataOptions — correct, since passing a programAddress there would silently conflict with instruction.programAddress.
  • README anchors (#decoded-nodes, #value-format, #formatting) all exist in packages/dynamic-codecs/README.md.
  • No other in-repo consumers of ParsedData, .data from the parsers, or name on parsed accounts that this would break (@codama/dynamic-client doesn't depend on dynamic-parsers on this branch).

Things to watch out for

  • ParsedInstruction inherits data?: DecodedTypeNode from DecodedInstructionNode, so for data-less instructions (e.g. the close test) parsed.data is undefined while parsed.value is also undefined. That's consistent with dynamic-codecs, but the "Decoded nodes" intro in this README says every parser returns "the decoded nodes of its data" without that caveat — see inline.
  • The first parseAccountData test asserts toStrictEqual(getNodeCodec(...).decode(...)), which is mostly tautological on its own; it's fine because the two tests right after it pin down the actual shape (path/value/preOffset/postOffset and isDecodedNode(result.data, 'structTypeNode')).

Notes for subsequent reviewers

  • Changeset: none in the PR, which matches the convention on the other [2.x] PRs (seeded major changeset at the end of the migration). When that changeset is written, this PR contributes: ParsedData removed; data → value on all parser results; accounts[].name → identifier and remainingAccounts now required on ParsedInstruction; new ParseDataOptions / bytesEncoding option on all parsers and parseInstruction.
  • Behaviour of identification, the single-candidate fallback, and program selection is untouched — only the decode step and the return shape changed.

Comment thread packages/dynamic-parsers/README.md Outdated
Comment thread packages/dynamic-parsers/README.md Outdated
@lorisleiva
lorisleiva force-pushed the 10-07-return_decoded_nodes_from_dynamic_parsers branch from 95df4cd to dbc49ce Compare October 7, 2026 16:02
@lorisleiva
lorisleiva force-pushed the 10-07-return_decoded_nodes_from_dynamic_parsers branch from dbc49ce to 7a17377 Compare October 9, 2026 09:08
@lorisleiva
lorisleiva force-pushed the 10-07-add_formatters_for_decoded_nodes branch 2 times, most recently from 7256a9f to 46c664f Compare October 9, 2026 09:11
@lorisleiva
lorisleiva force-pushed the 10-07-return_decoded_nodes_from_dynamic_parsers branch from 7a17377 to 6bcd8c7 Compare October 9, 2026 09:11
@lorisleiva
lorisleiva force-pushed the 10-07-add_formatters_for_decoded_nodes branch from 46c664f to cbd7116 Compare October 9, 2026 09:12
@lorisleiva
lorisleiva force-pushed the 10-07-return_decoded_nodes_from_dynamic_parsers branch 2 times, most recently from 0d78a47 to 50bd2bc Compare October 9, 2026 09:13
@lorisleiva
lorisleiva force-pushed the 10-07-add_formatters_for_decoded_nodes branch 2 times, most recently from 62035f2 to ebd5a98 Compare October 9, 2026 09:14
@lorisleiva
lorisleiva force-pushed the 10-07-return_decoded_nodes_from_dynamic_parsers branch 2 times, most recently from 1a602d4 to ca4dea7 Compare October 9, 2026 09:15
@lorisleiva
lorisleiva force-pushed the 10-07-add_formatters_for_decoded_nodes branch 2 times, most recently from 06c0d0a to 9dbd31f Compare October 9, 2026 09:16
@lorisleiva
lorisleiva force-pushed the 10-07-return_decoded_nodes_from_dynamic_parsers branch from ca4dea7 to a938ada Compare October 9, 2026 09:16
@lorisleiva
lorisleiva force-pushed the 10-07-add_formatters_for_decoded_nodes branch from 9dbd31f to 4a978e5 Compare October 9, 2026 09:17
@lorisleiva
lorisleiva force-pushed the 10-07-return_decoded_nodes_from_dynamic_parsers branch 2 times, most recently from 99dd664 to faa3e5d Compare October 9, 2026 09:17
@lorisleiva
lorisleiva force-pushed the 10-07-add_formatters_for_decoded_nodes branch from 4a978e5 to 1d26fb1 Compare October 9, 2026 09:17
@lorisleiva
lorisleiva force-pushed the 10-07-return_decoded_nodes_from_dynamic_parsers branch from faa3e5d to 775a40c Compare October 9, 2026 09:18
@lorisleiva
lorisleiva force-pushed the 10-07-add_formatters_for_decoded_nodes branch 2 times, most recently from 8093254 to 239b195 Compare October 9, 2026 09:18
@lorisleiva
lorisleiva force-pushed the 10-07-return_decoded_nodes_from_dynamic_parsers branch 2 times, most recently from 9c4cc3c to dd87bae Compare October 9, 2026 09:19
@lorisleiva
lorisleiva force-pushed the 10-07-add_formatters_for_decoded_nodes branch from 239b195 to e128735 Compare October 9, 2026 09:19
Base automatically changed from 10-07-add_formatters_for_decoded_nodes to main October 9, 2026 09:19
@lorisleiva
lorisleiva force-pushed the 10-07-return_decoded_nodes_from_dynamic_parsers branch from dd87bae to 9e05227 Compare October 9, 2026 09:19
@lorisleiva
lorisleiva marked this pull request as ready for review October 9, 2026 09:20
@lorisleiva
lorisleiva merged commit 61a35e6 into main Oct 9, 2026
1 of 3 checks passed
@lorisleiva
lorisleiva deleted the 10-07-return_decoded_nodes_from_dynamic_parsers branch October 9, 2026 09:20
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