Write States heading-link-icon

This tutorial guides you through writing the two states An immutable object representing a fact known by one or more participants at a specific point in time. You can use states to represent any type of data, and any kind of fact. you need in your CorDapp Corda Distributed Application. A Java (or any JVM targeting language) application built using the Corda build toolchain and CorDapp API to solve some problem that is best solved in a decentralized manner. : AppleStamp and BasketofApples. You will create these states in the contracts/src/main/kotlin/com/r3/developers/apples/states directory.

After you have completed this tutorial, you will know how to create and implement states in a CorDapp.

Before you start building states, read more about states.

First, create the AppleStamp state. This state is the voucher issued to customers.

  1. Go to the contracts/src/main/kotlin/com/r3/developers/apples folder.
  2. Right-click the states folder, select New > Kotlin Class and create a file called AppleStamp.
  3. Open the file.

The first thing you should do when writing a state is add the @BelongsToContract annotation. This annotation establishes the relationship between a state and a contract. Without this, your state does not know which contract is used to verify it.

Add the annotation @BelongsToContract(AppleStampContract::class) to your state. The contract will be defined later.

Your code should now look like:

@BelongsToContract(AppleStampContract::class)

When naming your CorDapp files, it’s best practice to match your contract and state names. In this case the state is called AppleStamp, so the contract is called AppleStampContract. Follow this naming convention when you write your own original CorDapp to avoid confusion.

The next line of code you add defines the type of ContractState you implement with the AppleStamp class. Add this line to ensure that Corda recognizes the AppleStamp as a state.

Add the public class AppleStamp implementing a ContractState.

Your code should now look as follows:

@BelongsToContract(AppleStampContract::class)
class AppleStamp : ContractState
  1. Add the properties for the following parameters required for the example:

    • The stamp identifier (id)
    • The stamp description (stampDesc)
    • The issuer of the stamp (issuer)
    • The current owner of the stamp (holder)
  2. All ContractStates must include a parameter to indicate the participants that store the states. As ContractState is a Java API, you must store the participants as private members Corda identity that has been granted admission to a membership group. Synonym for a virtual node or group member. . Add this property to the AppleStamp:

    private val participants: List<PublicKey>
    
  3. To expose the participants value, override the getParticipants() method in the AppleStamp:

    override fun getParticipants(): List<PublicKey> = participants
    

After following these steps, your code should look as follows:

@BelongsToContract(AppleStampContract::class)
class AppleStamp(
    val id: UUID,
    val stampDesc: String,
    val issuer: PublicKey,
    val holder: PublicKey,
    private val participants: List<PublicKey>
) : ContractState {

    override fun getParticipants(): List<PublicKey> = participants
}

If you are using IntelliJ or another IDE, the IDE automatically adds the imports you need. IntelliJ indicates that an import is missing with red text.

Once you have added all imports, your code should look like this:

package com.r3.developers.apples.states

import com.r3.developers.apples.contracts.AppleStampContract
import net.corda.v5.ledger.utxo.BelongsToContract
import net.corda.v5.ledger.utxo.ContractState
import java.security.PublicKey
import java.util.*

@BelongsToContract(AppleStampContract::class)
class AppleStamp(
    val id: UUID,
    val stampDesc: String,
    val issuer: PublicKey,
    val holder: PublicKey,
    private val participants: List<PublicKey>
) : ContractState {

    override fun getParticipants(): List<PublicKey> = participants
}

The BasketOfApples state is the basket of apples that Farmer Bob self-issues to prepare the apples for Dave. Now that you have written your first state, try writing the BasketOfApples state using the following properties:

  • description - The brand or type of apple. Use type String.
  • farm - The origin of the apples. Use type PublicKey.
  • owner - The current owner of the basket. Use type PublicKey.
  • weight - The weight of the basket of apples. Use type Int.

You will also need to define a participants property and override the getParticipants() getter method, as you did when creating the AppleStamp contract.

The BasketOfApples state is involved in two transactions. In the first transaction A transaction is a proposal to update the ledger. , Farmer Bob self-issues the BasketOfApples. At this point, Farmer Bob is both the owner and farm of the transaction. The second transaction occurs when Dave wishes to redeem his AppleStamp for the BasketOfApples. At this point, the owner changes from Bob to Dave.

To enable this, implement a changeOwner function within the state. It allows an updated state to be returned with a new owner. Add the following code to your BasketOfApples state class:

fun changeOwner(buyer: PublicKey): BasketOfApples {
    val participants = listOf(farm, buyer)
    return BasketOfApples(description, farm, buyer, weight, participants)
}

Once you’ve written the BasketOfApples state, check your code against the sample below. Your code should look something like this:

package com.r3.developers.apples.states

import com.r3.developers.apples.contracts.BasketOfApplesContract
import net.corda.v5.ledger.utxo.BelongsToContract
import net.corda.v5.ledger.utxo.ContractState
import java.security.PublicKey

@BelongsToContract(BasketOfApplesContract::class)
class BasketOfApples(
    val description: String,
    val farm: PublicKey,
    val owner: PublicKey,
    val weight: Int,
    private val participants: List<PublicKey>
) : ContractState {

    override fun getParticipants(): List<PublicKey> = participants

    fun changeOwner(buyer: PublicKey): BasketOfApples {
        val participants = listOf(farm, buyer)
        return BasketOfApples(description, farm, buyer, weight, participants)
    }
}

Follow the Write Contracts tutorial to continue on this learning path.

Was this page helpful?

Thanks for your feedback!

Chat with us

Chat with us on our #docs channel on slack. You can also join a lot of other slack channels there and have access to 1-on-1 communication with members of the R3 team and the online community.

Propose documentation improvements directly

Help us to improve the docs by contributing directly. It's simple - just fork this repository and raise a PR of your own - R3's Technical Writers will review it and apply the relevant suggestions.

We're sorry this page wasn't helpful. Let us know how we can make it better!

Chat with us

Chat with us on our #docs channel on slack. You can also join a lot of other slack channels there and have access to 1-on-1 communication with members of the R3 team and the online community.

Create an issue

Create a new GitHub issue in this repository - submit technical feedback, draw attention to a potential documentation bug, or share ideas for improvement and general feedback.

Propose documentation improvements directly

Help us to improve the docs by contributing directly. It's simple - just fork this repository and raise a PR of your own - R3's Technical Writers will review it and apply the relevant suggestions.