module Cooked.MockChain.GenerateTx.Output
  ( toCardanoTxOut,
  )
where

import Cardano.Api.Shelley qualified as Cardano
import Control.Monad.Reader
import Cooked.Conversion
import Cooked.MockChain.GenerateTx.Common
import Cooked.Output
import Cooked.Skeleton
import Ledger.Tx.CardanoAPI qualified as Ledger
import Optics.Core
import Plutus.Script.Utils.Scripts qualified as Script
import PlutusLedgerApi.V3 qualified as Api

type OutputGen a = TxGen Cardano.NetworkId a

-- | Convert a plutus data to a cardano data
toHashableScriptData :: (Api.ToData a) => a -> Cardano.HashableScriptData
toHashableScriptData :: forall a. ToData a => a -> HashableScriptData
toHashableScriptData = ScriptData -> HashableScriptData
Cardano.unsafeHashableScriptData (ScriptData -> HashableScriptData)
-> (a -> ScriptData) -> a -> HashableScriptData
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Data -> ScriptData
Cardano.fromPlutusData (Data -> ScriptData) -> (a -> Data) -> a -> ScriptData
forall b c a. (b -> c) -> (a -> b) -> a -> c
. BuiltinData -> Data
Api.builtinDataToData (BuiltinData -> Data) -> (a -> BuiltinData) -> a -> Data
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> BuiltinData
forall a. ToData a => a -> BuiltinData
Api.toBuiltinData

-- | Converts a 'TxSkelOut' to the corresponding 'Cardano.TxOut'
toCardanoTxOut :: TxSkelOut -> OutputGen (Cardano.TxOut Cardano.CtxTx Cardano.ConwayEra)
toCardanoTxOut :: TxSkelOut -> OutputGen (TxOut CtxTx ConwayEra)
toCardanoTxOut (Pays o
output) = do
  let oAddress :: Address
oAddress = o -> Address
forall o.
(IsAbstractOutput o, ToCredential (OwnerType o)) =>
o -> Address
outputAddress o
output
      oValue :: Value
oValue = o -> Value
forall o. (IsAbstractOutput o, ToValue (ValueType o)) => o -> Value
outputValue o
output
      oDatum :: TxSkelOutDatum
oDatum = o
output o -> Optic' A_Lens NoIx o TxSkelOutDatum -> TxSkelOutDatum
forall k s (is :: IxList) a.
Is k A_Getter =>
s -> Optic' k is s a -> a
^. Lens' o (DatumType o)
Optic' A_Lens NoIx o TxSkelOutDatum
forall o. IsAbstractOutput o => Lens' o (DatumType o)
outputDatumL
      oRefScript :: Maybe (ReferenceScriptType o)
oRefScript = o
output o
-> Optic' A_Lens NoIx o (Maybe (ReferenceScriptType o))
-> Maybe (ReferenceScriptType o)
forall k s (is :: IxList) a.
Is k A_Getter =>
s -> Optic' k is s a -> a
^. Optic' A_Lens NoIx o (Maybe (ReferenceScriptType o))
forall o.
IsAbstractOutput o =>
Lens' o (Maybe (ReferenceScriptType o))
outputReferenceScriptL
  NetworkId
networkId <- ReaderT NetworkId (Either GenerateTxError) NetworkId
forall r (m :: * -> *). MonadReader r m => m r
ask
  AddressInEra ConwayEra
address <-
    String
-> Either ToCardanoError (AddressInEra ConwayEra)
-> TxGen NetworkId (AddressInEra ConwayEra)
forall a context.
String -> Either ToCardanoError a -> TxGen context 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 -> TxGen NetworkId Value
forall a context.
String -> Either ToCardanoError a -> TxGen context 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
-> ReaderT
     NetworkId (Either GenerateTxError) (TxOutDatum CtxTx ConwayEra)
forall a. a -> ReaderT NetworkId (Either GenerateTxError) a
forall (m :: * -> *) a. Monad m => a -> m a
return TxOutDatum CtxTx ConwayEra
forall ctx era. TxOutDatum ctx era
Cardano.TxOutDatumNone
    TxSkelOutDatumHash a
datum ->
      String
-> Either ToCardanoError (TxOutDatum CtxTx ConwayEra)
-> ReaderT
     NetworkId (Either GenerateTxError) (TxOutDatum CtxTx ConwayEra)
forall a context.
String -> Either ToCardanoError a -> TxGen context a
throwOnToCardanoError
        String
"toCardanoTxOut: Unable to resolve/transate a datum hash."
        (Either ToCardanoError (TxOutDatum CtxTx ConwayEra)
 -> ReaderT
      NetworkId (Either GenerateTxError) (TxOutDatum CtxTx ConwayEra))
-> Either ToCardanoError (TxOutDatum CtxTx ConwayEra)
-> ReaderT
     NetworkId (Either GenerateTxError) (TxOutDatum CtxTx ConwayEra)
forall a b. (a -> b) -> a -> b
$ 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)
-> Either ToCardanoError (Hash ScriptData)
-> Either ToCardanoError (TxOutDatum CtxTx ConwayEra)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> DatumHash -> Either ToCardanoError (Hash ScriptData)
Ledger.toCardanoScriptDataHash (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
$ a -> BuiltinData
forall a. ToData a => a -> BuiltinData
Api.toBuiltinData a
datum)
    TxSkelOutDatum a
datum -> TxOutDatum CtxTx ConwayEra
-> ReaderT
     NetworkId (Either GenerateTxError) (TxOutDatum CtxTx ConwayEra)
forall a. a -> ReaderT NetworkId (Either GenerateTxError) a
forall (m :: * -> *) a. Monad m => a -> m a
return (TxOutDatum CtxTx ConwayEra
 -> ReaderT
      NetworkId (Either GenerateTxError) (TxOutDatum CtxTx ConwayEra))
-> TxOutDatum CtxTx ConwayEra
-> ReaderT
     NetworkId (Either GenerateTxError) (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.TxOutDatumInTx AlonzoEraOnwards ConwayEra
Cardano.AlonzoEraOnwardsConway (HashableScriptData -> TxOutDatum CtxTx ConwayEra)
-> HashableScriptData -> TxOutDatum CtxTx ConwayEra
forall a b. (a -> b) -> a -> b
$ a -> HashableScriptData
forall a. ToData a => a -> HashableScriptData
toHashableScriptData a
datum
    TxSkelOutInlineDatum a
datum -> TxOutDatum CtxTx ConwayEra
-> ReaderT
     NetworkId (Either GenerateTxError) (TxOutDatum CtxTx ConwayEra)
forall a. a -> ReaderT NetworkId (Either GenerateTxError) a
forall (m :: * -> *) a. Monad m => a -> m a
return (TxOutDatum CtxTx ConwayEra
 -> ReaderT
      NetworkId (Either GenerateTxError) (TxOutDatum CtxTx ConwayEra))
-> TxOutDatum CtxTx ConwayEra
-> ReaderT
     NetworkId (Either GenerateTxError) (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
$ a -> HashableScriptData
forall a. ToData a => a -> HashableScriptData
toHashableScriptData a
datum
  TxOut CtxTx ConwayEra -> OutputGen (TxOut CtxTx ConwayEra)
forall a. a -> ReaderT NetworkId (Either GenerateTxError) a
forall (m :: * -> *) a. Monad m => a -> m a
return (TxOut CtxTx ConwayEra -> OutputGen (TxOut CtxTx ConwayEra))
-> TxOut CtxTx ConwayEra -> OutputGen (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 (ReferenceScriptType o -> Versioned Script
forall a. ToVersionedScript a => a -> Versioned Script
toVersionedScript (ReferenceScriptType o -> Versioned Script)
-> Maybe (ReferenceScriptType o) -> Maybe (Versioned Script)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe (ReferenceScriptType o)
oRefScript)