Skip to content

fix(sorobanUtils): decode Bytes struct fields so struct args build - #2193

Open
yigitcangokmen wants to merge 1 commit into
stellar:mainfrom
yigitcangokmen:fix/struct-bytes-field
Open

fix(sorobanUtils): decode Bytes struct fields so struct args build#2193
yigitcangokmen wants to merge 1 commit into
stellar:mainfrom
yigitcangokmen:fix/struct-bytes-field

Conversation

@yigitcangokmen

Copy link
Copy Markdown

Resolves #2192

Problem

Invoking a contract function, or deploying a contract, with a struct argument that contains a Bytes field fails to build in the Lab with:

TypeError: invalid type ("bytes") specified for string value

convertPrimitiveField (the struct-encoding path in src/helpers/sorobanUtils.ts) special-cases only bool; a bytes field is passed through as a raw string with typeHint bytes, and nativeToScVal(string, { type: "bytes" }) rejects it. Top-level bytes args, and bytes inside vecs/tuples, all work because those paths decode the string to a Uint8Array first (via getScValFromPrimitive and detectBytesEncoding); only the struct-field path was missed. This has been the case since convertPrimitiveField was introduced.

The operation is hard-blocked with no UI workaround: the value passes DataUrl validation, then getTxnToSimulate catches the error and surfaces it as an error string. Reachable from the Contract Explorer invoke form, the JSON-schema invoke path, and the deploy-contract constructor args.

Fix

Add a bytes case in convertPrimitiveField that decodes with the existing detectBytesEncoding helper, mirroring exactly what getScValFromPrimitive and the vec/tuple paths already do. This also covers fixed-length BytesN<N> struct fields, since the form maps both Bytes and BytesN to type: "bytes".

Tests

Adds a getScValsFromArgs case: a struct with a bytes field (hex) encodes to the expected scvMap containing scvBytes. It fails on main (the invalid type ("bytes") throw) and passes with this change; the existing getScValsFromArgs suite and the full unit suite stay green.

convertPrimitiveField special-cased only bool, so a bytes field in a
struct argument was passed to nativeToScVal as a raw string with type
bytes and rejected with "invalid type (bytes) specified for string
value". Top-level bytes and bytes inside vecs/tuples already decode the
string to a Uint8Array first; only the struct-field path was missed.

Add a bytes case mirroring getScValFromPrimitive (reusing
detectBytesEncoding). Covers BytesN struct fields too, and adds a
getScValsFromArgs test for a struct with a bytes field.
Copilot AI balanced review requested due to automatic review settings August 27, 2026 15:16
@github-project-automation github-project-automation Bot moved this to Backlog (Not Ready) in DevX Aug 27, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Fixes struct arguments containing Bytes/BytesN fields by decoding byte strings before Soroban XDR conversion.

Changes:

  • Adds byte-encoding detection and Uint8Array conversion for struct fields.
  • Adds a regression test for hexadecimal bytes within a struct.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
src/helpers/sorobanUtils.ts Converts struct byte fields before nativeToScVal.
tests/unit/getScValsFromArgs.test.ts Tests struct-to-scvMap byte encoding.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

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

Labels

None yet

Projects

Status: Backlog (Not Ready)

Development

Successfully merging this pull request may close these issues.

Struct argument with a Bytes field fails to build ("invalid type (\"bytes\") specified for string value")

2 participants