The previous example used the POSIXTime type as the script parameter. For the following example, we will look at custom-defined parameter types as there is some extra work we need to do in that case. We will transform the SharedWallet script from earlier to be parameterised instead of relying on the UTxO datum. That means that either of the trusted parties can spend any UTxO sitting at the script address, regardless of what the datum associated is.
Writing the validator
Firstly, we create the same type as before, this time calling it sharedParam:
As before, we need to make our parameter type an instance of ToData/FromData via PlutusTx.unstableMakeIsData:
PlutusTx.unstableMakeIsData ''SharedWalletParam
In addition, when defining custom parameter types, we need to make them an instance of the Lift class. This allows the type to be lifted into so-called Plutus IR (intermediate representation), which is then handled further to Plutus Core, but essentially, we just need this to allow the compiler to compile our type to Plutus Core. This is done with the PlutusTx.makeLift function that automatically derives an instance for us:
PlutusTx.makeLift ''SharedWalletParam
Note that PubKeyHash type is an instance of both ToData/FromData and Lift, but our defined type SharedParam which contains two PubKeyHash fields is not.
The rest is pretty much the same as in the typed validator version. We need to create a ValidatorTypes instance, but since we are using a parameter that will bake our sharedParam inside the script, we do not need datum and redeemer:
dataSharedWalletParamValidatorinstance Scripts.ValidatorTypesSharedWalletParamValidator-- default types for datum and redeemer are ()
Our mkValidator function still for valid signatures in the transaction context, except this time the PubKeyHashes are deconstructed from the SharedParam argument:
As with the parameterised deadline script example, we use the PSU.V2.mkTypedValidatorParam to define a function that accepts the parameter to compile the validator.
Besides the DataKind extension we enabled when working with typed validators, for parameterised validators we also need to enable ScopedTypeVariables and MultiParamTypeClasses.
In order to compile this validator, we need to provide it with a parameter of type SharedWalletParam. Again, we can export this type and its constructor by adding it to the module interface.
Now, when we load the module in a REPL, we can construct a valid SharedWalletParam type. Let's do that by specifying the two public key hashes from our addresses as we did with the typed version of the shared wallet validator. When we have our parameter for the script, we can pass it to the writeSerialisedScript function.
We can now send some funds to the script. Remember, we don't care about the datum as the script was parameterised at compilation so it knows about our public key hashes. However, we always have to attach a datum to any script UTxO or it will be unspendable, so we can attach our unit.json in the transaction constructed by the send-funds-to-script.sh script.
We see the UTxO at the script address so we can try spending it by simply signing the transaction with one of our private keys. Let's use the key from the 02.addr and use one of its UTxOs for collateral as well in spend-script-funds.sh.