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

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

import PlutusLedgerApi.V1 qualified as Plutus

import Plutarch.Api.V1.Address (
  PStakingCredential,
 )
import Plutarch.Api.V1.Crypto (PPubKeyHash)
import Plutarch.Api.V1.DCert (PDCert)
import Plutarch.Api.V1.Scripts (PDatum, PDatumHash)
import Plutarch.Api.V1.Time (PPOSIXTimeRange)
import Plutarch.Api.V1.Tuple (PTuple)
import Plutarch.Api.V1.Tx (PTxId, PTxInInfo, PTxOut, PTxOutRef)
import Plutarch.Api.V1.Value (
  AmountGuarantees (NoGuarantees, Positive),
  KeyGuarantees (Sorted),
  PCurrencySymbol,
  PValue,
 )
import Plutarch.DataRepr (
  DerivePConstantViaData (DerivePConstantViaData),
  PDataFields,
 )
import Plutarch.Lift (
  PConstantDecl,
  PLifted,
  PUnsafeLiftDecl,
 )
import Plutarch.Prelude

-- | 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
               , "outputs" ':= PBuiltinList PTxOut -- Transaction outputs
               , "fee" ':= PValue 'Sorted 'Positive -- The fee paid by this transaction.
               , "mint" ':= PValue 'Sorted 'NoGuarantees -- The value minted by the transaction.
               , "dcert" ':= PBuiltinList PDCert -- Digests of the certificates included in this transaction.
               , "wdrl" ':= PBuiltinList (PAsData (PTuple PStakingCredential PInteger)) -- Staking withdrawals
               , "validRange" ':= PPOSIXTimeRange -- The valid range for the transaction.
               , "signatories" ':= PBuiltinList (PAsData PPubKeyHash) -- Signatories attesting that they all signed the tx.
               , "datums" ':= PBuiltinList (PAsData (PTuple PDatumHash 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 PTxInfo = Plutus.TxInfo
deriving via (DerivePConstantViaData Plutus.TxInfo PTxInfo) instance PConstantDecl Plutus.TxInfo

-- | Script context consists of the script purpose and the pending transaction info.
newtype PScriptContext (s :: S)
  = PScriptContext
      ( Term
          s
          ( PDataRecord
              '[ "txInfo" ':= PTxInfo
               , "purpose" ':= 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 PScriptContext = Plutus.ScriptContext
deriving via (DerivePConstantViaData Plutus.ScriptContext PScriptContext) instance PConstantDecl Plutus.ScriptContext

-- General types, used by V1 and V2

-- | The purpose of the script that is currently running
data PScriptPurpose (s :: S)
  = PMinting (Term s (PDataRecord '["_0" ':= PCurrencySymbol]))
  | PSpending (Term s (PDataRecord '["_0" ':= PTxOutRef]))
  | PRewarding (Term s (PDataRecord '["_0" ':= PStakingCredential]))
  | PCertifying (Term s (PDataRecord '["_0" ':= PDCert]))
  deriving stock (forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall (s :: S) x. Rep (PScriptPurpose s) x -> PScriptPurpose s
forall (s :: S) x. PScriptPurpose s -> Rep (PScriptPurpose s) x
$cto :: forall (s :: S) x. Rep (PScriptPurpose s) x -> PScriptPurpose s
$cfrom :: forall (s :: S) x. PScriptPurpose s -> Rep (PScriptPurpose s) x
Generic)
  deriving anyclass (forall (s :: S). PScriptPurpose s -> Term s (PInner PScriptPurpose)
forall (s :: S) (b :: PType).
Term s (PInner PScriptPurpose)
-> (PScriptPurpose 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 PScriptPurpose)
-> (PScriptPurpose s -> Term s b) -> Term s b
$cpmatch' :: forall (s :: S) (b :: PType).
Term s (PInner PScriptPurpose)
-> (PScriptPurpose s -> Term s b) -> Term s b
pcon' :: forall (s :: S). PScriptPurpose s -> Term s (PInner PScriptPurpose)
$cpcon' :: forall (s :: S). PScriptPurpose s -> Term s (PInner PScriptPurpose)
PlutusType, forall (s :: S).
Term s (PAsData PScriptPurpose) -> Term s PScriptPurpose
forall (s :: S). Term s PScriptPurpose -> 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 PScriptPurpose -> Term s PData
$cpdataImpl :: forall (s :: S). Term s PScriptPurpose -> Term s PData
pfromDataImpl :: forall (s :: S).
Term s (PAsData PScriptPurpose) -> Term s PScriptPurpose
$cpfromDataImpl :: forall (s :: S).
Term s (PAsData PScriptPurpose) -> Term s PScriptPurpose
PIsData, forall (s :: S).
Term s PScriptPurpose -> Term s PScriptPurpose -> 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 PScriptPurpose -> Term s PScriptPurpose -> Term s PBool
$c#== :: forall (s :: S).
Term s PScriptPurpose -> Term s PScriptPurpose -> Term s PBool
PEq, forall (s :: S). Bool -> Term s PScriptPurpose -> 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 PScriptPurpose -> Term s PString
$cpshow' :: forall (s :: S). Bool -> Term s PScriptPurpose -> Term s PString
PShow)

instance DerivePlutusType PScriptPurpose where type DPTStrat _ = PlutusTypeData

instance PUnsafeLiftDecl PScriptPurpose where type PLifted PScriptPurpose = Plutus.ScriptPurpose
deriving via (DerivePConstantViaData Plutus.ScriptPurpose PScriptPurpose) instance PConstantDecl Plutus.ScriptPurpose