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

FromData and ToData

On-chain, all data is stored in a universal format called Data (Plutus Core Data). Datums, redeemers, and script context are all encoded as Data. Scalus provides type-safe conversions to work with your Scala types instead of raw Data.

Quick Usage

// Convert Data to a typed value val owner = datum.to[PubKeyHash] // Convert a typed value to Data val data = myValue.toData

On-chain, to[T] is a retag, not a decoder: it compiles to nothing. No constructor tag is checked, no field count is verified, and fields are read from the underlying Data only when your code touches them. In particular, never cast to a concrete variant of a sealed hierarchy (redeemer.to[Order.Buy]) – match on the parent type instead. See The Constructor Tag.

Using Data in Validators

In validators, you receive Data and convert it to typed values:

@Compile object MyValidator extends Validator: inline override def spend(datum: Option[Data], redeemer: Data, tx: TxInfo, outRef: TxOutRef): Unit = // Extract typed values from Data val owner = datum.getOrFail("Datum not found").to[PubKeyHash] val action = redeemer.to[MyRedeemer] // ... validation logic

Two equivalent ways to convert:

// Using .to[T] extension method (preferred) val myDatum = datumData.to[MyDatumType] // Using fromData function import scalus.uplc.builtin.Data.fromData val myDatum = fromData[MyDatumType](datumData)

Deriving Instances

Scalus provides type classes FromData and ToData to convert between user-defined types and Data. Derive instances automatically using Scala 3’s derives syntax.

One caveat - you must always supply a companion object with @Compile annotation on it even if it is empty. This is because Scalus needs to compile the companion object to include the FromData instance in the UPLC script.

import scalus.uplc.builtin.*, Builtins.*, Data.* case class Account(hash: ByteString, balance: BigInt) derives FromData, ToData @Compile object Account enum State derives FromData, ToData: case Empty case Active(account: Account) @Compile object State

Here’s an example of converting standard and user-defined types to and from Data.

import scalus.uplc.builtin.*, Builtins.*, Data.* case class Account(hash: ByteString, balance: BigInt) enum State: case Empty case Active(account: Account) val fromDataExample = compile { // The `fromData` function is used to convert a `Data` value to a typed Scala value. val data = iData(123) // fromData is a method that looks up the appropriate `FromData` instance for the type // there are instances for all built-in types val a = fromData[BigInt](data) // also you can use extension method `to` on Data val b = data.to[BigInt] // you can define your own `FromData` instances { given FromData[Account] = (d: Data) => { val args = unConstrData(d).snd Account(args.head.to[ByteString], args.tail.head.to[BigInt]) } val account = data.to[Account] } // or you can use a macro to derive the FromData instance { given FromData[Account] = FromData.derived given FromData[State] = FromData.derived } }

You can derive FromData instances for your case classes and enums via standard Scala 3 derives syntax.

Last updated on