-- | This module exposes the proposals constructs used in a
-- 'Cooked.Skeleton.TxSkel' and their associated utilities. To issue proposals
-- in a skeleton, the usual way is to invoke @txSkelProposals = [simpleProposal
-- script govAction1, simpleProposal pk govAction2, ... ]@
module Cooked.Skeleton.Proposal
  ( -- * Data types
    ParameterChange (..),
    GovernanceAction (..),
    TxSkelProposal (..),

    -- * Optics
    txSkelProposalAnchorL,
    txSkelProposalMConstitutionAT,
    txSkelProposalReturnCredentialL,
    txSkelProposalGovernanceActionAT,
    txSkelProposalConstitutionAT,

    -- * Smart constructors
    simpleProposal,

    -- * Utilities
    fillConstitution,
  )
where

import Cooked.Skeleton.Anchor
import Cooked.Skeleton.Redeemer
import Cooked.Skeleton.User
import Data.Kind (Type)
import Data.Map (Map)
import Data.Typeable
import Optics.Core
import Optics.TH
import Plutus.Script.Utils.Address qualified as Script
import PlutusLedgerApi.V3 qualified as Api
import PlutusTx.Prelude qualified as PlutusTx

-- * Proposals for 'Cooked.Skeleton.TxSkel'

-- | These are all the protocol parameters. They are taken from
-- https://github.com/IntersectMBO/cardano-ledger/blob/c4fbc05999866fea7c0cb1b211fd5288f286b95d/eras/conway/impl/cddl-files/conway.cddl#L381-L412
-- and will most likely change in future eras.
data ParameterChange where
  -- | The linear factor for the minimum fee calculation
  FeePerByte :: Integer -> ParameterChange
  -- | The constant factor for the minimum fee calculation
  FeeFixed :: Integer -> ParameterChange
  -- | Maximal block body size
  MaxBlockBodySize :: Integer -> ParameterChange
  -- | Maximal transaction size
  MaxTxSize :: Integer -> ParameterChange
  -- | Maximal block header size
  MaxBlockHeaderSize :: Integer -> ParameterChange
  -- | The amount of a key registration deposit
  KeyDeposit :: Integer -> ParameterChange
  -- | The amount of a pool registration deposit
  PoolDeposit :: Integer -> ParameterChange
  -- | Maximum number of epochs in the future a pool retirement is allowed to
  -- be scheduled future for.
  PoolRetirementMaxEpoch :: Integer -> ParameterChange
  -- | Desired number of pools
  PoolNumber :: Integer -> ParameterChange
  -- | Pool influence
  PoolInfluence :: Rational -> ParameterChange
  -- | Monetary expansion
  MonetaryExpansion :: Rational -> ParameterChange
  -- | Treasury expansion
  TreasuryCut :: Rational -> ParameterChange
  -- | Minimum Stake Pool Cost
  MinPoolCost :: Integer -> ParameterChange
  -- | Cost in lovelace per byte of UTxO storage
  CoinsPerUTxOByte :: Integer -> ParameterChange
  -- | Cost models for non-native script languages
  CostModels ::
    { ParameterChange -> [Integer]
cmPlutusV1Costs :: [Integer],
      ParameterChange -> [Integer]
cmPlutusV2Costs :: [Integer],
      ParameterChange -> [Integer]
cmPlutusV3Costs :: [Integer]
    } ->
    ParameterChange
  -- | Prices of execution units
  Prices ::
    { ParameterChange -> Rational
pMemoryCost :: Rational,
      ParameterChange -> Rational
pStepCost :: Rational
    } ->
    ParameterChange
  -- | Max total script execution resources units allowed per tx
  MaxTxExUnits ::
    { ParameterChange -> Integer
mteuMemory :: Integer,
      ParameterChange -> Integer
mteuSteps :: Integer
    } ->
    ParameterChange
  -- | Max total script execution resources units allowed per block
  MaxBlockExUnits ::
    { ParameterChange -> Integer
mbeuMemory :: Integer,
      ParameterChange -> Integer
mbeuSteps :: Integer
    } ->
    ParameterChange
  -- | Max size of a Value in an output
  MaxValSize :: Integer -> ParameterChange
  -- | Percentage of the txfee which must be provided as collateral when
  -- including non-native scripts.
  CollateralPercentage :: Integer -> ParameterChange
  -- | Maximum number of collateral inputs allowed in a transaction
  MaxCollateralInputs :: Integer -> ParameterChange
  -- | Thresholds for pool votes
  PoolVotingThresholds ::
    { ParameterChange -> Rational
pvtMotionNoConfidence :: Rational,
      ParameterChange -> Rational
pvtCommitteeNormal :: Rational,
      ParameterChange -> Rational
pvtCommitteeNoConfidence :: Rational,
      ParameterChange -> Rational
pvtHardFork :: Rational,
      ParameterChange -> Rational
pvtSecurityGroup :: Rational
    } ->
    ParameterChange
  -- | Thresholds for DRep votes
  DRepVotingThresholds ::
    { ParameterChange -> Rational
drvtMotionNoConfidence :: Rational,
      ParameterChange -> Rational
drvtCommitteeNormal :: Rational,
      ParameterChange -> Rational
drvtCommitteeNoConfidence :: Rational,
      ParameterChange -> Rational
drvtUpdateConstitution :: Rational,
      ParameterChange -> Rational
drvtHardForkInitialization :: Rational,
      ParameterChange -> Rational
drvtNetworkGroup :: Rational,
      ParameterChange -> Rational
drvtEconomicGroup :: Rational,
      ParameterChange -> Rational
drvtTechnicalGroup :: Rational,
      ParameterChange -> Rational
drvtGovernanceGroup :: Rational,
      ParameterChange -> Rational
drvtTreasuryWithdrawal :: Rational
    } ->
    ParameterChange
  -- | Minimum size of the Constitutional Committee
  CommitteeMinSize :: Integer -> ParameterChange
  -- | The Constitutional Committee Term limit in number of Slots
  CommitteeMaxTermLength :: Integer -> ParameterChange
  -- | Gov action lifetime in number of Epochs
  GovActionLifetime :: Integer -> ParameterChange
  -- | The amount of the Gov Action deposit
  GovActionDeposit :: Integer -> ParameterChange
  -- | The amount of a DRep registration deposit
  DRepRegistrationDeposit :: Integer -> ParameterChange
  -- | The number of Epochs that a DRep can perform no activity without losing
  -- their @Active@ status.
  DRepActivity :: Integer -> ParameterChange
  -- | Reference scripts fee for the minimum fee calculation
  MinFeeRefScriptCostPerByte :: Rational -> ParameterChange
  deriving (Int -> ParameterChange -> ShowS
[ParameterChange] -> ShowS
ParameterChange -> String
(Int -> ParameterChange -> ShowS)
-> (ParameterChange -> String)
-> ([ParameterChange] -> ShowS)
-> Show ParameterChange
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> ParameterChange -> ShowS
showsPrec :: Int -> ParameterChange -> ShowS
$cshow :: ParameterChange -> String
show :: ParameterChange -> String
$cshowList :: [ParameterChange] -> ShowS
showList :: [ParameterChange] -> ShowS
Show, ParameterChange -> ParameterChange -> Bool
(ParameterChange -> ParameterChange -> Bool)
-> (ParameterChange -> ParameterChange -> Bool)
-> Eq ParameterChange
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: ParameterChange -> ParameterChange -> Bool
== :: ParameterChange -> ParameterChange -> Bool
$c/= :: ParameterChange -> ParameterChange -> Bool
/= :: ParameterChange -> ParameterChange -> Bool
Eq)

-- | This lists the various possible governance actions. Only two of these
-- action need to be witnessed by the constitution script, which are annotated
-- by 'IsScript'.
data GovernanceAction :: UserKind -> Type where
  -- If several parameter changes are of the same kind, only the last
  -- one will take effect
  ParameterChange :: [ParameterChange] -> GovernanceAction IsScript
  TreasuryWithdrawals :: Map Api.Credential Api.Lovelace -> GovernanceAction IsScript
  HardForkInitiation :: Api.ProtocolVersion -> GovernanceAction IsNone
  NoConfidence :: GovernanceAction IsNone
  UpdateCommittee :: [Api.ColdCommitteeCredential] -> Map Api.ColdCommitteeCredential Integer -> PlutusTx.Rational -> GovernanceAction IsNone
  NewConstitution :: Api.Constitution -> GovernanceAction IsNone

deriving instance Show (GovernanceAction a)

deriving instance Eq (GovernanceAction a)

-- | This bundles a governance action into an actual proposal
data TxSkelProposal where
  TxSkelProposal ::
    ( Typeable kind,
      Script.ToCredential cred
    ) =>
    { -- | The credential that should be used for a return account
      ()
txSkelProposalReturnCredential :: cred,
      -- | The proposed action gov action, either witnessed or simple
      ()
txSkelProposalGovernanceAction :: GovernanceAction kind,
      -- | The constitution witness of this proposal, when paired with a
      -- witnessed governance action. Is the governance action is simple,
      -- only 'Nothing' can be provided there.
      ()
txSkelProposalConstitution :: Maybe (User kind Redemption),
      -- | An optional anchor to be given as additional data. It should
      -- correspond to the URL of a web page
      TxSkelProposal -> TxSkelAnchor
txSkelProposalAnchor :: TxSkelAnchor
    } ->
    TxSkelProposal

instance Show TxSkelProposal where
  show :: TxSkelProposal -> String
show (TxSkelProposal (cred -> Credential
forall a. ToCredential a => a -> Credential
Script.toCredential -> Credential
cred) GovernanceAction kind
action Maybe (User kind 'Redemption)
constit TxSkelAnchor
anchor) = [String] -> String
forall a. Show a => a -> String
show [Credential -> String
forall a. Show a => a -> String
show Credential
cred, GovernanceAction kind -> String
forall a. Show a => a -> String
show GovernanceAction kind
action, Maybe (User kind 'Redemption) -> String
forall a. Show a => a -> String
show Maybe (User kind 'Redemption)
constit, TxSkelAnchor -> String
forall a. Show a => a -> String
show TxSkelAnchor
anchor]

instance Eq TxSkelProposal where
  (TxSkelProposal (cred -> Credential
forall a. ToCredential a => a -> Credential
Script.toCredential -> Credential
cred) GovernanceAction kind
action Maybe (User kind 'Redemption)
constit TxSkelAnchor
anchor) == :: TxSkelProposal -> TxSkelProposal -> Bool
== (TxSkelProposal (cred -> Credential
forall a. ToCredential a => a -> Credential
Script.toCredential -> Credential
cred') GovernanceAction kind
action' Maybe (User kind 'Redemption)
constit' TxSkelAnchor
anchor') =
    Credential
cred Credential -> Credential -> Bool
forall a. Eq a => a -> a -> Bool
== Credential
cred' Bool -> Bool -> Bool
&& GovernanceAction kind -> Maybe (GovernanceAction kind)
forall a b. (Typeable a, Typeable b) => a -> Maybe b
cast GovernanceAction kind
action Maybe (GovernanceAction kind)
-> Maybe (GovernanceAction kind) -> Bool
forall a. Eq a => a -> a -> Bool
== GovernanceAction kind -> Maybe (GovernanceAction kind)
forall a. a -> Maybe a
Just GovernanceAction kind
action' Bool -> Bool -> Bool
&& Maybe (User kind 'Redemption)
-> Maybe (Maybe (User kind 'Redemption))
forall a b. (Typeable a, Typeable b) => a -> Maybe b
cast Maybe (User kind 'Redemption)
constit Maybe (Maybe (User kind 'Redemption))
-> Maybe (Maybe (User kind 'Redemption)) -> Bool
forall a. Eq a => a -> a -> Bool
== Maybe (User kind 'Redemption)
-> Maybe (Maybe (User kind 'Redemption))
forall a. a -> Maybe a
Just Maybe (User kind 'Redemption)
constit' Bool -> Bool -> Bool
&& TxSkelAnchor
anchor TxSkelAnchor -> TxSkelAnchor -> Bool
forall a. Eq a => a -> a -> Bool
== TxSkelAnchor
anchor'

-- * Optics on 'TxSkelProposal'

-- | Focuses on the return credential from a 'TxSkelProposal'
txSkelProposalReturnCredentialL :: Lens' TxSkelProposal Api.Credential
txSkelProposalReturnCredentialL :: Lens' TxSkelProposal Credential
txSkelProposalReturnCredentialL =
  (TxSkelProposal -> Credential)
-> (TxSkelProposal -> Credential -> TxSkelProposal)
-> Lens' TxSkelProposal Credential
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens
    (\(TxSkelProposal {cred
txSkelProposalReturnCredential :: ()
txSkelProposalReturnCredential :: cred
txSkelProposalReturnCredential}) -> cred -> Credential
forall a. ToCredential a => a -> Credential
Script.toCredential cred
txSkelProposalReturnCredential)
    (\TxSkelProposal
txSkelProposal Credential
cred -> TxSkelProposal
txSkelProposal {txSkelProposalReturnCredential = cred})

-- | Focuses on the optional constitution of a 'TxSkelProposal'
txSkelProposalMConstitutionAT :: forall kind. (Typeable kind) => AffineTraversal' TxSkelProposal (Maybe (User kind Redemption))
txSkelProposalMConstitutionAT :: forall (kind :: UserKind).
Typeable kind =>
AffineTraversal' TxSkelProposal (Maybe (User kind 'Redemption))
txSkelProposalMConstitutionAT =
  (TxSkelProposal
 -> Either TxSkelProposal (Maybe (User kind 'Redemption)))
-> (TxSkelProposal
    -> Maybe (User kind 'Redemption) -> TxSkelProposal)
-> AffineTraversal
     TxSkelProposal
     TxSkelProposal
     (Maybe (User kind 'Redemption))
     (Maybe (User kind 'Redemption))
forall s t a b.
(s -> Either t a) -> (s -> b -> t) -> AffineTraversal s t a b
atraversal
    (\prop :: TxSkelProposal
prop@(TxSkelProposal {Maybe (User kind 'Redemption)
txSkelProposalConstitution :: ()
txSkelProposalConstitution :: Maybe (User kind 'Redemption)
txSkelProposalConstitution}) -> Either TxSkelProposal (Maybe (User kind 'Redemption))
-> (Maybe (User kind 'Redemption)
    -> Either TxSkelProposal (Maybe (User kind 'Redemption)))
-> Maybe (Maybe (User kind 'Redemption))
-> Either TxSkelProposal (Maybe (User kind 'Redemption))
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (TxSkelProposal
-> Either TxSkelProposal (Maybe (User kind 'Redemption))
forall a b. a -> Either a b
Left TxSkelProposal
prop) Maybe (User kind 'Redemption)
-> Either TxSkelProposal (Maybe (User kind 'Redemption))
forall a b. b -> Either a b
Right (Maybe (Maybe (User kind 'Redemption))
 -> Either TxSkelProposal (Maybe (User kind 'Redemption)))
-> Maybe (Maybe (User kind 'Redemption))
-> Either TxSkelProposal (Maybe (User kind 'Redemption))
forall a b. (a -> b) -> a -> b
$ Maybe (User kind 'Redemption)
-> Maybe (Maybe (User kind 'Redemption))
forall a b. (Typeable a, Typeable b) => a -> Maybe b
cast Maybe (User kind 'Redemption)
txSkelProposalConstitution)
    (\prop :: TxSkelProposal
prop@(TxSkelProposal @kind' cred
cred GovernanceAction kind
action Maybe (User kind 'Redemption)
_ TxSkelAnchor
anchor) Maybe (User kind 'Redemption)
constit' -> TxSkelProposal
-> ((kind :~: kind) -> TxSkelProposal)
-> Maybe (kind :~: kind)
-> TxSkelProposal
forall b a. b -> (a -> b) -> Maybe a -> b
maybe TxSkelProposal
prop (\kind :~: kind
Refl -> cred
-> GovernanceAction kind
-> Maybe (User kind 'Redemption)
-> TxSkelAnchor
-> TxSkelProposal
forall (kind :: UserKind) cred.
(Typeable kind, ToCredential cred) =>
cred
-> GovernanceAction kind
-> Maybe (User kind 'Redemption)
-> TxSkelAnchor
-> TxSkelProposal
TxSkelProposal cred
cred GovernanceAction kind
action Maybe (User kind 'Redemption)
Maybe (User kind 'Redemption)
constit' TxSkelAnchor
anchor) (Maybe (kind :~: kind) -> TxSkelProposal)
-> Maybe (kind :~: kind) -> TxSkelProposal
forall a b. (a -> b) -> a -> b
$ forall {k} (a :: k) (b :: k).
(Typeable a, Typeable b) =>
Maybe (a :~: b)
forall (a :: UserKind) (b :: UserKind).
(Typeable a, Typeable b) =>
Maybe (a :~: b)
eqT @kind @kind')

-- | Focuses on the constitution of a 'TxSkelProposal'
txSkelProposalConstitutionAT :: AffineTraversal' TxSkelProposal (User IsScript Redemption)
txSkelProposalConstitutionAT :: AffineTraversal' TxSkelProposal (User 'IsScript 'Redemption)
txSkelProposalConstitutionAT = AffineTraversal'
  TxSkelProposal (Maybe (User 'IsScript 'Redemption))
forall (kind :: UserKind).
Typeable kind =>
AffineTraversal' TxSkelProposal (Maybe (User kind 'Redemption))
txSkelProposalMConstitutionAT AffineTraversal'
  TxSkelProposal (Maybe (User 'IsScript 'Redemption))
-> Optic
     A_Prism
     NoIx
     (Maybe (User 'IsScript 'Redemption))
     (Maybe (User 'IsScript 'Redemption))
     (User 'IsScript 'Redemption)
     (User 'IsScript 'Redemption)
-> AffineTraversal' TxSkelProposal (User 'IsScript 'Redemption)
forall k l m (is :: IxList) (js :: IxList) (ks :: IxList) s t u v a
       b.
(JoinKinds k l m, AppendIndices is js ks) =>
Optic k is s t u v -> Optic l js u v a b -> Optic m ks s t a b
% Optic
  A_Prism
  NoIx
  (Maybe (User 'IsScript 'Redemption))
  (Maybe (User 'IsScript 'Redemption))
  (User 'IsScript 'Redemption)
  (User 'IsScript 'Redemption)
forall a b. Prism (Maybe a) (Maybe b) a b
_Just

-- | Focuses on the governance action of a 'TxSkelProposal'
txSkelProposalGovernanceActionAT :: forall req. (Typeable req) => AffineTraversal' TxSkelProposal (GovernanceAction req)
txSkelProposalGovernanceActionAT :: forall (req :: UserKind).
Typeable req =>
AffineTraversal' TxSkelProposal (GovernanceAction req)
txSkelProposalGovernanceActionAT =
  (TxSkelProposal -> Either TxSkelProposal (GovernanceAction req))
-> (TxSkelProposal -> GovernanceAction req -> TxSkelProposal)
-> AffineTraversal
     TxSkelProposal
     TxSkelProposal
     (GovernanceAction req)
     (GovernanceAction req)
forall s t a b.
(s -> Either t a) -> (s -> b -> t) -> AffineTraversal s t a b
atraversal
    (\prop :: TxSkelProposal
prop@(TxSkelProposal {GovernanceAction kind
txSkelProposalGovernanceAction :: ()
txSkelProposalGovernanceAction :: GovernanceAction kind
txSkelProposalGovernanceAction}) -> Either TxSkelProposal (GovernanceAction req)
-> (GovernanceAction req
    -> Either TxSkelProposal (GovernanceAction req))
-> Maybe (GovernanceAction req)
-> Either TxSkelProposal (GovernanceAction req)
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (TxSkelProposal -> Either TxSkelProposal (GovernanceAction req)
forall a b. a -> Either a b
Left TxSkelProposal
prop) GovernanceAction req
-> Either TxSkelProposal (GovernanceAction req)
forall a b. b -> Either a b
Right (Maybe (GovernanceAction req)
 -> Either TxSkelProposal (GovernanceAction req))
-> Maybe (GovernanceAction req)
-> Either TxSkelProposal (GovernanceAction req)
forall a b. (a -> b) -> a -> b
$ GovernanceAction kind -> Maybe (GovernanceAction req)
forall a b. (Typeable a, Typeable b) => a -> Maybe b
cast GovernanceAction kind
txSkelProposalGovernanceAction)
    (\prop :: TxSkelProposal
prop@(TxSkelProposal @req' cred
cred GovernanceAction kind
_ Maybe (User kind 'Redemption)
constit TxSkelAnchor
anchor) GovernanceAction req
newAction -> TxSkelProposal
-> ((req :~: kind) -> TxSkelProposal)
-> Maybe (req :~: kind)
-> TxSkelProposal
forall b a. b -> (a -> b) -> Maybe a -> b
maybe TxSkelProposal
prop (\req :~: kind
Refl -> cred
-> GovernanceAction req
-> Maybe (User req 'Redemption)
-> TxSkelAnchor
-> TxSkelProposal
forall (kind :: UserKind) cred.
(Typeable kind, ToCredential cred) =>
cred
-> GovernanceAction kind
-> Maybe (User kind 'Redemption)
-> TxSkelAnchor
-> TxSkelProposal
TxSkelProposal cred
cred GovernanceAction req
newAction Maybe (User req 'Redemption)
Maybe (User kind 'Redemption)
constit TxSkelAnchor
anchor) (Maybe (req :~: kind) -> TxSkelProposal)
-> Maybe (req :~: kind) -> TxSkelProposal
forall a b. (a -> b) -> a -> b
$ forall {k} (a :: k) (b :: k).
(Typeable a, Typeable b) =>
Maybe (a :~: b)
forall (a :: UserKind) (b :: UserKind).
(Typeable a, Typeable b) =>
Maybe (a :~: b)
eqT @req @req')

-- | A lens to get or set the anchor of a 'TxSkelProposal'
makeLensesFor [("txSkelProposalAnchor", "txSkelProposalAnchorL")] ''TxSkelProposal

-- * Smart constructors and updators

-- | Builds a 'TxSkelProposal' from a credential and a gov action. Does not set
-- any constitution (when applicable) nor anchor.
simpleProposal :: (Script.ToCredential cred, Typeable kind) => cred -> GovernanceAction kind -> TxSkelProposal
simpleProposal :: forall cred (kind :: UserKind).
(ToCredential cred, Typeable kind) =>
cred -> GovernanceAction kind -> TxSkelProposal
simpleProposal cred
cred GovernanceAction kind
action = cred
-> GovernanceAction kind
-> Maybe (User kind 'Redemption)
-> TxSkelAnchor
-> TxSkelProposal
forall (kind :: UserKind) cred.
(Typeable kind, ToCredential cred) =>
cred
-> GovernanceAction kind
-> Maybe (User kind 'Redemption)
-> TxSkelAnchor
-> TxSkelProposal
TxSkelProposal cred
cred GovernanceAction kind
action Maybe (User kind 'Redemption)
forall a. Maybe a
Nothing TxSkelAnchor
forall a. Maybe a
Nothing

-- | Sets the constitution script with an empty redeemer when empty. This will
-- not tamper with an existing constitution script and redeemer.
fillConstitution :: (ToVScript script, Typeable script) => script -> TxSkelProposal -> TxSkelProposal
fillConstitution :: forall script.
(ToVScript script, Typeable script) =>
script -> TxSkelProposal -> TxSkelProposal
fillConstitution script
constitution =
  AffineTraversal'
  TxSkelProposal (Maybe (User 'IsScript 'Redemption))
-> (Maybe (User 'IsScript 'Redemption)
    -> Maybe (User 'IsScript 'Redemption))
-> TxSkelProposal
-> TxSkelProposal
forall k (is :: IxList) s t a b.
Is k A_Setter =>
Optic k is s t a b -> (a -> b) -> s -> t
over
    (forall (kind :: UserKind).
Typeable kind =>
AffineTraversal' TxSkelProposal (Maybe (User kind 'Redemption))
txSkelProposalMConstitutionAT @IsScript)
    (Maybe (User 'IsScript 'Redemption)
-> (User 'IsScript 'Redemption
    -> Maybe (User 'IsScript 'Redemption))
-> Maybe (User 'IsScript 'Redemption)
-> Maybe (User 'IsScript 'Redemption)
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (User 'IsScript 'Redemption -> Maybe (User 'IsScript 'Redemption)
forall a. a -> Maybe a
Just (User 'IsScript 'Redemption -> Maybe (User 'IsScript 'Redemption))
-> User 'IsScript 'Redemption -> Maybe (User 'IsScript 'Redemption)
forall a b. (a -> b) -> a -> b
$ script -> TxSkelRedeemer -> User 'IsScript 'Redemption
forall script (a :: UserKind).
(a ∈ '[ 'IsScript, 'IsEither], ToVScript script,
 Typeable script) =>
script -> TxSkelRedeemer -> User a 'Redemption
UserRedeemedScript script
constitution TxSkelRedeemer
emptyTxSkelRedeemer) User 'IsScript 'Redemption -> Maybe (User 'IsScript 'Redemption)
forall a. a -> Maybe a
Just)