Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/transaction-output-deprecated.md
Original file line number Diff line number Diff line change
@@ -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.
21 changes: 21 additions & 0 deletions packages/evolution/src/TransactionOutput.ts
Original file line number Diff line number Diff line change
@@ -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"
Expand Down Expand Up @@ -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>()(
"ShelleyTransactionOutput",
Expand Down Expand Up @@ -82,6 +101,7 @@ export class ShelleyTransactionOutput extends Schema.TaggedClass<ShelleyTransact
*
* @since 2.0.0
* @category model
* @deprecated Use `TxOut.TransactionOutput` instead.
*/
export class BabbageTransactionOutput extends Schema.TaggedClass<BabbageTransactionOutput>()(
"BabbageTransactionOutput",
Expand Down Expand Up @@ -138,6 +158,7 @@ export class BabbageTransactionOutput extends Schema.TaggedClass<BabbageTransact
*
* @since 2.0.0
* @category schemas
* @deprecated Use `TxOut.TransactionOutput` instead.
*/
export const TransactionOutput = Schema.Union(ShelleyTransactionOutput, BabbageTransactionOutput)

Expand Down
40 changes: 40 additions & 0 deletions packages/evolution/test/TransactionOutput.deprecated.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { Schema } from "effect"
import { describe, expect, it } from "vitest"

import * as CoreAddress from "../src/Address.js"
import * as AddressEras from "../src/AddressEras.js"
import * as Assets from "../src/Assets.js"
import * as KeyHash from "../src/KeyHash.js"
import * as PrivateKey from "../src/PrivateKey.js"
import * as TransactionBody from "../src/TransactionBody.js"
import * as TransactionOutput from "../src/TransactionOutput.js"
import * as TxOut from "../src/TxOut.js"
import * as Value from "../src/Value.js"

/**
* The two output models are not interchangeable, which is what the deprecation on
* `TransactionOutput` is about: a body takes `TxOut`, and nothing else.
*/
const keyHash = KeyHash.fromPrivateKey(PrivateKey.fromBytes(PrivateKey.generate()))
const address = new CoreAddress.Address({ networkId: 0, paymentCredential: keyHash })

describe("TransactionOutput and TxOut are two models of one thing", () => {
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")
})
})