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

import Cardano.Api qualified as Cardano
import Cooked.MockChain.Error
import Cooked.MockChain.GenerateTx.Witness
import Cooked.MockChain.Read
import Cooked.Skeleton
import Ledger.Tx.CardanoAPI qualified as P.Ledger
import PlutusLedgerApi.V3 qualified as Api
import Polysemy
import Polysemy.Error

-- | Converts a 'TxSkel' input, which consists of a 'Api.TxOutRef' and a
-- 'TxSkelRedeemer', into a 'Cardano.TxIn', together with the appropriate witness.
toTxInAndWitness ::
  (Members '[MockChainRead, Error MockChainError, Error P.Ledger.ToCardanoError] effs) =>
  (Api.TxOutRef, TxSkelRedeemer) ->
  Sem
    effs
    ( Cardano.TxIn,
      Cardano.BuildTxWith Cardano.BuildTx (Cardano.Witness Cardano.WitCtxTxIn Cardano.ConwayEra)
    )
toTxInAndWitness :: forall (effs :: EffectRow).
Members
  '[MockChainRead, Error MockChainError, Error ToCardanoError]
  effs =>
(TxOutRef, TxSkelRedeemer)
-> Sem
     effs (TxIn, BuildTxWith BuildTx (Witness WitCtxTxIn ConwayEra))
toTxInAndWitness (TxOutRef
txOutRef, TxSkelRedeemer
txSkelRedeemer) = do
  TxSkelOut {User 'IsEither 'Allocation
txSkelOutOwner :: User 'IsEither 'Allocation
txSkelOutOwner :: TxSkelOut -> User 'IsEither 'Allocation
txSkelOutOwner, TxSkelOutDatum
txSkelOutDatum :: TxSkelOutDatum
txSkelOutDatum :: TxSkelOut -> TxSkelOutDatum
txSkelOutDatum} <- TxOutRef -> Sem effs TxSkelOut
forall (effs :: EffectRow).
Member MockChainRead effs =>
TxOutRef -> Sem effs TxSkelOut
txSkelOutByRef TxOutRef
txOutRef
  Witness WitCtxTxIn ConwayEra
witness <- case User 'IsEither 'Allocation
txSkelOutOwner of
    UserPubKey pkh
_ -> Witness WitCtxTxIn ConwayEra
-> Sem effs (Witness WitCtxTxIn ConwayEra)
forall a. a -> Sem effs a
forall (m :: * -> *) a. Monad m => a -> m a
return (Witness WitCtxTxIn ConwayEra
 -> Sem effs (Witness WitCtxTxIn ConwayEra))
-> Witness WitCtxTxIn ConwayEra
-> Sem effs (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
    UserScript script
script ->
      (ScriptWitness WitCtxTxIn ConwayEra
 -> Witness WitCtxTxIn ConwayEra)
-> Sem effs (ScriptWitness WitCtxTxIn ConwayEra)
-> Sem effs (Witness WitCtxTxIn ConwayEra)
forall a b. (a -> b) -> Sem effs a -> Sem effs 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) (Sem effs (ScriptWitness WitCtxTxIn ConwayEra)
 -> Sem effs (Witness WitCtxTxIn ConwayEra))
-> Sem effs (ScriptWitness WitCtxTxIn ConwayEra)
-> Sem effs (Witness WitCtxTxIn ConwayEra)
forall a b. (a -> b) -> a -> b
$
        script
-> TxSkelRedeemer
-> ScriptDatum WitCtxTxIn
-> Sem effs (ScriptWitness WitCtxTxIn ConwayEra)
forall (effs :: EffectRow) a b.
(Members
   '[MockChainRead, Error MockChainError, Error ToCardanoError] effs,
 ToVScript a) =>
a
-> TxSkelRedeemer
-> ScriptDatum b
-> Sem effs (ScriptWitness b ConwayEra)
toScriptWitness script
script TxSkelRedeemer
txSkelRedeemer (ScriptDatum WitCtxTxIn
 -> Sem effs (ScriptWitness WitCtxTxIn ConwayEra))
-> ScriptDatum WitCtxTxIn
-> Sem effs (ScriptWitness WitCtxTxIn ConwayEra)
forall a b. (a -> b) -> a -> b
$
          case TxSkelOutDatum
txSkelOutDatum of
            TxSkelOutDatum
NoTxSkelOutDatum -> Maybe HashableScriptData -> ScriptDatum WitCtxTxIn
Cardano.ScriptDatumForTxIn Maybe HashableScriptData
forall a. Maybe a
Nothing
            SomeTxSkelOutDatum dat
_ DatumKind
Inline -> ScriptDatum WitCtxTxIn
Cardano.InlineScriptDatum
            SomeTxSkelOutDatum dat
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
P.Ledger.toCardanoScriptData (BuiltinData -> HashableScriptData)
-> BuiltinData -> HashableScriptData
forall a b. (a -> b) -> a -> b
$ dat -> BuiltinData
forall a. ToData a => a -> BuiltinData
Api.toBuiltinData dat
dat
  (,Witness WitCtxTxIn ConwayEra
-> BuildTxWith BuildTx (Witness WitCtxTxIn ConwayEra)
forall a. a -> BuildTxWith BuildTx a
Cardano.BuildTxWith Witness WitCtxTxIn ConwayEra
witness) (TxIn
 -> (TxIn, BuildTxWith BuildTx (Witness WitCtxTxIn ConwayEra)))
-> Sem effs TxIn
-> Sem
     effs (TxIn, BuildTxWith BuildTx (Witness WitCtxTxIn ConwayEra))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Either ToCardanoError TxIn -> Sem effs TxIn
forall e (r :: EffectRow) a.
Member (Error e) r =>
Either e a -> Sem r a
fromEither (TxOutRef -> Either ToCardanoError TxIn
P.Ledger.toCardanoTxIn TxOutRef
txOutRef)