-- | This modules exposes the generation of transaction outputs
module Cooked.MockChain.GenerateTx.Output (toCardanoTxOut) where

import Cardano.Api.Shelley qualified as Cardano
import Cardano.Node.Emulator.Internal.Node.Params qualified as Emulator
import Cooked.MockChain.BlockChain
import Cooked.MockChain.GenerateTx.Common
import Cooked.Skeleton
import Ledger.Tx.CardanoAPI qualified as Ledger
import Optics.Core
import Plutus.Script.Utils.Data qualified as Script
import PlutusLedgerApi.V3 qualified as Api

-- | Converts a 'TxSkelOut' to the corresponding 'Cardano.TxOut'
toCardanoTxOut :: (MonadBlockChainBalancing m) => TxSkelOut -> m (Cardano.TxOut Cardano.CtxTx Cardano.ConwayEra)
toCardanoTxOut :: forall (m :: * -> *).
MonadBlockChainBalancing m =>
TxSkelOut -> m (TxOut CtxTx ConwayEra)
toCardanoTxOut TxSkelOut
output = do
  let oAddress :: Address
oAddress = Optic' A_Getter NoIx TxSkelOut Address -> TxSkelOut -> Address
forall k (is :: IxList) s a.
Is k A_Getter =>
Optic' k is s a -> s -> a
view Optic' A_Getter NoIx TxSkelOut Address
txSkelOutAddressG TxSkelOut
output
      oValue :: Value
oValue = Optic' A_Lens NoIx TxSkelOut Value -> TxSkelOut -> Value
forall k (is :: IxList) s a.
Is k A_Getter =>
Optic' k is s a -> s -> a
view Optic' A_Lens NoIx TxSkelOut Value
txSkelOutValueL TxSkelOut
output
      oDatum :: TxSkelOutDatum
oDatum = TxSkelOut
output TxSkelOut
-> Optic' A_Lens NoIx TxSkelOut TxSkelOutDatum -> TxSkelOutDatum
forall k s (is :: IxList) a.
Is k A_Getter =>
s -> Optic' k is s a -> a
^. Optic' A_Lens NoIx TxSkelOut TxSkelOutDatum
txSkelOutDatumL
      oRefScript :: Maybe (Versioned Script)
oRefScript = Optic' An_AffineTraversal NoIx TxSkelOut (Versioned Script)
-> TxSkelOut -> Maybe (Versioned Script)
forall k (is :: IxList) s a.
Is k An_AffineFold =>
Optic' k is s a -> s -> Maybe a
preview (Lens' TxSkelOut TxSkelOutReferenceScript
txSkelOutReferenceScriptL Lens' TxSkelOut TxSkelOutReferenceScript
-> Optic
     A_Prism
     NoIx
     TxSkelOutReferenceScript
     TxSkelOutReferenceScript
     (Versioned Script)
     (Versioned Script)
-> Optic' An_AffineTraversal NoIx TxSkelOut (Versioned Script)
forall k l m (is :: IxList) (js :: IxList) (ks :: IxList) s t u v a
       b.
(JoinKinds k l m, AppendIndices is js ks) =>
Optic k is s t u v -> Optic l js u v a b -> Optic m ks s t a b
% Optic
  A_Prism
  NoIx
  TxSkelOutReferenceScript
  TxSkelOutReferenceScript
  (Versioned Script)
  (Versioned Script)
txSkelOutReferenceScriptVersionedP) TxSkelOut
output
  NetworkId
networkId <- Params -> NetworkId
Emulator.pNetworkId (Params -> NetworkId) -> m Params -> m NetworkId
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m Params
forall (m :: * -> *). MonadBlockChainBalancing m => m Params
getParams
  AddressInEra ConwayEra
address <-
    String
-> Either ToCardanoError (AddressInEra ConwayEra)
-> m (AddressInEra ConwayEra)
forall (m :: * -> *) a.
MonadError MockChainError m =>
String -> Either ToCardanoError a -> m a
throwOnToCardanoError
      (String
"toCardanoTxOut: Unable to translate the following address: " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> Address -> String
forall a. Show a => a -> String
show Address
oAddress)
      (NetworkId
-> Address -> Either ToCardanoError (AddressInEra ConwayEra)
Ledger.toCardanoAddressInEra NetworkId
networkId Address
oAddress)
  (Value -> TxOutValue ConwayEra
Ledger.toCardanoTxOutValue -> TxOutValue ConwayEra
value) <-
    String -> Either ToCardanoError Value -> m Value
forall (m :: * -> *) a.
MonadError MockChainError m =>
String -> Either ToCardanoError a -> m a
throwOnToCardanoError
      (String
"toCardanoTxOut: Unable to translate the following value:" String -> String -> String
forall a. Semigroup a => a -> a -> a
<> Value -> String
forall a. Show a => a -> String
show Value
oValue)
      (Value -> Either ToCardanoError Value
Ledger.toCardanoValue Value
oValue)
  TxOutDatum CtxTx ConwayEra
datum <- case TxSkelOutDatum
oDatum of
    TxSkelOutDatum
NoTxSkelOutDatum -> TxOutDatum CtxTx ConwayEra -> m (TxOutDatum CtxTx ConwayEra)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return TxOutDatum CtxTx ConwayEra
forall ctx era. TxOutDatum ctx era
Cardano.TxOutDatumNone
    SomeTxSkelOutDatum dat
datum (Hashed DatumResolved
NotResolved) ->
      AlonzoEraOnwards ConwayEra
-> Hash ScriptData -> TxOutDatum CtxTx ConwayEra
forall era ctx.
AlonzoEraOnwards era -> Hash ScriptData -> TxOutDatum ctx era
Cardano.TxOutDatumHash AlonzoEraOnwards ConwayEra
Cardano.AlonzoEraOnwardsConway
        (Hash ScriptData -> TxOutDatum CtxTx ConwayEra)
-> m (Hash ScriptData) -> m (TxOutDatum CtxTx ConwayEra)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String
-> Either ToCardanoError (Hash ScriptData) -> m (Hash ScriptData)
forall (m :: * -> *) a.
MonadError MockChainError m =>
String -> Either ToCardanoError a -> m a
throwOnToCardanoError
          String
"toCardanoTxOut: Unable to resolve/transate a datum hash."
          (DatumHash -> Either ToCardanoError (Hash ScriptData)
Ledger.toCardanoScriptDataHash (DatumHash -> Either ToCardanoError (Hash ScriptData))
-> DatumHash -> Either ToCardanoError (Hash ScriptData)
forall a b. (a -> b) -> a -> b
$ Datum -> DatumHash
Script.datumHash (Datum -> DatumHash) -> Datum -> DatumHash
forall a b. (a -> b) -> a -> b
$ BuiltinData -> Datum
Api.Datum (BuiltinData -> Datum) -> BuiltinData -> Datum
forall a b. (a -> b) -> a -> b
$ dat -> BuiltinData
forall a. ToData a => a -> BuiltinData
Api.toBuiltinData dat
datum)
    SomeTxSkelOutDatum dat
datum (Hashed DatumResolved
Resolved) -> TxOutDatum CtxTx ConwayEra -> m (TxOutDatum CtxTx ConwayEra)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (TxOutDatum CtxTx ConwayEra -> m (TxOutDatum CtxTx ConwayEra))
-> TxOutDatum CtxTx ConwayEra -> m (TxOutDatum CtxTx ConwayEra)
forall a b. (a -> b) -> a -> b
$ AlonzoEraOnwards ConwayEra
-> HashableScriptData -> TxOutDatum CtxTx ConwayEra
forall era.
AlonzoEraOnwards era -> HashableScriptData -> TxOutDatum CtxTx era
Cardano.TxOutSupplementalDatum AlonzoEraOnwards ConwayEra
Cardano.AlonzoEraOnwardsConway (HashableScriptData -> TxOutDatum CtxTx ConwayEra)
-> HashableScriptData -> TxOutDatum CtxTx ConwayEra
forall a b. (a -> b) -> a -> b
$ BuiltinData -> HashableScriptData
Ledger.toCardanoScriptData (BuiltinData -> HashableScriptData)
-> BuiltinData -> HashableScriptData
forall a b. (a -> b) -> a -> b
$ dat -> BuiltinData
forall a. ToData a => a -> BuiltinData
Api.toBuiltinData dat
datum
    SomeTxSkelOutDatum dat
datum DatumKind
Inline -> TxOutDatum CtxTx ConwayEra -> m (TxOutDatum CtxTx ConwayEra)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (TxOutDatum CtxTx ConwayEra -> m (TxOutDatum CtxTx ConwayEra))
-> TxOutDatum CtxTx ConwayEra -> m (TxOutDatum CtxTx ConwayEra)
forall a b. (a -> b) -> a -> b
$ BabbageEraOnwards ConwayEra
-> HashableScriptData -> TxOutDatum CtxTx ConwayEra
forall era ctx.
BabbageEraOnwards era -> HashableScriptData -> TxOutDatum ctx era
Cardano.TxOutDatumInline BabbageEraOnwards ConwayEra
Cardano.BabbageEraOnwardsConway (HashableScriptData -> TxOutDatum CtxTx ConwayEra)
-> HashableScriptData -> TxOutDatum CtxTx ConwayEra
forall a b. (a -> b) -> a -> b
$ BuiltinData -> HashableScriptData
Ledger.toCardanoScriptData (BuiltinData -> HashableScriptData)
-> BuiltinData -> HashableScriptData
forall a b. (a -> b) -> a -> b
$ dat -> BuiltinData
forall a. ToData a => a -> BuiltinData
Api.toBuiltinData dat
datum
  TxOut CtxTx ConwayEra -> m (TxOut CtxTx ConwayEra)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (TxOut CtxTx ConwayEra -> m (TxOut CtxTx ConwayEra))
-> TxOut CtxTx ConwayEra -> m (TxOut CtxTx ConwayEra)
forall a b. (a -> b) -> a -> b
$ AddressInEra ConwayEra
-> TxOutValue ConwayEra
-> TxOutDatum CtxTx ConwayEra
-> ReferenceScript ConwayEra
-> TxOut CtxTx ConwayEra
forall ctx era.
AddressInEra era
-> TxOutValue era
-> TxOutDatum ctx era
-> ReferenceScript era
-> TxOut ctx era
Cardano.TxOut AddressInEra ConwayEra
address TxOutValue ConwayEra
value TxOutDatum CtxTx ConwayEra
datum (ReferenceScript ConwayEra -> TxOut CtxTx ConwayEra)
-> ReferenceScript ConwayEra -> TxOut CtxTx ConwayEra
forall a b. (a -> b) -> a -> b
$ Maybe (Versioned Script) -> ReferenceScript ConwayEra
Ledger.toCardanoReferenceScript Maybe (Versioned Script)
oRefScript