content: {-# LANGUAGE AllowAmbiguousTypes #-}
  {-# LANGUAGE DataKinds #-}
  {-# LANGUAGE DerivingStrategies #-}
  {-# LANGUAGE DisambiguateRecordFields #-}
  {-# LANGUAGE EmptyCase #-}
  {-# LANGUAGE FlexibleContexts #-}
  {-# LANGUAGE FlexibleInstances #-}
  {-# LANGUAGE LambdaCase #-}
  {-# LANGUAGE MultiParamTypeClasses #-}
  {-# LANGUAGE NamedFieldPuns #-}
  {-# LANGUAGE OverloadedStrings #-}
  {-# LANGUAGE QuantifiedConstraints #-}
  {-# LANGUAGE ScopedTypeVariables #-}
  {-# LANGUAGE TypeFamilies #-}
  {-# LANGUAGE TypeOperators #-}
  {-# LANGUAGE UndecidableInstances #-}
  
  {-# OPTIONS_GHC -Wno-orphans  #-}
  
  module Cardano.Tracing.OrphanInstances.Shelley () where
  
  import           Cardano.Api (textShow)
  import qualified Cardano.Api as Api
  
  import qualified Cardano.Crypto.Hash.Class as Crypto
  import qualified Cardano.Crypto.VRF.Class as Crypto
  import           Cardano.Ledger.Allegra.Rules (AllegraUtxoPredFailure)
  import qualified Cardano.Ledger.Allegra.Rules as Allegra
  import qualified Cardano.Ledger.Alonzo.Plutus.Evaluate as Alonzo
  import           Cardano.Ledger.Alonzo.Rules (AlonzoBbodyPredFailure (..), AlonzoUtxoPredFailure,
                     AlonzoUtxosPredFailure, AlonzoUtxowPredFailure (..))
  import qualified Cardano.Ledger.Alonzo.Rules as Alonzo
  import qualified Cardano.Ledger.Api as Ledger
  import           Cardano.Ledger.Babbage.Rules (BabbageUtxoPredFailure, BabbageUtxowPredFailure)
  import qualified Cardano.Ledger.Babbage.Rules as Babbage
  import           Cardano.Ledger.BaseTypes (Mismatch (..), activeSlotLog, strictMaybeToMaybe)
  import           Cardano.Ledger.Chain
  import           Cardano.Ledger.Conway.Governance (govActionIdToText)
  import           Cardano.Ledger.Conway.Rules (ConwayUtxosPredFailure)
  import qualified Cardano.Ledger.Conway.Rules as Conway
  import qualified Cardano.Ledger.Core as Core
  import qualified Cardano.Ledger.Core as Ledger
  import qualified Cardano.Ledger.Hashes as Hashes
  import           Cardano.Ledger.Shelley.API
  import           Cardano.Ledger.Shelley.Rules
  import           Cardano.Node.Tracing.Render (renderMissingRedeemers, renderScriptHash,
                     renderScriptIntegrityHash)
  import           Cardano.Node.Tracing.Tracers.KESInfo ()
  import qualified Cardano.Protocol.Crypto as Core
  import           Cardano.Protocol.TPraos.API (ChainTransitionError (ChainTransitionError))
  import           Cardano.Protocol.TPraos.BHeader (LastAppliedBlock, labBlockNo)
  import           Cardano.Protocol.TPraos.OCert (KESPeriod (KESPeriod))
  import           Cardano.Protocol.TPraos.Rules.OCert
  import           Cardano.Protocol.TPraos.Rules.Overlay
  import           Cardano.Protocol.TPraos.Rules.Prtcl
  import           Cardano.Protocol.TPraos.Rules.Tickn
  import           Cardano.Protocol.TPraos.Rules.Updn
  import           Cardano.Slotting.Block (BlockNo (..))
  import           Cardano.Tracing.OrphanInstances.Common
  import           Cardano.Tracing.OrphanInstances.Consensus ()
  import           Cardano.Tracing.Render (renderTxId)
  import qualified Ouroboros.Consensus.Cardano.Block as Consensus
  import           Ouroboros.Consensus.Ledger.SupportsMempool (txId)
  import qualified Ouroboros.Consensus.Ledger.SupportsMempool as SupportsMempool
  import qualified Ouroboros.Consensus.Protocol.Ledger.HotKey as HotKey
  import qualified Ouroboros.Consensus.Protocol.Praos as Praos
  import           Ouroboros.Consensus.Protocol.Praos.Common (PraosChainSelectView (..))
  import           Ouroboros.Consensus.Protocol.TPraos (TPraosCannotForge (..))
  import           Ouroboros.Consensus.Shelley.Ledger hiding (TxId)
  import           Ouroboros.Consensus.Shelley.Ledger.Inspect
  import qualified Ouroboros.Consensus.Shelley.Protocol.Praos as Praos
  import           Ouroboros.Consensus.Util.Condense (condense)
  import           Ouroboros.Network.Block (SlotNo (..), blockHash, blockNo, blockSlot)
  import           Ouroboros.Network.Point (WithOrigin, withOriginToMaybe)
  
  import           Data.Aeson (Value (..))
  import qualified Data.Aeson as Aeson
  import qualified Data.ByteString.Base16 as B16
  import qualified Data.List.NonEmpty as NonEmpty
  import           Data.Set (Set)
  import qualified Data.Set as Set
  import           Data.Text (Text)
  import qualified Data.Text as Text
  import qualified Data.Text.Encoding as Text
  
  {- HLINT ignore "Use :" -}
  
  --
  -- | instances of @ToObject@
  --
  -- NOTE: this list is sorted in roughly topological order.
  
  instance
    ( Consensus.ShelleyBasedEra ledgerera
    ) => ToObject (GenTx (ShelleyBlock protocol ledgerera)) where
    toObject _ tx = mconcat [ "txid" .= Text.take 8 (renderTxId (txId tx)) ]
  
  instance ToJSON (SupportsMempool.TxId (GenTx (ShelleyBlock protocol era))) where
    toJSON = String . Text.take 8 . renderTxId
  
  instance ShelleyCompatible protocol era => ToObject (Header (ShelleyBlock protocol era)) where
    toObject _verb b = mconcat
          [ "kind" .= String "ShelleyBlock"
          , "hash" .= condense (blockHash b)
          , "slotNo" .= condense (blockSlot b)
          , "blockNo" .= condense (blockNo b)
  --      , "delegate" .= condense (headerSignerVk h)
          ]
  
  instance
    ( ToObject (PredicateFailure (Core.EraRule "LEDGER" ledgerera))
    ) => ToObject (ApplyTxError ledgerera) where
    toObject verb (ApplyTxError predicateFailures) =
      mconcat $ NonEmpty.toList $ fmap (toObject verb) predicateFailures
  
  instance Core.Crypto crypto => ToObject (TPraosCannotForge crypto) where
    toObject _verb (TPraosCannotForgeKeyNotUsableYet wallClockPeriod keyStartPeriod) =
      mconcat
        [ "kind" .= String "TPraosCannotForgeKeyNotUsableYet"
        , "keyStart" .= keyStartPeriod
        , "wallClock" .= wallClockPeriod
        ]
    toObject _verb (TPraosCannotForgeWrongVRF genDlgVRFHash coreNodeVRFHash) =
      mconcat
        [ "kind" .= String "TPraosCannotLeadWrongVRF"
        , "expected" .= genDlgVRFHash
        , "actual" .= coreNodeVRFHash
        ]
  
  instance
    ( ToObject (PredicateFailure (Ledger.EraRule "BBODY" era))
    ) => ToObject (BlockTransitionError era) where
    toObject verb (BlockTransitionError fs) =
      mconcat [ "kind" .= String "BlockTransitionError"
              , "failures" .= fmap (toObject verb) fs
              ]
  
  instance
    ( Ledger.Era ledgerera
    , Show (Ledger.PParamsHKD Identity ledgerera)
    ) => ToObject (ShelleyLedgerUpdate ledgerera) where
    toObject _verb (ShelleyUpdatedPParams updates epochNo) =
      mconcat [ "kind" .= String "ShelleyUpdatedPParams"
               , "updates" .= show updates
               , "epochNo" .= show epochNo
               ]
  instance
    ( ToObject (PredicateFailure (Ledger.EraRule "DELEG" era))
    , ToObject (PredicateFailure (Ledger.EraRule "POOL" era))
    , ToObject (PredicateFailure (Ledger.EraRule "GOVCERT" era))
    ) => ToObject (Conway.ConwayCertPredFailure era) where
    toObject verb = mconcat . \case
      Conway.DelegFailure f ->
        [ "kind" .= String "DelegFailure " , "failure" .= toObject verb f ]
      Conway.PoolFailure f ->
        [ "kind" .= String "PoolFailure" , "failure" .= toObject verb f ]
      Conway.GovCertFailure f ->
        [ "kind" .= String "GovCertFailure" , "failure" .= toObject verb f ]
  
  instance ToObject (Conway.ConwayGovCertPredFailure era) where
    toObject _verb = mconcat . \case
      Conway.ConwayDRepAlreadyRegistered credential ->
        [ "kind" .= String "ConwayDRepAlreadyRegistered"
        , "credential" .= String (textShow credential)
        , "error" .= String "DRep is already registered"
        ]
      Conway.ConwayDRepNotRegistered credential ->
        [ "kind" .= String "ConwayDRepNotRegistered"
        , "credential" .= String (textShow credential)
        , "error" .= String "DRep is not registered"
        ]
      Conway.ConwayDRepIncorrectDeposit Mismatch {mismatchSupplied, mismatchExpected}  ->
        [ "kind" .= String "ConwayDRepIncorrectDeposit"
        , "givenCoin" .= mismatchSupplied
        , "expectedCoin" .= mismatchExpected
        , "error" .= String "DRep delegation has incorrect deposit"
        ]
      Conway.ConwayCommitteeHasPreviouslyResigned kHash ->
        [ "kind" .= String "ConwayCommitteeHasPreviouslyResigned"
        , "credential" .= String (textShow kHash)
        , "error" .= String "Committee has resigned"
        ]
      Conway.ConwayCommitteeIsUnknown kHash ->
        [ "kind" .= String "ConwayCommitteeIsUnknown"
        , "credential" .= String (textShow kHash)
        , "error" .= String "Committee is Unknown"
        ]
      Conway.ConwayDRepIncorrectRefund Mismatch {mismatchSupplied, mismatchExpected} ->
        [ "kind" .= String "ConwayDRepIncorrectRefund"
        , "givenRefund" .= String (textShow mismatchSupplied)
        , "expectedRefund" .= String (textShow mismatchExpected)
        , "error" .= String "Refund given does not match the expected one"
        ]
  
  
  instance ToObject (Conway.ConwayDelegPredFailure era) where
    toObject _verb = mconcat . \case
      Conway.DelegateeStakePoolNotRegisteredDELEG (KeyHash targetPool) ->
        [ "kind" .= String "DelegateeNotRegisteredDELEG"
        , "targetPool" .= Crypto.hashToTextAsHex targetPool
        ]
      Conway.IncorrectDepositDELEG coin ->
        [ "kind" .= String "IncorrectDepositDELEG"
        , "amount" .= coin
        , "error" .= String "Incorrect deposit amount"
        ]
      Conway.StakeKeyRegisteredDELEG credential ->
        [ "kind" .= String "StakeKeyRegisteredDELEG"
        , "credential" .= String (textShow credential)
        , "error" .= String "Stake key already registered"
        ]
      Conway.StakeKeyNotRegisteredDELEG credential ->
        [ "kind" .= String "StakeKeyNotRegisteredDELEG"
        , "amount" .= String (textShow credential)
        , "error" .= String "Stake key not registered"
        ]
      Conway.StakeKeyHasNonZeroRewardAccountBalanceDELEG coin ->
        [ "kind" .= String "StakeKeyHasNonZeroAccountBalanceDELEG"
        , "amount" .= coin
        , "error" .= String "Stake key has non-zero account balance"
        ]
      Conway.DelegateeDRepNotRegisteredDELEG credential ->
        [ "kind" .= String "DelegateeDRepNotRegisteredDELEG"
        , "credential" .= String (textShow credential)
        , "error" .= String "Delegated rep is not registered for provided stake key"
        ]
  
  instance ToObject (Set (Credential 'Staking)) where
    toObject _verb creds =
      mconcat [ "kind" .= String "StakeCreds"
               , "stakeCreds" .= map toJSON (Set.toList creds)
               ]
  
  instance ToObject (NonEmpty.NonEmpty (KeyHash 'Staking)) where
    toObject _verb keyHashes =
      mconcat [ "kind" .= String "StakeKeyHashes"
               , "stakeKeyHashes" .= toJSON keyHashes
               ]
  
  instance Core.Crypto crypto => ToObject (ChainTransitionError crypto) where
    toObject verb (ChainTransitionError fs) =
      mconcat [ "kind" .= String "ChainTransitionError"
               , "failures" .= fmap (toObject verb) fs
               ]
  
  instance ToObject ChainPredicateFailure where
    toObject _verb (HeaderSizeTooLargeCHAIN hdrSz maxHdrSz) =
      mconcat [ "kind" .= String "HeaderSizeTooLarge"
               , "headerSize" .= hdrSz
               , "maxHeaderSize" .= maxHdrSz
               ]
    toObject _verb (BlockSizeTooLargeCHAIN blkSz maxBlkSz) =
      mconcat [ "kind" .= String "BlockSizeTooLarge"
               , "blockSize" .= blkSz
               , "maxBlockSize" .= maxBlkSz
               ]
    toObject _verb (ObsoleteNodeCHAIN currentPtcl supportedPtcl) =
      mconcat [ "kind" .= String "ObsoleteNode"
               , "explanation" .= String explanation
               , "currentProtocol" .= currentPtcl
               , "supportedProtocol" .= supportedPtcl ]
        where
          explanation = mconcat
            [ "A scheduled major protocol version change (hard fork) "
            , "has taken place on the chain, but this node does not "
            , "understand the new major protocol version. This node "
            , "must be upgraded before it can continue with the new "
            , "protocol version."
            ]
  
  instance ToObject PrtlSeqFailure where
    toObject _verb (WrongSlotIntervalPrtclSeq (SlotNo lastSlot) (SlotNo currSlot)) =
      mconcat [ "kind" .= String "WrongSlotInterval"
               , "lastSlot" .= lastSlot
               , "currentSlot" .= currSlot
               ]
    toObject _verb (WrongBlockNoPrtclSeq lab currentBlockNo) =
      mconcat [ "kind" .= String "WrongBlockNo"
               , "lastAppliedBlockNo" .= showLastAppBlockNo lab
               , "currentBlockNo" .= (String . textShow $ unBlockNo currentBlockNo)
               ]
    toObject _verb (WrongBlockSequencePrtclSeq lastAppliedHash currentHash) =
      mconcat [ "kind" .= String "WrongBlockSequence"
               , "lastAppliedBlockHash" .= String (textShow lastAppliedHash)
               , "currentBlockHash" .= String (textShow currentHash)
               ]
  
  instance
    ( ToObject (PredicateFailure (Ledger.EraRule "LEDGERS" ledgerera))
    ) => ToObject (ShelleyBbodyPredFailure ledgerera) where
    toObject _verb (WrongBlockBodySizeBBODY Mismatch { mismatchSupplied = actualBodySz
                                                     , mismatchExpected = claimedBodySz }) =
      mconcat [ "kind" .= String "WrongBlockBodySizeBBODY"
               , "actualBlockBodySize" .= actualBodySz
               , "claimedBlockBodySize" .= claimedBodySz
               ]
    toObject _verb (InvalidBodyHashBBODY Mismatch { mismatchSupplied = actualHash
                                                  , mismatchExpected = claimedHash }) =
      mconcat [ "kind" .= String "InvalidBodyHashBBODY"
               , "actualBodyHash" .= textShow actualHash
               , "claimedBodyHash" .= textShow claimedHash
               ]
    toObject verb (LedgersFailure f) = toObject verb f
  
  
  instance
    ( ToObject (PredicateFailure (Core.EraRule "LEDGER" ledgerera))
    ) => ToObject (ShelleyLedgersPredFailure ledgerera) where
    toObject verb (LedgerFailure f) = toObject verb f
  
  
  instance
    ( ToObject (PredicateFailure (Core.EraRule "DELEGS" ledgerera))
    , ToObject (PredicateFailure (Core.EraRule "UTXOW" ledgerera))
    ) => ToObject (ShelleyLedgerPredFailure ledgerera) where
    toObject verb (UtxowFailure f) = toObject verb f
    toObject verb (DelegsFailure f) = toObject verb f
  
  instance
    ( ToObject (PredicateFailure (Core.EraRule "CERTS" ledgerera))
    , ToObject (PredicateFailure (Core.EraRule "UTXOW" ledgerera))
    , ToObject (PredicateFailure (Core.EraRule "GOV" ledgerera))
    ) => ToObject (Conway.ConwayLedgerPredFailure ledgerera) where
    toObject verb (Conway.ConwayUtxowFailure f) = toObject verb f
    toObject _    (Conway.ConwayTxRefScriptsSizeTooBig Mismatch {mismatchSupplied, mismatchExpected}) =
      mconcat [ "kind" .= String "ConwayTxRefScriptsSizeTooBig"
              , "actual" .= mismatchSupplied
              , "limit" .= mismatchExpected
              ]
    toObject verb (Conway.ConwayCertsFailure f) = toObject verb f
    toObject verb (Conway.ConwayGovFailure f) = toObject verb f
    toObject verb (Conway.ConwayWdrlNotDelegatedToDRep f) = toObject verb f
    toObject _    (Conway.ConwayTreasuryValueMismatch Mismatch {mismatchSupplied, mismatchExpected}) =
      mconcat [ "kind" .= String "ConwayTreasuryValueMismatch"
              , "actual" .= mismatchExpected
              , "submittedInTx" .= mismatchSupplied
              ]
    toObject _ (Conway.ConwayMempoolFailure msg) =
      mconcat [ "kind" .= String "ConwayMempoolFailure"
              , "message" .= msg
              ]
  
  
  instance Ledger.EraPParams era => ToObject (Conway.ConwayGovPredFailure era) where
    toObject _ (Conway.GovActionsDoNotExist govActionIds) =
      mconcat [ "kind" .= String "GovActionsDoNotExist"
              , "govActionIds" .= map govActionIdToText (NonEmpty.toList govActionIds)
              ]
    toObject _ (Conway.MalformedProposal govAction) =
      mconcat [ "kind" .= String "MalformedProposal"
              , "govAction" .= govAction
              ]
    toObject _ (Conway.ProposalProcedureNetworkIdMismatch rewardAcnt network) =
      mconcat [ "kind" .= String "ProposalProcedureNetworkIdMismatch"
              , "rewardAccount" .= toJSON rewardAcnt
              , "expectedNetworkId" .= toJSON network
              ]
    toObject _ (Conway.TreasuryWithdrawalsNetworkIdMismatch rewardAcnts network) =
      mconcat [ "kind" .= String "TreasuryWithdrawalsNetworkIdMismatch"
              , "rewardAccounts" .= toJSON rewardAcnts
              , "expectedNetworkId" .= toJSON network
              ]
    toObject _ (Conway.ProposalDepositIncorrect Mismatch {mismatchSupplied, mismatchExpected}) =
      mconcat [ "kind" .= String "ProposalDepositIncorrect"
              , "deposit" .= mismatchSupplied
              , "expectedDeposit" .= mismatchExpected
              ]
    toObject _ (Conway.DisallowedVoters govActionIdToVoter) =
      mconcat [ "kind" .= String "DisallowedVoters"
              , "govActionIdToVoter" .= NonEmpty.toList govActionIdToVoter
              ]
    toObject _ (Conway.VotersDoNotExist creds) =
      mconcat [ "kind" .= String "VotersDoNotExist"
              , "credentials" .= creds
              ]
    toObject _ (Conway.ConflictingCommitteeUpdate creds) =
      mconcat [ "kind" .= String "ConflictingCommitteeUpdate"
              , "credentials" .= creds
              ]
    toObject _ (Conway.ExpirationEpochTooSmall credsToEpoch) =
      mconcat [ "kind" .= String "ExpirationEpochTooSmall"
              , "credentialsToEpoch" .= credsToEpoch
              ]
    toObject _ (Conway.InvalidPrevGovActionId proposalProcedure) =
      mconcat [ "kind" .= String "InvalidPrevGovActionId"
              , "proposalProcedure" .= proposalProcedure
              ]
    toObject _ (Conway.VotingOnExpiredGovAction actions) =
      mconcat [ "kind" .= String "VotingOnExpiredGovAction"
              , "action" .= actions
              ]
    toObject _ (Conway.ProposalCantFollow prevGovActionId Mismatch {mismatchSupplied, mismatchExpected}) =
      mconcat [ "kind" .= String "ProposalCantFollow"
              , "prevGovActionId" .= prevGovActionId
              , "protVer" .= mismatchSupplied
              , "prevProtVer" .= mismatchExpected
              ]
    toObject _ (Conway.InvalidPolicyHash actualPolicyHash expectedPolicyHash) =
      mconcat [ "kind" .= String "InvalidPolicyHash"
              , "actualPolicyHash" .= actualPolicyHash
              , "expectedPolicyHash" .= expectedPolicyHash
              ]
    toObject _ (Conway.DisallowedProposalDuringBootstrap proposal) =
      mconcat [ "kind" .= String "DisallowedProposalDuringBootstrap"
              , "proposal" .= proposal
              ]
  
    toObject _ (Conway.DisallowedVotesDuringBootstrap votes) =
      mconcat [ "kind" .= String "DisallowedVotesDuringBootstrap"
              , "votes" .= votes
              ]
  
    toObject _ (Conway.ZeroTreasuryWithdrawals govAction) =
      mconcat [ "kind" .= String "ZeroTreasuryWithdrawals"
              , "govAction" .= govAction
              ]
  
    toObject _ (Conway.ProposalReturnAccountDoesNotExist account) =
      mconcat [ "kind" .= String "DisallowedVotesDuringBootstrap"
              , "invalidAccount" .= account
              ]
  
    toObject _ (Conway.TreasuryWithdrawalReturnAccountsDoNotExist accounts) =
      mconcat [ "kind" .= String "TreasuryWithdrawalReturnAccountsDoNotExist"
              , "invalidAccounts" .= accounts
              ]
  
  instance
    ( ToObject (PredicateFailure (Ledger.EraRule "CERT" era))
    ) => ToObject (Conway.ConwayCertsPredFailure era) where
    toObject verb = \case
      Conway.WithdrawalsNotInRewardsCERTS incorrectWithdrawals ->
        mconcat [ "kind" .= String "WithdrawalsNotInRewardsCERTS" , "incorrectWithdrawals" .= incorrectWithdrawals ]
      Conway.CertFailure f -> toObject verb f
  
  
  instance
    ( Api.ShelleyLedgerEra era ~ ledgerera
    , Api.IsShelleyBasedEra era
    , ToObject (Ledger.EraRuleFailure "PPUP" ledgerera)
    , ToObject (PredicateFailure (Ledger.EraRule "UTXO" ledgerera))
    , Show (Ledger.Value ledgerera)
    , ToJSON (Ledger.Value ledgerera)
    , ToJSON (Ledger.TxOut ledgerera)
    ) => ToObject (AlonzoUtxowPredFailure ledgerera) where
    toObject v (ShelleyInAlonzoUtxowPredFailure utxoPredFail) =
      toObject v utxoPredFail
    toObject _ (MissingRedeemers scripts) =
      mconcat [ "kind" .= String "MissingRedeemers"
               , "scripts" .= renderMissingRedeemers Api.shelleyBasedEra scripts
               ]
    toObject _ (MissingRequiredDatums required received) =
      mconcat [ "kind" .= String "MissingRequiredDatums"
               , "required" .= map (Crypto.hashToTextAsHex . Hashes.extractHash)
                                   (Set.toList required)
               , "received" .= map (Crypto.hashToTextAsHex . Hashes.extractHash)
                                   (Set.toList received)
               ]
    toObject _ (PPViewHashesDontMatch Mismatch {mismatchSupplied, mismatchExpected}) =
      mconcat [ "kind" .= String "PPViewHashesDontMatch"
               , "fromTxBody" .= renderScriptIntegrityHash (strictMaybeToMaybe mismatchSupplied)
               , "fromPParams" .= renderScriptIntegrityHash (strictMaybeToMaybe mismatchExpected)
               ]
    toObject _ (MissingRequiredSigners missingKeyWitnesses) =
      mconcat [ "kind" .= String "MissingRequiredSigners"
               , "witnesses" .= Set.toList missingKeyWitnesses
               ]
    toObject _ (UnspendableUTxONoDatumHash txins) =
      mconcat [ "kind" .= String "MissingRequiredSigners"
               , "txins" .= Set.toList txins
               ]
    toObject _ (NotAllowedSupplementalDatums disallowed acceptable) =
      mconcat [ "kind" .= String "NotAllowedSupplementalDatums"
               , "disallowed" .= Set.toList disallowed
               , "acceptable" .= Set.toList acceptable
               ]
    toObject _ (ExtraRedeemers rdmrs) =
      Api.caseShelleyToMaryOrAlonzoEraOnwards
        (const mempty)
        (\alonzoOnwards ->
           mconcat
             [ "kind" .= String "ExtraRedeemers"
             , "rdmrs" .=  map (Api.toScriptIndex alonzoOnwards) rdmrs
             ]
        )
        (Api.shelleyBasedEra :: Api.ShelleyBasedEra era)
  
  instance
    ( ToObject (PredicateFailure (Core.EraRule "UTXO" ledgerera))
    ) => ToObject (ShelleyUtxowPredFailure ledgerera) where
    toObject _verb (ExtraneousScriptWitnessesUTXOW extraneousScripts) =
      mconcat [ "kind" .= String "ExtraneousScriptWitnessesUTXOW"
               , "extraneousScripts" .= Set.map renderScriptHash extraneousScripts
               ]
    toObject _verb (InvalidWitnessesUTXOW wits') =
      mconcat [ "kind" .= String "InvalidWitnessesUTXOW"
               , "invalidWitnesses" .= map textShow wits'
               ]
    toObject _verb (MissingVKeyWitnessesUTXOW wits') =
      mconcat [ "kind" .= String "MissingVKeyWitnessesUTXOW"
               , "missingWitnesses" .= wits'
               ]
    toObject _verb (MissingScriptWitnessesUTXOW missingScripts) =
      mconcat [ "kind" .= String "MissingScriptWitnessesUTXOW"
               , "missingScripts" .= missingScripts
               ]
    toObject _verb (ScriptWitnessNotValidatingUTXOW failedScripts) =
      mconcat [ "kind" .= String "ScriptWitnessNotValidatingUTXOW"
               , "failedScripts" .= failedScripts
               ]
    toObject verb (UtxoFailure f) = toObject verb f
    toObject _verb (MIRInsufficientGenesisSigsUTXOW genesisSigs) =
      mconcat [ "kind" .= String "MIRInsufficientGenesisSigsUTXOW"
               , "genesisSigs" .= genesisSigs
               ]
    toObject _verb (MissingTxBodyMetadataHash metadataHash) =
      mconcat [ "kind" .= String "MissingTxBodyMetadataHash"
               , "metadataHash" .= metadataHash
               ]
    toObject _verb (MissingTxMetadata txBodyMetadataHash) =
      mconcat [ "kind" .= String "MissingTxMetadata"
               , "txBodyMetadataHash" .= txBodyMetadataHash
               ]
    -- TODO are these arguments in the right order?
    toObject _verb (ConflictingMetadataHash Mismatch { mismatchSupplied = txBodyMetadataHash
                                                     , mismatchExpected = fullMetadataHash }) =
      mconcat [ "kind" .= String "ConflictingMetadataHash"
               , "txBodyMetadataHash" .= txBodyMetadataHash
               , "fullMetadataHash" .= fullMetadataHash
               ]
    toObject _verb InvalidMetadata =
      mconcat [ "kind" .= String "InvalidMetadata"
               ]
  
  instance
    ( ToObject (Ledger.EraRuleFailure "PPUP" ledgerera)
    , Show (Ledger.Value ledgerera)
    , ToJSON (Ledger.Value ledgerera)
    , ToJSON (Ledger.TxOut ledgerera)
    ) => ToObject (ShelleyUtxoPredFailure ledgerera) where
    toObject _verb (BadInputsUTxO badInputs) =
      mconcat [ "kind" .= String "BadInputsUTxO"
               , "badInputs" .= badInputs
               , "error" .= renderBadInputsUTxOErr badInputs
               ]
    toObject _verb (ExpiredUTxO Mismatch {mismatchSupplied, mismatchExpected}) =
      mconcat [ "kind" .= String "ExpiredUTxO"
               , "ttl"  .= mismatchSupplied
               , "slot" .= mismatchExpected ]
    toObject _verb (MaxTxSizeUTxO Mismatch { mismatchSupplied = txsize
                                           , mismatchExpected = maxtxsize }) =
      mconcat [ "kind" .= String "MaxTxSizeUTxO"
               , "size" .= txsize
               , "maxSize" .= maxtxsize ]
    -- TODO: Add the minimum allowed UTxO value to OutputTooSmallUTxO
    toObject _verb (OutputTooSmallUTxO badOutputs) =
      mconcat [ "kind" .= String "OutputTooSmallUTxO"
              , "outputs" .= badOutputs
              , "error" .= String
                ( mconcat
                  [ "The output is smaller than the allow minimum "
                  , "UTxO value defined in the protocol parameters"
                  ]
                )
              ]
    toObject _verb (OutputBootAddrAttrsTooBig badOutputs) =
      mconcat [ "kind" .= String "OutputBootAddrAttrsTooBig"
               , "outputs" .= badOutputs
               , "error" .= String "The Byron address attributes are too big"
               ]
    toObject _verb InputSetEmptyUTxO =
      mconcat [ "kind" .= String "InputSetEmptyUTxO" ]
    toObject _verb (FeeTooSmallUTxO Mismatch { mismatchSupplied = minfee
                                             , mismatchExpected = txfee }) =
      mconcat [ "kind" .= String "FeeTooSmallUTxO"
               , "minimum" .= minfee
               , "fee" .= txfee ]
    toObject _verb (ValueNotConservedUTxO Mismatch {mismatchSupplied, mismatchExpected}) =
      mconcat [ "kind" .= String "ValueNotConservedUTxO"
               , "consumed" .= mismatchSupplied
               , "produced" .= mismatchExpected
               , "error" .= renderValueNotConservedErr mismatchSupplied mismatchExpected
               ]
    toObject verb (UpdateFailure f) = toObject verb f
  
    toObject _verb (WrongNetwork network addrs) =
      mconcat [ "kind" .= String "WrongNetwork"
               , "network" .= network
               , "addrs"   .= addrs
               ]
    toObject _verb (WrongNetworkWithdrawal network addrs) =
      mconcat [ "kind" .= String "WrongNetworkWithdrawal"
               , "network" .= network
               , "addrs"   .= addrs
               ]
  
  instance
    ( ToObject (Ledger.EraRuleFailure "PPUP" ledgerera)
    , ToJSON (Ledger.TxOut ledgerera)
    , Show (Ledger.Value ledgerera)
    , ToJSON (Ledger.Value ledgerera)
    ) => ToObject (AllegraUtxoPredFailure ledgerera) where
    toObject _verb (Allegra.BadInputsUTxO badInputs) =
      mconcat [ "kind" .= String "BadInputsUTxO"
               , "badInputs" .= badInputs
               , "error" .= renderBadInputsUTxOErr badInputs
               ]
    toObject _verb (Allegra.OutsideValidityIntervalUTxO validityInterval slot) =
      mconcat [ "kind" .= String "ExpiredUTxO"
               , "validityInterval" .= validityInterval
               , "slot" .= slot ]
    toObject _verb (Allegra.MaxTxSizeUTxO Mismatch {mismatchSupplied, mismatchExpected}) =
      mconcat [ "kind" .= String "MaxTxSizeUTxO"
               , "size" .= mismatchSupplied
               , "maxSize" .= mismatchExpected ]
    toObject _verb Allegra.InputSetEmptyUTxO =
      mconcat [ "kind" .= String "InputSetEmptyUTxO" ]
    toObject _verb (Allegra.FeeTooSmallUTxO Mismatch {mismatchSupplied, mismatchExpected}) =
      mconcat [ "kind" .= String "FeeTooSmallUTxO"
               , "minimum" .= mismatchExpected
               , "fee" .= mismatchSupplied ]
    toObject _verb (Allegra.ValueNotConservedUTxO Mismatch {mismatchSupplied, mismatchExpected}) =
      mconcat [ "kind" .= String "ValueNotConservedUTxO"
               , "consumed" .= mismatchSupplied
               , "produced" .= mismatchExpected
               , "error" .= renderValueNotConservedErr mismatchSupplied mismatchExpected
               ]
    toObject _verb (Allegra.WrongNetwork network addrs) =
      mconcat [ "kind" .= String "WrongNetwork"
               , "network" .= network
               , "addrs"   .= addrs
               ]
    toObject _verb (Allegra.WrongNetworkWithdrawal network addrs) =
      mconcat [ "kind" .= String "WrongNetworkWithdrawal"
               , "network" .= network
               , "addrs"   .= addrs
               ]
    -- TODO: Add the minimum allowed UTxO value to OutputTooSmallUTxO
    toObject _verb (Allegra.OutputTooSmallUTxO badOutputs) =
      mconcat [ "kind" .= String "OutputTooSmallUTxO"
              , "outputs" .= badOutputs
              , "error" .= String
                ( mconcat
                  [ "The output is smaller than the allow minimum "
                  , "UTxO value defined in the protocol parameters"
                  ]
                )
              ]
    toObject verb (Allegra.UpdateFailure f) = toObject verb f
    toObject _verb (Allegra.OutputBootAddrAttrsTooBig badOutputs) =
      mconcat [ "kind" .= String "OutputBootAddrAttrsTooBig"
               , "outputs" .= badOutputs
               , "error" .= String "The Byron address attributes are too big"
               ]
    toObject _verb Allegra.TriesToForgeADA =
      mconcat [ "kind" .= String "TriesToForgeADA" ]
    toObject _verb (Allegra.OutputTooBigUTxO badOutputs) =
      mconcat [ "kind" .= String "OutputTooBigUTxO"
               , "outputs" .= badOutputs
               , "error" .= String "Too many asset ids in the tx output"
               ]
  
  renderBadInputsUTxOErr :: Set TxIn -> Aeson.Value
  renderBadInputsUTxOErr txIns
    | Set.null txIns = String "The transaction contains no inputs."
    | otherwise = String "The transaction contains inputs that do not exist in the UTxO set."
  
  renderValueNotConservedErr :: Show val => val -> val -> Aeson.Value
  renderValueNotConservedErr consumed produced = String $
      "This transaction consumed " <> textShow consumed <> " but produced " <> textShow produced
  
  instance Ledger.Era era => ToObject (ShelleyPpupPredFailure era) where
    toObject _verb (NonGenesisUpdatePPUP Mismatch { mismatchSupplied = proposalKeys
                                                  , mismatchExpected = genesisKeys }) =
      mconcat [ "kind" .= String "NonGenesisUpdatePPUP"
               , "keys" .= proposalKeys Set.\\ genesisKeys ]
    toObject _verb (PPUpdateWrongEpoch currEpoch intendedEpoch votingPeriod) =
      mconcat [ "kind" .= String "PPUpdateWrongEpoch"
               , "currentEpoch" .= currEpoch
               , "intendedEpoch" .= intendedEpoch
               , "votingPeriod"  .= String (textShow votingPeriod)
               ]
    toObject _verb (PVCannotFollowPPUP badPv) =
      mconcat [ "kind" .= String "PVCannotFollowPPUP"
               , "badProtocolVersion" .= badPv
               ]
  
  
  instance
    ( ToObject (PredicateFailure (Core.EraRule "DELPL" ledgerera))
    ) => ToObject (ShelleyDelegsPredFailure ledgerera) where
    toObject _verb (DelegateeNotRegisteredDELEG targetPool) =
      mconcat [ "kind" .= String "DelegateeNotRegisteredDELEG"
               , "targetPool" .= targetPool
               ]
    toObject _verb (WithdrawalsNotInRewardsDELEGS incorrectWithdrawals) =
      mconcat [ "kind" .= String "WithdrawalsNotInRewardsCERTS"
               , "incorrectWithdrawals" .= incorrectWithdrawals
               ]
    toObject verb (DelplFailure f) = toObject verb f
  
  
  instance
    ( ToObject (PredicateFailure (Core.EraRule "POOL" ledgerera))
    , ToObject (PredicateFailure (Core.EraRule "DELEG" ledgerera))
    ) => ToObject (ShelleyDelplPredFailure ledgerera) where
    toObject verb (PoolFailure f) = toObject verb f
    toObject verb (DelegFailure f) = toObject verb f
  
  instance Ledger.Era era => ToObject (ShelleyDelegPredFailure era) where
    toObject _verb (StakeKeyAlreadyRegisteredDELEG alreadyRegistered) =
      mconcat [ "kind" .= String "StakeKeyAlreadyRegisteredDELEG"
               , "credential" .= String (textShow alreadyRegistered)
               , "error" .= String "Staking credential already registered"
               ]
    toObject _verb (StakeKeyNotRegisteredDELEG notRegistered) =
      mconcat [ "kind" .= String "StakeKeyNotRegisteredDELEG"
               , "credential" .= String (textShow notRegistered)
               , "error" .= String "Staking credential not registered"
               ]
    toObject _verb (StakeKeyNonZeroAccountBalanceDELEG remBalance) =
      mconcat [ "kind" .= String "StakeKeyNonZeroAccountBalanceDELEG"
               , "remainingBalance" .= remBalance
               ]
    toObject _verb (StakeDelegationImpossibleDELEG unregistered) =
      mconcat [ "kind" .= String "StakeDelegationImpossibleDELEG"
               , "credential" .= String (textShow unregistered)
               , "error" .= String "Cannot delegate this stake credential because it is not registered"
               ]
    toObject _verb WrongCertificateTypeDELEG =
      mconcat [ "kind" .= String "WrongCertificateTypeDELEG" ]
    toObject _verb (GenesisKeyNotInMappingDELEG (KeyHash genesisKeyHash)) =
      mconcat [ "kind" .= String "GenesisKeyNotInMappingDELEG"
               , "unknownKeyHash" .= String (textShow genesisKeyHash)
               , "error" .= String "This genesis key is not in the delegation mapping"
               ]
    toObject _verb (DuplicateGenesisDelegateDELEG (KeyHash genesisKeyHash)) =
      mconcat [ "kind" .= String "DuplicateGenesisDelegateDELEG"
               , "duplicateKeyHash" .= String (textShow genesisKeyHash)
               , "error" .= String "This genesis key has already been delegated to"
               ]
    toObject _verb (InsufficientForInstantaneousRewardsDELEG mirpot Mismatch {mismatchSupplied, mismatchExpected}) =
      mconcat [ "kind" .= String "InsufficientForInstantaneousRewardsDELEG"
               , "pot" .= String (case mirpot of
                                    ReservesMIR -> "Reserves"
                                    TreasuryMIR -> "Treasury")
               , "neededAmount" .= mismatchSupplied
               , "reserves" .= mismatchExpected
               ]
    toObject _verb (MIRCertificateTooLateinEpochDELEG Mismatch {mismatchSupplied, mismatchExpected}) =
      mconcat [ "kind" .= String "MIRCertificateTooLateinEpochDELEG"
               , "currentSlotNo" .= mismatchSupplied
               , "mustBeSubmittedBeforeSlotNo" .= mismatchExpected
               ]
    toObject _verb (DuplicateGenesisVRFDELEG vrfKeyHash) =
      mconcat [ "kind" .= String "DuplicateGenesisVRFDELEG"
               , "keyHash" .= vrfKeyHash
               ]
    toObject _verb MIRTransferNotCurrentlyAllowed =
      mconcat [ "kind" .= String "MIRTransferNotCurrentlyAllowed"
               ]
    toObject _verb MIRNegativesNotCurrentlyAllowed =
      mconcat [ "kind" .= String "MIRNegativesNotCurrentlyAllowed"
               ]
    toObject _verb (InsufficientForTransferDELEG mirpot Mismatch {mismatchSupplied, mismatchExpected}) =
      mconcat [ "kind" .= String "DuplicateGenesisVRFDELEG"
               , "pot" .= String (case mirpot of
                                    ReservesMIR -> "Reserves"
                                    TreasuryMIR -> "Treasury")
               , "attempted" .= mismatchSupplied
               , "available" .= mismatchExpected
               ]
    toObject _verb MIRProducesNegativeUpdate =
      mconcat [ "kind" .= String "MIRProducesNegativeUpdate"
               ]
    toObject _verb (MIRNegativeTransfer pot coin) =
      mconcat [ "kind" .= String "MIRNegativeTransfer"
               , "error" .= String "Attempt to transfer a negative amount from a pot."
               , "pot" .= String (case pot of
                                    ReservesMIR -> "Reserves"
                                    TreasuryMIR -> "Treasury")
               , "amount" .= coin
               ]
  
  instance ToObject (ShelleyPoolPredFailure era) where
    toObject _verb (StakePoolNotRegisteredOnKeyPOOL (KeyHash unregStakePool)) =
      mconcat [ "kind" .= String "StakePoolNotRegisteredOnKeyPOOL"
               , "unregisteredKeyHash" .= String (textShow unregStakePool)
               , "error" .= String "This stake pool key hash is unregistered"
               ]
    toObject _dtal (StakePoolRetirementWrongEpochPOOL
                     -- inspired by Ledger's Test.Cardano.Ledger.Generic.PrettyCore
                     -- but is it correct here?
                      Mismatch { mismatchExpected = currentEpoch }
                      Mismatch { mismatchSupplied = intendedRetireEpoch
                               , mismatchExpected = maxRetireEpoch}) =
      mconcat [ "kind" .= String "StakePoolRetirementWrongEpochPOOL"
               , "currentEpoch" .= String (textShow currentEpoch)
               , "intendedRetirementEpoch" .= String (textShow intendedRetireEpoch)
               , "maxEpochForRetirement" .= String (textShow maxRetireEpoch)
               ]
    -- TODO is this in the right order?
    toObject _verb (StakePoolCostTooLowPOOL
                     Mismatch { mismatchSupplied = certCost
                              , mismatchExpected = protCost }) =
      mconcat [ "kind" .= String "StakePoolCostTooLowPOOL"
               , "certificateCost" .= String (textShow certCost)
               , "protocolParCost" .= String (textShow protCost)
               , "error" .= String "The stake pool cost is too low"
               ]
    toObject _verb (PoolMedataHashTooBig poolID hashSize) =
      mconcat [ "kind" .= String "PoolMedataHashTooBig"
               , "poolID" .= String (textShow poolID)
               , "hashSize" .= String (textShow hashSize)
               , "error" .= String "The stake pool metadata hash is too large"
               ]
  
  -- Apparently this should never happen according to the Shelley exec spec
    -- toObject _verb (WrongCertificateTypePOOL index) =
    --   case index of
    --     0 -> mconcat [ "kind" .= String "WrongCertificateTypePOOL"
    --                   , "error" .= String "Wrong certificate type: Delegation certificate"
    --                   ]
    --     1 -> mconcat [ "kind" .= String "WrongCertificateTypePOOL"
    --                   , "error" .= String "Wrong certificate type: MIR certificate"
    --                   ]
    --     2 -> mconcat [ "kind" .= String "WrongCertificateTypePOOL"
    --                   , "error" .= String "Wrong certificate type: Genesis certificate"
    --                   ]
    --     k -> mconcat [ "kind" .= String "WrongCertificateTypePOOL"
    --                   , "certificateType" .= k
    --                   , "error" .= String "Wrong certificate type: Unknown certificate type"
    --                   ]
  
    -- TODO are these in the right order?
    toObject _verb (WrongNetworkPOOL Mismatch { mismatchSupplied = networkId
                                              , mismatchExpected = listedNetworkId }
                                     poolId) =
      mconcat [ "kind" .= String "WrongNetworkPOOL"
               , "networkId" .= String (textShow networkId)
               , "listedNetworkId" .= String (textShow listedNetworkId)
               , "poolId" .= String (textShow poolId)
               , "error" .= String "Wrong network ID in pool registration certificate"
               ]
  
  instance
    ( ToObject (PredicateFailure (Core.EraRule "NEWEPOCH" ledgerera))
    , ToObject (PredicateFailure (Core.EraRule "RUPD" ledgerera))
    ) => ToObject (ShelleyTickPredFailure ledgerera) where
    toObject verb (NewEpochFailure f) = toObject verb f
    toObject verb (RupdFailure f) = toObject verb f
  
  instance ToObject TicknPredicateFailure where
    toObject _verb x = case x of {} -- no constructors
  
  instance
    ( ToObject (PredicateFailure (Core.EraRule "EPOCH" ledgerera))
    , ToObject (PredicateFailure (Core.EraRule "MIR" ledgerera))
    ) => ToObject (ShelleyNewEpochPredFailure ledgerera) where
    toObject verb (EpochFailure f) = toObject verb f
    toObject verb (MirFailure f) = toObject verb f
    toObject _verb (CorruptRewardUpdate update) =
      mconcat [ "kind" .= String "CorruptRewardUpdate"
               , "update" .= String (textShow update) ]
  
  
  instance
    ( ToObject (PredicateFailure (Core.EraRule "POOLREAP" ledgerera))
    , ToObject (PredicateFailure (Core.EraRule "SNAP" ledgerera))
    , ToObject (UpecPredFailure ledgerera)
    ) => ToObject (ShelleyEpochPredFailure ledgerera) where
    toObject verb (PoolReapFailure f) = toObject verb f
    toObject verb (SnapFailure f) = toObject verb f
    toObject verb (UpecFailure f) = toObject verb f
  
  
  instance ToObject (ShelleyPoolreapPredFailure ledgerera) where
    toObject _verb x = case x of {} -- no constructors
  
  
  instance ToObject (ShelleySnapPredFailure ledgerera) where
    toObject _verb x = case x of {} -- no constructors
  
  instance ToObject (ShelleyMirPredFailure ledgerera) where
    toObject _verb x = case x of {} -- no constructors
  
  
  instance ToObject (ShelleyRupdPredFailure ledgerera) where
    toObject _verb x = case x of {} -- no constructors
  
  
  instance Core.Crypto crypto => ToObject (PrtclPredicateFailure crypto) where
    toObject  verb (OverlayFailure f) = toObject verb f
    toObject  verb (UpdnFailure f) = toObject verb f
  
  
  instance Core.Crypto crypto => ToObject (OverlayPredicateFailure crypto) where
    toObject _verb (UnknownGenesisKeyOVERLAY (KeyHash genKeyHash)) =
      mconcat [ "kind" .= String "UnknownGenesisKeyOVERLAY"
               , "unknownKeyHash" .= String (textShow genKeyHash)
               ]
    toObject _verb (VRFKeyBadLeaderValue seedNonce (SlotNo currSlotNo) prevHashNonce leaderElecVal) =
      mconcat [ "kind" .= String "VRFKeyBadLeaderValueOVERLAY"
               , "seedNonce" .= String (textShow seedNonce)
               , "currentSlot" .= String (textShow currSlotNo)
               , "previousHashAsNonce" .= String (textShow prevHashNonce)
               , "leaderElectionValue" .= String (textShow leaderElecVal)
               ]
    toObject _verb (VRFKeyBadNonce seedNonce (SlotNo currSlotNo) prevHashNonce blockNonce) =
      mconcat [ "kind" .= String "VRFKeyBadNonceOVERLAY"
               , "seedNonce" .= String (textShow seedNonce)
               , "currentSlot" .= String (textShow currSlotNo)
               , "previousHashAsNonce" .= String (textShow prevHashNonce)
               , "blockNonce" .= String (textShow blockNonce)
               ]
    toObject _verb (VRFKeyWrongVRFKey issuerHash regVRFKeyHash unregVRFKeyHash) =
      mconcat [ "kind" .= String "VRFKeyWrongVRFKeyOVERLAY"
               , "poolHash" .= textShow issuerHash
               , "registeredVRFKeHash" .= textShow regVRFKeyHash
               , "unregisteredVRFKeyHash" .= textShow unregVRFKeyHash
               ]
    --TODO: Pipe slot number with VRFKeyUnknown
    toObject _verb (VRFKeyUnknown (KeyHash kHash)) =
      mconcat [ "kind" .= String "VRFKeyUnknownOVERLAY"
               , "keyHash" .= String (textShow kHash)
               ]
    toObject _verb (VRFLeaderValueTooBig leadElecVal weightOfDelegPool actSlotCoefff) =
      mconcat [ "kind" .= String "VRFLeaderValueTooBigOVERLAY"
               , "leaderElectionValue" .= String (textShow leadElecVal)
               , "delegationPoolWeight" .= String (textShow weightOfDelegPool)
               , "activeSlotCoefficient" .= String (textShow actSlotCoefff)
               ]
    toObject _verb (NotActiveSlotOVERLAY notActiveSlotNo) =
      -- TODO: Elaborate on NotActiveSlot error
      mconcat [ "kind" .= String "NotActiveSlotOVERLAY"
               , "slot" .= String (textShow notActiveSlotNo)
               ]
    toObject _verb (WrongGenesisColdKeyOVERLAY actual expected) =
      mconcat [ "kind" .= String "WrongGenesisColdKeyOVERLAY"
               , "actual" .= actual
               , "expected" .= expected ]
    toObject _verb (WrongGenesisVRFKeyOVERLAY issuer actual expected) =
      mconcat [ "kind" .= String "WrongGenesisVRFKeyOVERLAY"
               , "issuer" .= issuer
               , "actual" .= actual
               , "expected" .= expected ]
    toObject verb (OcertFailure f) = toObject verb f
  
  
  instance ToObject OcertPredicateFailure where
    toObject _verb (KESBeforeStartOCERT (KESPeriod oCertstart) (KESPeriod current)) =
      mconcat [ "kind" .= String "KESBeforeStartOCERT"
              , "opCertKESStartPeriod" .= String (textShow oCertstart)
              , "currentKESPeriod" .= String (textShow current)
              , "error" .= String
                ( mconcat
                  [ "Your operational certificate's KES start period "
                  , "is before the KES current period."
                  ]
                )
              ]
    toObject _verb (KESAfterEndOCERT (KESPeriod current) (KESPeriod oCertstart) maxKESEvolutions) =
      mconcat [ "kind" .= String "KESAfterEndOCERT"
              , "currentKESPeriod" .= String (textShow current)
              , "opCertKESStartPeriod" .= String (textShow oCertstart)
              , "maxKESEvolutions" .= String  (textShow maxKESEvolutions)
              , "error" .= String
                ( mconcat
                  [ "The operational certificate's KES start period is "
                  , "greater than the max number of KES + the KES current period"
                  ]
                )
              ]
    toObject _verb (CounterTooSmallOCERT lastKEScounterUsed currentKESCounter) =
      mconcat [ "kind" .= String "CounterTooSmallOCert"
              , "currentKESCounter" .= String (textShow currentKESCounter)
              , "lastKESCounter" .= String (textShow lastKEScounterUsed)
              , "error" .= String
                ( mconcat
                  [ "The operational certificate's last KES counter is greater "
                  , "than the current KES counter."
                  ]
                )
              ]
    toObject _verb (InvalidSignatureOCERT oCertCounter oCertKESStartPeriod) =
      mconcat [ "kind" .= String "InvalidSignatureOCERT"
               , "opCertKESStartPeriod" .= String (textShow oCertKESStartPeriod)
               , "opCertCounter" .= String (textShow oCertCounter)
               ]
    toObject _verb (InvalidKesSignatureOCERT currKESPeriod startKESPeriod expectedKESEvolutions err) =
      mconcat [ "kind" .= String "InvalidKesSignatureOCERT"
               , "opCertKESStartPeriod" .= String (textShow startKESPeriod)
               , "opCertKESCurrentPeriod" .= String (textShow currKESPeriod)
               , "opCertExpectedKESEvolutions" .= String (textShow expectedKESEvolutions)
               , "error" .= err ]
    toObject _verb (NoCounterForKeyHashOCERT (KeyHash stakePoolKeyHash)) =
      mconcat [ "kind" .= String "NoCounterForKeyHashOCERT"
               , "stakePoolKeyHash" .= String (textShow stakePoolKeyHash)
               , "error" .= String "A counter was not found for this stake pool key hash"
               ]
  
  instance ToObject HotKey.KESInfo where
    toObject _verb HotKey.KESInfo { kesStartPeriod, kesEndPeriod, kesEvolution } =
      mconcat
        [ "kind" .= String "KESInfo"
        , "startPeriod" .= kesStartPeriod
        , "endPeriod" .= kesEndPeriod
        , "evolution" .= kesEvolution
        ]
  
  instance ToObject HotKey.KESEvolutionError where
    toObject verb (HotKey.KESCouldNotEvolve kesInfo targetPeriod) =
      mconcat
        [ "kind" .= String "KESCouldNotEvolve"
        , "kesInfo" .= toObject verb kesInfo
        , "targetPeriod" .= targetPeriod
        ]
    toObject verb (HotKey.KESKeyAlreadyPoisoned kesInfo targetPeriod) =
      mconcat
        [ "kind" .= String "KESKeyAlreadyPoisoned"
        , "kesInfo" .= toObject verb kesInfo
        , "targetPeriod" .= targetPeriod
        ]
  
  instance ToObject (UpdnPredicateFailure crypto) where
    toObject _verb x = case x of {} -- no constructors
  
  -- instance ToObject (ShelleyUpecPredFailure era) where
  --   toObject _verb (NewPpFailure (UnexpectedDepositPot totalOutstanding depositPot)) =
  --     mconcat [ "kind" .= String "UnexpectedDepositPot"
  --              , "totalOutstanding" .=  String (textShow totalOutstanding)
  --              , "depositPot" .= String (textShow depositPot)
  --              ]
  
  
  --------------------------------------------------------------------------------
  -- Alonzo related
  --------------------------------------------------------------------------------
  
  
  instance
    ( Ledger.Era ledgerera
    , ToObject (PredicateFailure (Ledger.EraRule "UTXOS" ledgerera))
    , ToObject (Ledger.EraRuleFailure "PPUP" ledgerera)
    , ToJSON (Ledger.TxOut ledgerera)
    , Show (Ledger.Value ledgerera)
    , ToJSON (Ledger.Value ledgerera)
    ) => ToObject (AlonzoUtxoPredFailure ledgerera) where
    toObject _verb (Alonzo.BadInputsUTxO badInputs) =
      mconcat [ "kind" .= String "BadInputsUTxO"
               , "badInputs" .= badInputs
               , "error" .= renderBadInputsUTxOErr badInputs
               ]
    toObject _verb (Alonzo.OutsideValidityIntervalUTxO validtyInterval slot) =
      mconcat [ "kind" .= String "ExpiredUTxO"
               , "validityInterval" .= validtyInterval
               , "slot" .= slot
               ]
    toObject _verb (Alonzo.MaxTxSizeUTxO Mismatch {mismatchSupplied, mismatchExpected}) =
      mconcat [ "kind" .= String "MaxTxSizeUTxO"
               , "size" .= mismatchSupplied
               , "maxSize" .= mismatchExpected
               ]
    toObject _verb Alonzo.InputSetEmptyUTxO =
      mconcat [ "kind" .= String "InputSetEmptyUTxO" ]
    toObject _verb (Alonzo.FeeTooSmallUTxO Mismatch {mismatchSupplied, mismatchExpected}) =
      mconcat [ "kind" .= String "FeeTooSmallUTxO"
               , "minimum" .= mismatchExpected
               , "fee" .= mismatchSupplied
               ]
    toObject _verb (Alonzo.ValueNotConservedUTxO Mismatch {mismatchSupplied, mismatchExpected}) =
      mconcat [ "kind" .= String "ValueNotConservedUTxO"
               , "consumed" .= mismatchSupplied
               , "produced" .= mismatchExpected
               , "error" .= renderValueNotConservedErr mismatchSupplied mismatchExpected
               ]
    toObject _verb (Alonzo.WrongNetwork network addrs) =
      mconcat [ "kind" .= String "WrongNetwork"
               , "network" .= network
               , "addrs"   .= addrs
               ]
    toObject _verb (Alonzo.WrongNetworkWithdrawal network addrs) =
      mconcat [ "kind" .= String "WrongNetworkWithdrawal"
               , "network" .= network
               , "addrs"   .= addrs
               ]
    toObject _verb (Alonzo.OutputTooSmallUTxO badOutputs) =
      mconcat [ "kind" .= String "OutputTooSmallUTxO"
              , "outputs" .= badOutputs
              , "error" .= String
                ( mconcat
                  [ "The output is smaller than the allow minimum "
                  , "UTxO value defined in the protocol parameters"
                  ]
                )
              ]
    toObject verb (Alonzo.UtxosFailure predFailure) =
      toObject verb predFailure
    toObject _verb (Alonzo.OutputBootAddrAttrsTooBig txouts) =
      mconcat [ "kind" .= String "OutputBootAddrAttrsTooBig"
               , "outputs" .= txouts
               , "error" .= String "The Byron address attributes are too big"
               ]
    toObject _verb Alonzo.TriesToForgeADA =
      mconcat [ "kind" .= String "TriesToForgeADA" ]
    toObject _verb (Alonzo.OutputTooBigUTxO badOutputs) =
      mconcat [ "kind" .= String "OutputTooBigUTxO"
               , "outputs" .= badOutputs
               , "error" .= String "Too many asset ids in the tx output"
               ]
    toObject _verb (Alonzo.InsufficientCollateral computedBalance suppliedFee) =
      mconcat [ "kind" .= String "InsufficientCollateral"
               , "balance" .= computedBalance
               , "txfee" .= suppliedFee
               ]
    toObject _verb (Alonzo.ScriptsNotPaidUTxO utxos) =
      mconcat [ "kind" .= String "ScriptsNotPaidUTxO"
               , "utxos" .= utxos
               ]
    toObject _verb (Alonzo.ExUnitsTooBigUTxO Mismatch {mismatchSupplied, mismatchExpected}) =
      mconcat [ "kind" .= String "ExUnitsTooBigUTxO"
               , "maxexunits" .= mismatchExpected
               , "exunits" .= mismatchSupplied
               ]
    toObject _verb (Alonzo.CollateralContainsNonADA inputs) =
      mconcat [ "kind" .= String "CollateralContainsNonADA"
               , "inputs" .= inputs
               ]
    toObject _verb (Alonzo.WrongNetworkInTxBody Mismatch {mismatchSupplied, mismatchExpected}) =
      mconcat [ "kind" .= String "WrongNetworkInTxBody"
               , "networkid" .= mismatchExpected
               , "txbodyNetworkId" .= mismatchSupplied
               ]
    toObject _verb (Alonzo.OutsideForecast slotNum) =
      mconcat [ "kind" .= String "OutsideForecast"
               , "slot" .= slotNum
               ]
    toObject _verb (Alonzo.TooManyCollateralInputs Mismatch {mismatchSupplied, mismatchExpected}) =
      mconcat [ "kind" .= String "TooManyCollateralInputs"
               , "max" .= mismatchExpected
               , "inputs" .= mismatchSupplied
               ]
    toObject _verb Alonzo.NoCollateralInputs =
      mconcat [ "kind" .= String "NoCollateralInputs" ]
  
  instance
    ( ToJSON (Alonzo.CollectError ledgerera)
    , ToObject (Ledger.EraRuleFailure "PPUP" ledgerera)
    ) => ToObject (AlonzoUtxosPredFailure ledgerera) where
    toObject _ (Alonzo.ValidationTagMismatch isValidating reason) =
      mconcat [ "kind" .= String "ValidationTagMismatch"
               , "isvalidating" .= isValidating
               , "reason" .= reason
               ]
    toObject _ (Alonzo.CollectErrors errors) =
      mconcat [ "kind" .= String "CollectErrors"
               , "errors" .= errors
               ]
    toObject verb (Alonzo.UpdateFailure pFailure) =
      toObject verb pFailure
  
  instance
    ( Ledger.Era ledgerera
    , Show (PredicateFailure (Ledger.EraRule "LEDGERS" ledgerera))
    ) => ToObject (AlonzoBbodyPredFailure ledgerera) where
    toObject _ err = mconcat [ "kind" .= String "AlonzoBbodyPredFail"
                              , "error" .= String (textShow err)
                              ]
  
  --------------------------------------------------------------------------------
  -- Babbage related
  --------------------------------------------------------------------------------
  
  instance
    ( Ledger.Era ledgerera
    , ToObject (ShelleyUtxowPredFailure ledgerera)
    , ToObject (PredicateFailure (Ledger.EraRule "UTXOS" ledgerera))
    , ToObject (Ledger.EraRuleFailure "PPUP" ledgerera)
    , ToJSON (Ledger.TxOut ledgerera)
    , Show (Ledger.Value ledgerera)
    , ToJSON (Ledger.Value ledgerera)
    ) => ToObject (BabbageUtxoPredFailure ledgerera) where
    toObject v err =
      case err of
        Babbage.AlonzoInBabbageUtxoPredFailure alonzoFail ->
          toObject v alonzoFail
  
        Babbage.IncorrectTotalCollateralField provided declared ->
          mconcat [ "kind" .= String "UnequalCollateralReturn"
                  , "collateralProvided" .= provided
                  , "collateralDeclared" .= declared
                  ]
        Babbage.BabbageOutputTooSmallUTxO outputs->
          mconcat [ "kind" .= String "BabbageOutputTooSmall"
                  , "outputs" .= outputs
                  ]
  
        Babbage.BabbageNonDisjointRefInputs nonDisjointInputs ->
          mconcat [ "kind" .= String "BabbageNonDisjointRefInputs"
                  , "outputs" .= nonDisjointInputs
                  ]
  
  instance
    ( Api.ShelleyLedgerEra era ~ ledgerera
    , Api.IsShelleyBasedEra era
    , Ledger.Era ledgerera
    , Show (Ledger.Value ledgerera)
    , ToObject (Ledger.EraRuleFailure "PPUP" ledgerera)
    , ToObject (PredicateFailure (Ledger.EraRule "UTXO" ledgerera))
    , ToJSON (Ledger.Value ledgerera)
    , ToJSON (Ledger.TxOut ledgerera)
    ) => ToObject (BabbageUtxowPredFailure ledgerera) where
    toObject v err =
      case err of
        Babbage.AlonzoInBabbageUtxowPredFailure alonzoFail ->
          toObject v alonzoFail
        Babbage.UtxoFailure utxoFail ->
          toObject v utxoFail
        -- TODO: Plutus team needs to expose a better error type.
        Babbage.MalformedScriptWitnesses s ->
          mconcat [ "kind" .= String "MalformedScriptWitnesses"
                  , "scripts" .= s
                  ]
        Babbage.MalformedReferenceScripts s ->
          mconcat [ "kind" .= String "MalformedReferenceScripts"
                  , "scripts" .= s
                  ]
  
  instance Core.Crypto crypto => ToObject (Praos.PraosValidationErr crypto) where
    toObject _ err' =
      case err' of
        Praos.VRFKeyUnknown unknownKeyHash ->
          mconcat [ "kind" .= String "VRFKeyUnknown"
                  , "vrfKey" .= unknownKeyHash
                  ]
        Praos.VRFKeyWrongVRFKey stakePoolKeyHash registeredVrfForSaidStakepool wrongKeyHashInBlockHeader ->
          mconcat [ "kind" .= String "VRFKeyWrongVRFKey"
                  , "stakePoolKeyHash" .= stakePoolKeyHash
                  , "stakePoolVrfKey" .= registeredVrfForSaidStakepool
                  , "blockHeaderVrfKey" .= wrongKeyHashInBlockHeader
                  ]
        Praos.VRFKeyBadProof slotNo nonce vrfCalculatedVal->
          mconcat [ "kind" .= String "VRFKeyBadProof"
                  , "slotNumberUsedInVrfCalculation" .= slotNo
                  , "nonceUsedInVrfCalculation" .= nonce
                  , "calculatedVrfValue" .= String (textShow vrfCalculatedVal)
                  ]
        Praos.VRFLeaderValueTooBig leaderValue sigma f->
          mconcat [ "kind" .= String "VRFLeaderValueTooBig"
                  , "leaderValue" .= leaderValue
                  , "sigma" .= sigma
                  , "f" .= activeSlotLog f
                  ]
        Praos.KESBeforeStartOCERT startKesPeriod currKesPeriod ->
          mconcat [ "kind" .= String "KESBeforeStartOCERT"
                  , "opCertStartingKesPeriod" .= startKesPeriod
                  , "currentKesPeriod" .= currKesPeriod
                  ]
        Praos.KESAfterEndOCERT currKesPeriod startKesPeriod maxKesKeyEvos ->
          mconcat [ "kind" .= String "KESAfterEndOCERT"
                  , "opCertStartingKesPeriod" .= startKesPeriod
                  , "currentKesPeriod" .= currKesPeriod
                  , "maxKesKeyEvolutions" .= maxKesKeyEvos
                  ]
        Praos.CounterTooSmallOCERT lastCounter currentCounter ->
          mconcat [ "kind" .= String "CounterTooSmallOCERT"
                  , "lastCounter" .= lastCounter
                  , "currentCounter" .= currentCounter
                  ]
        Praos.CounterOverIncrementedOCERT lastCounter currentCounter ->
          mconcat [ "kind" .= String "CounterOverIncrementedOCERT"
                  , "lastCounter" .= lastCounter
                  , "currentCounter" .= currentCounter
                  ]
        Praos.InvalidSignatureOCERT counter oCertStartKesPeriod err ->
          mconcat [ "kind" .= String "InvalidSignatureOCERT"
                  , "counter" .= counter
                  , "opCertStartingKesPeriod" .= oCertStartKesPeriod
                  , "error" .= err
                  ]
        Praos.InvalidKesSignatureOCERT currentKesPeriod opCertStartKesPeriod expectedKesEvos maxKesEvos err ->
          mconcat [ "kind" .= String "InvalidKesSignatureOCERT"
                  , "currentKesPeriod" .= currentKesPeriod
                  , "opCertStartingKesPeriod" .= opCertStartKesPeriod
                  , "expectedKesEvolutions" .= expectedKesEvos
                  , "maximumKesEvolutions" .= maxKesEvos
                  , "error" .= err
                  ]
        Praos.NoCounterForKeyHashOCERT stakePoolKeyHash->
          mconcat [ "kind" .= String "NoCounterForKeyHashOCERT"
                  , "stakePoolKeyHash" .= stakePoolKeyHash
                  ]
  
  instance ToObject (Praos.PraosCannotForge crypto) where
    toObject _ (Praos.PraosCannotForgeKeyNotUsableYet currentKesPeriod startingKesPeriod) =
      mconcat [ "kind" .= String "PraosCannotForgeKeyNotUsableYet"
              , "currentKesPeriod" .= currentKesPeriod
              , "opCertStartingKesPeriod" .= startingKesPeriod
              ]
  
  instance ToObject Praos.PraosEnvelopeError where
    toObject _ err' =
      case err' of
        Praos.ObsoleteNode maxPtclVersionFromPparams blkHeaderPtclVersion ->
          mconcat [ "kind" .= String "ObsoleteNode"
                  , "maxMajorProtocolVersion" .= maxPtclVersionFromPparams
                  , "headerProtocolVersion" .= blkHeaderPtclVersion
                  ]
        Praos.HeaderSizeTooLarge headerSize ledgerViewMaxHeaderSize ->
          mconcat [ "kind" .= String "HeaderSizeTooLarge"
                  , "maxHeaderSize" .= ledgerViewMaxHeaderSize
                  , "headerSize" .= headerSize
                  ]
        Praos.BlockSizeTooLarge blockSize ledgerViewMaxBlockSize ->
          mconcat [ "kind" .= String "BlockSizeTooLarge"
                  , "maxBlockSize" .= ledgerViewMaxBlockSize
                  , "blockSize" .= blockSize
                  ]
  
  instance ToJSON ShelleyNodeToNodeVersion where
    toJSON ShelleyNodeToNodeVersion1 = String "ShelleyNodeToNodeVersion1"
  
  instance ToJSON ShelleyNodeToClientVersion where
    toJSON ShelleyNodeToClientVersion8 = String "ShelleyNodeToClientVersion8"
    toJSON ShelleyNodeToClientVersion9 = String "ShelleyNodeToClientVersion9"
    toJSON ShelleyNodeToClientVersion10 = String "ShelleyNodeToClientVersion10"
    toJSON ShelleyNodeToClientVersion11 = String "ShelleyNodeToClientVersion11"
    toJSON ShelleyNodeToClientVersion12 = String "ShelleyNodeToClientVersion12"
  
  instance Core.Crypto c => ToObject (PraosChainSelectView c) where
    toObject _ PraosChainSelectView {
        csvChainLength
      , csvSlotNo
      , csvIssuer
      , csvIssueNo
      , csvTieBreakVRF
      } =
        mconcat [ "kind" .= String "PraosChainSelectView"
                , "chainLength" .= csvChainLength
                , "slotNo" .= csvSlotNo
                , "issuerHash" .= hashKey csvIssuer
                , "issueNo" .= csvIssueNo
                , "tieBreakVRF" .= renderVRF csvTieBreakVRF
                ]
      where
        renderVRF = Text.decodeUtf8 . B16.encode . Crypto.getOutputVRFBytes
  
  --------------------------------------------------------------------------------
  -- Conway related
  --------------------------------------------------------------------------------
  
  instance
    ( Ledger.Era ledgerera
    , Show (PredicateFailure (Ledger.EraRule "LEDGERS" ledgerera))
    ) => ToObject (Conway.ConwayBbodyPredFailure ledgerera) where
    toObject _ err = mconcat [ "kind" .= String "ConwayBbodyPredFail"
                              , "error" .= String (textShow err)
                              ]
  
  instance
    ( ToJSON (Alonzo.CollectError ledgerera)
    ) => ToObject (ConwayUtxosPredFailure ledgerera) where
    toObject _ (Conway.ValidationTagMismatch isValidating reason) =
      mconcat [ "kind" .= String "ValidationTagMismatch"
               , "isvalidating" .= isValidating
               , "reason" .= reason
               ]
    toObject _ (Conway.CollectErrors errors) =
      mconcat [ "kind" .= String "CollectErrors"
               , "errors" .= errors
               ]
  
  -- We define this bogus instance as it is required by some of the
  -- 'ToObject' instances in this module
  instance ToObject (Ledger.VoidEraRule rule era) where
    -- NOTE: There are no values of type 'Ledger.VoidEraRule rule era'
    toObject _ = \case
  
  instance
    ( Ledger.Era ledgerera
    , ToObject (PredicateFailure (Ledger.EraRule "UTXOS" ledgerera))
    , Show (Ledger.Value ledgerera)
    , ToJSON (Ledger.Value ledgerera)
    , ToJSON (Ledger.TxOut ledgerera)
    ) => ToObject (Conway.ConwayUtxoPredFailure ledgerera) where
    toObject v = \case
      Conway.UtxosFailure utxosPredFailure -> toObject v utxosPredFailure
      Conway.BadInputsUTxO badInputs ->
        mconcat [ "kind" .= String "BadInputsUTxO"
                , "badInputs" .= badInputs
                , "error" .= renderBadInputsUTxOErr badInputs
                ]
      Conway.OutsideValidityIntervalUTxO validityInterval slot ->
        mconcat [ "kind" .= String "ExpiredUTxO"
                , "validityInterval" .= validityInterval
                , "slot" .= slot
                ]
      Conway.MaxTxSizeUTxO Mismatch {mismatchSupplied, mismatchExpected} ->
        mconcat [ "kind" .= String "MaxTxSizeUTxO"
                , "size" .= mismatchSupplied
                , "maxSize" .= mismatchExpected
                ]
      Conway.InputSetEmptyUTxO ->
        mconcat [ "kind" .= String "InputSetEmptyUTxO" ]
      Conway.FeeTooSmallUTxO Mismatch {mismatchSupplied, mismatchExpected} ->
        mconcat [ "kind" .= String "FeeTooSmallUTxO"
                , "minimum" .= mismatchExpected
                , "fee" .= mismatchSupplied
                ]
      Conway.ValueNotConservedUTxO Mismatch {mismatchSupplied, mismatchExpected} ->
        mconcat [ "kind" .= String "ValueNotConservedUTxO"
                , "consumed" .= mismatchSupplied
                , "produced" .= mismatchExpected
                , "error" .= renderValueNotConservedErr mismatchSupplied mismatchExpected
                ]
      Conway.WrongNetwork network addrs ->
        mconcat [ "kind" .= String "WrongNetwork"
                , "network" .= network
                , "addrs"   .= addrs
                ]
      Conway.WrongNetworkWithdrawal network addrs ->
        mconcat [ "kind" .= String "WrongNetworkWithdrawal"
                , "network" .= network
                , "addrs"   .= addrs
                ]
      Conway.OutputTooSmallUTxO badOutputs ->
        mconcat [ "kind" .= String "OutputTooSmallUTxO"
                , "outputs" .= badOutputs
                , "error" .= String
                  ( mconcat
                    [ "The output is smaller than the allow minimum "
                    , "UTxO value defined in the protocol parameters"
                    ]
                  )
                ]
      Conway.OutputBootAddrAttrsTooBig badOutputs ->
        mconcat [ "kind" .= String "OutputBootAddrAttrsTooBig"
                , "outputs" .= badOutputs
                , "error" .= String "The Byron address attributes are too big"
                ]
      Conway.OutputTooBigUTxO badOutputs ->
        mconcat [ "kind" .= String "OutputTooBigUTxO"
                , "outputs" .= badOutputs
                , "error" .= String "Too many asset ids in the tx output"
                ]
      Conway.InsufficientCollateral computedBalance suppliedFee ->
        mconcat [ "kind" .= String "InsufficientCollateral"
                , "balance" .= computedBalance
                , "txfee" .= suppliedFee
                ]
      Conway.ScriptsNotPaidUTxO utxos ->
        mconcat [ "kind" .= String "ScriptsNotPaidUTxO"
                , "utxos" .= utxos
                ]
      Conway.ExUnitsTooBigUTxO Mismatch {mismatchSupplied, mismatchExpected} ->
        mconcat [ "kind" .= String "ExUnitsTooBigUTxO"
                , "maxexunits" .= mismatchExpected
                , "exunits" .= mismatchSupplied
                ]
      Conway.CollateralContainsNonADA inputs ->
        mconcat [ "kind" .= String "CollateralContainsNonADA"
                , "inputs" .= inputs
                ]
      Conway.WrongNetworkInTxBody Mismatch {mismatchSupplied, mismatchExpected} ->
        mconcat [ "kind" .= String "WrongNetworkInTxBody"
                , "networkid" .= mismatchExpected
                , "txbodyNetworkId" .= mismatchSupplied
                ]
      Conway.OutsideForecast slotNum ->
        mconcat [ "kind" .= String "OutsideForecast"
                , "slot" .= slotNum
                ]
      Conway.TooManyCollateralInputs Mismatch {mismatchSupplied, mismatchExpected} ->
        mconcat [ "kind" .= String "TooManyCollateralInputs"
                , "max" .= mismatchExpected
                , "inputs" .= mismatchSupplied
                ]
      Conway.NoCollateralInputs ->
        mconcat [ "kind" .= String "NoCollateralInputs" ]
      Conway.IncorrectTotalCollateralField provided declared ->
        mconcat [ "kind" .= String "UnequalCollateralReturn"
                , "collateralProvided" .= provided
                , "collateralDeclared" .= declared
                ]
      Conway.BabbageOutputTooSmallUTxO outputs ->
        mconcat [ "kind" .= String "BabbageOutputTooSmall"
                , "outputs" .= outputs
                ]
      Conway.BabbageNonDisjointRefInputs nonDisjointInputs ->
        mconcat [ "kind" .= String "BabbageNonDisjointRefInputs"
                , "outputs" .= nonDisjointInputs
                ]
  
  instance
    ( Api.ShelleyLedgerEra era ~ ledgerera
    , Api.IsShelleyBasedEra era
    , Ledger.Era ledgerera
    , Show (Ledger.Value ledgerera)
    , ToObject (PredicateFailure (Ledger.EraRule "UTXO" ledgerera))
    , ToJSON (Ledger.Value ledgerera)
    , ToJSON (Ledger.TxOut ledgerera)
    ) => ToObject (Conway.ConwayUtxowPredFailure ledgerera) where
    toObject v = \case
      Conway.UtxoFailure utxoPredFail -> toObject v utxoPredFail
      Conway.InvalidWitnessesUTXOW ws ->
        mconcat [ "kind" .= String "InvalidWitnessesUTXOW"
                , "invalidWitnesses" .= map textShow ws
                ]
      Conway.MissingVKeyWitnessesUTXOW ws ->
        mconcat [ "kind" .= String "MissingVKeyWitnessesUTXOW"
                , "missingWitnesses" .= ws
                ]
      Conway.MissingScriptWitnessesUTXOW scripts ->
        mconcat [ "kind" .= String "MissingScriptWitnessesUTXOW"
                , "missingScripts" .= scripts
                ]
      Conway.ScriptWitnessNotValidatingUTXOW failedScripts ->
        mconcat [ "kind" .= String "ScriptWitnessNotValidatingUTXOW"
                , "failedScripts" .= failedScripts
                ]
      Conway.MissingTxBodyMetadataHash hash ->
        mconcat [ "kind" .= String "MissingTxMetadata"
                , "txBodyMetadataHash" .= hash
                ]
      Conway.MissingTxMetadata hash ->
        mconcat [ "kind" .= String "MissingTxMetadata"
                , "txBodyMetadataHash" .= hash
                ]
      Conway.ConflictingMetadataHash Mismatch {mismatchSupplied, mismatchExpected} ->
        mconcat [ "kind" .= String "ConflictingMetadataHash"
                , "txBodyMetadataHash" .= mismatchSupplied
                , "fullMetadataHash" .= mismatchExpected
                ]
      Conway.InvalidMetadata ->
        mconcat [ "kind" .= String "InvalidMetadata"
                ]
      Conway.ExtraneousScriptWitnessesUTXOW scripts ->
        mconcat [ "kind" .= String "InvalidWitnessesUTXOW"
                , "extraneousScripts" .= Set.map renderScriptHash scripts
                ]
      Conway.MissingRedeemers scripts ->
        mconcat [ "kind" .= String "MissingRedeemers"
                , "scripts" .= renderMissingRedeemers Api.shelleyBasedEra scripts
                ]
      Conway.MissingRequiredDatums required received ->
        mconcat [ "kind" .= String "MissingRequiredDatums"
                , "required" .= map (Crypto.hashToTextAsHex . Hashes.extractHash)
                                        (Set.toList required)
                , "received" .= map (Crypto.hashToTextAsHex . Hashes.extractHash)
                                        (Set.toList received)
                ]
      Conway.NotAllowedSupplementalDatums disallowed acceptable ->
        mconcat [ "kind" .= String "NotAllowedSupplementalDatums"
                , "disallowed" .= Set.toList disallowed
                , "acceptable" .= Set.toList acceptable
                ]
      Conway.PPViewHashesDontMatch Mismatch {mismatchSupplied, mismatchExpected} ->
        mconcat [ "kind" .= String "PPViewHashesDontMatch"
                , "fromTxBody" .= renderScriptIntegrityHash (strictMaybeToMaybe mismatchSupplied)
                , "fromPParams" .= renderScriptIntegrityHash (strictMaybeToMaybe mismatchExpected)
                ]
      Conway.UnspendableUTxONoDatumHash ins ->
        mconcat [ "kind" .= String "MissingRequiredSigners"
                , "txins" .= Set.toList ins
                ]
      Conway.ExtraRedeemers rs ->
        Api.caseShelleyToMaryOrAlonzoEraOnwards
          (const mempty)
          (\alonzoOnwards ->
             mconcat
               [ "kind" .= String "ExtraRedeemers"
               , "rdmrs" .=  map (Api.toScriptIndex alonzoOnwards) rs
               ]
          )
          (Api.shelleyBasedEra :: Api.ShelleyBasedEra era)
      Conway.MalformedScriptWitnesses scripts ->
        mconcat [ "kind" .= String "MalformedScriptWitnesses"
                , "scripts" .= scripts
                ]
      Conway.MalformedReferenceScripts scripts ->
        mconcat [ "kind" .= String "MalformedReferenceScripts"
                , "scripts" .= scripts
                ]
  
  --------------------------------------------------------------------------------
  -- Helper functions
  --------------------------------------------------------------------------------
  
  showLastAppBlockNo :: WithOrigin LastAppliedBlock -> Text
  showLastAppBlockNo wOblk =  case withOriginToMaybe wOblk of
                       Nothing -> "Genesis Block"
                       Just blk -> textShow . unBlockNo $ labBlockNo blk
  