Skip to content

[2.x] Adapt the dynamic-instructions builder to Codama v2 - #1194

Merged
lorisleiva merged 1 commit into
mainfrom
09-30-adapt_the_dynamic-instructions_builder_to_codama_v2
Sep 30, 2026
Merged

lorisleiva merged 1 commit into
mainfrom
09-30-adapt_the_dynamic-instructions_builder_to_codama_v2

Conversation

@lorisleiva

@lorisleiva lorisleiva commented Sep 30, 2026 •

Copy link
Copy Markdown
Member

This PR adapts the instruction builder of @codama/dynamic-instructions to Codama v2. Its display layer is adapted separately.

  • createInstructionsBuilder(path) takes the NodePath of the instruction, e.g. [root, program, instruction], and returns build({ accounts, data, signers }). The program address now comes from the program defining the instruction, so instructions of additional programs are supported.
  • encodeInstructionArguments becomes encodeInstructionData(path, data), alongside createInstructionDataEncoder(path). Data is encoded with the codec of @codama/dynamic-codecs, which rejects values of the wrong type, so the superstruct validator and dependency are removed. Codama errors raised while encoding pass through, and other encoding errors throw DYNAMIC_CLIENT__FAILED_TO_ENCODE_DATA with the original error as cause.
  • createAccountMeta becomes createAccountMetas({ path, accounts, data, signers }), resolving accounts through resolveInstructionAccountAddress. Remaining accounts are provided as lists of addresses under their identifier, e.g. { signers: [a, b] }, which AccountsInput now accepts.
  • Custom resolvers are removed, following the removal of resolverValueNode, and ArgumentsInput becomes DataInput.
  • Generated builder types use InstructionsBuilderFn<${Name}InstructionDataArgs, ${Name}Accounts, ${Name}Signers>.
  • Renames the DYNAMIC_CLIENT__FAILED_TO_ENCODE_ARGUMENT and DYNAMIC_CLIENT__INVALID_ARGUMENT_INPUT errors to DYNAMIC_CLIENT__FAILED_TO_ENCODE_DATA and DYNAMIC_CLIENT__INVALID_ACCOUNT_INPUT, keeping their codes, and deprecates DYNAMIC_CLIENT__DEFAULT_VALUE_MISSING.

@changeset-bot

changeset-bot Bot commented Sep 30, 2026 •

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: d8e6a86

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

Adapts the @codama/dynamic-instructions builder to Codama v2: every entry point now takes the instruction's NodePath (so additional programs work via findProgramNodeFromPath), data encoding is delegated to getNodeValueCodec from @codama/dynamic-codecs (dropping superstruct and the hand-rolled validators), remaining accounts move from data/argument values to identifier-keyed address lists under accounts, and custom resolvers are removed. AccountsInput in dynamic-address-resolution gains readonly AddressInput[], with a new getAccountInput guard so the resolvers reject lists for named accounts. Error constants are renamed keeping their codes.

The shape is a clear improvement — ~1.3k lines of validation removed in exchange for the codec's own type checks, a single { accounts, data, signers } input object, and much better test coverage (the old package had no builder-level test at all). The optionalAccountStrategy ?? 'programId' default in the readonly downgrade also fixes a v1 gap where the strict === 'programId' check missed IDLs that omit the strategy.

Things to watch out for

  • FAILED_TO_ENCODE_DATA wraps all non-UNEXPECTED_VALUE_TYPE errors, including other CodamaErrors. Since getNodeValueCodecVisitor evaluates struct field defaults lazily at encode time (see getDefaultValueGetter), an injectedValueNode default with no provider, or a link failing to resolve inside a default, throws its own Codama error during codec.encode(...) — and gets hidden behind a generic FAILED_TO_ENCODE_DATA with the real code only in cause. Suggested inline: rethrow any isCodamaError(error) as-is and only wrap foreign errors (Kit SolanaErrors like out-of-range). Non-blocking.
  • Codec creation is now eager in createInstructionsBuilder. getNodeValueCodec(path) runs at builder creation, so an instruction with a broken definedTypeLinkNode throws synchronously from createInstructionsBuilder rather than rejecting on build(). Fail-fast is arguably better, but whoever adapts dynamic-client (which creates a builder per instruction) should be aware a single bad instruction will now take down createProgramClient unless it catches per-instruction.
  • Empty list for a required remaining-accounts tail is accepted. The spec docblock says isOptional is "whether the remaining-accounts tail may be empty". getRemainingAccountMetas only rejects undefined, so signers: [] passes for a required tail (and the test explicitly asserts this). Same as v1 behaviour, so fine to defer, but worth a deliberate decision — see inline.
  • Two ways to fail on the same input. A named account given a list throws INVALID_ACCOUNT_ADDRESS via assertValidAccountAddresses in createAccountMetas, but UNEXPECTED_ADDRESS_TYPE via getAccountInput if you call resolveInstructionAccountAddress directly. Minor, see inline.

Notes for subsequent reviewers

  • test/test-utils.ts is untouched and still uses the v1 node API (name, arguments) — it's the display layer's helper file, being adapted separately. Codegen/CLI tests were moved to the new _setup.ts, so there are now two makeRoot/generateAddress helpers side by side. Consolidate when the display PR lands.
  • dynamic-client/src/index.ts still re-exports ArgumentsInput from dynamic-address-resolution, which no longer exists. Pre-existing on this branch and out of scope here — only the error constant renames were touched — but it confirms dynamic-client won't type-check until its own adaptation.
  • No changeset in the diff. @codama/errors (renamed exports), @codama/dynamic-address-resolution (AccountsInput widened) and @codama/dynamic-instructions all have user-facing changes. Per CONTRIBUTING the major cut seeds a changeset covering all packages, so this may be intentional on the 2.x branch — just verify that's the convention being followed for the other [2.x] PRs.
  • The codegen map still only iterates idl.program.instructions, so builder types aren't generated for additional programs even though the runtime now supports them. Pre-existing scope, not a regression.

Comment thread packages/dynamic-instructions/src/data/encode-instruction-data.ts Outdated
Comment thread packages/dynamic-instructions/src/accounts/create-account-metas.ts
Comment thread packages/dynamic-instructions/src/accounts/create-account-metas.ts Outdated
Comment thread packages/dynamic-instructions/src/accounts/create-account-metas.ts Outdated
@lorisleiva
lorisleiva force-pushed the 09-30-adapt_the_dynamic-instructions_builder_to_codama_v2 branch from 2a7865f to 2f32ece Compare September 30, 2026 11:37

@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

Re-fetched the diff. All four points from the previous pass have been addressed:

  • Codama errors pass through unchanged — createInstructionDataEncoder now rethrows isCodamaError(error) and only wraps foreign errors in FAILED_TO_ENCODE_DATA. Covered by the new it throws other Codama errors as is test (INJECTED_VALUE_NOT_PROVIDED surfacing from a lazily-evaluated default), and the docblock/README paragraph were updated to match.
  • Empty required remaining-accounts tail — now a documented decision in the createAccountMetas docblock ("must be provided, possibly as an empty list"). Fine by me.
  • One error code for a list given to a named account — assertValidAccountAddresses lets arrays fall through to the resolver, so both createAccountMetas and resolveInstructionAccountAddress throw UNEXPECTED_ADDRESS_TYPE. Test updated accordingly.
  • toAddressOrThrow reuse — exported from dynamic-address-resolution (signature widened to string so signers[1]-style names work) and used in getRemainingAccountMetas; the redundant as Address is gone.

Nothing new to flag. The remaining (addresses as unknown[]) cast is a pragmatic workaround for Array.isArray narrowing poorly on readonly unions — not worth fighting.

The notes for follow-ups from the previous review still stand (eager codec creation in createInstructionsBuilder when adapting dynamic-client, the duplicated test-utils.ts/_setup.ts helpers until the display PR lands, the stale ArgumentsInput re-export in dynamic-client, and confirming the 2.x changeset convention).

@lorisleiva
lorisleiva force-pushed the 09-30-adapt_the_dynamic-instructions_builder_to_codama_v2 branch from 2f32ece to 7e26f27 Compare September 30, 2026 13:54
@lorisleiva
lorisleiva force-pushed the 09-29-reject_values_of_the_wrong_type_when_encoding_dynamic_codecs branch 2 times, most recently from 2e559ef to 1655168 Compare September 30, 2026 14:07
@lorisleiva
lorisleiva force-pushed the 09-30-adapt_the_dynamic-instructions_builder_to_codama_v2 branch from 43372f4 to b6d6105 Compare September 30, 2026 14:13
@lorisleiva
lorisleiva force-pushed the 09-29-reject_values_of_the_wrong_type_when_encoding_dynamic_codecs branch 2 times, most recently from b79b1c0 to 50f84a6 Compare September 30, 2026 14:13
@lorisleiva
lorisleiva force-pushed the 09-30-adapt_the_dynamic-instructions_builder_to_codama_v2 branch from b6d6105 to 86623ec Compare September 30, 2026 14:14
@lorisleiva
lorisleiva force-pushed the 09-29-reject_values_of_the_wrong_type_when_encoding_dynamic_codecs branch from 0b55a54 to a72493e Compare September 30, 2026 14:15
@lorisleiva
lorisleiva force-pushed the 09-30-adapt_the_dynamic-instructions_builder_to_codama_v2 branch from 86623ec to 126d297 Compare September 30, 2026 14:15
@lorisleiva
lorisleiva force-pushed the 09-29-reject_values_of_the_wrong_type_when_encoding_dynamic_codecs branch from a72493e to a5ba85a Compare September 30, 2026 14:16
@lorisleiva
lorisleiva force-pushed the 09-30-adapt_the_dynamic-instructions_builder_to_codama_v2 branch from 126d297 to 570230c Compare September 30, 2026 14:16
@lorisleiva
lorisleiva force-pushed the 09-29-reject_values_of_the_wrong_type_when_encoding_dynamic_codecs branch from a5ba85a to 6845cc7 Compare September 30, 2026 14:17
@lorisleiva
lorisleiva force-pushed the 09-30-adapt_the_dynamic-instructions_builder_to_codama_v2 branch 2 times, most recently from 4bfb4f6 to 6c6aeb0 Compare September 30, 2026 14:18
@lorisleiva
lorisleiva force-pushed the 09-29-reject_values_of_the_wrong_type_when_encoding_dynamic_codecs branch from 6845cc7 to b57efa1 Compare September 30, 2026 14:18
@lorisleiva
lorisleiva force-pushed the 09-30-adapt_the_dynamic-instructions_builder_to_codama_v2 branch from 6c6aeb0 to b74e525 Compare September 30, 2026 14:18
@lorisleiva
lorisleiva force-pushed the 09-29-reject_values_of_the_wrong_type_when_encoding_dynamic_codecs branch 2 times, most recently from 8a311bc to a773e2e Compare September 30, 2026 14:19
@lorisleiva
lorisleiva force-pushed the 09-30-adapt_the_dynamic-instructions_builder_to_codama_v2 branch 2 times, most recently from 6d153a0 to db46f59 Compare September 30, 2026 14:20
@lorisleiva
lorisleiva force-pushed the 09-29-reject_values_of_the_wrong_type_when_encoding_dynamic_codecs branch 2 times, most recently from add2ee0 to cac2333 Compare September 30, 2026 14:21
@lorisleiva
lorisleiva force-pushed the 09-30-adapt_the_dynamic-instructions_builder_to_codama_v2 branch from db46f59 to 45e5f64 Compare September 30, 2026 14:21
@lorisleiva
lorisleiva force-pushed the 09-29-reject_values_of_the_wrong_type_when_encoding_dynamic_codecs branch from cac2333 to eadafbd Compare September 30, 2026 14:21
@lorisleiva
lorisleiva force-pushed the 09-30-adapt_the_dynamic-instructions_builder_to_codama_v2 branch 2 times, most recently from 2e6b2d4 to 5a4f4c0 Compare September 30, 2026 14:22
@lorisleiva
lorisleiva force-pushed the 09-29-reject_values_of_the_wrong_type_when_encoding_dynamic_codecs branch from eadafbd to 7f7c898 Compare September 30, 2026 14:22
Base automatically changed from 09-29-reject_values_of_the_wrong_type_when_encoding_dynamic_codecs to main September 30, 2026 14:22
@lorisleiva
lorisleiva force-pushed the 09-30-adapt_the_dynamic-instructions_builder_to_codama_v2 branch from 5a4f4c0 to d8e6a86 Compare September 30, 2026 14:23
@lorisleiva
lorisleiva marked this pull request as ready for review September 30, 2026 15:16
@lorisleiva
lorisleiva merged commit be5f894 into main Sep 30, 2026
2 of 4 checks passed
@lorisleiva
lorisleiva deleted the 09-30-adapt_the_dynamic-instructions_builder_to_codama_v2 branch September 30, 2026 15:16
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