Skip to content

feat: decommission SealedTx cardano-api surface (follow-up to #5236)#5271

Merged
paolino merged 8 commits into
masterfrom
feat/drop-cardano-api-sealedtx
May 8, 2026
Merged

feat: decommission SealedTx cardano-api surface (follow-up to #5236)#5271
paolino merged 8 commits into
masterfrom
feat/drop-cardano-api-sealedtx

Conversation

@paolino
Copy link
Copy Markdown
Collaborator

@paolino paolino commented Apr 24, 2026

Summary

Progress toward removing Cardano.Api* from Cardano.Wallet.Primitive.Types.Tx.SealedTx. Moves the first set of production and test call sites off the deprecated surface. Follow-up #5272 now finishes the remaining SealedTx cleanup.

Base branch: 001-drop-cardano-api (#5236).
Rebased after #5270 merged and #5236 was rebased onto master.

What this PR does

Eight bisect-safe commits:

# SHA Effect
1 04d65b2 docs: plan document for the decommission series
2 b4b87af Test helper compareOnCBOR -> raw serialisedTx bytes, avoiding a cardano-api roundtrip
3 282807d Submission path _postSealedTx -> EraValue Read.Tx + consensusGenTxFromTxRecent; deletes unsealShelleyTx / UnsealException
4 a6d0c9d parsePartialTx -> deserializeTx :: Either DecoderError (Read.Tx era) per era
5 f1ba908 Delete cardanoTxInExactEra after the callers are gone
6 55f2bd9 Add sealedTxFromLedgerTx :: Read.IsEra era => Read.Tx era -> SealedTx; migrate sealWriteTx off toCardanoApiTx/sealedTxFromCardano'
7 e6feabc Add sealedTxWitnessCount :: SealedTx -> Int via ledger witnesses; migrate Server.hs away from getSealedTxWitnesses
8 c2ca434 Integration test getMetadataFromTx -> Meta.getMetadata . Meta.getEraMetadata on EraValue Read.Tx

New ledger-native surface added to SealedTx:

  • sealedTxFromLedgerTx :: Read.IsEra era => Read.Tx era -> SealedTx
  • sealedTxWitnessCount :: SealedTx -> Int

Deleted:

  • cardanoTxInExactEra
  • Cardano.Wallet.Primitive.Ledger.Shelley.unsealShelleyTx / UnsealException

What this PR does not do

The deprecated SealedTx cardano-api exports are removed in #5272, not here.

Out of scope:

  • Removing cardano-api from cardano-wallet-primitive.cabal.
  • Removing lib/cardano-api-extra/.

Test plan

@paolino paolino added the Refactoring No functional changes label Apr 24, 2026
@paolino paolino self-assigned this Apr 24, 2026
@paolino paolino force-pushed the 001-drop-cardano-api branch from 4178799 to 26bad3e Compare April 25, 2026 09:41
@paolino paolino force-pushed the feat/drop-cardano-api-sealedtx branch from b530ab1 to 65a5529 Compare April 25, 2026 09:41
paolino added a commit that referenced this pull request Apr 25, 2026
Enumerates every remaining caller of the deprecated surface after
#5271: production (Cardano.Wallet.hs, Server.hs), old tx builder
(Shelley/Transaction.hs, partially overlaps with #5243), integration
tests (Shared/Transactions.hs, addRequiredSigners in TransactionsNew)
and unit tests (TransactionSpec, TransactionLedgerSpec).

Organises the work into three phases:
  A. reachable without #5243 (4 sites)
  B. unit-test migration (~20 sites, two files)
  C. delete the bridge functions and the three Cardano.Api*
     imports in SealedTx.hs
@paolino paolino force-pushed the feat/drop-cardano-api-sealedtx branch from 65a5529 to c2ca434 Compare April 25, 2026 10:11
paolino added a commit that referenced this pull request Apr 25, 2026
Enumerates every remaining caller of the deprecated surface after
#5271: production (Cardano.Wallet.hs, Server.hs), old tx builder
(Shelley/Transaction.hs, partially overlaps with #5243), integration
tests (Shared/Transactions.hs, addRequiredSigners in TransactionsNew)
and unit tests (TransactionSpec, TransactionLedgerSpec).

Organises the work into three phases:
  A. reachable without #5243 (4 sites)
  B. unit-test migration (~20 sites, two files)
  C. delete the bridge functions and the three Cardano.Api*
     imports in SealedTx.hs
@paolino paolino marked this pull request as ready for review April 25, 2026 10:18
@paolino paolino requested review from paweljakubas and removed request for paweljakubas April 25, 2026 10:18
@paolino
Copy link
Copy Markdown
Collaborator Author

paolino commented Apr 27, 2026

@copilot

Copy link
Copy Markdown

Copilot AI commented Apr 27, 2026

@copilot

Hi @paolino! The latest CI run on this branch is passing ✅. Is there anything specific you'd like me to look at or change?

@paolino
Copy link
Copy Markdown
Collaborator Author

paolino commented Apr 27, 2026

@copilot, pls review

Copy link
Copy Markdown

Copilot AI commented Apr 27, 2026

@copilot, pls review

Review complete. One real bug found and fixed:

Duplicate MsgPostTx log (18a23ac): _postSealedTx was logging MsgPostTx before delegating to postTxToQueue, which also logs MsgPostTx — causing every postSealedTx call to emit two identical log entries. The redundant log line and its now-unused import qualified Data.ByteString as BS have been removed.

Other observations (no action taken):

  • Left _ -> readErr in balanceTransaction's deserializeTx match discards the DecoderError; acceptable since the upstream ErrPartialTxNotInNodeEra is informative enough.
  • compareOnCBOR's IsShelleyBasedEra constraint is still required for Cardano.serialiseToCBOR.
  • unsafeReadTx in getMetadataFromTx is appropriate for test-only code.
  • sealedTxWitnessCount exhaustive era case-match looks correct; Byron txs returning 0 is documented.
  • sealWriteTx constraint simplification (dropping IsRecentEra) is correct since the RecentEra GADT evidence already pins the era at each branch.

Copy link
Copy Markdown
Collaborator

@paweljakubas paweljakubas left a comment

Choose a reason for hiding this comment

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

also should be fine with this one 👍 nothing scary here, quite clear

paolino added a commit that referenced this pull request May 8, 2026
…5236)

## Summary

Remaining call-site migration after #5270 merged. This branch is rebased
directly onto current `master` and contains the commits that switch
existing wallet call sites onto the ledger-native surfaces introduced by
#5270.

Base branch: `master`.
Follow-ups: #5271, then #5272.

## What is in this PR

| # | SHA | Purpose |
|---|---|---|
| 1 | `84bd668` | Use `constructUnsignedTxLedger` in `balanceTx` paths |
| 2 | `4c8b61b` | Replace `AnyCardanoEra` with `Read.EraValue` in
NetworkLayer |
| 3 | `55097e6` | Build delegation and voting certificates in
`balanceTx` paths |
| 4 | `f5b8ed2` | Replace `StakeAddress` with wallet-owned
`RewardAccount` |
| 5 | `26bad3e` | Migrate `TxMetadata` end-to-end to wallet-owned types
|
| 6 | `d543a6b` | Adapt singleton network conversions to #5270's
`sNetworkIdToLedger` helper |

The foundation work previously described here landed in #5270. In
particular, the wallet-owned `NetworkId`, `TxMetadata`, `SealedTx`,
ledger-native transaction builders, certificate helpers, and witness
helpers are now part of `master`.

## What this PR does not do

- It does not delete the remaining cardano-api bridges.
- It does not remove `cardano-api` from cabal files.
- It does not delete `lib/cardano-api-extra/`.
- It does not finish the `SealedTx` decommission; that remains split
across #5271 and #5272.

## Test plan

- [x] Rebased cleanly onto `origin/master` after #5270 merged
(2026-04-25).
- [x] `nix develop --command cabal build cardano-wallet
cardano-wallet-api cardano-wallet-unit:unit --enable-benchmarks
--enable-tests --minimize-conflict-set -O0 -v0`
- [ ] CI green on the rebased tip.

Note: `just build 'cardano-wallet cardano-wallet-unit:unit'` reaches
unrelated `cardano-wallet-read` deprecation/unused warnings promoted by
`-Werror` on this branch; the same target without `-Werror` passes.
Base automatically changed from 001-drop-cardano-api to master May 8, 2026 09:23
paolino added 6 commits May 8, 2026 10:36
Five-step plan to remove the three remaining Cardano.Api imports from
lib/primitive/lib/Cardano/Wallet/Primitive/Types/Tx/SealedTx.hs by
eliminating the bridge functions (cardanoTxIdeallyNoLaterThan,
cardanoTxInExactEra, sealedTxFromCardano*, getSealedTxBody,
getSealedTxWitnesses, cardanoApiTxToReadTx).
…erSpec

Replace compareOnCBOR's roundtrip through cardano-api
(cardanoTx → Cardano.serialiseToCBOR) with the raw bytes
already stored in SealedTx.serialisedTx. Identical
comparison outcome, one fewer caller of
cardanoTxIdeallyNoLaterThan. Step 1 of SealedTx
decommission plan.
…ead.Tx

Replace the cardano-api path
(SealedTx → unsealShelleyTx → TxInMode → toConsensusGenTx → GenTx)
with a direct ledger-native path
(SealedTx → unsafeReadTx :: EraValue Read.Tx → consensusGenTxFromTxRecent → GenTx).

The stored 'EraValue Read.Tx' already knows its era, so the
separate 'readCurrentEra' query is no longer needed, and
'TxInMode' / 'toConsensusGenTx' / 'unsealShelleyTx' /
'UnsealException' all become unused.

Deletes:
  - Cardano.Wallet.Primitive.Ledger.Shelley.unsealShelleyTx
  - Cardano.Wallet.Primitive.Ledger.Shelley.UnsealException
  - cardano-api 'TxInMode' import in primitive
  - cardano-api 'toConsensusGenTx' import in network-layer

Adds 'unsafeReadTx' to the re-export of 'SealedTx' in
Cardano.Wallet.Primitive.Types.Tx. Step 1 of SealedTx decommission
plan. One fewer caller of 'cardanoTxIdeallyNoLaterThan'; the
submission path no longer touches cardano-api.
Replace cardanoTxInExactEra (cardano-api path) with
deserializeTx (ledger-native) in the redeemer-bearing
partial tx parser. Pattern-matches on RecentEra era so
the era singleton witnesses the target ledger type.

One fewer caller of cardano-api's
'deserialiseFromCBOR / InAnyCardanoEra Cardano.Tx' path.
'fromCardanoApiTx' → direct use of 'Read.Tx era' unwrapped
into 'Write.Tx era'.
Following the migration of parsePartialTx to deserializeTx,
cardanoTxInExactEra has no external callers. Remove it along
with the now-redundant Data.Data import in SealedTx.hs.
Introduce sealedTxFromLedgerTx :: Read.IsEra era => Read.Tx era -> SealedTx.
Serialises via Read.serializeTx (ledger-native) and wraps in EraValue
without any cardano-api involvement.

Migrate sealWriteTx in Transaction.Ledger.hs to use the new
constructor, pattern-matching on RecentEra to witness the era.
Removes the toCardanoApiTx -> sealedTxFromCardano' roundtrip,
dropping the Cardano.Api.Extra import from that module.

Step 2a of SealedTx decommission plan.
paolino added 2 commits May 8, 2026 10:36
Introduce sealedTxWitnessCount :: SealedTx -> Int, counting VKey
plus bootstrap witnesses via 'addrTxWitsL'/'bootAddrTxWitsL' on the
stored 'EraValue Read.Tx'. Byron txs counted as 0 (wallet doesn't
construct them through SealedTx).

Migrate Server.hs's two 'length $ getSealedTxWitnesses sealedTx'
sites (redeemer and witness accounting) to use it. Drops
'getSealedTxWitnesses' from Server.hs's import list.

Step 2b of SealedTx decommission plan.
Replace cardano-api round-trip with direct Read.Tx era projection via
Meta.getMetadata . Meta.getEraMetadata. Drops the four callers of
cardanoTxIdeallyNoLaterThan in this file (the cardano-api re-decode
was only used to feed getTxBody/txMetadata).

No behavioural change: the ledger metadata path is what Server.hs and
DB.TransactionInfo already use.
@paolino paolino force-pushed the feat/drop-cardano-api-sealedtx branch from 18a23ac to fdfadf0 Compare May 8, 2026 10:21
@paolino paolino merged commit 43f5241 into master May 8, 2026
57 checks passed
@paolino paolino deleted the feat/drop-cardano-api-sealedtx branch May 8, 2026 11:00
paolino added a commit that referenced this pull request May 8, 2026
Enumerates every remaining caller of the deprecated surface after
#5271: production (Cardano.Wallet.hs, Server.hs), old tx builder
(Shelley/Transaction.hs, partially overlaps with #5243), integration
tests (Shared/Transactions.hs, addRequiredSigners in TransactionsNew)
and unit tests (TransactionSpec, TransactionLedgerSpec).

Organises the work into three phases:
  A. reachable without #5243 (4 sites)
  B. unit-test migration (~20 sites, two files)
  C. delete the bridge functions and the three Cardano.Api*
     imports in SealedTx.hs
paolino added a commit that referenced this pull request May 8, 2026
…5272)

## Summary

Follow-up to #5271. This PR finishes the
`Cardano.Wallet.Primitive.Types.Tx.SealedTx` cardano-api decommission:
the primitive `SealedTx` module no longer imports `Cardano.Api`, and the
deprecated cardano-api-facing SealedTx exports are removed.

Base branch: `feat/drop-cardano-api-sealedtx` (#5271).
Rebased after #5270 merged, #5236 was rebased onto `master`, and #5271
was rebased onto #5236.

## What changed

| # | SHA | Purpose |
|---|---|---|
| 1 | `734f624` | Plan for finishing the SealedTx cardano-api
decommission |
| 2 | `80a3de4` | Port metadata extraction in `Shared/Transactions` to
ledger-native |
| 3 | `8faf76e` | Drop the dead cardano-api body in `addRequiredSigners`
|
| 4 | `a929e8e` | Migrate `buildAndSignTransactionPure` to ledger-native
seal |
| 5 | `e2e72af` | Drop the local `sealWriteTx` cardano-api bridge in
Server.hs |
| 6 | `0b619dd` | Remove the `SealedTx` cardano-api surface and move
remaining unit-test adapters local to tests |
| 7 | `b4da418` | Keep default sealed transaction byte decoding capped
at the supported Conway era, and make signing/decoding re-read sealed
bytes with the caller's preferred latest era |

## SealedTx surface removed

Removed from `Cardano.Wallet.Primitive.Types.Tx.SealedTx` and the
umbrella `Cardano.Wallet.Primitive.Types.Tx` export list:

- `cardanoTxIdeallyNoLaterThan`
- `sealedTxFromCardano`
- `sealedTxFromCardano'`
- `sealedTxFromCardanoBody`
- `getSealedTxBody`
- `getSealedTxWitnesses`
- internal `cardanoTxFromBytes`
- internal `cardanoApiTxToReadTx`

`sealedTxFromBytes'` now takes `Read.EraValue Read.Era` instead of
`AnyCardanoEra`, which lets the primitive module avoid `Cardano.Api`
entirely.

## CI fix after rerun

The first rerun of #5272 exposed a real Conway integration failure:
sealed Conway transaction bytes could be decoded as Dijkstra by the new
ledger-native default path, after which downstream code hit the
still-incomplete Dijkstra transaction support.

This PR now keeps the public `sealedTxFromBytes` default capped at
Conway, and the transaction layer re-decodes sealed bytes with the
preferred latest era supplied by the caller before signing or decoding.
That preserves the old "no later than current era" behavior without
restoring the cardano-api bridge.

## Remaining out of scope

- Removing `cardano-api` from `cardano-wallet-primitive.cabal`; other
primitive modules still import it.
- Removing `lib/cardano-api-extra/`.
- Full deletion of the old `Shelley/Transaction.hs` module.

## Test plan

- [x] `nix develop --command fourmolu --mode inplace ...` on touched
Haskell files
- [x] `git diff --check`
- [x] `nix develop --command just build 'cardano-wallet-primitive
cardano-wallet cardano-wallet-unit:unit'`
- [x] `nix develop --command cabal test cardano-wallet-unit:unit -O0 -v0
--test-options '--match="TransactionSpec"'`
- [x] `nix develop --command cabal test cardano-wallet-unit:unit -O0 -v0
--test-options '--match="SealedTx serialisation/deserialisation"'`
- [x] `nix develop --command cabal build cardano-wallet
cardano-wallet-api cardano-wallet-unit:unit --enable-tests
--enable-benchmarks --minimize-conflict-set -O0 -v0`
- [x] `rg 'Cardano\.Api|qualified Cardano.Api'
lib/primitive/lib/Cardano/Wallet/Primitive/Types/Tx/SealedTx.hs` returns
no matches
- [x] CI green on the rebased tip
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Refactoring No functional changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants