Skip to content

fix: preserve Map (and bigint) in cloneOutput via structuredClone#831

Open
OscarOzaine wants to merge 1 commit into
MeshJS:mainfrom
OscarOzaine:fix/clone-output-map-704
Open

fix: preserve Map (and bigint) in cloneOutput via structuredClone#831
OscarOzaine wants to merge 1 commit into
MeshJS:mainfrom
OscarOzaine:fix/clone-output-map-704

Conversation

@OscarOzaine
Copy link
Copy Markdown

Summary

cloneOutput deep-cloned outputs via a JSON round-trip (JSONBig.parse(JSONBig.stringify(...))), which silently drops Map entries (and mangles bigint) inside a Mesh Data inline datum. When an inline datum contains a Map — e.g. CIP-68 metadata produced by metadataToCip68 and used with .txOutInlineDatumValue(..., "Mesh") — the Map was cloned to an empty {}, and serialization later threw TypeError: Cannot convert undefined to a BigInt in toPlutusData.

This switches cloneOutput to structuredClone, which preserves Map, bigint, Uint8Array and nested structures. It's also consistent with how the tx builder already clones txOutput and other queue items in tx-builder-core.ts.

Fixes #704

Root cause

packages/mesh-transaction/src/mesh-tx-builder/index.tscloneOutput is called by getOutputMinLovelace on every min-ADA calculation, so any output whose inline datum holds a Map was corrupted during transaction building.

// before
export const cloneOutput = (output: Output): Output => {
  return JSONBig.parse(JSONBig.stringify(output));
};
// after
export const cloneOutput = (output: Output): Output => {
  return structuredClone(output);
};

Tests

Adds packages/mesh-transaction/test/clone-output.test.ts:

  • a Map inside a Mesh Data inline datum survives cloning (size + entries),
  • bigint fields survive,
  • the clone is a deep, independent copy,
  • plain ADA-only outputs are unaffected.

All existing @meshsdk/transaction tests pass (24 suites / 128 tests); tsc --noEmit clean; prettier clean.

Credit

Thanks to @Daennes for the precise diagnosis and for suggesting structuredClone in the issue.

🤖 Generated with Claude Code

cloneOutput used a JSON round-trip, which silently drops Map entries and
mangles bigint inside Mesh Data inline datums (e.g. CIP-68 metadata from
metadataToCip68). The empty Map then made serializeOutput throw
"Cannot convert undefined to a BigInt".

Use structuredClone, consistent with how the tx builder already clones
txOutput and other queue items in tx-builder-core.ts.

Adds regression tests for Map preservation, bigint preservation,
deep-copy independence, and plain ADA-only outputs.

Fixes MeshJS#704

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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.

cloneOutput helper function Map support

1 participant