Additional Features
Blueprint

Blueprint

Plutus Contract Blueprint, as introduced by CIP-57 (opens in a new tab) is an effective way of communicating desired structure of validator's associated types such as datum and redeemer to your off-chain code.

With Atlas, you can easily have these types generated for you based on provided schema, along with useful helper utilities!

💡

If your validator is parameterised, parameters must be "data" encoded (instead of scott or sums-of-products encoding1) as blueprint notation requires it (data) to be primary binary interface. This is not an issue for datums & redeemers as they are required to be data encoded anyway.

Validators written by tools such as Aiken use data encoding for validator parameters.

Here (opens in a new tab) we have a parameterised Aiken validator. Mainly, it checks that sum of integers and length of bytestrings given in parameters, datum & redeemer sum up to a specific value.

For this validator, we have a simple off-chain code here (opens in a new tab), have a look at it and we provide some description for it below.

We first use Template Haskell to splice declarations from makeBPTypes (opens in a new tab) and uponBPTypes (opens in a new tab). makeBPTypes introduces types from definitions given in blueprint file and uponBPTypes creates data related instances such as ToData (opens in a new tab), FromData (opens in a new tab) for these types2.

It is useful to see generated Template Haskell code to know for type and provided utility names which can be done via -ddump-splices GHC flag. You may combine this with -ddump-to-file to save the output to a file. If you are using cabal, see this (opens in a new tab) answer on where one can find dumped splice files.

Now we can apply parameters (whose types have been generated by Atlas) to our validator with provided applyParamsToBPValidator_baz_baz_spend function and obtain GYScript from it using scriptFromBPSerialisedScript function. Likewise we have types generated for our datum & redeemer, sweet!

Rest of the off-chain code just tries to interact with the validator by creating a UTxO towards it and then later consuming from it.

💡

To interact with blueprint file, you'll usually just need to import GeniusYield.Types.Blueprint.TH (opens in a new tab) module (which is exposed by GeniusYield.Types module), however if you want to inspect the parsed blueprint file, you can use readBlueprint (opens in a new tab).

Footnotes

  1. See CIP-85 (opens in a new tab) to understand about different encodings used.

  2. We could achieve both in single splice, however, since we are using utilities from PlutusTx to derive ToData etc. instances, they require type to be in scope first.