-- | Pretty printing transactions and utxo's
module Hydra.Cardano.Api.Pretty where

import Hydra.Cardano.Api qualified as Api
import Hydra.Cardano.Api.Prelude

import Cardano.Api.UTxO qualified as UTxO
import Cardano.Binary (serialize)
import Cardano.Ledger.Alonzo.Scripts qualified as Ledger
import Cardano.Ledger.Alonzo.TxWits qualified as Ledger
import Cardano.Ledger.Core qualified as Ledger
import Cardano.Ledger.SafeHash qualified as Ledger
import Data.Aeson qualified as Aeson
import Data.ByteString.Lazy qualified as BL
import Data.Function (on)
import Data.List (intercalate, sort, sortBy)
import Data.Map.Strict qualified as Map
import Data.Text qualified as T
import Hydra.Cardano.Api.ScriptData (fromLedgerData)

-- | Obtain a human-readable pretty text representation of a transaction.
renderTx :: Api.Tx -> String
renderTx :: Tx -> String
renderTx = UTxO -> Tx -> String
renderTxWithUTxO UTxO
forall a. Monoid a => a
mempty

renderTxs :: [Api.Tx] -> String
renderTxs :: [Tx] -> String
renderTxs [Tx]
xs = String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
intercalate String
"\n\n" (Tx -> String
renderTx (Tx -> String) -> [Tx] -> [String]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Tx]
xs)

-- | Like 'renderTx', but uses the given UTxO to resolve inputs.
renderTxWithUTxO :: UTxO -> Api.Tx -> String
renderTxWithUTxO :: UTxO -> Tx -> String
renderTxWithUTxO UTxO
utxo (Tx TxBody Era
body [KeyWitness Era]
_wits) =
  [String] -> String
unlines ([String] -> String) -> [String] -> String
forall a b. (a -> b) -> a -> b
$
    [TxId -> String
forall a. Show a => a -> String
show (TxBody Era -> TxId
forall era. TxBody era -> TxId
getTxId TxBody Era
body)]
      [String] -> [String] -> [String]
forall a. Semigroup a => a -> a -> a
<> [String
""]
      [String] -> [String] -> [String]
forall a. Semigroup a => a -> a -> a
<> [String]
inputLines
      [String] -> [String] -> [String]
forall a. Semigroup a => a -> a -> a
<> [String
""]
      [String] -> [String] -> [String]
forall a. Semigroup a => a -> a -> a
<> [String]
referenceInputLines
      [String] -> [String] -> [String]
forall a. Semigroup a => a -> a -> a
<> [String
""]
      [String] -> [String] -> [String]
forall a. Semigroup a => a -> a -> a
<> [String]
outputLines
      [String] -> [String] -> [String]
forall a. Semigroup a => a -> a -> a
<> [String
""]
      [String] -> [String] -> [String]
forall a. Semigroup a => a -> a -> a
<> [String]
validityLines
      [String] -> [String] -> [String]
forall a. Semigroup a => a -> a -> a
<> [String
""]
      [String] -> [String] -> [String]
forall a. Semigroup a => a -> a -> a
<> [String]
mintLines
      [String] -> [String] -> [String]
forall a. Semigroup a => a -> a -> a
<> [String
""]
      [String] -> [String] -> [String]
forall a. Semigroup a => a -> a -> a
<> [String]
scriptLines
      [String] -> [String] -> [String]
forall a. Semigroup a => a -> a -> a
<> [String
""]
      [String] -> [String] -> [String]
forall a. Semigroup a => a -> a -> a
<> [String]
datumLines
      [String] -> [String] -> [String]
forall a. Semigroup a => a -> a -> a
<> [String
""]
      [String] -> [String] -> [String]
forall a. Semigroup a => a -> a -> a
<> [String]
redeemerLines
      [String] -> [String] -> [String]
forall a. Semigroup a => a -> a -> a
<> [String
""]
      [String] -> [String] -> [String]
forall a. Semigroup a => a -> a -> a
<> [String]
requiredSignersLines
      [String] -> [String] -> [String]
forall a. Semigroup a => a -> a -> a
<> [String
""]
      [String] -> [String] -> [String]
forall a. Semigroup a => a -> a -> a
<> [String]
metadataLines
 where
  Api.ShelleyTxBody TxBody LedgerEra
_lbody [Script LedgerEra]
scripts TxBodyScriptData
scriptsData Maybe (AlonzoTxAuxData LedgerEra)
_auxData TxScriptValidity
_validity = TxBody Era
body
  outs :: [TxOut CtxTx Era]
outs = TxBodyContent ViewTx Era -> [TxOut CtxTx Era]
forall build era. TxBodyContent build era -> [TxOut CtxTx era]
txOuts TxBodyContent ViewTx Era
content
  TxBody TxBodyContent ViewTx Era
content = TxBody Era
body

  inputLines :: [String]
inputLines =
    String
"== INPUTS (" String -> String -> String
forall a. Semigroup a => a -> a -> a
<> Int -> String
forall a. Show a => a -> String
show ([(TxIn, BuildTxWith ViewTx (Witness WitCtxTxIn Era))] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length (TxBodyContent ViewTx Era
-> [(TxIn, BuildTxWith ViewTx (Witness WitCtxTxIn Era))]
forall build era. TxBodyContent build era -> TxIns build era
txIns TxBodyContent ViewTx Era
content)) String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
")"
      String -> [String] -> [String]
forall a. a -> [a] -> [a]
: ((String
"- " <>) (String -> String)
-> ((TxIn, BuildTxWith ViewTx (Witness WitCtxTxIn Era)) -> String)
-> (TxIn, BuildTxWith ViewTx (Witness WitCtxTxIn Era))
-> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TxIn -> String
prettyTxIn (TxIn -> String)
-> ((TxIn, BuildTxWith ViewTx (Witness WitCtxTxIn Era)) -> TxIn)
-> (TxIn, BuildTxWith ViewTx (Witness WitCtxTxIn Era))
-> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (TxIn, BuildTxWith ViewTx (Witness WitCtxTxIn Era)) -> TxIn
forall a b. (a, b) -> a
fst ((TxIn, BuildTxWith ViewTx (Witness WitCtxTxIn Era)) -> String)
-> [(TxIn, BuildTxWith ViewTx (Witness WitCtxTxIn Era))]
-> [String]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ((TxIn, BuildTxWith ViewTx (Witness WitCtxTxIn Era))
 -> (TxIn, BuildTxWith ViewTx (Witness WitCtxTxIn Era)) -> Ordering)
-> [(TxIn, BuildTxWith ViewTx (Witness WitCtxTxIn Era))]
-> [(TxIn, BuildTxWith ViewTx (Witness WitCtxTxIn Era))]
forall a. (a -> a -> Ordering) -> [a] -> [a]
sortBy (TxIn -> TxIn -> Ordering
forall a. Ord a => a -> a -> Ordering
compare (TxIn -> TxIn -> Ordering)
-> ((TxIn, BuildTxWith ViewTx (Witness WitCtxTxIn Era)) -> TxIn)
-> (TxIn, BuildTxWith ViewTx (Witness WitCtxTxIn Era))
-> (TxIn, BuildTxWith ViewTx (Witness WitCtxTxIn Era))
-> Ordering
forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
`on` (TxIn, BuildTxWith ViewTx (Witness WitCtxTxIn Era)) -> TxIn
forall a b. (a, b) -> a
fst) (TxBodyContent ViewTx Era
-> [(TxIn, BuildTxWith ViewTx (Witness WitCtxTxIn Era))]
forall build era. TxBodyContent build era -> TxIns build era
txIns TxBodyContent ViewTx Era
content))

  referenceInputLines :: [String]
referenceInputLines =
    String
"== REFERENCE INPUTS (" String -> String -> String
forall a. Semigroup a => a -> a -> a
<> Int -> String
forall a. Show a => a -> String
show ([TxIn] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [TxIn]
referenceInputs) String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
")"
      String -> [String] -> [String]
forall a. a -> [a] -> [a]
: ((String
"- " <>) (String -> String) -> (TxIn -> String) -> TxIn -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TxIn -> String
prettyTxIn (TxIn -> String) -> [TxIn] -> [String]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [TxIn] -> [TxIn]
forall a. Ord a => [a] -> [a]
sort [TxIn]
referenceInputs)

  referenceInputs :: [TxIn]
referenceInputs =
    case TxBodyContent ViewTx Era -> TxInsReference ViewTx Era
forall build era.
TxBodyContent build era -> TxInsReference build era
txInsReference TxBodyContent ViewTx Era
content of
      TxInsReference ViewTx Era
Api.TxInsReferenceNone -> []
      Api.TxInsReference [TxIn]
refInputs -> [TxIn]
refInputs

  prettyTxIn :: TxIn -> String
prettyTxIn TxIn
i =
    case TxIn -> UTxO -> Maybe (TxOut CtxUTxO Era)
forall out. TxIn -> UTxO' out -> Maybe out
UTxO.resolve TxIn
i UTxO
utxo of
      Maybe (TxOut CtxUTxO Era)
Nothing -> Text -> String
T.unpack (Text -> String) -> Text -> String
forall a b. (a -> b) -> a -> b
$ TxIn -> Text
renderTxIn TxIn
i
      Just TxOut CtxUTxO Era
o ->
        Text -> String
T.unpack (TxIn -> Text
renderTxIn TxIn
i)
          String -> String -> String
forall a. Semigroup a => a -> a -> a
<> (String
"\n      " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> AddressInEra -> String
prettyAddr (TxOut CtxUTxO Era -> AddressInEra
forall ctx. TxOut ctx -> AddressInEra
Api.txOutAddress TxOut CtxUTxO Era
o))
          String -> String -> String
forall a. Semigroup a => a -> a -> a
<> (String
"\n      " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> Int -> Value -> String
prettyValue Int
1 (TxOut CtxUTxO Era -> Value
forall ctx. TxOut ctx -> Value
Api.txOutValue TxOut CtxUTxO Era
o))
          String -> String -> String
forall a. Semigroup a => a -> a -> a
<> (String
"\n      " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> TxOutDatum CtxUTxO Era -> String
forall {ctx}. TxOutDatum ctx Era -> String
prettyDatumUtxo (TxOut CtxUTxO Era -> TxOutDatum CtxUTxO Era
forall ctx. TxOut ctx -> TxOutDatum ctx
Api.txOutDatum TxOut CtxUTxO Era
o))

  outputLines :: [String]
outputLines =
    [ String
"== OUTPUTS (" String -> String -> String
forall a. Semigroup a => a -> a -> a
<> Int -> String
forall a. Show a => a -> String
show ([TxOut CtxTx Era] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [TxOut CtxTx Era]
outs) String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
")"
    , String
"Total number of assets: " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> Int -> String
forall a. Show a => a -> String
show Int
totalNumberOfAssets
    ]
      [String] -> [String] -> [String]
forall a. Semigroup a => a -> a -> a
<> ((String
"- " <>) (String -> String)
-> (TxOut CtxTx Era -> String) -> TxOut CtxTx Era -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TxOut CtxTx Era -> String
prettyOut (TxOut CtxTx Era -> String) -> [TxOut CtxTx Era] -> [String]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [TxOut CtxTx Era]
outs)

  prettyOut :: TxOut CtxTx Era -> String
prettyOut TxOut CtxTx Era
o =
    [String] -> String
forall a. Monoid a => [a] -> a
mconcat
      [ AddressInEra -> String
prettyAddr (TxOut CtxTx Era -> AddressInEra
forall ctx. TxOut ctx -> AddressInEra
Api.txOutAddress TxOut CtxTx Era
o)
      , String
"\n      " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> Int -> Value -> String
prettyValue Int
1 (TxOut CtxTx Era -> Value
forall ctx. TxOut ctx -> Value
Api.txOutValue TxOut CtxTx Era
o)
      , String
"\n      " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> TxOutDatum CtxTx -> String
prettyDatumCtx (TxOut CtxTx Era -> TxOutDatum CtxTx
forall ctx. TxOut ctx -> TxOutDatum ctx
Api.txOutDatum TxOut CtxTx Era
o)
      ]

  prettyAddr :: AddressInEra -> String
prettyAddr = \case
    Api.ShelleyAddressInEra Address ShelleyAddr
addr -> Address ShelleyAddr -> String
forall a. Show a => a -> String
show Address ShelleyAddr
addr
    Api.ByronAddressInEra Address ByronAddr
addr -> Address ByronAddr -> String
forall a. Show a => a -> String
show Address ByronAddr
addr

  totalNumberOfAssets :: Int
totalNumberOfAssets =
    let totalValue :: Value
totalValue = (TxOut CtxTx Era -> Value) -> [TxOut CtxTx Era] -> Value
forall m a. Monoid m => (a -> m) -> [a] -> m
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap TxOut CtxTx Era -> Value
forall ctx. TxOut ctx -> Value
Api.txOutValue [TxOut CtxTx Era]
outs
     in [(AssetId, Quantity)] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length ([(AssetId, Quantity)] -> Int) -> [(AssetId, Quantity)] -> Int
forall a b. (a -> b) -> a -> b
$ Value -> [(AssetId, Quantity)]
valueToList Value
totalValue

  validityLines :: [String]
validityLines =
    [ String
"== VALIDITY"
    , TxValidityLowerBound Era -> String
forall a. Show a => a -> String
show (TxBodyContent ViewTx Era -> TxValidityLowerBound Era
forall build era.
TxBodyContent build era -> TxValidityLowerBound era
txValidityLowerBound TxBodyContent ViewTx Era
content)
    , TxValidityUpperBound Era -> String
forall a. Show a => a -> String
show (TxBodyContent ViewTx Era -> TxValidityUpperBound Era
forall build era.
TxBodyContent build era -> TxValidityUpperBound era
txValidityUpperBound TxBodyContent ViewTx Era
content)
    ]

  mintLines :: [String]
mintLines =
    [ String
"== MINT/BURN\n" String -> String -> String
forall a. Semigroup a => a -> a -> a
<> case TxBodyContent ViewTx Era -> TxMintValue ViewTx Era
forall build era. TxBodyContent build era -> TxMintValue build era
txMintValue TxBodyContent ViewTx Era
content of
        TxMintValue ViewTx Era
Api.TxMintValueNone -> String
"[]"
        Api.TxMintValue Value
val BuildTxWith ViewTx (Map PolicyId (ScriptWitness WitCtxMint))
_ -> Int -> Value -> String
prettyValue Int
0 Value
val
    ]

  prettyValue :: Int -> Value -> String
prettyValue Int
n =
    Text -> String
T.unpack (Text -> String) -> (Value -> Text) -> Value -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. HasCallStack => Text -> Text -> Text -> Text
Text -> Text -> Text -> Text
T.replace Text
" + " Text
indent (Text -> Text) -> (Value -> Text) -> Value -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Value -> Text
renderValue
   where
    indent :: Text
indent = Text
"\n  " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Int -> Text -> Text
T.replicate Int
n Text
"    "

  prettyDatumUtxo :: TxOutDatum ctx Era -> String
prettyDatumUtxo = \case
    TxOutDatum ctx Era
TxOutDatumNone ->
      String
"TxOutDatumNone"
    Api.TxOutDatumHash Hash ScriptData
h ->
      String
"TxOutDatumHash " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> Hash ScriptData -> String
forall a. Show a => a -> String
show Hash ScriptData
h
    Api.TxOutDatumInline HashableScriptData
scriptData ->
      String
"TxOutDatumInline " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> HashableScriptData -> String
prettyScriptData HashableScriptData
scriptData
    TxOutDatum ctx Era
_ -> String -> String
forall a. HasCallStack => String -> a
error String
"absurd"

  prettyDatumCtx :: TxOutDatum CtxTx -> String
prettyDatumCtx = \case
    TxOutDatum CtxTx
Api.TxOutDatumNone ->
      String
"TxOutDatumNone"
    Api.TxOutDatumHash Hash ScriptData
h ->
      String
"TxOutDatumHash " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> Hash ScriptData -> String
forall a. Show a => a -> String
show Hash ScriptData
h
    Api.TxOutDatumInTx HashableScriptData
scriptData ->
      String
"TxOutDatumInTx " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> HashableScriptData -> String
prettyScriptData HashableScriptData
scriptData
    Api.TxOutDatumInline HashableScriptData
scriptData ->
      String
"TxOutDatumInline " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> HashableScriptData -> String
prettyScriptData HashableScriptData
scriptData

  scriptLines :: [String]
scriptLines =
    [ String
"== SCRIPTS (" String -> String -> String
forall a. Semigroup a => a -> a -> a
<> Int -> String
forall a. Show a => a -> String
show ([AlonzoScript (BabbageEra StandardCrypto)] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [AlonzoScript (BabbageEra StandardCrypto)]
[Script LedgerEra]
scripts) String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
")"
    , String
"Total size (bytes):  " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> Int64 -> String
forall a. Show a => a -> String
show Int64
totalScriptSize
    ]
      [String] -> [String] -> [String]
forall a. Semigroup a => a -> a -> a
<> ((String
"- " <>) (String -> String)
-> (Script (BabbageEra StandardCrypto) -> String)
-> Script (BabbageEra StandardCrypto)
-> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Script (BabbageEra StandardCrypto) -> String
forall {era}.
(Assert
   (OrdCond
      (CmpNat (ProtVerLow era) (ProtVerHigh era)) 'True 'True 'False)
   (TypeError ...),
 Assert
   (OrdCond (CmpNat 0 (ProtVerLow era)) 'True 'True 'False)
   (TypeError ...),
 Assert
   (OrdCond (CmpNat 0 (ProtVerHigh era)) 'True 'True 'False)
   (TypeError ...),
 EraScript era) =>
Script era -> String
prettyScript (Script (BabbageEra StandardCrypto) -> String)
-> [Script (BabbageEra StandardCrypto)] -> [String]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Script LedgerEra]
[Script (BabbageEra StandardCrypto)]
scripts)

  totalScriptSize :: Int64
totalScriptSize = [Int64] -> Int64
forall a. Num a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum ([Int64] -> Int64) -> [Int64] -> Int64
forall a b. (a -> b) -> a -> b
$ ByteString -> Int64
BL.length (ByteString -> Int64)
-> (AlonzoScript (BabbageEra StandardCrypto) -> ByteString)
-> AlonzoScript (BabbageEra StandardCrypto)
-> Int64
forall b c a. (b -> c) -> (a -> b) -> a -> c
. AlonzoScript (BabbageEra StandardCrypto) -> ByteString
forall a. ToCBOR a => a -> ByteString
serialize (AlonzoScript (BabbageEra StandardCrypto) -> Int64)
-> [AlonzoScript (BabbageEra StandardCrypto)] -> [Int64]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [AlonzoScript (BabbageEra StandardCrypto)]
[Script LedgerEra]
scripts

  prettyScript :: Script era -> String
prettyScript Script era
script =
    String
"Script (" String -> String -> String
forall a. Semigroup a => a -> a -> a
<> ScriptHash (EraCrypto era) -> String
forall a. Show a => a -> String
show (Script era -> ScriptHash (EraCrypto era)
forall era.
EraScript era =>
Script era -> ScriptHash (EraCrypto era)
Ledger.hashScript Script era
script) String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
")"

  datumLines :: [String]
datumLines = case TxBodyScriptData
scriptsData of
    TxBodyScriptData
Api.TxBodyNoScriptData -> []
    (Api.TxBodyScriptData (Ledger.TxDats Map
  (DataHash (EraCrypto (BabbageEra StandardCrypto)))
  (Data (BabbageEra StandardCrypto))
dats) Redeemers LedgerEra
_) ->
      String
"== DATUMS (" String -> String -> String
forall a. Semigroup a => a -> a -> a
<> Int -> String
forall a. Show a => a -> String
show (Map (DataHash StandardCrypto) (Data (BabbageEra StandardCrypto))
-> Int
forall a. Map (DataHash StandardCrypto) a -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length Map
  (DataHash (EraCrypto (BabbageEra StandardCrypto)))
  (Data (BabbageEra StandardCrypto))
Map (DataHash StandardCrypto) (Data (BabbageEra StandardCrypto))
dats) String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
")"
        String -> [String] -> [String]
forall a. a -> [a] -> [a]
: ((String
"- " <>) (String -> String)
-> ((DataHash StandardCrypto, Data (BabbageEra StandardCrypto))
    -> String)
-> (DataHash StandardCrypto, Data (BabbageEra StandardCrypto))
-> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (DataHash StandardCrypto, Data (BabbageEra StandardCrypto))
-> String
forall {c} {i} {era}. (SafeHash c i, Data era) -> String
showDatumAndHash ((DataHash StandardCrypto, Data (BabbageEra StandardCrypto))
 -> String)
-> [(DataHash StandardCrypto, Data (BabbageEra StandardCrypto))]
-> [String]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Map (DataHash StandardCrypto) (Data (BabbageEra StandardCrypto))
-> [(DataHash StandardCrypto, Data (BabbageEra StandardCrypto))]
forall k a. Map k a -> [(k, a)]
Map.toList Map
  (DataHash (EraCrypto (BabbageEra StandardCrypto)))
  (Data (BabbageEra StandardCrypto))
Map (DataHash StandardCrypto) (Data (BabbageEra StandardCrypto))
dats)

  showDatumAndHash :: (SafeHash c i, Data era) -> String
showDatumAndHash (SafeHash c i
k, Data era
v) =
    [String] -> String
forall a. Monoid a => [a] -> a
mconcat
      [ Hash (HASH c) i -> String
forall a. Show a => a -> String
show (SafeHash c i -> Hash (HASH c) i
forall c i. SafeHash c i -> Hash (HASH c) i
Ledger.extractHash SafeHash c i
k)
      , String
"\n  "
      , HashableScriptData -> String
prettyScriptData (Data era -> HashableScriptData
forall era. Data era -> HashableScriptData
fromLedgerData Data era
v)
      ]

  prettyScriptData :: HashableScriptData -> String
prettyScriptData =
    Text -> String
T.unpack (Text -> String)
-> (HashableScriptData -> Text) -> HashableScriptData -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Text
decodeUtf8 (ByteString -> Text)
-> (HashableScriptData -> ByteString) -> HashableScriptData -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> ByteString
BL.toStrict (ByteString -> ByteString)
-> (HashableScriptData -> ByteString)
-> HashableScriptData
-> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Value -> ByteString
forall a. ToJSON a => a -> ByteString
Aeson.encode (Value -> ByteString)
-> (HashableScriptData -> Value)
-> HashableScriptData
-> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ScriptDataJsonSchema -> HashableScriptData -> Value
scriptDataToJson ScriptDataJsonSchema
ScriptDataJsonNoSchema

  redeemerLines :: [String]
redeemerLines = case TxBodyScriptData
scriptsData of
    TxBodyScriptData
Api.TxBodyNoScriptData -> []
    (Api.TxBodyScriptData TxDats LedgerEra
_ Redeemers LedgerEra
re) ->
      let rdmrs :: [(PlutusPurpose AsIndex (BabbageEra StandardCrypto),
  (Data (BabbageEra StandardCrypto), ExUnits))]
rdmrs = Map
  (PlutusPurpose AsIndex (BabbageEra StandardCrypto))
  (Data (BabbageEra StandardCrypto), ExUnits)
-> [(PlutusPurpose AsIndex (BabbageEra StandardCrypto),
     (Data (BabbageEra StandardCrypto), ExUnits))]
forall k a. Map k a -> [(k, a)]
Map.toList (Map
   (PlutusPurpose AsIndex (BabbageEra StandardCrypto))
   (Data (BabbageEra StandardCrypto), ExUnits)
 -> [(PlutusPurpose AsIndex (BabbageEra StandardCrypto),
      (Data (BabbageEra StandardCrypto), ExUnits))])
-> Map
     (PlutusPurpose AsIndex (BabbageEra StandardCrypto))
     (Data (BabbageEra StandardCrypto), ExUnits)
-> [(PlutusPurpose AsIndex (BabbageEra StandardCrypto),
     (Data (BabbageEra StandardCrypto), ExUnits))]
forall a b. (a -> b) -> a -> b
$ Redeemers (BabbageEra StandardCrypto)
-> Map
     (PlutusPurpose AsIndex (BabbageEra StandardCrypto))
     (Data (BabbageEra StandardCrypto), ExUnits)
forall era.
Redeemers era
-> Map (PlutusPurpose AsIndex era) (Data era, ExUnits)
Ledger.unRedeemers Redeemers LedgerEra
Redeemers (BabbageEra StandardCrypto)
re
       in String
"== REDEEMERS (" String -> String -> String
forall a. Semigroup a => a -> a -> a
<> Int -> String
forall a. Show a => a -> String
show ([(PlutusPurpose AsIndex (BabbageEra StandardCrypto),
  (Data (BabbageEra StandardCrypto), ExUnits))]
-> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [(PlutusPurpose AsIndex (BabbageEra StandardCrypto),
  (Data (BabbageEra StandardCrypto), ExUnits))]
rdmrs) String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
")"
            String -> [String] -> [String]
forall a. a -> [a] -> [a]
: ((String
"- " <>) (String -> String)
-> ((PlutusPurpose AsIndex (BabbageEra StandardCrypto),
     (Data (BabbageEra StandardCrypto), ExUnits))
    -> String)
-> (PlutusPurpose AsIndex (BabbageEra StandardCrypto),
    (Data (BabbageEra StandardCrypto), ExUnits))
-> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (PlutusPurpose AsIndex (BabbageEra StandardCrypto),
 (Data (BabbageEra StandardCrypto), ExUnits))
-> String
forall {a} {era}. Show a => (a, (Data era, ExUnits)) -> String
prettyRedeemer ((PlutusPurpose AsIndex (BabbageEra StandardCrypto),
  (Data (BabbageEra StandardCrypto), ExUnits))
 -> String)
-> [(PlutusPurpose AsIndex (BabbageEra StandardCrypto),
     (Data (BabbageEra StandardCrypto), ExUnits))]
-> [String]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [(PlutusPurpose AsIndex (BabbageEra StandardCrypto),
  (Data (BabbageEra StandardCrypto), ExUnits))]
rdmrs)

  prettyRedeemer :: (a, (Data era, ExUnits)) -> String
prettyRedeemer (a
purpose, (Data era
redeemerData, ExUnits
redeemerBudget)) =
    [String] -> String
unwords
      [ a -> String
forall a. Show a => a -> String
show a
purpose
      , [String] -> String
forall a. Monoid a => [a] -> a
mconcat
          [ String
"( cpu = " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> Nat -> String
forall a. Show a => a -> String
show (ExUnits -> Nat
Ledger.exUnitsSteps ExUnits
redeemerBudget)
          , String
", mem = " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> Nat -> String
forall a. Show a => a -> String
show (ExUnits -> Nat
Ledger.exUnitsMem ExUnits
redeemerBudget) String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
" )"
          ]
      , String
"\n  " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> HashableScriptData -> String
prettyScriptData (Data era -> HashableScriptData
forall era. Data era -> HashableScriptData
fromLedgerData Data era
redeemerData)
      ]

  requiredSignersLines :: [String]
requiredSignersLines =
    String
"== REQUIRED SIGNERS" String -> [String] -> [String]
forall a. a -> [a] -> [a]
: case TxBodyContent ViewTx Era -> TxExtraKeyWitnesses Era
forall build era.
TxBodyContent build era -> TxExtraKeyWitnesses era
txExtraKeyWits TxBodyContent ViewTx Era
content of
      TxExtraKeyWitnesses Era
Api.TxExtraKeyWitnessesNone -> [String
"[]"]
      Api.TxExtraKeyWitnesses [Hash PaymentKey]
xs -> (String
"- " <>) (String -> String)
-> (Hash PaymentKey -> String) -> Hash PaymentKey -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Hash PaymentKey -> String
forall a. Show a => a -> String
show (Hash PaymentKey -> String) -> [Hash PaymentKey] -> [String]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Hash PaymentKey]
xs

  metadataLines :: [String]
metadataLines =
    [ String
"== METADATA"
    , TxMetadataInEra Era -> String
forall a. Show a => a -> String
show (TxBodyContent ViewTx Era -> TxMetadataInEra Era
forall build era. TxBodyContent build era -> TxMetadataInEra era
txMetadata TxBodyContent ViewTx Era
content)
    ]