-- | 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
  TxSkelOut (owner -> Either PubKeyHash (Versioned Validator)
forall a.
IsTxSkelOutAllowedOwner a =>
a -> Either PubKeyHash (Versioned Validator)
toPKHOrValidator -> Either PubKeyHash (Versioned Validator)
owner) Maybe StakingCredential
_ TxSkelOutDatum
datum TxSkelOutValue
_ TxSkelOutReferenceScript
_ <- TxOutRef -> m TxSkelOut
forall (m :: * -> *).
MonadBlockChainBalancing m =>
TxOutRef -> m TxSkelOut
unsafeTxOutByRef TxOutRef
txOutRef
  Witness WitCtxTxIn ConwayEra
witness <- case Either PubKeyHash (Versioned Validator)
owner of
    Left 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
    Right Versioned Validator
validator ->
      (ScriptWitness WitCtxTxIn ConwayEra
 -> Witness WitCtxTxIn ConwayEra)
-> m (ScriptWitness WitCtxTxIn ConwayEra)
-> m (Witness WitCtxTxIn ConwayEra)
forall a b. (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (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) (m (ScriptWitness WitCtxTxIn ConwayEra)
 -> m (Witness WitCtxTxIn ConwayEra))
-> m (ScriptWitness WitCtxTxIn ConwayEra)
-> m (Witness WitCtxTxIn ConwayEra)
forall a b. (a -> b) -> a -> b
$
        Versioned Validator
-> 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 Validator
validator TxSkelRedeemer
txSkelRedeemer (ScriptDatum WitCtxTxIn -> m (ScriptWitness WitCtxTxIn ConwayEra))
-> ScriptDatum WitCtxTxIn -> m (ScriptWitness WitCtxTxIn ConwayEra)
forall a b. (a -> b) -> a -> b
$
          case TxSkelOutDatum
datum of
            TxSkelOutDatum
TxSkelOutNoDatum -> Maybe HashableScriptData -> ScriptDatum WitCtxTxIn
Cardano.ScriptDatumForTxIn Maybe HashableScriptData
forall a. Maybe a
Nothing
            TxSkelOutSomeDatum DatumContent
_ DatumKind
Inline -> ScriptDatum WitCtxTxIn
Cardano.InlineScriptDatum
            TxSkelOutSomeDatum DatumContent
dat DatumKind
_ -> 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
$ DatumContent -> BuiltinData
forall a. ToData a => a -> BuiltinData
Api.toBuiltinData DatumContent
dat
  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)