before I can answer there is an important distinction that must be done
on-chain code can be serialized, off-chain code stays "off the chain" so there is nothing to serialize
so if you are searching for a way to serialize your off-chain code (which can be written in any language, from Haskell with the Contract
monad to javascript thanks to the cardano-serialization-library
) unfortunately there is nothing to do
serialize the on-chain code
from the chain point of view there is no difference between Validator
s and MintingPolicy
(ies) and StakeValidator
all of them are Script
s for the chain, treated differently based on the ScriptPourpose
of that transaction
so you first need to get the raw Script
of your smart contract
you can do that with the following functions (all form Plutus.V1.Ledger.Api
module)
unValidatorScript :: Validator -> Script
getMintingPolicy :: MintingPolicy -> Script
getStakeValidator :: StakeValidator -> Script
once you have your Script
the process is always the same
Script
has an instance of the Srialize
typeclass which conviniently exposes the serialise
function:
serialise :: forall a. Serialise a => a -> ByteString
then we need to strictly evaluate the byte-string and make sure the values do fit in short
s types, this can be done by concatenating the following two functions
import qualified Data.ByteString.Short as SBS
import qualified Data.ByteString.Lazy as LBS
-- LBS.toStrict :: ByteString -> ByteString
-- SBS.toShort :: ByteString -> ShortByteString
asStrictBS :: ByteString -> ShortByteString
asStrictBS = SBS.toShort . LBS.toStrict
then we have to specify how to interpret the ShortByteString
we have:
-- PlutusScriptSerialized is a constrctor
PlutusScriptSerialized :: ShortByteString -> PlutusScript PlutusScriptV1
and finally get our Script
into a file, which can be done thanks to the writeFileTextEnvelope
from the Cardano.Api.SerialiseTextEnvelope
module:
writeFileTextEnvelope :: forall a.
HasTextEnvelope a =>
FilePath
-> Maybe TextEnvelopeDescr -> a -> IO (Either (FileError ()) ())
I usually do all this whit the following utility funciutons:
getAndWriteScript :: ( willBeScript -> Ledger.Script ) -> FilePath -> willBeScript -> IO (Either (FileError ()) ())
getAndWriteScript getScript filePath =
-- PlutusScript PlutusScriptV1 instance of HasTextEnvelope
writeFileTextEnvelope @(PlutusScript PlutusScriptV1) filePath
Nothing -- Maybe TextEnvelopeDescr ( Nothing => default )
. PlutusScriptSerialised . SBS.toShort . LBS.toStrict . serialise . getScript
writeMintingPolicy :: FilePath -> Scripts.MintingPolicy -> IO (Either (FileError ()) ())
writeMintingPolicy = getAndWriteScript Ledger.getMintingPolicy
writeValidator :: FilePath -> Scripts.Validator -> IO (Either (FileError ()) ())
writeValidator = getAndWriteScript Ledger.unValidatorScript