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.Conversion
import Cooked.MockChain.BlockChain
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

-- | 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 (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 <- 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
    TxSkelOutDatumHash a
datum ->
      String
-> Either ToCardanoError (TxOutDatum CtxTx ConwayEra)
-> m (TxOutDatum CtxTx ConwayEra)
forall (m :: * -> *) a.
MonadError MockChainError m =>
String -> Either ToCardanoError a -> m a
throwOnToCardanoError
        String
"toCardanoTxOut: Unable to resolve/transate a datum hash."
        (Either ToCardanoError (TxOutDatum CtxTx ConwayEra)
 -> m (TxOutDatum CtxTx ConwayEra))
-> Either ToCardanoError (TxOutDatum CtxTx ConwayEra)
-> m (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 -> 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.TxOutDatumInTx 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
$ a -> BuiltinData
forall a. ToData a => a -> BuiltinData
Api.toBuiltinData a
datum
    TxSkelOutInlineDatum a
datum -> 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
$ a -> BuiltinData
forall a. ToData a => a -> BuiltinData
Api.toBuiltinData a
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 (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)