-- | 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 Plutus.Script.Utils.Scripts 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 = TxSkelOut -> Address
txSkelOutAddress TxSkelOut
output
      oValue :: Value
oValue = TxSkelOut -> Value
txSkelOutValue 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 = TxSkelOut -> Maybe (Versioned Script)
txSkelOutReferenceScript 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
TxSkelOutNoDatum -> 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
    TxSkelOutSomeDatum DatumContent
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
$ DatumContent -> BuiltinData
forall a. ToData a => a -> BuiltinData
Api.toBuiltinData DatumContent
datum)
    TxSkelOutSomeDatum DatumContent
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
$ DatumContent -> BuiltinData
forall a. ToData a => a -> BuiltinData
Api.toBuiltinData DatumContent
datum
    TxSkelOutSomeDatum DatumContent
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
$ DatumContent -> BuiltinData
forall a. ToData a => a -> BuiltinData
Api.toBuiltinData DatumContent
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 (Versioned Script -> Versioned Script
forall s a. ToVersioned s a => a -> Versioned s
Script.toVersioned (Versioned Script -> Versioned Script)
-> Maybe (Versioned Script) -> Maybe (Versioned Script)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe (Versioned Script)
oRefScript)