From 6541c64b6eaee90198d27b6ffee69b6630858cd9 Mon Sep 17 00:00:00 2001 From: jorbuedo Date: Wed, 21 Oct 2026 13:03:34 +0200 Subject: [PATCH] docs(transaction-output): deprecate it in favour of TxOut Two models of a transaction output are public from the entry point under names that give no hint which is which: this one (`address: AddressEras`, `amount: Value`, a Shelley and a Babbage class) and `TxOut` (`address: Address`, `assets: Assets`, one class for both eras), which is what `TransactionBody`, the builders and the sdk take. They reject each other, and the error says `Expected TransactionOutput, actual [toString threw]` about a value that IS a `TransactionOutput` -- the other one. Deprecation rather than removal or an alias: every caller holding a `BabbageTransactionOutput` keeps working, and new code is pointed at `TxOut`. The test pins the claim the note makes. --- .changeset/transaction-output-deprecated.md | 5 +++ packages/evolution/src/TransactionOutput.ts | 21 ++++++++++ .../test/TransactionOutput.deprecated.test.ts | 40 +++++++++++++++++++ 3 files changed, 66 insertions(+) create mode 100644 .changeset/transaction-output-deprecated.md create mode 100644 packages/evolution/test/TransactionOutput.deprecated.test.ts diff --git a/.changeset/transaction-output-deprecated.md b/.changeset/transaction-output-deprecated.md new file mode 100644 index 000000000..93ba79918 --- /dev/null +++ b/.changeset/transaction-output-deprecated.md @@ -0,0 +1,5 @@ +--- +"@evolution-sdk/evolution": patch +--- + +`TransactionOutput` is deprecated in favour of `TxOut`. It is a second, parallel model of a transaction output (`address: AddressEras`, `amount: Value`, a Shelley and a Babbage class) while `TxOut` carries the one `TransactionBody`, the builders and the sdk use (`address: Address`, `assets: Assets`, one class for both eras). Both are public under names that give no hint which is which, and they reject each other: an output built with `TransactionOutput` cannot go into a `TransactionBody`. Nothing is removed or re-pointed, so no caller breaks. diff --git a/packages/evolution/src/TransactionOutput.ts b/packages/evolution/src/TransactionOutput.ts index 24c4225c6..c2c7e4b0e 100644 --- a/packages/evolution/src/TransactionOutput.ts +++ b/packages/evolution/src/TransactionOutput.ts @@ -1,3 +1,21 @@ +/** + * Transaction outputs, as a union of a Shelley-era and a Babbage-era class. + * + * ⚠️ **Deprecated: use {@link TxOut} instead.** This is a SECOND, parallel model of a transaction + * output -- `address: AddressEras` and `amount: Value` -- while `TxOut` carries the one + * `TransactionBody`, the builders and the sdk actually use (`address: Address`, `assets: Assets`, + * one class covering both eras). Both are public from the package entry point under names that + * give no hint which is which, and they reject each other: an output built here cannot be placed + * in a `TransactionBody`, and the error reads `Expected TransactionOutput, actual [toString + * threw]` about a value that IS a `TransactionOutput` -- the other one. + * + * It stays exported, and keeps working, because removing it or pointing it at `TxOut` would break + * every caller that holds a `BabbageTransactionOutput`. New code should reach for `TxOut`. + * + * @since 2.0.0 + * @deprecated Use `TxOut` instead; see the module note above. + */ + import { Either as E, Equal, FastCheck, Hash, Inspectable, ParseResult, Schema } from "effect" import * as AddressEras from "./AddressEras.js" @@ -30,6 +48,7 @@ const decScriptRef = ParseResult.decodeUnknownEither(ScriptRef.FromCDDL) * * @since 2.0.0 * @category model + * @deprecated Use `TxOut.TransactionOutput` instead. */ export class ShelleyTransactionOutput extends Schema.TaggedClass()( "ShelleyTransactionOutput", @@ -82,6 +101,7 @@ export class ShelleyTransactionOutput extends Schema.TaggedClass()( "BabbageTransactionOutput", @@ -138,6 +158,7 @@ export class BabbageTransactionOutput extends Schema.TaggedClass { + it("a TransactionBody takes a TxOut output", () => { + const body = new TransactionBody.TransactionBody({ + inputs: [], + outputs: [new TxOut.TransactionOutput({ address, assets: Assets.fromLovelace(2_000_000n) })], + fee: 200_000n + }) + expect(body.outputs).toHaveLength(1) + }) + + it("refuses a TransactionOutput in a TransactionBody, which is why new code wants TxOut", () => { + const legacy = new TransactionOutput.BabbageTransactionOutput({ + address: AddressEras.fromHex(CoreAddress.toHex(address)), + amount: Value.onlyCoin(2_000_000n) + }) + const decode = Schema.decodeUnknownEither(TransactionBody.TransactionBody) + const result = decode({ inputs: [], outputs: [legacy], fee: 200_000n }) + expect(result._tag).toBe("Left") + }) +})