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

module Plutarch.Api.V2.Tx (
  V1.PTxOutRef (PTxOutRef),
  PTxOut (PTxOut),
  V1.PTxId (PTxId),
  PTxInInfo (PTxInInfo),
  POutputDatum (POutputDatumHash, PNoOutputDatum, POutputDatum),
) where

import Plutarch.Api.V1.Address qualified as V1
import Plutarch.Api.V1.Maybe qualified as V1
import Plutarch.Api.V1.Scripts qualified as V1
import Plutarch.Api.V1.Tx qualified as V1
import Plutarch.Api.V1.Value qualified as V1
import Plutarch.DataRepr (
  DerivePConstantViaData (DerivePConstantViaData),
  PDataFields,
 )
import Plutarch.Lift (
  PConstantDecl,
  PLifted,
  PUnsafeLiftDecl,
 )
import Plutarch.Prelude
import PlutusLedgerApi.V2 qualified as Plutus

-- | A transaction output. This consists of a target address, value and maybe a datum hash
newtype PTxOut (s :: S)
  = PTxOut
      ( Term
          s
          ( PDataRecord
              '[ "address" ':= V1.PAddress
               , -- negative values may appear in a future Cardano version
                 "value" ':= V1.PValue 'V1.Sorted 'V1.Positive
               , "datum" ':= POutputDatum
               , "referenceScript" ':= V1.PMaybeData V1.PScriptHash
               ]
          )
      )
  deriving stock (forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall (s :: S) x. Rep (PTxOut s) x -> PTxOut s
forall (s :: S) x. PTxOut s -> Rep (PTxOut s) x
$cto :: forall (s :: S) x. Rep (PTxOut s) x -> PTxOut s
$cfrom :: forall (s :: S) x. PTxOut s -> Rep (PTxOut s) x
Generic)
  deriving anyclass (forall (s :: S). PTxOut s -> Term s (PInner PTxOut)
forall (s :: S) (b :: PType).
Term s (PInner PTxOut) -> (PTxOut 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 PTxOut) -> (PTxOut s -> Term s b) -> Term s b
$cpmatch' :: forall (s :: S) (b :: PType).
Term s (PInner PTxOut) -> (PTxOut s -> Term s b) -> Term s b
pcon' :: forall (s :: S). PTxOut s -> Term s (PInner PTxOut)
$cpcon' :: forall (s :: S). PTxOut s -> Term s (PInner PTxOut)
PlutusType, forall (s :: S). Term s (PAsData PTxOut) -> Term s PTxOut
forall (s :: S). Term s PTxOut -> 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 PTxOut -> Term s PData
$cpdataImpl :: forall (s :: S). Term s PTxOut -> Term s PData
pfromDataImpl :: forall (s :: S). Term s (PAsData PTxOut) -> Term s PTxOut
$cpfromDataImpl :: forall (s :: S). Term s (PAsData PTxOut) -> Term s PTxOut
PIsData, forall (s :: S).
Term s PTxOut -> Term s (PDataRecord (PFields PTxOut))
forall (a :: PType).
(forall (s :: S). Term s a -> Term s (PDataRecord (PFields a)))
-> PDataFields a
ptoFields :: forall (s :: S).
Term s PTxOut -> Term s (PDataRecord (PFields PTxOut))
$cptoFields :: forall (s :: S).
Term s PTxOut -> Term s (PDataRecord (PFields PTxOut))
PDataFields, forall (s :: S). Term s PTxOut -> Term s PTxOut -> 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 PTxOut -> Term s PTxOut -> Term s PBool
$c#== :: forall (s :: S). Term s PTxOut -> Term s PTxOut -> Term s PBool
PEq, forall (s :: S). Bool -> Term s PTxOut -> 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 PTxOut -> Term s PString
$cpshow' :: forall (s :: S). Bool -> Term s PTxOut -> Term s PString
PShow)

instance DerivePlutusType PTxOut where type DPTStrat _ = PlutusTypeData

instance PUnsafeLiftDecl PTxOut where type PLifted PTxOut = Plutus.TxOut
deriving via (DerivePConstantViaData Plutus.TxOut PTxOut) instance PConstantDecl Plutus.TxOut

-- | A input of the pending transaction.
newtype PTxInInfo (s :: S)
  = PTxInInfo
      ( Term
          s
          ( PDataRecord
              '[ "outRef" ':= V1.PTxOutRef
               , "resolved" ':= PTxOut
               ]
          )
      )
  deriving stock (forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall (s :: S) x. Rep (PTxInInfo s) x -> PTxInInfo s
forall (s :: S) x. PTxInInfo s -> Rep (PTxInInfo s) x
$cto :: forall (s :: S) x. Rep (PTxInInfo s) x -> PTxInInfo s
$cfrom :: forall (s :: S) x. PTxInInfo s -> Rep (PTxInInfo s) x
Generic)
  deriving anyclass (forall (s :: S). PTxInInfo s -> Term s (PInner PTxInInfo)
forall (s :: S) (b :: PType).
Term s (PInner PTxInInfo) -> (PTxInInfo 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 PTxInInfo) -> (PTxInInfo s -> Term s b) -> Term s b
$cpmatch' :: forall (s :: S) (b :: PType).
Term s (PInner PTxInInfo) -> (PTxInInfo s -> Term s b) -> Term s b
pcon' :: forall (s :: S). PTxInInfo s -> Term s (PInner PTxInInfo)
$cpcon' :: forall (s :: S). PTxInInfo s -> Term s (PInner PTxInInfo)
PlutusType, forall (s :: S). Term s (PAsData PTxInInfo) -> Term s PTxInInfo
forall (s :: S). Term s PTxInInfo -> 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 PTxInInfo -> Term s PData
$cpdataImpl :: forall (s :: S). Term s PTxInInfo -> Term s PData
pfromDataImpl :: forall (s :: S). Term s (PAsData PTxInInfo) -> Term s PTxInInfo
$cpfromDataImpl :: forall (s :: S). Term s (PAsData PTxInInfo) -> Term s PTxInInfo
PIsData, forall (s :: S).
Term s PTxInInfo -> Term s (PDataRecord (PFields PTxInInfo))
forall (a :: PType).
(forall (s :: S). Term s a -> Term s (PDataRecord (PFields a)))
-> PDataFields a
ptoFields :: forall (s :: S).
Term s PTxInInfo -> Term s (PDataRecord (PFields PTxInInfo))
$cptoFields :: forall (s :: S).
Term s PTxInInfo -> Term s (PDataRecord (PFields PTxInInfo))
PDataFields, forall (s :: S).
Term s PTxInInfo -> Term s PTxInInfo -> 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 PTxInInfo -> Term s PTxInInfo -> Term s PBool
$c#== :: forall (s :: S).
Term s PTxInInfo -> Term s PTxInInfo -> Term s PBool
PEq, forall (s :: S). Bool -> Term s PTxInInfo -> 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 PTxInInfo -> Term s PString
$cpshow' :: forall (s :: S). Bool -> Term s PTxInInfo -> Term s PString
PShow)

instance DerivePlutusType PTxInInfo where type DPTStrat _ = PlutusTypeData

instance PUnsafeLiftDecl PTxInInfo where type PLifted PTxInInfo = Plutus.TxInInfo
deriving via (DerivePConstantViaData Plutus.TxInInfo PTxInInfo) instance PConstantDecl Plutus.TxInInfo

-- | The datum attached to an output: either nothing, a datum hash or an inline datum (CIP 32)
data POutputDatum (s :: S)
  = PNoOutputDatum (Term s (PDataRecord '[]))
  | POutputDatumHash (Term s (PDataRecord '["datumHash" ':= V1.PDatumHash]))
  | POutputDatum (Term s (PDataRecord '["outputDatum" ':= V1.PDatum]))
  deriving stock (forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall (s :: S) x. Rep (POutputDatum s) x -> POutputDatum s
forall (s :: S) x. POutputDatum s -> Rep (POutputDatum s) x
$cto :: forall (s :: S) x. Rep (POutputDatum s) x -> POutputDatum s
$cfrom :: forall (s :: S) x. POutputDatum s -> Rep (POutputDatum s) x
Generic)
  deriving anyclass (forall (s :: S). POutputDatum s -> Term s (PInner POutputDatum)
forall (s :: S) (b :: PType).
Term s (PInner POutputDatum)
-> (POutputDatum 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 POutputDatum)
-> (POutputDatum s -> Term s b) -> Term s b
$cpmatch' :: forall (s :: S) (b :: PType).
Term s (PInner POutputDatum)
-> (POutputDatum s -> Term s b) -> Term s b
pcon' :: forall (s :: S). POutputDatum s -> Term s (PInner POutputDatum)
$cpcon' :: forall (s :: S). POutputDatum s -> Term s (PInner POutputDatum)
PlutusType, forall (s :: S).
Term s (PAsData POutputDatum) -> Term s POutputDatum
forall (s :: S). Term s POutputDatum -> 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 POutputDatum -> Term s PData
$cpdataImpl :: forall (s :: S). Term s POutputDatum -> Term s PData
pfromDataImpl :: forall (s :: S).
Term s (PAsData POutputDatum) -> Term s POutputDatum
$cpfromDataImpl :: forall (s :: S).
Term s (PAsData POutputDatum) -> Term s POutputDatum
PIsData, forall (s :: S).
Term s POutputDatum -> Term s POutputDatum -> 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 POutputDatum -> Term s POutputDatum -> Term s PBool
$c#== :: forall (s :: S).
Term s POutputDatum -> Term s POutputDatum -> Term s PBool
PEq, forall (s :: S). Bool -> Term s POutputDatum -> 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 POutputDatum -> Term s PString
$cpshow' :: forall (s :: S). Bool -> Term s POutputDatum -> Term s PString
PShow)

instance DerivePlutusType POutputDatum where type DPTStrat _ = PlutusTypeData

instance PUnsafeLiftDecl POutputDatum where type PLifted POutputDatum = Plutus.OutputDatum
deriving via (DerivePConstantViaData Plutus.OutputDatum POutputDatum) instance PConstantDecl Plutus.OutputDatum