{-# LANGUAGE UndecidableInstances #-}
{-# OPTIONS_GHC -Wno-orphans #-}

module Plutarch.Api.V2.Contexts (
  PScriptContext (PScriptContext),
  PTxInfo (PTxInfo),
  V1.PScriptPurpose (PMinting, PSpending, PRewarding, PCertifying),
) where

import Plutarch.Api.V1 qualified as V1
import Plutarch.Api.V2.Tx (PTxId, PTxInInfo, PTxOut)
import PlutusLedgerApi.V2 qualified as Plutus

import Plutarch.DataRepr (
  DerivePConstantViaData (DerivePConstantViaData),
  PDataFields,
 )

import Plutarch.Lift (
  PConstantDecl,
  PLifted,
  PUnsafeLiftDecl,
 )
import Plutarch.Prelude

-- FIXME: add PDataFields to Prelude

-- | Script context consists of the script purpose and the pending transaction info.
newtype PScriptContext (s :: S)
  = PScriptContext
      ( Term
          s
          ( PDataRecord
              '[ "txInfo" ':= PTxInfo
               , "purpose" ':= V1.PScriptPurpose
               ]
          )
      )
  deriving stock (forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall (s :: S) x. Rep (PScriptContext s) x -> PScriptContext s
forall (s :: S) x. PScriptContext s -> Rep (PScriptContext s) x
$cto :: forall (s :: S) x. Rep (PScriptContext s) x -> PScriptContext s
$cfrom :: forall (s :: S) x. PScriptContext s -> Rep (PScriptContext s) x
Generic)
  deriving anyclass (forall (s :: S). PScriptContext s -> Term s (PInner PScriptContext)
forall (s :: S) (b :: PType).
Term s (PInner PScriptContext)
-> (PScriptContext s -> Term s b) -> Term s b
forall (a :: PType).
(forall (s :: S). a s -> Term s (PInner a))
-> (forall (s :: S) (b :: PType).
    Term s (PInner a) -> (a s -> Term s b) -> Term s b)
-> PlutusType a
pmatch' :: forall (s :: S) (b :: PType).
Term s (PInner PScriptContext)
-> (PScriptContext s -> Term s b) -> Term s b
$cpmatch' :: forall (s :: S) (b :: PType).
Term s (PInner PScriptContext)
-> (PScriptContext s -> Term s b) -> Term s b
pcon' :: forall (s :: S). PScriptContext s -> Term s (PInner PScriptContext)
$cpcon' :: forall (s :: S). PScriptContext s -> Term s (PInner PScriptContext)
PlutusType, forall (s :: S).
Term s (PAsData PScriptContext) -> Term s PScriptContext
forall (s :: S). Term s PScriptContext -> Term s PData
forall (a :: PType).
(forall (s :: S). Term s (PAsData a) -> Term s a)
-> (forall (s :: S). Term s a -> Term s PData) -> PIsData a
pdataImpl :: forall (s :: S). Term s PScriptContext -> Term s PData
$cpdataImpl :: forall (s :: S). Term s PScriptContext -> Term s PData
pfromDataImpl :: forall (s :: S).
Term s (PAsData PScriptContext) -> Term s PScriptContext
$cpfromDataImpl :: forall (s :: S).
Term s (PAsData PScriptContext) -> Term s PScriptContext
PIsData, forall (s :: S).
Term s PScriptContext
-> Term s (PDataRecord (PFields PScriptContext))
forall (a :: PType).
(forall (s :: S). Term s a -> Term s (PDataRecord (PFields a)))
-> PDataFields a
ptoFields :: forall (s :: S).
Term s PScriptContext
-> Term s (PDataRecord (PFields PScriptContext))
$cptoFields :: forall (s :: S).
Term s PScriptContext
-> Term s (PDataRecord (PFields PScriptContext))
PDataFields, forall (s :: S).
Term s PScriptContext -> Term s PScriptContext -> Term s PBool
forall (t :: PType).
(forall (s :: S). Term s t -> Term s t -> Term s PBool) -> PEq t
#== :: forall (s :: S).
Term s PScriptContext -> Term s PScriptContext -> Term s PBool
$c#== :: forall (s :: S).
Term s PScriptContext -> Term s PScriptContext -> Term s PBool
PEq, forall (s :: S). Bool -> Term s PScriptContext -> Term s PString
forall (t :: PType).
(forall (s :: S). Bool -> Term s t -> Term s PString) -> PShow t
pshow' :: forall (s :: S). Bool -> Term s PScriptContext -> Term s PString
$cpshow' :: forall (s :: S). Bool -> Term s PScriptContext -> Term s PString
PShow)

instance DerivePlutusType PScriptContext where type DPTStrat _ = PlutusTypeData

instance PUnsafeLiftDecl PScriptContext where type PLifted _ = Plutus.ScriptContext
deriving via (DerivePConstantViaData Plutus.ScriptContext PScriptContext) instance PConstantDecl Plutus.ScriptContext

-- | A pending transaction. This is the view as seen by the validator script.
newtype PTxInfo (s :: S)
  = PTxInfo
      ( Term
          s
          ( PDataRecord
              '[ "inputs" ':= PBuiltinList PTxInInfo -- Transaction inputs
               , "referenceInputs" ':= PBuiltinList PTxInInfo
               , "outputs" ':= PBuiltinList PTxOut -- Transaction outputs
               , "fee" ':= V1.PValue 'V1.Sorted 'V1.Positive -- The fee paid by this transaction.
               , "mint" ':= V1.PValue 'V1.Sorted 'V1.NoGuarantees -- The value minted by the transaction.
               , "dcert" ':= PBuiltinList V1.PDCert -- Digests of the certificates included in this transaction.
               , "wdrl" ':= V1.PMap 'V1.Unsorted V1.PStakingCredential PInteger -- Staking withdrawals
               , "validRange" ':= V1.PPOSIXTimeRange -- The valid range for the transaction.
               , "signatories" ':= PBuiltinList (PAsData V1.PPubKeyHash) -- Signatories attesting that they all signed the tx.
               , "redeemers" ':= V1.PMap 'V1.Unsorted V1.PScriptPurpose V1.PRedeemer
               , "datums" ':= V1.PMap 'V1.Unsorted V1.PDatumHash V1.PDatum
               , "id" ':= PTxId -- The hash of the pending transaction.
               ]
          )
      )
  deriving stock (forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall (s :: S) x. Rep (PTxInfo s) x -> PTxInfo s
forall (s :: S) x. PTxInfo s -> Rep (PTxInfo s) x
$cto :: forall (s :: S) x. Rep (PTxInfo s) x -> PTxInfo s
$cfrom :: forall (s :: S) x. PTxInfo s -> Rep (PTxInfo s) x
Generic)
  deriving anyclass (forall (s :: S). PTxInfo s -> Term s (PInner PTxInfo)
forall (s :: S) (b :: PType).
Term s (PInner PTxInfo) -> (PTxInfo s -> Term s b) -> Term s b
forall (a :: PType).
(forall (s :: S). a s -> Term s (PInner a))
-> (forall (s :: S) (b :: PType).
    Term s (PInner a) -> (a s -> Term s b) -> Term s b)
-> PlutusType a
pmatch' :: forall (s :: S) (b :: PType).
Term s (PInner PTxInfo) -> (PTxInfo s -> Term s b) -> Term s b
$cpmatch' :: forall (s :: S) (b :: PType).
Term s (PInner PTxInfo) -> (PTxInfo s -> Term s b) -> Term s b
pcon' :: forall (s :: S). PTxInfo s -> Term s (PInner PTxInfo)
$cpcon' :: forall (s :: S). PTxInfo s -> Term s (PInner PTxInfo)
PlutusType, forall (s :: S). Term s (PAsData PTxInfo) -> Term s PTxInfo
forall (s :: S). Term s PTxInfo -> Term s PData
forall (a :: PType).
(forall (s :: S). Term s (PAsData a) -> Term s a)
-> (forall (s :: S). Term s a -> Term s PData) -> PIsData a
pdataImpl :: forall (s :: S). Term s PTxInfo -> Term s PData
$cpdataImpl :: forall (s :: S). Term s PTxInfo -> Term s PData
pfromDataImpl :: forall (s :: S). Term s (PAsData PTxInfo) -> Term s PTxInfo
$cpfromDataImpl :: forall (s :: S). Term s (PAsData PTxInfo) -> Term s PTxInfo
PIsData, forall (s :: S).
Term s PTxInfo -> Term s (PDataRecord (PFields PTxInfo))
forall (a :: PType).
(forall (s :: S). Term s a -> Term s (PDataRecord (PFields a)))
-> PDataFields a
ptoFields :: forall (s :: S).
Term s PTxInfo -> Term s (PDataRecord (PFields PTxInfo))
$cptoFields :: forall (s :: S).
Term s PTxInfo -> Term s (PDataRecord (PFields PTxInfo))
PDataFields, forall (s :: S). Term s PTxInfo -> Term s PTxInfo -> Term s PBool
forall (t :: PType).
(forall (s :: S). Term s t -> Term s t -> Term s PBool) -> PEq t
#== :: forall (s :: S). Term s PTxInfo -> Term s PTxInfo -> Term s PBool
$c#== :: forall (s :: S). Term s PTxInfo -> Term s PTxInfo -> Term s PBool
PEq, forall (s :: S). Bool -> Term s PTxInfo -> Term s PString
forall (t :: PType).
(forall (s :: S). Bool -> Term s t -> Term s PString) -> PShow t
pshow' :: forall (s :: S). Bool -> Term s PTxInfo -> Term s PString
$cpshow' :: forall (s :: S). Bool -> Term s PTxInfo -> Term s PString
PShow)

instance DerivePlutusType PTxInfo where type DPTStrat _ = PlutusTypeData

instance PUnsafeLiftDecl PTxInfo where type PLifted _ = Plutus.TxInfo
deriving via (DerivePConstantViaData Plutus.TxInfo PTxInfo) instance PConstantDecl Plutus.TxInfo