-- | This module exposes the generation of transaction inputs
module Cooked.MockChain.GenerateTx.Input (toTxInAndWitness) where

import Cardano.Api qualified as Cardano
import Cooked.MockChain.BlockChain
import Cooked.MockChain.GenerateTx.Common
import Cooked.MockChain.GenerateTx.Witness
import Cooked.Skeleton
import Ledger.Tx.CardanoAPI qualified as Ledger
import PlutusLedgerApi.V3 qualified as Api

-- | Converts a 'TxSkel' input, which consists of a 'Api.TxOutRef' and a
-- 'TxSkelRedeemer', into a 'Cardano.TxIn', together with the appropriate witness.
toTxInAndWitness ::
  (MonadBlockChainBalancing m) =>
  (Api.TxOutRef, TxSkelRedeemer) ->
  m (Cardano.TxIn, Cardano.BuildTxWith Cardano.BuildTx (Cardano.Witness Cardano.WitCtxTxIn Cardano.ConwayEra))
toTxInAndWitness :: forall (m :: * -> *).
MonadBlockChainBalancing m =>
(TxOutRef, TxSkelRedeemer)
-> m (TxIn, BuildTxWith BuildTx (Witness WitCtxTxIn ConwayEra))
toTxInAndWitness (TxOutRef
txOutRef, TxSkelRedeemer
txSkelRedeemer) = do
  Api.TxOut (Api.Address Credential
cred Maybe StakingCredential
_) Value
_ OutputDatum
datum Maybe ScriptHash
_ <- String -> Maybe TxOut -> m TxOut
forall (m :: * -> *) a.
MonadError MockChainError m =>
String -> Maybe a -> m a
throwOnMaybe String
"toCollateralTriplet: unresolved txOutRefs" (Maybe TxOut -> m TxOut) -> m (Maybe TxOut) -> m TxOut
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< TxOutRef -> m (Maybe TxOut)
forall (m :: * -> *).
MonadBlockChainBalancing m =>
TxOutRef -> m (Maybe TxOut)
txOutByRef TxOutRef
txOutRef
  Witness WitCtxTxIn ConwayEra
witness <- case Credential
cred of
    Api.PubKeyCredential PubKeyHash
_ -> Witness WitCtxTxIn ConwayEra -> m (Witness WitCtxTxIn ConwayEra)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Witness WitCtxTxIn ConwayEra -> m (Witness WitCtxTxIn ConwayEra))
-> Witness WitCtxTxIn ConwayEra -> m (Witness WitCtxTxIn ConwayEra)
forall a b. (a -> b) -> a -> b
$ KeyWitnessInCtx WitCtxTxIn -> Witness WitCtxTxIn ConwayEra
forall witctx era. KeyWitnessInCtx witctx -> Witness witctx era
Cardano.KeyWitness KeyWitnessInCtx WitCtxTxIn
Cardano.KeyWitnessForSpending
    Api.ScriptCredential ScriptHash
scriptHash -> do
      Versioned Script
validator <- String -> Maybe (Versioned Script) -> m (Versioned Script)
forall (m :: * -> *) a.
MonadError MockChainError m =>
String -> Maybe a -> m a
throwOnMaybe String
"toTxInAndWitness: Unknown validator" (Maybe (Versioned Script) -> m (Versioned Script))
-> m (Maybe (Versioned Script)) -> m (Versioned Script)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< ScriptHash -> m (Maybe (Versioned Script))
forall (m :: * -> *).
MonadBlockChainBalancing m =>
ScriptHash -> m (Maybe (Versioned Script))
scriptFromHash ScriptHash
scriptHash
      ScriptDatum WitCtxTxIn
scriptDatum <- case OutputDatum
datum of
        OutputDatum
Api.NoOutputDatum -> ScriptDatum WitCtxTxIn -> m (ScriptDatum WitCtxTxIn)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (ScriptDatum WitCtxTxIn -> m (ScriptDatum WitCtxTxIn))
-> ScriptDatum WitCtxTxIn -> m (ScriptDatum WitCtxTxIn)
forall a b. (a -> b) -> a -> b
$ Maybe HashableScriptData -> ScriptDatum WitCtxTxIn
Cardano.ScriptDatumForTxIn Maybe HashableScriptData
forall a. Maybe a
Nothing
        Api.OutputDatum Datum
_ -> ScriptDatum WitCtxTxIn -> m (ScriptDatum WitCtxTxIn)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptDatum WitCtxTxIn
Cardano.InlineScriptDatum
        Api.OutputDatumHash DatumHash
datumHash -> do
          Datum
sDatum <- String -> Maybe Datum -> m Datum
forall (m :: * -> *) a.
MonadError MockChainError m =>
String -> Maybe a -> m a
throwOnMaybe String
"toTxInAndWitness: Unknown datum hash" (Maybe Datum -> m Datum) -> m (Maybe Datum) -> m Datum
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< DatumHash -> m (Maybe Datum)
forall (m :: * -> *).
MonadBlockChainBalancing m =>
DatumHash -> m (Maybe Datum)
datumFromHash DatumHash
datumHash
          ScriptDatum WitCtxTxIn -> m (ScriptDatum WitCtxTxIn)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (ScriptDatum WitCtxTxIn -> m (ScriptDatum WitCtxTxIn))
-> ScriptDatum WitCtxTxIn -> m (ScriptDatum WitCtxTxIn)
forall a b. (a -> b) -> a -> b
$ Maybe HashableScriptData -> ScriptDatum WitCtxTxIn
Cardano.ScriptDatumForTxIn (Maybe HashableScriptData -> ScriptDatum WitCtxTxIn)
-> Maybe HashableScriptData -> ScriptDatum WitCtxTxIn
forall a b. (a -> b) -> a -> b
$ HashableScriptData -> Maybe HashableScriptData
forall a. a -> Maybe a
Just (HashableScriptData -> Maybe HashableScriptData)
-> HashableScriptData -> Maybe HashableScriptData
forall a b. (a -> b) -> a -> b
$ BuiltinData -> HashableScriptData
Ledger.toCardanoScriptData (BuiltinData -> HashableScriptData)
-> BuiltinData -> HashableScriptData
forall a b. (a -> b) -> a -> b
$ Datum -> BuiltinData
Api.getDatum Datum
sDatum
      ScriptWitnessInCtx WitCtxTxIn
-> ScriptWitness WitCtxTxIn ConwayEra
-> Witness WitCtxTxIn ConwayEra
forall witctx era.
ScriptWitnessInCtx witctx
-> ScriptWitness witctx era -> Witness witctx era
Cardano.ScriptWitness ScriptWitnessInCtx WitCtxTxIn
Cardano.ScriptWitnessForSpending (ScriptWitness WitCtxTxIn ConwayEra
 -> Witness WitCtxTxIn ConwayEra)
-> m (ScriptWitness WitCtxTxIn ConwayEra)
-> m (Witness WitCtxTxIn ConwayEra)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Versioned Script
-> TxSkelRedeemer
-> ScriptDatum WitCtxTxIn
-> m (ScriptWitness WitCtxTxIn ConwayEra)
forall (m :: * -> *) a b.
(MonadBlockChainBalancing m, ToVersioned Script a) =>
a
-> TxSkelRedeemer -> ScriptDatum b -> m (ScriptWitness b ConwayEra)
toScriptWitness Versioned Script
validator TxSkelRedeemer
txSkelRedeemer ScriptDatum WitCtxTxIn
scriptDatum
  String
-> (TxIn
    -> (TxIn, BuildTxWith BuildTx (Witness WitCtxTxIn ConwayEra)))
-> Either ToCardanoError TxIn
-> m (TxIn, BuildTxWith BuildTx (Witness WitCtxTxIn ConwayEra))
forall (m :: * -> *) a b.
MonadError MockChainError m =>
String -> (a -> b) -> Either ToCardanoError a -> m b
throwOnToCardanoErrorOrApply
    String
"toTxInAndWitness: Unable to translate TxOutRef"
    (,Witness WitCtxTxIn ConwayEra
-> BuildTxWith BuildTx (Witness WitCtxTxIn ConwayEra)
forall a. a -> BuildTxWith BuildTx a
Cardano.BuildTxWith Witness WitCtxTxIn ConwayEra
witness)
    (TxOutRef -> Either ToCardanoError TxIn
Ledger.toCardanoTxIn TxOutRef
txOutRef)