How to implement your well designed CorDapp
September 07, 2020
In my previous article, we had designed a badge CorDapp. In this article, we will go through the implementation journey of the CorDapp. As a result, you will have a template for systematically implementing a CorDapp.
Customize the Badge project from template CorDapp
- Clone the template code from Corda’s Github home page (Java version, kotlin version). Open the project in your choice of IDE. We will continue the tutorial using the Java template using IntelliJ.
- Before we edit any code, we would need to do some housekeeping to customize the template project to customized setups, such as changing the package name (shown in the below screenshot) and some other dependencies to “badge”.
TIPS: you can do a holistic search by holding Cmd+shft + f and look for any occurrence of the word template, and selectively change the related ones to the badge.
Now, we are ready to implement the code for our badge CorDapp.
In the previous article, we divided our Badge CorDapp into these four modules. Along with these modules, we will also implement some tester as well. We will implement as the order of:
- Required Network Participants
- Corda States & Corda Contract
- Unit test for States and Contract
- Corda flows
- Unit test for flows
Network Participants
In the previous designing phase, we decide that we have three nodes to demonstrate our simple badge system. In the real production environment, the network will be handled by the network operators. However, during the development process, we will be running our application on a bootstrapped local network. Then we will progress to the remote server to test database integration and etc. So let’s configure the bootstrapper.
? Navigate to the build.gradle
in the project root level, and scroll to the task deployNodes
function. You will see one nodeDefaults
and 3 node
instances named Notary, PartyA, and PartyB. Leave the Notary instance untouched and change the node name to IssuerNode, YourName, and add another node called ByStandar. (Remember to modify the RPC address to a different address). That is all we need to configure to bootstrap 3 nodes in a network.
The State
In our design, we decide that the build block of our Badge app will be a Badge State and we gave a set of attributes to our badge state, such as Name
, Badge ID
, and etc.
? Navigate to /contracts/main/java/com/badge/states
and create a new state java file BadgeState.java
that contains all the attributes.
Tips:
BelongsToContract
annotation defines which contract should this state follows. This annotation will create a bond between the state and the Contract.- There is great flexibility in what you can have in the state class, such as a private method that modifies the states.
BadgeState Implementation:
The Contract
In our design, we mentioned that Contracts are the checks that transactions would need to go through. Each State is linked to a contract. Inside of the contract, it consists of one verify method and Commands sub-interface, which describes different intends of the different transactions involving the pegged state.
? Navigate to /contracts/main/java/com/badge/contracts
and create a new contract java file BadgeContract.java
.
Notes:
- The command interface indicates the intends of different transactions. We will also implement the verify methods accordingly.
BadgeContract Implementation:
Unit test for States & Contract
The reason we implement unit tests at this point is that States and contracts are strictly coupled. It is better we test them together.
? Navigate to workflows/src/test/java/com/badge
and create a StateTest.java file and modify the existing ContractTest.java
StateTest implementation:
ContractTest implementation:
The Flows
In our design article, we planned that we will have two flows.
1. Issue flow that issues the badge
2. Show flow that display the badge while the badge still has available show counts.
? Navigate to workflows/src/main/java/com/badge/flows
and create IssueFlow and ShowFlow java files.
Note:
- In our design, only the receiver cares about the badge state. Therefore, only the receiver will store the BadgeState in their database.
- The issuing process involves the issuer and receiver, so it will have two signatures on the transaction. Whereas, the showbadge flow only matters to the receiver, so we only ask for the receiver’s signature.
IssueFlow implementation:
ShowFlow implementation:
Unit test for the Flows
We need to customize the flow a little bit before we implement the flow test. we would need to change the String return type to signedTransaction in order to use the unit tests. If you go to Line #25, #53, and #91, you should see the return type is String for better information displaying. Change it to SignedTransaction in order to use the flow test.
? Navigate to workflows/src/test/java/com/badge
and create a FlowTests.java file
Running the Badge CorDapp
Step 1: Deploy and Run the nodes:
./gradlew deployNodes
./build/nodes/runnodes
Step 2: Test the flow
- Issue a badge from IssuerNode to PeterLi:
flow start IssueInitiator badgeName: BestCoder, receiver: PeterLi, description: Best Software developer in town, showCounts: 2
. This should output a message with the Badge ID which we will need to use in the next flow. - Show the badge:
flow start ShowBadge badgeId: <xxxx-xxxx-xxxxx-xxx>
(replace the badge ID with the one from the previous return message.)
You can query the BadgeState at any time by run: run vaultQuery contractStateType: com.badge.states.BadgeState
Congratulations, you had completely implemented a simple CorDapp.
Peter Li is a Developer Evangelist at R3, an enterprise blockchain software firm working with a global ecosystem of more than 350 participants across multiple industries from both the private and public sectors to develop on Corda, its open-source blockchain platform, and Corda Enterprise, a commercial version of Corda for enterprise usage.
Follow us on twitter here.