So far, we have worked only with the low-level untyped version of validator functions which use the BuiltinData type for its arguments. With typed validators, we can define our own types for validation arguments, simplifying things. These types still get compiled down to the low-level BuiltinData type, but our high-level code can be more understandable.
data ArbitraryValidatorTypeNameinstance Scripts.ValidatorTypesArbitraryValidatorTypeNamewhere type instance DatumTypeArbitraryValidatorTypeName = Slot -- Datum type (basic Plutus) type instance RedeemerTypeArbitraryValidatorTypeName = Integer -- Redeemer type (basic Haskell)
With a typed validator, we use our defined types for Datum and Redeemer instead of the BuiltinData so the type signature of the mkValidator changes. Besides using our defined types for Datum and Redeemer, it also now returns a Bool instead of a (), with True signifying successful validation and False signifying a failed one.
PSU.TypedValidator is version agnostic, but we must use PSU.V2.mkTypedValidator if we want to compile to Plutus V2. We also need the {-# LANGUAGE TypeApplications #-} and {-# LANGUAGE TypeFamilies #-} extensions for the above syntax to work properly.
Creating Custom Data Types
If we want to create custom data types for our datum or redeemer, we must also create them as instances of the aforementioned ToData typeclass. We should simply use the PlutusTx.unstableMakeIsData on our defined datum/redeemer type. The difference between unstableMakeIsData and makeIsDataIndexed is that the latter ensures consistent indexing that is required to be specified and it is recommended to use makeIsDataIndexed in production because it ensures the same data structure results across different Plutus versions.
The rest is the same, we just use our data type for the datum/redeemer types:
data ArbitraryValidatorTypeName
instance Scripts.ValidatorTypes ArbitraryValidatorTypeName where
type instance DatumType ArbitraryValidatorTypeName = ExampleDatum -- Datum type (custom defined)
type instance RedeemerType ArbitraryValidatorTypeName = Integer -- Redeemer type (basic Haskell)