Skip to Content
Scalus Club is now open! Join us to get an early access to new features 🎉

Scalus SBT Plugin

The ScalusSbtPlugin adds two sbt tasks to your project: blueprint for embedding CIP-57  blueprint JSON files into JARs, and deploy for publishing a contract as a reference script UTxO via Blockfrost.

Projects scaffolded from the hello.g8 or validator.g8 templates come with this plugin already wired in, so the blueprint and deploy tasks below work out of the box. (Those templates also select the test backend and profiling through the SCALUS_TEST_ENV and SCALUS_PROFILE environment variables — see Project Commands.) The setup below is for adding the plugin to an existing project.

Setup

project/plugins.sbt:

addSbtPlugin("org.scalus" % "scalus-sbt-plugin" % "<scalus-version>")

build.sbt:

lazy val myProject = (project in file(".")) .enablePlugins(ScalusSbtPlugin) .settings( scalaVersion := "3.3.7", addCompilerPlugin("org.scalus" % "scalus-plugin" % "<scalus-version>" cross CrossVersion.full), libraryDependencies ++= Seq( "org.scalus" %% "scalus" % "<scalus-version>", "org.scalus" %% "scalus-cardano-ledger" % "<scalus-version>", ), )

The plugin was previously named ScalusBlueprintPlugin. That name still works as a deprecated alias, so existing builds keep compiling; switch to ScalusSbtPlugin to clear the warning.

The compiler plugin discovers objects extending Contract automatically. Each one needs a compiled validator and a blueprint:

@Compile object MyValidator extends Validator { inline override def spend( datum: Option[Data], redeemer: Data, tx: TxInfo, ownRef: TxOutRef ): Unit = { val owner = datum.getOrFail("No datum").to[PubKeyHash] require(tx.signatories.contains(owner), "Not signed by owner") } } object MyContract extends Contract { private given Options = Options.release lazy val compiled = PlutusV3.compile(MyValidator.validate) lazy val blueprint = Blueprint.plutusV3[PubKeyHash, Unit]( title = "My Validator", description = "Owner-signed spending validator", version = "1.0.0", license = None, compiled = compiled ) }

Blueprint Generation

When a Cardano smart contract is deployed on-chain, only its script hash is visible. How do you verify that a given source code produced that hash?

The verifiable artifact is the JAR. The blueprint task generates a CIP-57 blueprint JSON for every Contract in the project and writes it to META-INF/scalus/blueprints/. Each blueprint contains the compiledCode (CBOR hex) and hash (script hash), so anyone with the JAR, or anyone who can build it from source, can independently confirm the on-chain script hash.

sbt package

blueprint is a resource generator, so package (and publish) embed the JSON automatically:

[info] Wrote META-INF/scalus/blueprints/MyContract.json

Run sbt blueprint to generate without packaging. To skip generation during package, set blueprint / skip := true in build.sbt, or pass SCALUS_SKIP_BLUEPRINT=1.

sbt package is the standard sbt command for producing a JAR. A JAR is just a ZIP archive, so standard tools work to inspect it:

unzip -p my-project.jar META-INF/scalus/blueprints/MyContract.json

The hash field is the standard Cardano script hash: blake2b_224(0x03 || compiledCode). If you have the JAR, you can verify that this hash matches what’s deployed on-chain. No Scalus installation or JVM required for verification, just the JAR and a blake2b implementation.

Disabling blueprint generation

Because blueprint is a resource generator, it runs whenever the resources are needed — package, publish, run, and test. There are two ways to turn it off.

Disable it for a project in build.sbt:

blueprint / skip := true

Or skip it for a single command, without editing the build, via an environment variable:

SCALUS_SKIP_BLUEPRINT=1 sbt package

Both leave the explicit task untouched: sbt blueprint still generates on demand, regardless of skip. Use skip when you want fast test/package cycles and only generate blueprints deliberately (for example, in a release step or CI job).

Deploying Contracts

The deploy task creates a reference script UTxO from a Contract object. It extracts the compiled script, attaches it to a new UTxO, builds and signs the transaction, and submits it via Blockfrost.

sbt "deploy MyContract --network preprod --blockfrost-key <key> --mnemonic '<24 words>' --address <bech32-address>"

The first argument is the simple name of your Contract object. Named flags:

FlagEnv VariableDefaultDescription
--networkCARDANO_NETWORKpreviewpreview, preprod, or mainnet
--blockfrost-keyBLOCKFROST_API_KEYBlockfrost API key
--mnemonicCARDANO_MNEMONICBIP-39 mnemonic phrase
--addressBech32 address for the reference script UTXO

CLI flags take precedence over environment variables. Using env vars avoids secrets in shell history:

export BLOCKFROST_API_KEY=preprodXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX export CARDANO_MNEMONIC="word1 word2 ... word24" export CARDANO_NETWORK=preprod sbt "deploy MyContract --address addr_test1q..."

Example output:

[info] Deploying contract 'MyContract' to preprod... [info] Tx e484fdac... submitted successfully [info] Deployed successfully! Transaction hash: e484fdac...

What’s Next?

Last updated on