{- |
Module     : Agora.Utils
Maintainer : emi@haskell.fyi
Description: Plutarch utility functions that should be upstreamed or don't belong anywhere else.

Plutarch utility functions that should be upstreamed or don't belong anywhere else.
-}
module Agora.Utils (
  scriptHashFromAddress,
  findOutputsToAddress,
  findTxOutDatum,
  validatorHashToTokenName,
  pvalidatorHashToTokenName,
  getMintingPolicySymbol,
  hasOnlyOneTokenOfCurrencySymbol,
  mustFindDatum',
  mustBePJust,
  mustBePDJust,
  validatorHashToAddress,
  isScriptAddress,
  isPubKey,
) where

import Plutarch.Api.V1 (
  AmountGuarantees,
  KeyGuarantees,
  PAddress,
  PCredential (PScriptCredential),
  PCurrencySymbol,
  PDatum,
  PDatumHash,
  PMaybeData (PDJust),
  PMintingPolicy,
  PTokenName (PTokenName),
  PTuple,
  PTxOut,
  PValidatorHash,
  PValue,
  mintingPolicySymbol,
  mkMintingPolicy,
 )
import Plutarch.Api.V1.ScriptContext (pfindDatum)
import "liqwid-plutarch-extra" Plutarch.Api.V1.Value (psymbolValueOf)
import Plutarch.Builtin (pforgetData)
import Plutarch.Extra.List (plookupTuple)
import Plutarch.Extra.TermCont (pletC, pmatchC)
import PlutusLedgerApi.V1 (
  Address (..),
  Credential (..),
  CurrencySymbol,
  TokenName (..),
  ValidatorHash (..),
 )

{- Functions which should (probably) not be upstreamed
   All of these functions are quite inefficient.
-}

{- | Get script hash from an Address.

     @since 0.1.0
-}
scriptHashFromAddress :: Term s (PAddress :--> PMaybe PValidatorHash)
scriptHashFromAddress :: forall (s :: S). Term s (PAddress :--> PMaybe PValidatorHash)
scriptHashFromAddress = (forall (s :: S). Term s (PAddress :--> PMaybe PValidatorHash))
-> Term s (PAddress :--> PMaybe PValidatorHash)
forall (a :: PType) (s :: S).
HasCallStack =>
ClosedTerm a -> Term s a
phoistAcyclic ((forall (s :: S). Term s (PAddress :--> PMaybe PValidatorHash))
 -> Term s (PAddress :--> PMaybe PValidatorHash))
-> (forall (s :: S). Term s (PAddress :--> PMaybe PValidatorHash))
-> Term s (PAddress :--> PMaybe PValidatorHash)
forall a b. (a -> b) -> a -> b
$
  (Term s PAddress -> Term s (PMaybe PValidatorHash))
-> Term s (PAddress :--> PMaybe PValidatorHash)
forall a (b :: PType) (s :: S) (c :: PType).
PLamN a b s =>
(Term s c -> a) -> Term s (c :--> b)
plam ((Term s PAddress -> Term s (PMaybe PValidatorHash))
 -> Term s (PAddress :--> PMaybe PValidatorHash))
-> (Term s PAddress -> Term s (PMaybe PValidatorHash))
-> Term s (PAddress :--> PMaybe PValidatorHash)
forall a b. (a -> b) -> a -> b
$ \Term s PAddress
addr ->
    Term s PCredential
-> (PCredential s -> Term s (PMaybe PValidatorHash))
-> Term s (PMaybe PValidatorHash)
forall (a :: PType) (s :: S) (b :: PType).
PMatch a =>
Term s a -> (a s -> Term s b) -> Term s b
pmatch (Term s (PAsData PCredential) -> Term s PCredential
forall (a :: PType) (s :: S).
PIsData a =>
Term s (PAsData a) -> Term s a
pfromData (Term s (PAsData PCredential) -> Term s PCredential)
-> Term s (PAsData PCredential) -> Term s PCredential
forall a b. (a -> b) -> a -> b
$ forall (name :: Symbol) (p :: PType) (s :: S) (a :: PType)
       (as :: [PLabeledType]) (n :: Nat) (b :: PType).
(PDataFields p,
 (as :: [PLabeledType]) ~ (PFields p :: [PLabeledType]),
 (n :: Nat) ~ (PLabelIndex name as :: Nat), KnownNat n,
 (a :: PType) ~ (PUnLabel (IndexList @PLabeledType n as) :: PType),
 PFromDataable a b) =>
Term s (p :--> b)
pfield @"credential" Term s (PAddress :--> PAsData PCredential)
-> Term s PAddress -> Term s (PAsData PCredential)
forall (s :: S) (a :: PType) (b :: PType).
Term s (a :--> b) -> Term s a -> Term s b
# Term s PAddress
addr) ((PCredential s -> Term s (PMaybe PValidatorHash))
 -> Term s (PMaybe PValidatorHash))
-> (PCredential s -> Term s (PMaybe PValidatorHash))
-> Term s (PMaybe PValidatorHash)
forall a b. (a -> b) -> a -> b
$ \case
      PScriptCredential ((forall (name :: Symbol) (p :: PType) (s :: S) (a :: PType)
       (as :: [PLabeledType]) (n :: Nat) (b :: PType).
(PDataFields p,
 (as :: [PLabeledType]) ~ (PFields p :: [PLabeledType]),
 (n :: Nat) ~ (PLabelIndex name as :: Nat), KnownNat n,
 (a :: PType) ~ (PUnLabel (IndexList @PLabeledType n as) :: PType),
 PFromDataable a b) =>
Term s (p :--> b)
pfield @"_0" #) -> Term s PValidatorHash
h) -> PMaybe PValidatorHash s -> Term s (PMaybe PValidatorHash)
forall (a :: PType) (s :: S). PCon a => a s -> Term s a
pcon (PMaybe PValidatorHash s -> Term s (PMaybe PValidatorHash))
-> PMaybe PValidatorHash s -> Term s (PMaybe PValidatorHash)
forall a b. (a -> b) -> a -> b
$ Term s PValidatorHash -> PMaybe PValidatorHash s
forall (a :: PType) (s :: S). Term s a -> PMaybe a s
PJust Term s PValidatorHash
h
      PCredential s
_ -> PMaybe PValidatorHash s -> Term s (PMaybe PValidatorHash)
forall (a :: PType) (s :: S). PCon a => a s -> Term s a
pcon PMaybe PValidatorHash s
forall (a :: PType) (s :: S). PMaybe a s
PNothing

{- | Return true if the given address is a script address.

     @since 0.1.0
-}
isScriptAddress :: Term s (PAddress :--> PBool)
isScriptAddress :: forall (s :: S). Term s (PAddress :--> PBool)
isScriptAddress = (forall (s :: S). Term s (PAddress :--> PBool))
-> Term s (PAddress :--> PBool)
forall (a :: PType) (s :: S).
HasCallStack =>
ClosedTerm a -> Term s a
phoistAcyclic ((forall (s :: S). Term s (PAddress :--> PBool))
 -> Term s (PAddress :--> PBool))
-> (forall (s :: S). Term s (PAddress :--> PBool))
-> Term s (PAddress :--> PBool)
forall a b. (a -> b) -> a -> b
$
  (Term s PAddress -> Term s PBool) -> Term s (PAddress :--> PBool)
forall a (b :: PType) (s :: S) (c :: PType).
PLamN a b s =>
(Term s c -> a) -> Term s (c :--> b)
plam ((Term s PAddress -> Term s PBool) -> Term s (PAddress :--> PBool))
-> (Term s PAddress -> Term s PBool)
-> Term s (PAddress :--> PBool)
forall a b. (a -> b) -> a -> b
$ \Term s PAddress
addr -> Term s (PBool :--> PBool)
forall (s :: S). Term s (PBool :--> PBool)
pnot Term s (PBool :--> PBool) -> Term s PBool -> Term s PBool
forall (s :: S) (a :: PType) (b :: PType).
Term s (a :--> b) -> Term s a -> Term s b
#$ Term s (PCredential :--> PBool)
forall (s :: S). Term s (PCredential :--> PBool)
isPubKey Term s (PCredential :--> PBool)
-> Term s PCredential -> Term s PBool
forall (s :: S) (a :: PType) (b :: PType).
Term s (a :--> b) -> Term s a -> Term s b
#$ Term s (PAsData PCredential) -> Term s PCredential
forall (a :: PType) (s :: S).
PIsData a =>
Term s (PAsData a) -> Term s a
pfromData (Term s (PAsData PCredential) -> Term s PCredential)
-> Term s (PAsData PCredential) -> Term s PCredential
forall a b. (a -> b) -> a -> b
$ forall (name :: Symbol) (p :: PType) (s :: S) (a :: PType)
       (as :: [PLabeledType]) (n :: Nat) (b :: PType).
(PDataFields p,
 (as :: [PLabeledType]) ~ (PFields p :: [PLabeledType]),
 (n :: Nat) ~ (PLabelIndex name as :: Nat), KnownNat n,
 (a :: PType) ~ (PUnLabel (IndexList @PLabeledType n as) :: PType),
 PFromDataable a b) =>
Term s (p :--> b)
pfield @"credential" Term s (PAddress :--> PAsData PCredential)
-> Term s PAddress -> Term s (PAsData PCredential)
forall (s :: S) (a :: PType) (b :: PType).
Term s (a :--> b) -> Term s a -> Term s b
# Term s PAddress
addr

{- | Return true if the given credential is a pub-key-hash.

     @since 0.1.0
-}
isPubKey :: Term s (PCredential :--> PBool)
isPubKey :: forall (s :: S). Term s (PCredential :--> PBool)
isPubKey = (forall (s :: S). Term s (PCredential :--> PBool))
-> Term s (PCredential :--> PBool)
forall (a :: PType) (s :: S).
HasCallStack =>
ClosedTerm a -> Term s a
phoistAcyclic ((forall (s :: S). Term s (PCredential :--> PBool))
 -> Term s (PCredential :--> PBool))
-> (forall (s :: S). Term s (PCredential :--> PBool))
-> Term s (PCredential :--> PBool)
forall a b. (a -> b) -> a -> b
$
  (Term s PCredential -> Term s PBool)
-> Term s (PCredential :--> PBool)
forall a (b :: PType) (s :: S) (c :: PType).
PLamN a b s =>
(Term s c -> a) -> Term s (c :--> b)
plam ((Term s PCredential -> Term s PBool)
 -> Term s (PCredential :--> PBool))
-> (Term s PCredential -> Term s PBool)
-> Term s (PCredential :--> PBool)
forall a b. (a -> b) -> a -> b
$ \Term s PCredential
cred ->
    Term s PCredential
-> (PCredential s -> Term s PBool) -> Term s PBool
forall (a :: PType) (s :: S) (b :: PType).
PMatch a =>
Term s a -> (a s -> Term s b) -> Term s b
pmatch Term s PCredential
cred ((PCredential s -> Term s PBool) -> Term s PBool)
-> (PCredential s -> Term s PBool) -> Term s PBool
forall a b. (a -> b) -> a -> b
$ \case
      PScriptCredential Term
  s
  (PDataRecord
     ((':) @PLabeledType ("_0" ':= PValidatorHash) ('[] @PLabeledType)))
_ -> PLifted PBool -> Term s PBool
forall (p :: PType) (s :: S). PLift p => PLifted p -> Term s p
pconstant Bool
PLifted PBool
False
      PCredential s
_ -> PLifted PBool -> Term s PBool
forall (p :: PType) (s :: S). PLift p => PLifted p -> Term s p
pconstant Bool
PLifted PBool
True

{- | Find all TxOuts sent to an Address

     @since 0.1.0
-}
findOutputsToAddress :: Term s (PBuiltinList (PAsData PTxOut) :--> PAddress :--> PBuiltinList (PAsData PTxOut))
findOutputsToAddress :: forall (s :: S).
Term
  s
  (PBuiltinList (PAsData PTxOut)
   :--> (PAddress :--> PBuiltinList (PAsData PTxOut)))
findOutputsToAddress = (forall (s :: S).
 Term
   s
   (PBuiltinList (PAsData PTxOut)
    :--> (PAddress :--> PBuiltinList (PAsData PTxOut))))
-> Term
     s
     (PBuiltinList (PAsData PTxOut)
      :--> (PAddress :--> PBuiltinList (PAsData PTxOut)))
forall (a :: PType) (s :: S).
HasCallStack =>
ClosedTerm a -> Term s a
phoistAcyclic ((forall (s :: S).
  Term
    s
    (PBuiltinList (PAsData PTxOut)
     :--> (PAddress :--> PBuiltinList (PAsData PTxOut))))
 -> Term
      s
      (PBuiltinList (PAsData PTxOut)
       :--> (PAddress :--> PBuiltinList (PAsData PTxOut))))
-> (forall (s :: S).
    Term
      s
      (PBuiltinList (PAsData PTxOut)
       :--> (PAddress :--> PBuiltinList (PAsData PTxOut))))
-> Term
     s
     (PBuiltinList (PAsData PTxOut)
      :--> (PAddress :--> PBuiltinList (PAsData PTxOut)))
forall a b. (a -> b) -> a -> b
$
  (Term s (PBuiltinList (PAsData PTxOut))
 -> Term s PAddress -> Term s (PBuiltinList (PAsData PTxOut)))
-> Term
     s
     (PBuiltinList (PAsData PTxOut)
      :--> (PAddress :--> PBuiltinList (PAsData PTxOut)))
forall a (b :: PType) (s :: S) (c :: PType).
PLamN a b s =>
(Term s c -> a) -> Term s (c :--> b)
plam ((Term s (PBuiltinList (PAsData PTxOut))
  -> Term s PAddress -> Term s (PBuiltinList (PAsData PTxOut)))
 -> Term
      s
      (PBuiltinList (PAsData PTxOut)
       :--> (PAddress :--> PBuiltinList (PAsData PTxOut))))
-> (Term s (PBuiltinList (PAsData PTxOut))
    -> Term s PAddress -> Term s (PBuiltinList (PAsData PTxOut)))
-> Term
     s
     (PBuiltinList (PAsData PTxOut)
      :--> (PAddress :--> PBuiltinList (PAsData PTxOut)))
forall a b. (a -> b) -> a -> b
$ \Term s (PBuiltinList (PAsData PTxOut))
outputs Term s PAddress
address' -> TermCont
  @(PBuiltinList (PAsData PTxOut))
  s
  (Term s (PBuiltinList (PAsData PTxOut)))
-> Term s (PBuiltinList (PAsData PTxOut))
forall (a :: PType) (s :: S). TermCont @a s (Term s a) -> Term s a
unTermCont (TermCont
   @(PBuiltinList (PAsData PTxOut))
   s
   (Term s (PBuiltinList (PAsData PTxOut)))
 -> Term s (PBuiltinList (PAsData PTxOut)))
-> TermCont
     @(PBuiltinList (PAsData PTxOut))
     s
     (Term s (PBuiltinList (PAsData PTxOut)))
-> Term s (PBuiltinList (PAsData PTxOut))
forall a b. (a -> b) -> a -> b
$ do
    Term s (PAsData PAddress)
address <- Term s (PAsData PAddress)
-> TermCont
     @(PBuiltinList (PAsData PTxOut)) s (Term s (PAsData PAddress))
forall {r :: PType} (s :: S) (a :: PType).
Term s a -> TermCont @r s (Term s a)
pletC (Term s (PAsData PAddress)
 -> TermCont
      @(PBuiltinList (PAsData PTxOut)) s (Term s (PAsData PAddress)))
-> Term s (PAsData PAddress)
-> TermCont
     @(PBuiltinList (PAsData PTxOut)) s (Term s (PAsData PAddress))
forall a b. (a -> b) -> a -> b
$ Term s PAddress -> Term s (PAsData PAddress)
forall (a :: PType) (s :: S).
PIsData a =>
Term s a -> Term s (PAsData a)
pdata Term s PAddress
address'
    Term s (PBuiltinList (PAsData PTxOut))
-> TermCont
     @(PBuiltinList (PAsData PTxOut))
     s
     (Term s (PBuiltinList (PAsData PTxOut)))
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure (Term s (PBuiltinList (PAsData PTxOut))
 -> TermCont
      @(PBuiltinList (PAsData PTxOut))
      s
      (Term s (PBuiltinList (PAsData PTxOut))))
-> Term s (PBuiltinList (PAsData PTxOut))
-> TermCont
     @(PBuiltinList (PAsData PTxOut))
     s
     (Term s (PBuiltinList (PAsData PTxOut)))
forall a b. (a -> b) -> a -> b
$
      Term
  s
  ((PAsData PTxOut :--> PBool)
   :--> (PBuiltinList (PAsData PTxOut)
         :--> PBuiltinList (PAsData PTxOut)))
forall (list :: PType -> PType) (a :: PType) (s :: S).
PIsListLike list a =>
Term s ((a :--> PBool) :--> (list a :--> list a))
pfilter Term
  s
  ((PAsData PTxOut :--> PBool)
   :--> (PBuiltinList (PAsData PTxOut)
         :--> PBuiltinList (PAsData PTxOut)))
-> Term s (PAsData PTxOut :--> PBool)
-> Term
     s
     (PBuiltinList (PAsData PTxOut) :--> PBuiltinList (PAsData PTxOut))
forall (s :: S) (a :: PType) (b :: PType).
Term s (a :--> b) -> Term s a -> Term s b
# (Term s (PAsData PTxOut) -> Term s PBool)
-> Term s (PAsData PTxOut :--> PBool)
forall a (b :: PType) (s :: S) (c :: PType).
PLamN a b s =>
(Term s c -> a) -> Term s (c :--> b)
plam (\(Term s (PAsData PTxOut) -> Term s PTxOut
forall (a :: PType) (s :: S).
PIsData a =>
Term s (PAsData a) -> Term s a
pfromData -> Term s PTxOut
txOut) -> forall (name :: Symbol) (p :: PType) (s :: S) (a :: PType)
       (as :: [PLabeledType]) (n :: Nat) (b :: PType).
(PDataFields p,
 (as :: [PLabeledType]) ~ (PFields p :: [PLabeledType]),
 (n :: Nat) ~ (PLabelIndex name as :: Nat), KnownNat n,
 (a :: PType) ~ (PUnLabel (IndexList @PLabeledType n as) :: PType),
 PFromDataable a b) =>
Term s (p :--> b)
pfield @"address" Term s (PTxOut :--> PAsData PAddress)
-> Term s PTxOut -> Term s (PAsData PAddress)
forall (s :: S) (a :: PType) (b :: PType).
Term s (a :--> b) -> Term s a -> Term s b
# Term s PTxOut
txOut Term s (PAsData PAddress)
-> Term s (PAsData PAddress) -> Term s PBool
forall (t :: PType) (s :: S).
PEq t =>
Term s t -> Term s t -> Term s PBool
#== Term s (PAsData PAddress)
address)
        # outputs

{- | Find the data corresponding to a TxOut, if there is one

     @since 0.1.0
-}
findTxOutDatum :: Term s (PBuiltinList (PAsData (PTuple PDatumHash PDatum)) :--> PTxOut :--> PMaybe PDatum)
findTxOutDatum :: forall (s :: S).
Term
  s
  (PBuiltinList (PAsData (PTuple PDatumHash PDatum))
   :--> (PTxOut :--> PMaybe PDatum))
findTxOutDatum = (forall (s :: S).
 Term
   s
   (PBuiltinList (PAsData (PTuple PDatumHash PDatum))
    :--> (PTxOut :--> PMaybe PDatum)))
-> Term
     s
     (PBuiltinList (PAsData (PTuple PDatumHash PDatum))
      :--> (PTxOut :--> PMaybe PDatum))
forall (a :: PType) (s :: S).
HasCallStack =>
ClosedTerm a -> Term s a
phoistAcyclic ((forall (s :: S).
  Term
    s
    (PBuiltinList (PAsData (PTuple PDatumHash PDatum))
     :--> (PTxOut :--> PMaybe PDatum)))
 -> Term
      s
      (PBuiltinList (PAsData (PTuple PDatumHash PDatum))
       :--> (PTxOut :--> PMaybe PDatum)))
-> (forall (s :: S).
    Term
      s
      (PBuiltinList (PAsData (PTuple PDatumHash PDatum))
       :--> (PTxOut :--> PMaybe PDatum)))
-> Term
     s
     (PBuiltinList (PAsData (PTuple PDatumHash PDatum))
      :--> (PTxOut :--> PMaybe PDatum))
forall a b. (a -> b) -> a -> b
$
  (Term s (PBuiltinList (PAsData (PTuple PDatumHash PDatum)))
 -> Term s PTxOut -> Term s (PMaybe PDatum))
-> Term
     s
     (PBuiltinList (PAsData (PTuple PDatumHash PDatum))
      :--> (PTxOut :--> PMaybe PDatum))
forall a (b :: PType) (s :: S) (c :: PType).
PLamN a b s =>
(Term s c -> a) -> Term s (c :--> b)
plam ((Term s (PBuiltinList (PAsData (PTuple PDatumHash PDatum)))
  -> Term s PTxOut -> Term s (PMaybe PDatum))
 -> Term
      s
      (PBuiltinList (PAsData (PTuple PDatumHash PDatum))
       :--> (PTxOut :--> PMaybe PDatum)))
-> (Term s (PBuiltinList (PAsData (PTuple PDatumHash PDatum)))
    -> Term s PTxOut -> Term s (PMaybe PDatum))
-> Term
     s
     (PBuiltinList (PAsData (PTuple PDatumHash PDatum))
      :--> (PTxOut :--> PMaybe PDatum))
forall a b. (a -> b) -> a -> b
$ \Term s (PBuiltinList (PAsData (PTuple PDatumHash PDatum)))
datums Term s PTxOut
out -> TermCont @(PMaybe PDatum) s (Term s (PMaybe PDatum))
-> Term s (PMaybe PDatum)
forall (a :: PType) (s :: S). TermCont @a s (Term s a) -> Term s a
unTermCont (TermCont @(PMaybe PDatum) s (Term s (PMaybe PDatum))
 -> Term s (PMaybe PDatum))
-> TermCont @(PMaybe PDatum) s (Term s (PMaybe PDatum))
-> Term s (PMaybe PDatum)
forall a b. (a -> b) -> a -> b
$ do
    PMaybeData PDatumHash s
datumHash' <- Term s (PMaybeData PDatumHash)
-> TermCont @(PMaybe PDatum) s (PMaybeData PDatumHash s)
forall {r :: PType} (a :: PType) (s :: S).
PMatch a =>
Term s a -> TermCont @r s (a s)
pmatchC (Term s (PMaybeData PDatumHash)
 -> TermCont @(PMaybe PDatum) s (PMaybeData PDatumHash s))
-> Term s (PMaybeData PDatumHash)
-> TermCont @(PMaybe PDatum) s (PMaybeData PDatumHash s)
forall a b. (a -> b) -> a -> b
$ Term s (PAsData (PMaybeData PDatumHash))
-> Term s (PMaybeData PDatumHash)
forall (a :: PType) (s :: S).
PIsData a =>
Term s (PAsData a) -> Term s a
pfromData (Term s (PAsData (PMaybeData PDatumHash))
 -> Term s (PMaybeData PDatumHash))
-> Term s (PAsData (PMaybeData PDatumHash))
-> Term s (PMaybeData PDatumHash)
forall a b. (a -> b) -> a -> b
$ forall (name :: Symbol) (p :: PType) (s :: S) (a :: PType)
       (as :: [PLabeledType]) (n :: Nat) (b :: PType).
(PDataFields p,
 (as :: [PLabeledType]) ~ (PFields p :: [PLabeledType]),
 (n :: Nat) ~ (PLabelIndex name as :: Nat), KnownNat n,
 (a :: PType) ~ (PUnLabel (IndexList @PLabeledType n as) :: PType),
 PFromDataable a b) =>
Term s (p :--> b)
pfield @"datumHash" Term s (PTxOut :--> PAsData (PMaybeData PDatumHash))
-> Term s PTxOut -> Term s (PAsData (PMaybeData PDatumHash))
forall (s :: S) (a :: PType) (b :: PType).
Term s (a :--> b) -> Term s a -> Term s b
# Term s PTxOut
out
    Term s (PMaybe PDatum)
-> TermCont @(PMaybe PDatum) s (Term s (PMaybe PDatum))
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure (Term s (PMaybe PDatum)
 -> TermCont @(PMaybe PDatum) s (Term s (PMaybe PDatum)))
-> Term s (PMaybe PDatum)
-> TermCont @(PMaybe PDatum) s (Term s (PMaybe PDatum))
forall a b. (a -> b) -> a -> b
$ case PMaybeData PDatumHash s
datumHash' of
      PDJust ((forall (name :: Symbol) (p :: PType) (s :: S) (a :: PType)
       (as :: [PLabeledType]) (n :: Nat) (b :: PType).
(PDataFields p,
 (as :: [PLabeledType]) ~ (PFields p :: [PLabeledType]),
 (n :: Nat) ~ (PLabelIndex name as :: Nat), KnownNat n,
 (a :: PType) ~ (PUnLabel (IndexList @PLabeledType n as) :: PType),
 PFromDataable a b) =>
Term s (p :--> b)
pfield @"_0" #) -> Term s PDatumHash
datumHash) -> Term
  s
  (PDatumHash
   :--> (PBuiltinList (PAsData (PTuple PDatumHash PDatum))
         :--> PMaybe PDatum))
forall (s :: S).
Term
  s
  (PDatumHash
   :--> (PBuiltinList (PAsData (PTuple PDatumHash PDatum))
         :--> PMaybe PDatum))
pfindDatum Term
  s
  (PDatumHash
   :--> (PBuiltinList (PAsData (PTuple PDatumHash PDatum))
         :--> PMaybe PDatum))
-> Term s PDatumHash
-> Term
     s
     (PBuiltinList (PAsData (PTuple PDatumHash PDatum))
      :--> PMaybe PDatum)
forall (s :: S) (a :: PType) (b :: PType).
Term s (a :--> b) -> Term s a -> Term s b
# Term s PDatumHash
datumHash Term
  s
  (PBuiltinList (PAsData (PTuple PDatumHash PDatum))
   :--> PMaybe PDatum)
-> Term s (PBuiltinList (PAsData (PTuple PDatumHash PDatum)))
-> Term s (PMaybe PDatum)
forall (s :: S) (a :: PType) (b :: PType).
Term s (a :--> b) -> Term s a -> Term s b
# Term s (PBuiltinList (PAsData (PTuple PDatumHash PDatum)))
datums
      PMaybeData PDatumHash s
_ -> PMaybe PDatum s -> Term s (PMaybe PDatum)
forall (a :: PType) (s :: S). PCon a => a s -> Term s a
pcon PMaybe PDatum s
forall (a :: PType) (s :: S). PMaybe a s
PNothing

{- | Safely convert a 'PValidatorHash' into a 'PTokenName'. This can be useful for tagging
     tokens for extra safety.

     @since 0.1.0
-}
validatorHashToTokenName :: ValidatorHash -> TokenName
validatorHashToTokenName :: ValidatorHash -> TokenName
validatorHashToTokenName (ValidatorHash BuiltinByteString
hash) = BuiltinByteString -> TokenName
TokenName BuiltinByteString
hash

{- | Plutarch level 'validatorHashToTokenName'.

     @since 0.1.0
-}
pvalidatorHashToTokenName :: forall (s :: S). Term s PValidatorHash -> Term s PTokenName
pvalidatorHashToTokenName :: forall (s :: S). Term s PValidatorHash -> Term s PTokenName
pvalidatorHashToTokenName Term s PValidatorHash
vh = PTokenName s -> Term s PTokenName
forall (a :: PType) (s :: S). PCon a => a s -> Term s a
pcon (Term s (PByteString @S) -> PTokenName s
forall (s :: S). Term s (PByteString @S) -> PTokenName s
PTokenName (Term s PValidatorHash
-> forall (b :: PType). Term s (PInner PValidatorHash b)
forall (s :: S) (a :: PType).
Term s a -> forall (b :: PType). Term s (PInner a b)
pto Term s PValidatorHash
vh))

{- | Get the CurrencySymbol of a PMintingPolicy.

     @since 0.1.0
-}
getMintingPolicySymbol :: ClosedTerm PMintingPolicy -> CurrencySymbol
getMintingPolicySymbol :: ClosedTerm PMintingPolicy -> CurrencySymbol
getMintingPolicySymbol ClosedTerm PMintingPolicy
v = MintingPolicy -> CurrencySymbol
mintingPolicySymbol (MintingPolicy -> CurrencySymbol)
-> MintingPolicy -> CurrencySymbol
forall a b. (a -> b) -> a -> b
$ ClosedTerm PMintingPolicy -> MintingPolicy
mkMintingPolicy ClosedTerm PMintingPolicy
v

{- | The entire value only contains one token of the given currency symbol.

     @since 0.1.0
-}
hasOnlyOneTokenOfCurrencySymbol ::
  forall (keys :: KeyGuarantees) (amounts :: AmountGuarantees) (s :: S).
  Term s (PCurrencySymbol :--> PValue keys amounts :--> PBool)
hasOnlyOneTokenOfCurrencySymbol :: forall (keys :: KeyGuarantees) (amounts :: AmountGuarantees)
       (s :: S).
Term s (PCurrencySymbol :--> (PValue keys amounts :--> PBool))
hasOnlyOneTokenOfCurrencySymbol = ClosedTerm (PCurrencySymbol :--> (PValue keys amounts :--> PBool))
-> Term s (PCurrencySymbol :--> (PValue keys amounts :--> PBool))
forall (a :: PType) (s :: S).
HasCallStack =>
ClosedTerm a -> Term s a
phoistAcyclic (ClosedTerm (PCurrencySymbol :--> (PValue keys amounts :--> PBool))
 -> Term s (PCurrencySymbol :--> (PValue keys amounts :--> PBool)))
-> ClosedTerm
     (PCurrencySymbol :--> (PValue keys amounts :--> PBool))
-> Term s (PCurrencySymbol :--> (PValue keys amounts :--> PBool))
forall a b. (a -> b) -> a -> b
$
  (Term s PCurrencySymbol
 -> Term s (PValue keys amounts) -> Term s PBool)
-> Term s (PCurrencySymbol :--> (PValue keys amounts :--> PBool))
forall a (b :: PType) (s :: S) (c :: PType).
PLamN a b s =>
(Term s c -> a) -> Term s (c :--> b)
plam ((Term s PCurrencySymbol
  -> Term s (PValue keys amounts) -> Term s PBool)
 -> Term s (PCurrencySymbol :--> (PValue keys amounts :--> PBool)))
-> (Term s PCurrencySymbol
    -> Term s (PValue keys amounts) -> Term s PBool)
-> Term s (PCurrencySymbol :--> (PValue keys amounts :--> PBool))
forall a b. (a -> b) -> a -> b
$ \Term s PCurrencySymbol
cs Term s (PValue keys amounts)
vs -> P.do
    Term
  s (PCurrencySymbol :--> (PValue keys amounts :--> PInteger @S))
forall (keys :: KeyGuarantees) (amounts :: AmountGuarantees)
       (s :: S).
Term
  s (PCurrencySymbol :--> (PValue keys amounts :--> PInteger @S))
psymbolValueOf Term
  s (PCurrencySymbol :--> (PValue keys amounts :--> PInteger @S))
-> Term s PCurrencySymbol
-> Term s (PValue keys amounts :--> PInteger @S)
forall (s :: S) (a :: PType) (b :: PType).
Term s (a :--> b) -> Term s a -> Term s b
# Term s PCurrencySymbol
cs Term s (PValue keys amounts :--> PInteger @S)
-> Term s (PValue keys amounts) -> Term s (PInteger @S)
forall (s :: S) (a :: PType) (b :: PType).
Term s (a :--> b) -> Term s a -> Term s b
# Term s (PValue keys amounts)
vs Term s (PInteger @S) -> Term s (PInteger @S) -> Term s PBool
forall (t :: PType) (s :: S).
PEq t =>
Term s t -> Term s t -> Term s PBool
#== Term s (PInteger @S)
1
      #&& (plength #$ pto $ pto $ pto vs) #== 1

{- | Find datum given a maybe datum hash

     @since 0.1.0
-}
mustFindDatum' ::
  forall (datum :: PType).
  (PIsData datum, PTryFrom PData (PAsData datum)) =>
  forall s.
  Term
    s
    ( PMaybeData PDatumHash
        :--> PBuiltinList (PAsData (PTuple PDatumHash PDatum))
        :--> datum
    )
mustFindDatum' :: forall (datum :: PType) (s :: S).
(PIsData datum, PTryFrom PData (PAsData datum)) =>
Term
  s
  (PMaybeData PDatumHash
   :--> (PBuiltinList (PAsData (PTuple PDatumHash PDatum))
         :--> datum))
mustFindDatum' = ClosedTerm
  (PMaybeData PDatumHash
   :--> (PBuiltinList (PAsData (PTuple PDatumHash PDatum))
         :--> datum))
-> Term
     s
     (PMaybeData PDatumHash
      :--> (PBuiltinList (PAsData (PTuple PDatumHash PDatum))
            :--> datum))
forall (a :: PType) (s :: S).
HasCallStack =>
ClosedTerm a -> Term s a
phoistAcyclic (ClosedTerm
   (PMaybeData PDatumHash
    :--> (PBuiltinList (PAsData (PTuple PDatumHash PDatum))
          :--> datum))
 -> Term
      s
      (PMaybeData PDatumHash
       :--> (PBuiltinList (PAsData (PTuple PDatumHash PDatum))
             :--> datum)))
-> ClosedTerm
     (PMaybeData PDatumHash
      :--> (PBuiltinList (PAsData (PTuple PDatumHash PDatum))
            :--> datum))
-> Term
     s
     (PMaybeData PDatumHash
      :--> (PBuiltinList (PAsData (PTuple PDatumHash PDatum))
            :--> datum))
forall a b. (a -> b) -> a -> b
$
  (Term s (PMaybeData PDatumHash)
 -> Term s (PBuiltinList (PAsData (PTuple PDatumHash PDatum)))
 -> Term s datum)
-> Term
     s
     (PMaybeData PDatumHash
      :--> (PBuiltinList (PAsData (PTuple PDatumHash PDatum))
            :--> datum))
forall a (b :: PType) (s :: S) (c :: PType).
PLamN a b s =>
(Term s c -> a) -> Term s (c :--> b)
plam ((Term s (PMaybeData PDatumHash)
  -> Term s (PBuiltinList (PAsData (PTuple PDatumHash PDatum)))
  -> Term s datum)
 -> Term
      s
      (PMaybeData PDatumHash
       :--> (PBuiltinList (PAsData (PTuple PDatumHash PDatum))
             :--> datum)))
-> (Term s (PMaybeData PDatumHash)
    -> Term s (PBuiltinList (PAsData (PTuple PDatumHash PDatum)))
    -> Term s datum)
-> Term
     s
     (PMaybeData PDatumHash
      :--> (PBuiltinList (PAsData (PTuple PDatumHash PDatum))
            :--> datum))
forall a b. (a -> b) -> a -> b
$ \Term s (PMaybeData PDatumHash)
mdh Term s (PBuiltinList (PAsData (PTuple PDatumHash PDatum)))
datums -> TermCont @datum s (Term s datum) -> Term s datum
forall (a :: PType) (s :: S). TermCont @a s (Term s a) -> Term s a
unTermCont (TermCont @datum s (Term s datum) -> Term s datum)
-> TermCont @datum s (Term s datum) -> Term s datum
forall a b. (a -> b) -> a -> b
$ do
    let dh :: Term s PDatumHash
dh = Term s (PString @S :--> (PMaybeData PDatumHash :--> PDatumHash))
forall (a :: PType) (s :: S).
PIsData a =>
Term s (PString @S :--> (PMaybeData a :--> a))
mustBePDJust Term s (PString @S :--> (PMaybeData PDatumHash :--> PDatumHash))
-> Term s (PString @S)
-> Term s (PMaybeData PDatumHash :--> PDatumHash)
forall (s :: S) (a :: PType) (b :: PType).
Term s (a :--> b) -> Term s a -> Term s b
# Term s (PString @S)
"Given TxOut dones't have a datum" Term s (PMaybeData PDatumHash :--> PDatumHash)
-> Term s (PMaybeData PDatumHash) -> Term s PDatumHash
forall (s :: S) (a :: PType) (b :: PType).
Term s (a :--> b) -> Term s a -> Term s b
# Term s (PMaybeData PDatumHash)
mdh
        dt :: Term s PDatum
dt = Term s (PString @S :--> (PMaybe PDatum :--> PDatum))
forall (a :: PType) (s :: S).
Term s (PString @S :--> (PMaybe a :--> a))
mustBePJust Term s (PString @S :--> (PMaybe PDatum :--> PDatum))
-> Term s (PString @S) -> Term s (PMaybe PDatum :--> PDatum)
forall (s :: S) (a :: PType) (b :: PType).
Term s (a :--> b) -> Term s a -> Term s b
# Term s (PString @S)
"Datum not found in the transaction" Term s (PMaybe PDatum :--> PDatum)
-> Term s (PMaybe PDatum) -> Term s PDatum
forall (s :: S) (a :: PType) (b :: PType).
Term s (a :--> b) -> Term s a -> Term s b
#$ Term
  s
  (PDatumHash
   :--> (PBuiltinList (PAsData (PTuple PDatumHash PDatum))
         :--> PMaybe PDatum))
forall (a :: PType) (list :: PType -> PType) (b :: PType) (s :: S).
(PEq a, PIsListLike list (PAsData (PTuple a b)), PIsData a,
 PIsData b) =>
Term s (a :--> (list (PAsData (PTuple a b)) :--> PMaybe b))
plookupTuple Term
  s
  (PDatumHash
   :--> (PBuiltinList (PAsData (PTuple PDatumHash PDatum))
         :--> PMaybe PDatum))
-> Term s PDatumHash
-> Term
     s
     (PBuiltinList (PAsData (PTuple PDatumHash PDatum))
      :--> PMaybe PDatum)
forall (s :: S) (a :: PType) (b :: PType).
Term s (a :--> b) -> Term s a -> Term s b
# Term s PDatumHash
dh Term
  s
  (PBuiltinList (PAsData (PTuple PDatumHash PDatum))
   :--> PMaybe PDatum)
-> Term s (PBuiltinList (PAsData (PTuple PDatumHash PDatum)))
-> Term s (PMaybe PDatum)
forall (s :: S) (a :: PType) (b :: PType).
Term s (a :--> b) -> Term s a -> Term s b
# Term s (PBuiltinList (PAsData (PTuple PDatumHash PDatum)))
datums
    (Term s (PAsData datum)
d, Reduce @Type (PTryFromExcess PData (PAsData datum) s)
_) <- (((Term s (PAsData datum),
   Reduce @Type (PTryFromExcess PData (PAsData datum) s))
  -> Term s datum)
 -> Term s datum)
-> TermCont
     @datum
     s
     (Term s (PAsData datum),
      Reduce @Type (PTryFromExcess PData (PAsData datum) s))
forall a (s :: S) (r :: PType).
((a -> Term s r) -> Term s r) -> TermCont @r s a
tcont ((((Term s (PAsData datum),
    Reduce @Type (PTryFromExcess PData (PAsData datum) s))
   -> Term s datum)
  -> Term s datum)
 -> TermCont
      @datum
      s
      (Term s (PAsData datum),
       Reduce @Type (PTryFromExcess PData (PAsData datum) s)))
-> (((Term s (PAsData datum),
      Reduce @Type (PTryFromExcess PData (PAsData datum) s))
     -> Term s datum)
    -> Term s datum)
-> TermCont
     @datum
     s
     (Term s (PAsData datum),
      Reduce @Type (PTryFromExcess PData (PAsData datum) s))
forall a b. (a -> b) -> a -> b
$ Term s PData
-> ((Term s (PAsData datum),
     Reduce @Type (PTryFromExcess PData (PAsData datum) s))
    -> Term s datum)
-> Term s datum
forall (b :: PType) (a :: PType) (s :: S) (r :: PType).
PTryFrom a b =>
Term s a
-> ((Term s b, Reduce @Type (PTryFromExcess a b s)) -> Term s r)
-> Term s r
ptryFrom (Term s PData
 -> ((Term s (PAsData datum),
      Reduce @Type (PTryFromExcess PData (PAsData datum) s))
     -> Term s datum)
 -> Term s datum)
-> Term s PData
-> ((Term s (PAsData datum),
     Reduce @Type (PTryFromExcess PData (PAsData datum) s))
    -> Term s datum)
-> Term s datum
forall a b. (a -> b) -> a -> b
$ Term s (PAsData PDatum) -> Term s PData
forall (s :: S) (a :: PType). Term s (PAsData a) -> Term s PData
pforgetData (Term s (PAsData PDatum) -> Term s PData)
-> Term s (PAsData PDatum) -> Term s PData
forall a b. (a -> b) -> a -> b
$ Term s PDatum -> Term s (PAsData PDatum)
forall (a :: PType) (s :: S).
PIsData a =>
Term s a -> Term s (PAsData a)
pdata Term s PDatum
dt
    Term s datum -> TermCont @datum s (Term s datum)
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure (Term s datum -> TermCont @datum s (Term s datum))
-> Term s datum -> TermCont @datum s (Term s datum)
forall a b. (a -> b) -> a -> b
$ Term s (PAsData datum) -> Term s datum
forall (a :: PType) (s :: S).
PIsData a =>
Term s (PAsData a) -> Term s a
pfromData Term s (PAsData datum)
d

{- | Extract the value stored in a PMaybe container.
     If there's no value, throw an error with the given message.

     @since 0.1.0
-}
mustBePJust :: forall a s. Term s (PString :--> PMaybe a :--> a)
mustBePJust :: forall (a :: PType) (s :: S).
Term s (PString @S :--> (PMaybe a :--> a))
mustBePJust = ClosedTerm (PString @S :--> (PMaybe a :--> a))
-> Term s (PString @S :--> (PMaybe a :--> a))
forall (a :: PType) (s :: S).
HasCallStack =>
ClosedTerm a -> Term s a
phoistAcyclic (ClosedTerm (PString @S :--> (PMaybe a :--> a))
 -> Term s (PString @S :--> (PMaybe a :--> a)))
-> ClosedTerm (PString @S :--> (PMaybe a :--> a))
-> Term s (PString @S :--> (PMaybe a :--> a))
forall a b. (a -> b) -> a -> b
$
  (Term s (PString @S) -> Term s (PMaybe a) -> Term s a)
-> Term s (PString @S :--> (PMaybe a :--> a))
forall a (b :: PType) (s :: S) (c :: PType).
PLamN a b s =>
(Term s c -> a) -> Term s (c :--> b)
plam ((Term s (PString @S) -> Term s (PMaybe a) -> Term s a)
 -> Term s (PString @S :--> (PMaybe a :--> a)))
-> (Term s (PString @S) -> Term s (PMaybe a) -> Term s a)
-> Term s (PString @S :--> (PMaybe a :--> a))
forall a b. (a -> b) -> a -> b
$ \Term s (PString @S)
emsg Term s (PMaybe a)
mv' -> Term s (PMaybe a) -> (PMaybe a s -> Term s a) -> Term s a
forall (a :: PType) (s :: S) (b :: PType).
PMatch a =>
Term s a -> (a s -> Term s b) -> Term s b
pmatch Term s (PMaybe a)
mv' ((PMaybe a s -> Term s a) -> Term s a)
-> (PMaybe a s -> Term s a) -> Term s a
forall a b. (a -> b) -> a -> b
$ \case
    PJust Term s a
v -> Term s a
v
    PMaybe a s
_ -> Term s (PString @S) -> Term s a
forall (s :: S) (a :: PType). Term s (PString @S) -> Term s a
ptraceError Term s (PString @S)
emsg

{- | Extract the value stored in a PMaybeData container.
     If there's no value, throw an error with the given message.

     @since 0.1.0
-}
mustBePDJust :: forall a s. (PIsData a) => Term s (PString :--> PMaybeData a :--> a)
mustBePDJust :: forall (a :: PType) (s :: S).
PIsData a =>
Term s (PString @S :--> (PMaybeData a :--> a))
mustBePDJust = ClosedTerm (PString @S :--> (PMaybeData a :--> a))
-> Term s (PString @S :--> (PMaybeData a :--> a))
forall (a :: PType) (s :: S).
HasCallStack =>
ClosedTerm a -> Term s a
phoistAcyclic (ClosedTerm (PString @S :--> (PMaybeData a :--> a))
 -> Term s (PString @S :--> (PMaybeData a :--> a)))
-> ClosedTerm (PString @S :--> (PMaybeData a :--> a))
-> Term s (PString @S :--> (PMaybeData a :--> a))
forall a b. (a -> b) -> a -> b
$
  (Term s (PString @S) -> Term s (PMaybeData a) -> Term s a)
-> Term s (PString @S :--> (PMaybeData a :--> a))
forall a (b :: PType) (s :: S) (c :: PType).
PLamN a b s =>
(Term s c -> a) -> Term s (c :--> b)
plam ((Term s (PString @S) -> Term s (PMaybeData a) -> Term s a)
 -> Term s (PString @S :--> (PMaybeData a :--> a)))
-> (Term s (PString @S) -> Term s (PMaybeData a) -> Term s a)
-> Term s (PString @S :--> (PMaybeData a :--> a))
forall a b. (a -> b) -> a -> b
$ \Term s (PString @S)
emsg Term s (PMaybeData a)
mv' -> Term s (PMaybeData a) -> (PMaybeData a s -> Term s a) -> Term s a
forall (a :: PType) (s :: S) (b :: PType).
PMatch a =>
Term s a -> (a s -> Term s b) -> Term s b
pmatch Term s (PMaybeData a)
mv' ((PMaybeData a s -> Term s a) -> Term s a)
-> (PMaybeData a s -> Term s a) -> Term s a
forall a b. (a -> b) -> a -> b
$ \case
    PDJust ((forall (name :: Symbol) (p :: PType) (s :: S) (a :: PType)
       (as :: [PLabeledType]) (n :: Nat) (b :: PType).
(PDataFields p,
 (as :: [PLabeledType]) ~ (PFields p :: [PLabeledType]),
 (n :: Nat) ~ (PLabelIndex name as :: Nat), KnownNat n,
 (a :: PType) ~ (PUnLabel (IndexList @PLabeledType n as) :: PType),
 PFromDataable a b) =>
Term s (p :--> b)
pfield @"_0" #) -> Term s a
v) -> Term s a
v
    PMaybeData a s
_ -> Term s (PString @S) -> Term s a
forall (s :: S) (a :: PType). Term s (PString @S) -> Term s a
ptraceError Term s (PString @S)
emsg

{- | Create an 'Address' from a given 'ValidatorHash' with no 'PlutusLedgerApi.V1.Credential.StakingCredential'.

     @since 0.1.0
-}
validatorHashToAddress :: ValidatorHash -> Address
validatorHashToAddress :: ValidatorHash -> Address
validatorHashToAddress ValidatorHash
vh = Credential -> Maybe StakingCredential -> Address
Address (ValidatorHash -> Credential
ScriptCredential ValidatorHash
vh) Maybe StakingCredential
forall a. Maybe a
Nothing