You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
cardano-api defines its own uninhabited era tag types (data ByronEra, data ShelleyEra, ..., data DijkstraEra) in Cardano.Api.Era.Internal.Core, and bridges them to cardano-ledger's era types through type families.
cardano-ledger already defines the same eight tags (Byron included) as bare data declarations of kind Type, exported from Cardano.Ledger.Api.Era.
This issue proposes deleting cardano-api's copies and re-exporting ledger's types instead, so that the api era and the ledger era are the same type and every bridging family collapses to identity.
The switch happens inside Cardano.Api.Era.Internal.Core: the module keeps exporting the same names through the same export chain (Cardano.Api.Era, Cardano.Api, Cardano.Api.Experimental), so the transition is seamless for consumers - no import changes, no renamed types, only the type identity underneath changes.
We currently maintain four hand-written copies of the same bijection:
ShelleyLedgerEra (closed, injective, 7 equations) in Cardano.Api.Era.Internal.Eon.ShelleyBasedEra
CardanoLedgerEra (closed, injective, Byron to Conway, missing Dijkstra, zero internal consumers, still exported from Cardano.Api) in Cardano.Api.Era.Internal.Core
LedgerEra (Conway and Dijkstra only) in Cardano.Api.Experimental.Era
ToApiEra (the reverse direction, all 8 eras, private) in Cardano.Api.Experimental.Tx.Internal.Type
None of these needs to exist after the switch; the publicly exported ones are kept as deprecated identity synonyms for a deprecation period, then removed.
Why now
The experimental API is already halfway there. UnsignedTx, Exp.TxOut, TxBodyContent, AnyWitness, Certificate and the other experimental leaf types are parameterised by the ledger era directly (#1089, implemented in #1093). LedgerEra era exists only as glue between tag-indexed signatures (Era era, IsEra era) and those ledger-indexed data types, and users have to write Exp.TxOut (LedgerEra era) instead of Exp.TxOut era because GHC cannot see the two eras are equal without obtainCommonConstraints in scope. EraCommonConstraints even carries ShelleyLedgerEra era ~ LedgerEra era (in both directions) to keep the old and new families in agreement.
Unifying the tags removes this entire class of friction rather than documenting around it.
On the ledger side, the crypto parameter removal (IntersectMBO/cardano-ledger#4223, implemented in #4788) left the era types as plain phantom tags: data ShelleyEra with no parameters, kind Type, exactly the shape of our own tags.
Ledger also defines a deliberately minimal ByronEra (an Era instance and nothing else, kept alive so that PreviousEra ShelleyEra resolves), so even Byron has a direct counterpart.
Consensus already sits on ledger's types: Ouroboros.Consensus.Shelley.Eras re-exports them, so Consensus.ShelleyEra in our code is already ledger's ShelleyEra.
cardano-api is the only layer left with its own era universe.
Alternatives considered
Keep the status quo and document the friction.
The four bridging families stay, every new era adds an equation to each of them, and the Exp.TxOut (LedgerEra era) workaround stays with them.
This is the baseline cost the proposal removes, and it grows with each era.
Unify only the experimental API.
The experimental leaf types are already ledger-parameterised, so this is nearly done, but it leaves ShelleyLedgerEra and its ~613 use sites untouched in the old API and keeps the SignedTx-style seams at the old/new boundary.
Bridge with something weaker than type identity.
The tags are phantom types with no values, so there is nothing to coerce or wrap; a type family is the only possible bridge between distinct tags, and that is exactly what we maintain today.
Push in the other direction, i.e. ledger adopts cardano-api's tags.
Wrong dependency direction: consensus and ledger already agree on ledger's types, cardano-api is the odd one out.
Proposed change
In Cardano.Api.Era.Internal.Core, delete the eight data XEra declarations and re-export the ledger types instead (imported from Cardano.Ledger.Api.Era, the sanctioned export point; the defining module in cardano-ledger-core is warning-tagged internal).
This is the seamlessness requirement: the tags stay reachable under the exact same names from the exact same modules, so no consumer changes an import line.
Keep every existing instance where it is.
All instances on the tags (IsCardanoEra, HasTypeProxy with its AsType data instances, IsShelleyBasedEra, the era-onwards classes, HasScriptLanguageInEra, IsEra, ...) are instances of cardano-api-owned classes, so they stay non-orphan when the type moves to ledger.
Replace all three public families with deprecated identity synonyms: type ShelleyLedgerEra era = era, and likewise CardanoLedgerEra and the experimental LedgerEra.
Existing signatures keep compiling (now with a deprecation warning), and applications to concrete eras (ShelleyLedgerEra ConwayEra) reduce to the era itself.
As synonyms the families also become total: CardanoLedgerEra gains the Dijkstra case the current family is missing, and LedgerEra applies beyond Conway and Dijkstra.
Delete the private ToApiEra family.
It is not exported (its module exports only UnsignedTx (..)), so no deprecation period is needed.
Simplify the constraint bundles.
Every eon bundle (ShelleyBasedEraConstraints and the ten others) constrains L.EraX (ShelleyLedgerEra era); these become L.EraX era.
The ShelleyLedgerEra era ~ LedgerEra era pair in EraCommonConstraints and the ShelleyBlock (ConsensusProtocol era) (ShelleyLedgerEra era) ~ ConsensusBlockForEra era equalities become trivial and can go.
Align SignedTx with UnsignedTx. SignedTx is currently the one experimental type still keyed on the api tag via ShelleyLedgerEra (a deliberate choice in Widen Exp.SignedTx to all Shelley-based eras #1199, because LedgerEra only covers two eras and SignedTx needs all Shelley-based ones).
With unified tags both conventions denote the same type, so the special case disappears.
How broad is the change
Numbers from a survey of cardano-api and its main consumers (cardano-cli, all cardano-api-consuming packages of the cardano-node repo including the bench family, cardano-testnet and a few smaller tools) against cardano-api commit bf5c2a916 (2026-07-27), with cardano-ledger-core 1.20.0.0 and cardano-ledger-api 1.13.0.0 pinned.
Inside the cardano-api repo:
Measure
Count
ShelleyLedgerEra occurrences
~613 in ~54 files (cardano-api, tests, cardano-rpc)
... of which applied to a type variable
90 to 95 % (compile unchanged with the identity synonym)
LedgerEra (experimental) occurrences
341 in 21 modules
obtainCommonConstraints call sites
171 in 22 modules (including cardano-wasm and cardano-rpc)
Instance declarations on concrete era tags
80, all in the main library, all stay well-typed
Files that mix unqualified api tags with qualified ledger tags
8 (the real edit sites)
Concrete @XEra type applications
effectively zero
The edits concentrate in Cardano.Api.Era.Internal.Core (the definition site), Cardano.Api.Experimental.Era, Cardano.Api.Era.Internal.Eon.ShelleyBasedEra, and the 11 eon modules' constraint bundles.
The rest of the library compiles unchanged or loses redundant qualifiers.
No DataKinds promotion of the tags exists anywhere, no instance head mentions ShelleyLedgerEra era, and the three TestEquality instances match on term-level constructors, so none of the usual type-swap traps apply.
Downstream (surveyed consumers):
Repo
ShelleyLedgerEra sites
Notes
cardano-cli
34 in 11 files
one identity shim (fromShelleyLedgerPParamsShim) becomes deletable; the rest compiles via the synonym
cardano-node
7 in 2 files
tracing instances with ShelleyLedgerEra era ~ ledgerera constraints, which become trivially satisfied
cardano-testnet
12 in 6 files
plain projections, become no-ops
tx-generator (cardano-node bench)
4 in 2 files
generic era projections, compile unchanged via the synonym
era handling goes through eon witnesses, unaffected
Zero downstream instances are declared on a concrete api era tag, so no instance overlap arises in any surveyed repo.
Effort estimate: one core PR for steps 1 to 5 (roughly 10 files of real edits plus mechanical constraint-bundle changes, 2 to 4 days including CI matrix fallout on GHC 9.6/9.10/9.12), one small follow-up PR for SignedTx and experimental cleanup, and trivial downstream PRs (hours each).
A major version bump of cardano-api either way.
What actually breaks
The baseline: a consumer that reaches the tags and ShelleyLedgerEra through Cardano.Api's public surface does not break at the source level.
The names and modules are unchanged, the identity synonym keeps every ShelleyLedgerEra era signature compiling, and all term-level code (era witnesses, eon dispatch, TestEquality) is untouched, so for the ~90-95 % generic-era majority the change arrives as a recompile against a new major version.
What does break:
Nothing breaks immediately from the family collapse itself, because ShelleyLedgerEra, CardanoLedgerEra and the experimental LedgerEra all stay on as deprecated identity synonyms for the deprecation period.
Even signatures written in today's recommended style, such as f :: Era era -> Exp.TxOut (LedgerEra era) -> ..., keep compiling, now with a deprecation warning.
Consumers building with -Werror and without -Wno-deprecations turn those warnings into errors; that is the usual cost of that setting, and cardano-api itself avoids it because the core PR rewrites all internal uses (it must, since the repo builds with -Werror).
The real source break is deferred to the synonyms' removal at the end of the deprecation period: across the surveyed repos that would be ~613 ShelleyLedgerEra and 341 LedgerEra occurrences, nearly all inside cardano-api and already rewritten by the core PR, leaving only the small downstream counts in the table above.
A package that defines instances of the same class for both cardano-api's XEra and ledger's XEra gets a duplicate-instance error, since the two heads become identical.
Zero such cases exist in the surveyed repos; possible in principle on Hackage/CHaP, so the changelog must call it out.
Code that deliberately told the two type universes apart becomes redundant rather than wrong.
The only such code found is bridging glue: cardano-cli's fromShelleyLedgerPParamsShim and cardano-api's own ToApiEra, both deletable.
Typeable fingerprints and fully qualified TypeRep output for the eight tags change, since the types now originate in ledger's defining module.
Nothing in the surveyed code persists or compares these across versions, but it is observable behaviour.
Inside cardano-api the transitional compile errors concentrate in the 8 dual-namespace files and the 11 eon constraint bundles: duplicate imports of the now-identical types, redundant qualifiers, and hlint duplicate-import warnings.
All of this is contained in the core PR; it is listed here so reviewers know where the diff noise will come from.
Risks
Ledger's ByronEra carries a doc comment saying it "cannot have any other class instances, except for the Era type class".
Our HasTypeProxy/IsCardanoEra instances are on cardano-api-owned classes, so they do not violate coherence or create orphans, but the intent of that comment should be clarified with the ledger team before we rely on the type.
The identity synonyms are total where the old families were partial: ShelleyLedgerEra ByronEra used to be a stuck type, now it reduces to ByronEra, and likewise LedgerEra accepts all eras instead of two and CardanoLedgerEra quietly gains Dijkstra.
Misuse still fails to compile, only later: ledger gives ByronEra no EraTx/EraTxOut/... instances, so any Shelley-based constraint remains unsatisfiable for Byron.
The term-level guards (ShelleyBasedEra era witnesses) are untouched.
The duplicate-instance breakage above cannot be surveyed exhaustively: the surveyed repos are clean, but wallet and plutus tooling on Hackage/CHaP were outside the survey's reach, so the first ecosystem build after release is the real test.
Type errors change shape: users will see ledger era types where they previously saw the family application.
Mostly an improvement (the family reduced to those types in error messages anyway once concrete), but expect some confusion during the transition.
We lose the insulation layer.
Today ledger can rename, move or restructure its era types and cardano-api absorbs it in one family definition; afterwards such changes propagate straight into cardano-api's public API and to every consumer.
In practice the tags have been stable since the crypto parameter removal, and the coupling to ledger is already tight everywhere else, but the escape hatch is gone.
We lose control over the era set.
cardano-api can currently introduce or withhold an era tag independently of what the pinned ledger exposes.
After the switch the pinned ledger's tag set is our tag set; a ledger bump that adds an era makes the type nameable downstream immediately, before cardano-api wires any support for it.
(Witness-driven dispatch means a nameable type with no Era/IsCardanoEra constructor support is inert, so this is mostly cosmetic.)
We lose the Byron stuckness guard (covered under risks): misuse fails at instance resolution instead of at the family application.
We lose the option of api-only eras, or of splitting one ledger era into several api-visible ones.
Never used in the project's history, but the option goes away.
We pay a one-time ecosystem cost: a hard major bump where the type identity of eight exported types changes, requiring coordinated releases (CHaP, downstream pins) even though most sources compile unchanged.
Implementation plan
Prerequisites (no code): confirm the ByronEra doc-comment question with the ledger team, and agree ordering with the author of the in-flight era-ranges work (see open questions).
Preparation PR: deprecate CardanoLedgerEra (dead code, missing Dijkstra), with a message pointing at ShelleyLedgerEra for now.
Independently mergeable today, regardless of the rest.
Core PR: steps 1 to 5 above in one atomic change (the tag swap, the identity synonym, constraint bundle simplification).
Acceptance: the full build and both test suites pass, the whole GHC matrix (9.6/9.10/9.12) passes in CI, and cardano-cli's golden and round-trip tests pass across all eight eras - the coverage that caught the refactor(api): migrate ToJSON instances to use experimental Era type #1038 regression.
Experimental cleanup PR: re-parameterise SignedTx, swap LedgerEra to its deprecated identity synonym, delete the private ToApiEra, drop the now-tautological equalities from EraCommonConstraints, and update the experimental API documentation (the Exp.TxOut (LedgerEra era) gotcha disappears).
Downstream PRs: cardano-cli (delete the shim), cardano-node (optional tidy-up of the ~ ledgerera constraints), cardano-testnet (optional removal of redundant projections).
These are verified against the branch before release (via source-repository-package pins) and land once the cardano-api release is on CHaP.
Deprecation follow-through: keep ShelleyLedgerEra, CardanoLedgerEra and LedgerEra as deprecated synonyms for at least one major release, then remove them together (exact window to be agreed in review).
Open questions
Recommendation needing a yes/no: Cardano.Api.Ledger should start re-exporting the era tags too.
After unification it would re-export the same entities as Cardano.Api, which GHC handles fine (importing the same entity from two modules is legal), and it would make Cardano.Api.Ledger self-contained.
Is Cardano.Ledger.Api.Era a stability-guaranteed export point from the ledger team's perspective, or should we import the tags from the per-era packages?
How does this interact with the in-progress era-ranges design (the REMOVEME: era ranges plan commits on master, which sketch a different representation of era spans)?
Ordering needs agreeing with its author before the core PR (implementation plan step 1).
ADR-004 (cardano-node-wiki): introduced the experimental Era/LedgerEra machinery and explicitly called it scaffolding to be removed later; this proposal is that removal.
Summary
cardano-api defines its own uninhabited era tag types (
data ByronEra,data ShelleyEra, ...,data DijkstraEra) inCardano.Api.Era.Internal.Core, and bridges them to cardano-ledger's era types through type families.cardano-ledger already defines the same eight tags (Byron included) as bare
datadeclarations of kindType, exported fromCardano.Ledger.Api.Era.This issue proposes deleting cardano-api's copies and re-exporting ledger's types instead, so that the api era and the ledger era are the same type and every bridging family collapses to identity.
The switch happens inside
Cardano.Api.Era.Internal.Core: the module keeps exporting the same names through the same export chain (Cardano.Api.Era,Cardano.Api,Cardano.Api.Experimental), so the transition is seamless for consumers - no import changes, no renamed types, only the type identity underneath changes.We currently maintain four hand-written copies of the same bijection:
ShelleyLedgerEra(closed, injective, 7 equations) inCardano.Api.Era.Internal.Eon.ShelleyBasedEraCardanoLedgerEra(closed, injective, Byron to Conway, missing Dijkstra, zero internal consumers, still exported fromCardano.Api) inCardano.Api.Era.Internal.CoreLedgerEra(Conway and Dijkstra only) inCardano.Api.Experimental.EraToApiEra(the reverse direction, all 8 eras, private) inCardano.Api.Experimental.Tx.Internal.TypeNone of these needs to exist after the switch; the publicly exported ones are kept as deprecated identity synonyms for a deprecation period, then removed.
Why now
The experimental API is already halfway there.
UnsignedTx,Exp.TxOut,TxBodyContent,AnyWitness,Certificateand the other experimental leaf types are parameterised by the ledger era directly (#1089, implemented in #1093).LedgerEra eraexists only as glue between tag-indexed signatures (Era era,IsEra era) and those ledger-indexed data types, and users have to writeExp.TxOut (LedgerEra era)instead ofExp.TxOut erabecause GHC cannot see the two eras are equal withoutobtainCommonConstraintsin scope.EraCommonConstraintseven carriesShelleyLedgerEra era ~ LedgerEra era(in both directions) to keep the old and new families in agreement.Unifying the tags removes this entire class of friction rather than documenting around it.
On the ledger side, the crypto parameter removal (IntersectMBO/cardano-ledger#4223, implemented in #4788) left the era types as plain phantom tags:
data ShelleyErawith no parameters, kindType, exactly the shape of our own tags.Ledger also defines a deliberately minimal
ByronEra(anErainstance and nothing else, kept alive so thatPreviousEra ShelleyEraresolves), so even Byron has a direct counterpart.Consensus already sits on ledger's types:
Ouroboros.Consensus.Shelley.Erasre-exports them, soConsensus.ShelleyErain our code is already ledger'sShelleyEra.cardano-api is the only layer left with its own era universe.
Alternatives considered
The four bridging families stay, every new era adds an equation to each of them, and the
Exp.TxOut (LedgerEra era)workaround stays with them.This is the baseline cost the proposal removes, and it grows with each era.
The experimental leaf types are already ledger-parameterised, so this is nearly done, but it leaves
ShelleyLedgerEraand its ~613 use sites untouched in the old API and keeps theSignedTx-style seams at the old/new boundary.The tags are phantom types with no values, so there is nothing to coerce or wrap; a type family is the only possible bridge between distinct tags, and that is exactly what we maintain today.
Wrong dependency direction: consensus and ledger already agree on ledger's types, cardano-api is the odd one out.
Proposed change
Cardano.Api.Era.Internal.Core, delete the eightdata XEradeclarations and re-export the ledger types instead (imported fromCardano.Ledger.Api.Era, the sanctioned export point; the defining module in cardano-ledger-core is warning-tagged internal).This is the seamlessness requirement: the tags stay reachable under the exact same names from the exact same modules, so no consumer changes an import line.
All instances on the tags (
IsCardanoEra,HasTypeProxywith itsAsTypedata instances,IsShelleyBasedEra, the era-onwards classes,HasScriptLanguageInEra,IsEra, ...) are instances of cardano-api-owned classes, so they stay non-orphan when the type moves to ledger.type ShelleyLedgerEra era = era, and likewiseCardanoLedgerEraand the experimentalLedgerEra.Existing signatures keep compiling (now with a deprecation warning), and applications to concrete eras (
ShelleyLedgerEra ConwayEra) reduce to the era itself.As synonyms the families also become total:
CardanoLedgerEragains the Dijkstra case the current family is missing, andLedgerEraapplies beyond Conway and Dijkstra.ToApiErafamily.It is not exported (its module exports only
UnsignedTx (..)), so no deprecation period is needed.Every eon bundle (
ShelleyBasedEraConstraintsand the ten others) constrainsL.EraX (ShelleyLedgerEra era); these becomeL.EraX era.The
ShelleyLedgerEra era ~ LedgerEra erapair inEraCommonConstraintsand theShelleyBlock (ConsensusProtocol era) (ShelleyLedgerEra era) ~ ConsensusBlockForEra eraequalities become trivial and can go.SignedTxwithUnsignedTx.SignedTxis currently the one experimental type still keyed on the api tag viaShelleyLedgerEra(a deliberate choice in Widen Exp.SignedTx to all Shelley-based eras #1199, becauseLedgerEraonly covers two eras andSignedTxneeds all Shelley-based ones).With unified tags both conventions denote the same type, so the special case disappears.
How broad is the change
Numbers from a survey of cardano-api and its main consumers (cardano-cli, all cardano-api-consuming packages of the cardano-node repo including the bench family, cardano-testnet and a few smaller tools) against cardano-api commit
bf5c2a916(2026-07-27), with cardano-ledger-core 1.20.0.0 and cardano-ledger-api 1.13.0.0 pinned.Inside the cardano-api repo:
ShelleyLedgerEraoccurrencesLedgerEra(experimental) occurrencesobtainCommonConstraintscall sites@XEratype applicationsThe edits concentrate in
Cardano.Api.Era.Internal.Core(the definition site),Cardano.Api.Experimental.Era,Cardano.Api.Era.Internal.Eon.ShelleyBasedEra, and the 11 eon modules' constraint bundles.The rest of the library compiles unchanged or loses redundant qualifiers.
No DataKinds promotion of the tags exists anywhere, no instance head mentions
ShelleyLedgerEra era, and the threeTestEqualityinstances match on term-level constructors, so none of the usual type-swap traps apply.Downstream (surveyed consumers):
ShelleyLedgerErasitesfromShelleyLedgerPParamsShim) becomes deletable; the rest compiles via the synonymShelleyLedgerEra era ~ ledgereraconstraints, which become trivially satisfiederaprojections, compile unchanged via the synonymZero downstream instances are declared on a concrete api era tag, so no instance overlap arises in any surveyed repo.
Effort estimate: one core PR for steps 1 to 5 (roughly 10 files of real edits plus mechanical constraint-bundle changes, 2 to 4 days including CI matrix fallout on GHC 9.6/9.10/9.12), one small follow-up PR for
SignedTxand experimental cleanup, and trivial downstream PRs (hours each).A major version bump of cardano-api either way.
What actually breaks
The baseline: a consumer that reaches the tags and
ShelleyLedgerErathroughCardano.Api's public surface does not break at the source level.The names and modules are unchanged, the identity synonym keeps every
ShelleyLedgerEra erasignature compiling, and all term-level code (era witnesses, eon dispatch,TestEquality) is untouched, so for the ~90-95 % generic-era majority the change arrives as a recompile against a new major version.What does break:
ShelleyLedgerEra,CardanoLedgerEraand the experimentalLedgerEraall stay on as deprecated identity synonyms for the deprecation period.Even signatures written in today's recommended style, such as
f :: Era era -> Exp.TxOut (LedgerEra era) -> ..., keep compiling, now with a deprecation warning.Consumers building with
-Werrorand without-Wno-deprecationsturn those warnings into errors; that is the usual cost of that setting, and cardano-api itself avoids it because the core PR rewrites all internal uses (it must, since the repo builds with-Werror).The real source break is deferred to the synonyms' removal at the end of the deprecation period: across the surveyed repos that would be ~613
ShelleyLedgerEraand 341LedgerEraoccurrences, nearly all inside cardano-api and already rewritten by the core PR, leaving only the small downstream counts in the table above.XEraand ledger'sXEragets a duplicate-instance error, since the two heads become identical.Zero such cases exist in the surveyed repos; possible in principle on Hackage/CHaP, so the changelog must call it out.
The only such code found is bridging glue: cardano-cli's
fromShelleyLedgerPParamsShimand cardano-api's ownToApiEra, both deletable.Typeablefingerprints and fully qualifiedTypeRepoutput for the eight tags change, since the types now originate in ledger's defining module.Nothing in the surveyed code persists or compares these across versions, but it is observable behaviour.
All of this is contained in the core PR; it is listed here so reviewers know where the diff noise will come from.
Risks
ByronEracarries a doc comment saying it "cannot have any other class instances, except for theEratype class".Our
HasTypeProxy/IsCardanoErainstances are on cardano-api-owned classes, so they do not violate coherence or create orphans, but the intent of that comment should be clarified with the ledger team before we rely on the type.ShelleyLedgerEra ByronEraused to be a stuck type, now it reduces toByronEra, and likewiseLedgerEraaccepts all eras instead of two andCardanoLedgerEraquietly gains Dijkstra.Misuse still fails to compile, only later: ledger gives
ByronEranoEraTx/EraTxOut/... instances, so any Shelley-based constraint remains unsatisfiable for Byron.The term-level guards (
ShelleyBasedEra erawitnesses) are untouched.Mostly an improvement (the family reduced to those types in error messages anyway once concrete), but expect some confusion during the transition.
PR Merge
ShelleyLedgerEraandCardanoLedgerErato a single type familyLedgerEra#361 (mergingShelleyLedgerEraandCardanoLedgerErainto one family) was rejected for blurring the Byron/Shelley-based distinction; this proposal does not touch that distinction, sinceCardanoEra,ShelleyBasedEraand all eon witnesses stay exactly as they are, and Byron remains excluded from Shelley-based machinery by instance absence and witnesses.PR refactor(api): migrate ToJSON instances to use experimental Era type #1038 (migrating JSON instances to the experimental
Era) was reverted by Revert "refactor(api): migrate ToJSON instances to use experimental Era type" #1048 after breakingcardano-cli query utxoin old eras; this proposal narrows nothing, all eight eras keep working with the same witnesses, and the cardano-cli test suite should gate the release.Downsides: what we lose with the switch
Today ledger can rename, move or restructure its era types and cardano-api absorbs it in one family definition; afterwards such changes propagate straight into cardano-api's public API and to every consumer.
In practice the tags have been stable since the crypto parameter removal, and the coupling to ledger is already tight everywhere else, but the escape hatch is gone.
cardano-api can currently introduce or withhold an era tag independently of what the pinned ledger exposes.
After the switch the pinned ledger's tag set is our tag set; a ledger bump that adds an era makes the type nameable downstream immediately, before cardano-api wires any support for it.
(Witness-driven dispatch means a nameable type with no
Era/IsCardanoEraconstructor support is inert, so this is mostly cosmetic.)Never used in the project's history, but the option goes away.
Implementation plan
ByronEradoc-comment question with the ledger team, and agree ordering with the author of the in-flight era-ranges work (see open questions).CardanoLedgerEra(dead code, missing Dijkstra), with a message pointing atShelleyLedgerErafor now.Independently mergeable today, regardless of the rest.
Acceptance: the full build and both test suites pass, the whole GHC matrix (9.6/9.10/9.12) passes in CI, and cardano-cli's golden and round-trip tests pass across all eight eras - the coverage that caught the refactor(api): migrate ToJSON instances to use experimental Era type #1038 regression.
SignedTx, swapLedgerErato its deprecated identity synonym, delete the privateToApiEra, drop the now-tautological equalities fromEraCommonConstraints, and update the experimental API documentation (theExp.TxOut (LedgerEra era)gotcha disappears).~ ledgereraconstraints), cardano-testnet (optional removal of redundant projections).These are verified against the branch before release (via
source-repository-packagepins) and land once the cardano-api release is on CHaP.ShelleyLedgerEra,CardanoLedgerEraandLedgerEraas deprecated synonyms for at least one major release, then remove them together (exact window to be agreed in review).Open questions
Cardano.Api.Ledgershould start re-exporting the era tags too.After unification it would re-export the same entities as
Cardano.Api, which GHC handles fine (importing the same entity from two modules is legal), and it would makeCardano.Api.Ledgerself-contained.Cardano.Ledger.Api.Eraa stability-guaranteed export point from the ledger team's perspective, or should we import the tags from the per-era packages?REMOVEME: era ranges plancommits on master, which sketch a different representation of era spans)?Ordering needs agreeing with its author before the core PR (implementation plan step 1).
Prior art
UnsignedTx#1089 / TxBodyContent refactoring related fixes #1093:UnsignedTxre-parameterised on ledger's era; the direct precursor, scoped to one type.Exp.SignedTxto all Shelley-based eras, and documents whyLedgerErawas kept narrower thanShelleyLedgerEra.ShelleyLedgerEraandCardanoLedgerErato a single type familyLedgerEra#361: earlier attempt to merge the two api-side families, rejected; see risks for why this proposal differs.Era, merged and reverted (see risks).Era/LedgerEramachinery and explicitly called it scaffolding to be removed later; this proposal is that removal.