{-# LANGUAGE DerivingVia       #-}
{-# LANGUAGE NamedFieldPuns    #-}
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE PatternSynonyms   #-}
{-# LANGUAGE TemplateHaskell   #-}
{-# LANGUAGE ViewPatterns      #-}
{-# OPTIONS_GHC -Wno-simplifiable-class-constraints #-}
{-# OPTIONS_GHC -fexpose-all-unfoldings #-} -- needed for asData pattern synonyms
{-# OPTIONS_GHC -fno-omit-interface-pragmas #-}
{-# OPTIONS_GHC -fno-specialise #-}
{-# OPTIONS_GHC -fno-strictness #-}

module PlutusLedgerApi.V2.Data.Contexts (
  -- * Pending transactions and related types
  TxInfo,
  pattern TxInfo,
  txInfoInputs,
  txInfoReferenceInputs,
  txInfoOutputs,
  txInfoFee,
  txInfoMint,
  txInfoDCert,
  txInfoWdrl,
  txInfoValidRange,
  txInfoSignatories,
  txInfoRedeemers,
  txInfoData,
  txInfoId,
  ScriptContext,
  pattern ScriptContext,
  scriptContextTxInfo,
  scriptContextPurpose,
  ScriptPurpose,
  pattern Minting,
  pattern Spending,
  pattern Rewarding,
  pattern Certifying,
  TxId (..),
  TxOut,
  pattern TxOut,
  txOutAddress,
  txOutValue,
  txOutDatum,
  txOutReferenceScript,
  TxOutRef,
  pattern TxOutRef,
  txOutRefId,
  txOutRefIdx,
  TxInInfo,
  pattern TxInInfo,
  txInInfoOutRef,
  txInInfoResolved,
  findOwnInput,
  findDatum,
  findDatumHash,
  findTxInByTxOutRef,
  findContinuingOutputs,
  getContinuingOutputs,

  -- * Validator functions
  pubKeyOutputsAt,
  valuePaidTo,
  spendsOutput,
  txSignedBy,
  valueSpent,
  valueProduced,
  ownCurrencySymbol,
) where

import GHC.Generics (Generic)
import PlutusTx
import PlutusTx.AsData qualified as PlutusTx
import PlutusTx.Data.AssocMap hiding (any)
import PlutusTx.Data.List (List)
import PlutusTx.Data.List qualified as Data.List
import PlutusTx.Prelude hiding (toList)
import Prettyprinter (Pretty (..), nest, vsep, (<+>))

import PlutusLedgerApi.V1.Crypto (PubKeyHash (..))
import PlutusLedgerApi.V1.Data.Address (pattern Address)
import PlutusLedgerApi.V1.Data.Contexts (ScriptPurpose, pattern Certifying, pattern Minting,
                                         pattern Rewarding, pattern Spending)
import PlutusLedgerApi.V1.Data.Credential (StakingCredential, pattern PubKeyCredential)
import PlutusLedgerApi.V1.Data.DCert (DCert)
import PlutusLedgerApi.V1.Data.Time (POSIXTimeRange)
import PlutusLedgerApi.V1.Data.Value (CurrencySymbol, Value)
import PlutusLedgerApi.V1.Scripts
import PlutusLedgerApi.V2.Data.Tx (TxId (..), TxOut, TxOutRef, pattern TxOut, pattern TxOutRef,
                                   txOutAddress, txOutDatum, txOutRefId, txOutRefIdx,
                                   txOutReferenceScript, txOutValue)

import Prelude qualified as Haskell

-- | An input of a pending transaction.
PlutusTx.asData
  [d|
    data TxInInfo = TxInInfo
      { txInInfoOutRef   :: TxOutRef
      , txInInfoResolved :: TxOut
      }
      deriving stock (Generic, Haskell.Show, Haskell.Eq)
      deriving newtype (PlutusTx.FromData, PlutusTx.UnsafeFromData, PlutusTx.ToData)
  |]

makeLift ''TxInInfo

instance Eq TxInInfo where
  TxInInfo TxOutRef
ref TxOut
res == :: TxInInfo -> TxInInfo -> Bool
== TxInInfo TxOutRef
ref' TxOut
res' = TxOutRef
ref TxOutRef -> TxOutRef -> Bool
forall a. Eq a => a -> a -> Bool
== TxOutRef
ref' Bool -> Bool -> Bool
&& TxOut
res TxOut -> TxOut -> Bool
forall a. Eq a => a -> a -> Bool
== TxOut
res'

instance Pretty TxInInfo where
  pretty :: forall ann. TxInInfo -> Doc ann
pretty TxInInfo{TxOutRef
txInInfoOutRef :: TxInInfo -> TxOutRef
txInInfoOutRef :: TxOutRef
txInInfoOutRef, TxOut
txInInfoResolved :: TxInInfo -> TxOut
txInInfoResolved :: TxOut
txInInfoResolved} =
    TxOutRef -> Doc ann
forall ann. TxOutRef -> Doc ann
forall a ann. Pretty a => a -> Doc ann
pretty TxOutRef
txInInfoOutRef Doc ann -> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann -> Doc ann
<+> Doc ann
"->" Doc ann -> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann -> Doc ann
<+> TxOut -> Doc ann
forall ann. TxOut -> Doc ann
forall a ann. Pretty a => a -> Doc ann
pretty TxOut
txInInfoResolved

{-| A pending transaction. This is the view as seen by validator scripts,
so some details are stripped out.
-}
PlutusTx.asData
  [d|
    data TxInfo = TxInfo
      { txInfoInputs          :: List TxInInfo
      -- ^ Transaction inputs; cannot be an empty list
      , txInfoReferenceInputs :: List TxInInfo
      -- ^ /Added in V2:/ Transaction reference inputs
      , txInfoOutputs         :: List TxOut
      -- ^ Transaction outputs
      , txInfoFee             :: Value
      -- ^ The fee paid by this transaction.
      , txInfoMint            :: Value
      -- ^ The 'Value' minted by this transaction.
      , txInfoDCert           :: List DCert
      -- ^ Digests of certificates included in this transaction
      , txInfoWdrl            :: Map StakingCredential Integer
      -- ^ Withdrawals
      -- /V1->V2/: changed from assoc list to a 'PlutusTx.AssocMap'
      , txInfoValidRange      :: POSIXTimeRange
      -- ^ The valid range for the transaction.
      , txInfoSignatories     :: List PubKeyHash
      -- ^ Signatures provided with the transaction, attested that they all signed the tx
      , txInfoRedeemers       :: Map ScriptPurpose Redeemer
      -- ^ /Added in V2:/ a table of redeemers attached to the transaction
      , txInfoData            :: Map DatumHash Datum
      -- ^ The lookup table of datums attached to the transaction
      -- /V1->V2/: changed from assoc list to a 'PlutusTx.AssocMap'
      , txInfoId              :: TxId
      -- ^ Hash of the pending transaction body (i.e. transaction excluding witnesses)
      }
      deriving stock (Generic, Haskell.Show)
      deriving newtype (PlutusTx.FromData, PlutusTx.UnsafeFromData, PlutusTx.ToData)
  |]

makeLift ''TxInfo

instance Pretty TxInfo where
  pretty :: forall ann. TxInfo -> Doc ann
pretty
    TxInfo
      { List TxInInfo
txInfoInputs :: TxInfo -> List TxInInfo
txInfoInputs :: List TxInInfo
txInfoInputs
      , List TxInInfo
txInfoReferenceInputs :: TxInfo -> List TxInInfo
txInfoReferenceInputs :: List TxInInfo
txInfoReferenceInputs
      , List TxOut
txInfoOutputs :: TxInfo -> List TxOut
txInfoOutputs :: List TxOut
txInfoOutputs
      , Value
txInfoFee :: TxInfo -> Value
txInfoFee :: Value
txInfoFee
      , Value
txInfoMint :: TxInfo -> Value
txInfoMint :: Value
txInfoMint
      , List DCert
txInfoDCert :: TxInfo -> List DCert
txInfoDCert :: List DCert
txInfoDCert
      , Map StakingCredential Integer
txInfoWdrl :: TxInfo -> Map StakingCredential Integer
txInfoWdrl :: Map StakingCredential Integer
txInfoWdrl
      , POSIXTimeRange
txInfoValidRange :: TxInfo -> POSIXTimeRange
txInfoValidRange :: POSIXTimeRange
txInfoValidRange
      , List PubKeyHash
txInfoSignatories :: TxInfo -> List PubKeyHash
txInfoSignatories :: List PubKeyHash
txInfoSignatories
      , Map ScriptPurpose Redeemer
txInfoRedeemers :: TxInfo -> Map ScriptPurpose Redeemer
txInfoRedeemers :: Map ScriptPurpose Redeemer
txInfoRedeemers
      , Map DatumHash Datum
txInfoData :: TxInfo -> Map DatumHash Datum
txInfoData :: Map DatumHash Datum
txInfoData
      , TxId
txInfoId :: TxInfo -> TxId
txInfoId :: TxId
txInfoId
      } =
      [Doc ann] -> Doc ann
forall ann. [Doc ann] -> Doc ann
vsep
        [ Doc ann
"TxId:" Doc ann -> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann -> Doc ann
<+> TxId -> Doc ann
forall a ann. Pretty a => a -> Doc ann
forall ann. TxId -> Doc ann
pretty TxId
txInfoId
        , Doc ann
"Inputs:" Doc ann -> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann -> Doc ann
<+> List TxInInfo -> Doc ann
forall a ann. Pretty a => a -> Doc ann
forall ann. List TxInInfo -> Doc ann
pretty List TxInInfo
txInfoInputs
        , Doc ann
"Reference inputs:" Doc ann -> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann -> Doc ann
<+> List TxInInfo -> Doc ann
forall a ann. Pretty a => a -> Doc ann
forall ann. List TxInInfo -> Doc ann
pretty List TxInInfo
txInfoReferenceInputs
        , Doc ann
"Outputs:" Doc ann -> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann -> Doc ann
<+> List TxOut -> Doc ann
forall a ann. Pretty a => a -> Doc ann
forall ann. List TxOut -> Doc ann
pretty List TxOut
txInfoOutputs
        , Doc ann
"Fee:" Doc ann -> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann -> Doc ann
<+> Value -> Doc ann
forall a ann. Pretty a => a -> Doc ann
forall ann. Value -> Doc ann
pretty Value
txInfoFee
        , Doc ann
"Value minted:" Doc ann -> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann -> Doc ann
<+> Value -> Doc ann
forall a ann. Pretty a => a -> Doc ann
forall ann. Value -> Doc ann
pretty Value
txInfoMint
        , Doc ann
"DCerts:" Doc ann -> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann -> Doc ann
<+> List DCert -> Doc ann
forall a ann. Pretty a => a -> Doc ann
forall ann. List DCert -> Doc ann
pretty List DCert
txInfoDCert
        , Doc ann
"Wdrl:" Doc ann -> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann -> Doc ann
<+> Map StakingCredential Integer -> Doc ann
forall a ann. Pretty a => a -> Doc ann
forall ann. Map StakingCredential Integer -> Doc ann
pretty Map StakingCredential Integer
txInfoWdrl
        , Doc ann
"Valid range:" Doc ann -> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann -> Doc ann
<+> POSIXTimeRange -> Doc ann
forall ann. POSIXTimeRange -> Doc ann
forall a ann. Pretty a => a -> Doc ann
pretty POSIXTimeRange
txInfoValidRange
        , Doc ann
"Signatories:" Doc ann -> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann -> Doc ann
<+> List PubKeyHash -> Doc ann
forall a ann. Pretty a => a -> Doc ann
forall ann. List PubKeyHash -> Doc ann
pretty List PubKeyHash
txInfoSignatories
        , Doc ann
"Redeemers:" Doc ann -> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann -> Doc ann
<+> Map ScriptPurpose Redeemer -> Doc ann
forall a ann. Pretty a => a -> Doc ann
forall ann. Map ScriptPurpose Redeemer -> Doc ann
pretty Map ScriptPurpose Redeemer
txInfoRedeemers
        , Doc ann
"Datums:" Doc ann -> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann -> Doc ann
<+> Map DatumHash Datum -> Doc ann
forall a ann. Pretty a => a -> Doc ann
forall ann. Map DatumHash Datum -> Doc ann
pretty Map DatumHash Datum
txInfoData
        ]

-- | The context that the currently-executing script can access.
PlutusTx.asData
  [d|
    data ScriptContext = ScriptContext
      { scriptContextTxInfo  :: TxInfo
      -- ^ information about the transaction the currently-executing script is included in
      , scriptContextPurpose :: ScriptPurpose
      -- ^ the purpose of the currently-executing script
      }
      deriving stock (Generic, Haskell.Show)
      deriving newtype (PlutusTx.FromData, PlutusTx.UnsafeFromData, PlutusTx.ToData)
  |]

makeLift ''ScriptContext

instance Pretty ScriptContext where
  pretty :: forall ann. ScriptContext -> Doc ann
pretty ScriptContext{TxInfo
scriptContextTxInfo :: ScriptContext -> TxInfo
scriptContextTxInfo :: TxInfo
scriptContextTxInfo, ScriptPurpose
scriptContextPurpose :: ScriptContext -> ScriptPurpose
scriptContextPurpose :: ScriptPurpose
scriptContextPurpose} =
    [Doc ann] -> Doc ann
forall ann. [Doc ann] -> Doc ann
vsep
      [ Doc ann
"Purpose:" Doc ann -> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann -> Doc ann
<+> ScriptPurpose -> Doc ann
forall ann. ScriptPurpose -> Doc ann
forall a ann. Pretty a => a -> Doc ann
pretty ScriptPurpose
scriptContextPurpose
      , Int -> Doc ann -> Doc ann
forall ann. Int -> Doc ann -> Doc ann
nest Int
2 (Doc ann -> Doc ann) -> Doc ann -> Doc ann
forall a b. (a -> b) -> a -> b
$ [Doc ann] -> Doc ann
forall ann. [Doc ann] -> Doc ann
vsep [Doc ann
"TxInfo:", TxInfo -> Doc ann
forall ann. TxInfo -> Doc ann
forall a ann. Pretty a => a -> Doc ann
pretty TxInfo
scriptContextTxInfo]
      ]

-- | Find the input currently being validated.
findOwnInput :: ScriptContext -> Maybe TxInInfo
findOwnInput :: ScriptContext -> Maybe TxInInfo
findOwnInput
  ScriptContext
    { scriptContextTxInfo :: ScriptContext -> TxInfo
scriptContextTxInfo = TxInfo{List TxInInfo
txInfoInputs :: TxInfo -> List TxInInfo
txInfoInputs :: List TxInInfo
txInfoInputs}
    , scriptContextPurpose :: ScriptContext -> ScriptPurpose
scriptContextPurpose = Spending TxOutRef
txOutRef
    } =
    (TxInInfo -> Bool) -> List TxInInfo -> Maybe TxInInfo
forall a. UnsafeFromData a => (a -> Bool) -> List a -> Maybe a
Data.List.find
      (\TxInInfo{TxOutRef
txInInfoOutRef :: TxInInfo -> TxOutRef
txInInfoOutRef :: TxOutRef
txInInfoOutRef} -> TxOutRef
txInInfoOutRef TxOutRef -> TxOutRef -> Bool
forall a. Eq a => a -> a -> Bool
== TxOutRef
txOutRef)
      List TxInInfo
txInfoInputs
findOwnInput ScriptContext
_ = Maybe TxInInfo
forall a. Maybe a
Nothing
{-# INLINEABLE findOwnInput #-}

-- | Find the data corresponding to a data hash, if there is one
findDatum :: DatumHash -> TxInfo -> Maybe Datum
findDatum :: DatumHash -> TxInfo -> Maybe Datum
findDatum DatumHash
dsh TxInfo{Map DatumHash Datum
txInfoData :: TxInfo -> Map DatumHash Datum
txInfoData :: Map DatumHash Datum
txInfoData} = DatumHash -> Map DatumHash Datum -> Maybe Datum
forall k a. (ToData k, UnsafeFromData a) => k -> Map k a -> Maybe a
lookup DatumHash
dsh Map DatumHash Datum
txInfoData
{-# INLINEABLE findDatum #-}

{-| Find the hash of a datum, if it is part of the pending transaction's
hashes
-}
findDatumHash :: Datum -> TxInfo -> Maybe DatumHash
findDatumHash :: Datum -> TxInfo -> Maybe DatumHash
findDatumHash Datum
ds TxInfo{Map DatumHash Datum
txInfoData :: TxInfo -> Map DatumHash Datum
txInfoData :: Map DatumHash Datum
txInfoData} = (DatumHash, Datum) -> DatumHash
forall a b. (a, b) -> a
fst ((DatumHash, Datum) -> DatumHash)
-> Maybe (DatumHash, Datum) -> Maybe DatumHash
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ((DatumHash, Datum) -> Bool)
-> [(DatumHash, Datum)] -> Maybe (DatumHash, Datum)
forall a. (a -> Bool) -> [a] -> Maybe a
find (DatumHash, Datum) -> Bool
forall {a}. (a, Datum) -> Bool
f (Map DatumHash Datum -> [(DatumHash, Datum)]
forall k a.
(UnsafeFromData k, UnsafeFromData a) =>
Map k a -> [(k, a)]
toList Map DatumHash Datum
txInfoData)
 where
  f :: (a, Datum) -> Bool
f (a
_, Datum
ds') = Datum
ds' Datum -> Datum -> Bool
forall a. Eq a => a -> a -> Bool
== Datum
ds
{-# INLINEABLE findDatumHash #-}

{-| Given a UTXO reference and a transaction (`TxInfo`), resolve it to one
of the transaction's inputs (`TxInInfo`).
Note: this only searches the true transaction inputs and not the referenced
transaction inputs.
-}
findTxInByTxOutRef :: TxOutRef -> TxInfo -> Maybe TxInInfo
findTxInByTxOutRef :: TxOutRef -> TxInfo -> Maybe TxInInfo
findTxInByTxOutRef TxOutRef
outRef TxInfo{List TxInInfo
txInfoInputs :: TxInfo -> List TxInInfo
txInfoInputs :: List TxInInfo
txInfoInputs} =
  (TxInInfo -> Bool) -> List TxInInfo -> Maybe TxInInfo
forall a. UnsafeFromData a => (a -> Bool) -> List a -> Maybe a
Data.List.find
    (\TxInInfo{TxOutRef
txInInfoOutRef :: TxInInfo -> TxOutRef
txInInfoOutRef :: TxOutRef
txInInfoOutRef} -> TxOutRef
txInInfoOutRef TxOutRef -> TxOutRef -> Bool
forall a. Eq a => a -> a -> Bool
== TxOutRef
outRef)
    List TxInInfo
txInfoInputs
{-# INLINEABLE findTxInByTxOutRef #-}

{-| Find the indices of all the outputs that pay to the same script address
we are currently spending from, if any.
-}
findContinuingOutputs :: ScriptContext -> List Integer
findContinuingOutputs :: ScriptContext -> List Integer
findContinuingOutputs ScriptContext
ctx
  | Just
      TxInInfo
        { txInInfoResolved :: TxInInfo -> TxOut
txInInfoResolved = TxOut{txOutAddress :: TxOut -> Address
txOutAddress = Address
addr}
        } <-
      ScriptContext -> Maybe TxInInfo
findOwnInput ScriptContext
ctx =
      (TxOut -> Bool) -> List TxOut -> List Integer
forall a. UnsafeFromData a => (a -> Bool) -> List a -> List Integer
Data.List.findIndices (Address -> TxOut -> Bool
f Address
addr) (TxInfo -> List TxOut
txInfoOutputs (TxInfo -> List TxOut) -> TxInfo -> List TxOut
forall a b. (a -> b) -> a -> b
$ ScriptContext -> TxInfo
scriptContextTxInfo ScriptContext
ctx)
 where
  f :: Address -> TxOut -> Bool
f Address
addr TxOut{txOutAddress :: TxOut -> Address
txOutAddress = Address
otherAddress} = Address
addr Address -> Address -> Bool
forall a. Eq a => a -> a -> Bool
== Address
otherAddress
findContinuingOutputs ScriptContext
_ = BuiltinString -> List Integer
forall a. BuiltinString -> a
traceError BuiltinString
"Le" -- "Can't find any continuing outputs"
{-# INLINEABLE findContinuingOutputs #-}

{-| Get all the outputs that pay to the same script address we are currently spending
from, if any.
-}
getContinuingOutputs :: ScriptContext -> List TxOut
getContinuingOutputs :: ScriptContext -> List TxOut
getContinuingOutputs ScriptContext
ctx
  | Just
      TxInInfo
        { txInInfoResolved :: TxInInfo -> TxOut
txInInfoResolved = TxOut{txOutAddress :: TxOut -> Address
txOutAddress = Address
addr}
        } <-
      ScriptContext -> Maybe TxInInfo
findOwnInput ScriptContext
ctx =
      (TxOut -> Bool) -> List TxOut -> List TxOut
forall a.
(UnsafeFromData a, ToData a) =>
(a -> Bool) -> List a -> List a
Data.List.filter (Address -> TxOut -> Bool
f Address
addr) (TxInfo -> List TxOut
txInfoOutputs (TxInfo -> List TxOut) -> TxInfo -> List TxOut
forall a b. (a -> b) -> a -> b
$ ScriptContext -> TxInfo
scriptContextTxInfo ScriptContext
ctx)
 where
  f :: Address -> TxOut -> Bool
f Address
addr TxOut{txOutAddress :: TxOut -> Address
txOutAddress = Address
otherAddress} = Address
addr Address -> Address -> Bool
forall a. Eq a => a -> a -> Bool
== Address
otherAddress
getContinuingOutputs ScriptContext
_ = BuiltinString -> List TxOut
forall a. BuiltinString -> a
traceError BuiltinString
"Lf" -- "Can't get any continuing outputs"
{-# INLINEABLE getContinuingOutputs #-}

-- | Check if a transaction was signed by the given public key.
txSignedBy :: TxInfo -> PubKeyHash -> Bool
txSignedBy :: TxInfo -> PubKeyHash -> Bool
txSignedBy TxInfo{List PubKeyHash
txInfoSignatories :: TxInfo -> List PubKeyHash
txInfoSignatories :: List PubKeyHash
txInfoSignatories} PubKeyHash
k =
  case (PubKeyHash -> Bool) -> List PubKeyHash -> Maybe PubKeyHash
forall a. UnsafeFromData a => (a -> Bool) -> List a -> Maybe a
Data.List.find (PubKeyHash -> PubKeyHash -> Bool
forall a. Eq a => a -> a -> Bool
(==) PubKeyHash
k) List PubKeyHash
txInfoSignatories of
    Just PubKeyHash
_  -> Bool
True
    Maybe PubKeyHash
Nothing -> Bool
False
{-# INLINEABLE txSignedBy #-}

-- | Get the values paid to a public key address by a pending transaction.
pubKeyOutputsAt :: PubKeyHash -> TxInfo -> List Value
pubKeyOutputsAt :: PubKeyHash -> TxInfo -> List Value
pubKeyOutputsAt PubKeyHash
pk TxInfo
p =
  let flt :: TxOut -> Maybe Value
flt
        TxOut
          { txOutAddress :: TxOut -> Address
txOutAddress = Address (PubKeyCredential PubKeyHash
pk') Maybe StakingCredential
_
          , txOutValue :: TxOut -> Value
txOutValue = Value
txOutVal
          } | PubKeyHash
pk PubKeyHash -> PubKeyHash -> Bool
forall a. Eq a => a -> a -> Bool
== PubKeyHash
pk' = Value -> Maybe Value
forall a. a -> Maybe a
Just Value
txOutVal
      flt TxOut
_ = Maybe Value
forall a. Maybe a
Nothing
   in (TxOut -> Maybe Value) -> List TxOut -> List Value
forall a b.
(UnsafeFromData a, ToData b) =>
(a -> Maybe b) -> List a -> List b
Data.List.mapMaybe TxOut -> Maybe Value
flt (TxInfo -> List TxOut
txInfoOutputs TxInfo
p)
{-# INLINEABLE pubKeyOutputsAt #-}

-- | Get the total value paid to a public key address by a pending transaction.
valuePaidTo :: TxInfo -> PubKeyHash -> Value
valuePaidTo :: TxInfo -> PubKeyHash -> Value
valuePaidTo TxInfo
ptx PubKeyHash
pkh = List Value -> Value
forall a. (Monoid a, UnsafeFromData a) => List a -> a
Data.List.mconcat (PubKeyHash -> TxInfo -> List Value
pubKeyOutputsAt PubKeyHash
pkh TxInfo
ptx)
{-# INLINEABLE valuePaidTo #-}

-- | Get the total value of inputs spent by this transaction.
valueSpent :: TxInfo -> Value
valueSpent :: TxInfo -> Value
valueSpent = (TxInInfo -> Value) -> List TxInInfo -> Value
forall a m. (UnsafeFromData a, Monoid m) => (a -> m) -> List a -> m
Data.List.foldMap (TxOut -> Value
txOutValue (TxOut -> Value) -> (TxInInfo -> TxOut) -> TxInInfo -> Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TxInInfo -> TxOut
txInInfoResolved) (List TxInInfo -> Value)
-> (TxInfo -> List TxInInfo) -> TxInfo -> Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TxInfo -> List TxInInfo
txInfoInputs
{-# INLINEABLE valueSpent #-}

-- | Get the total value of outputs produced by this transaction.
valueProduced :: TxInfo -> Value
valueProduced :: TxInfo -> Value
valueProduced = (TxOut -> Value) -> List TxOut -> Value
forall a m. (UnsafeFromData a, Monoid m) => (a -> m) -> List a -> m
Data.List.foldMap TxOut -> Value
txOutValue (List TxOut -> Value) -> (TxInfo -> List TxOut) -> TxInfo -> Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TxInfo -> List TxOut
txInfoOutputs
{-# INLINEABLE valueProduced #-}

-- | The 'CurrencySymbol' of the current validator script.
ownCurrencySymbol :: ScriptContext -> CurrencySymbol
ownCurrencySymbol :: ScriptContext -> CurrencySymbol
ownCurrencySymbol ScriptContext{scriptContextPurpose :: ScriptContext -> ScriptPurpose
scriptContextPurpose = Minting CurrencySymbol
cs} = CurrencySymbol
cs
ownCurrencySymbol ScriptContext
_ =
  BuiltinString -> CurrencySymbol
forall a. BuiltinString -> a
traceError BuiltinString
"Lh" -- "Can't get currency symbol of the current validator script"
{-# INLINEABLE ownCurrencySymbol #-}

{-| Check if the pending transaction spends a specific transaction output
(identified by the hash of a transaction and an index into that
transactions' outputs)
-}
spendsOutput :: TxInfo -> TxId -> Integer -> Bool
spendsOutput :: TxInfo -> TxId -> Integer -> Bool
spendsOutput TxInfo
p TxId
h Integer
i =
  let spendsOutRef :: TxInInfo -> Bool
spendsOutRef TxInInfo
inp =
        let outRef :: TxOutRef
outRef = TxInInfo -> TxOutRef
txInInfoOutRef TxInInfo
inp
         in TxId
h
              TxId -> TxId -> Bool
forall a. Eq a => a -> a -> Bool
== TxOutRef -> TxId
txOutRefId TxOutRef
outRef
              Bool -> Bool -> Bool
&& Integer
i
              Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== TxOutRef -> Integer
txOutRefIdx TxOutRef
outRef
   in (TxInInfo -> Bool) -> List TxInInfo -> Bool
forall a. UnsafeFromData a => (a -> Bool) -> List a -> Bool
Data.List.any TxInInfo -> Bool
spendsOutRef (TxInfo -> List TxInInfo
txInfoInputs TxInfo
p)
{-# INLINEABLE spendsOutput #-}