SlideShare a Scribd company logo
1 of 34
Download to read offline
A Simple Write/Read
Example with R3 Corda
Eric Lee

cheng-yu.eric.lee@accenture.com
Objectives
• Define a database schema in Corda “State”

• Define the contract rules and data flows

• Unit test design

• Create REST API to write and read the data

• Test with POSTMAN
Preparation
• Install Oracle Java JDK 8 (Build >139)

• Install IntelliJ 2017.2

• Clone example code from git repository
Clone the Example From Git
git clone https://github.com/DAYUCS/cordapp-bill-of-lading.git
*M14 based
Define the Schema
date seller buyer referenceNumber totalAmount
I want to record this five columns to ledger as order information.
Open the Cloned Project by
IntelliJ 2017.02
1 2
3 4
From File menu, click “Open”
Browse the cloned folder and open
Click “Import Gradle Project” Apply default configuration, click “OK” button
Add IDE Panels
View > Tool Windows > Project
Can see the folder structure now.
You can add “Terminal” panel too.
Modelling the Solution with
Corda
• Define the State

The data model, the record you want to store in the
ledger, define the table schema.

• Define the Contract

The relationships between participants, obligations and
the rules.

• Define the Flow

The workflow for data commitment.
State Related Files (Classes)
• Model

Data structure for participants. REST API requires these
fields for JSON data submission.

• Schema

Column name definition for H2 database.

• State

Data class for state, invoked the Model and Schema
classes.
Create Order class in model
1. Right click on kotlin-source/src/main/kotlin/com.example/model ,

New > Kotlin Files/Class
2. Name is Order, Kind is Class.
3. Add this new file(class) to git or not?
Edit the Code for Order.kt
package com.example.model



import net.corda.core.serialization.CordaSerializable



@CordaSerializable 

data class Order(val referenceNumber: String, val totalAmount: Double)
Field name is referenceNumber, data type is string. Field name is totalAmount, data type is double.
Create the Code for
Schema
•Create OrderSchema.kt under kotlin-source/src/main/kotlin/
com.example/schema

package com.example.schema

import net.corda.core.schemas.MappedSchema
import net.corda.core.schemas.PersistentState
import java.time.Instant
import java.util.*
import javax.persistence.Column
import javax.persistence.Entity
import javax.persistence.Table
object OrderSchema
object OrderSchemaV1 : MappedSchema(
schemaFamily = OrderSchema.javaClass,
version = 1,
mappedTypes = listOf(PersistentBL::class.java)) {
@Entity
@Table(name = "order_states")
class PersistentBL(
@Column(name = "seller_name")
var sellerName: String,
@Column(name = "buyer_name")
var buyerName: String,
@Column(name = "amount")
var totalAmount: Double,
@Column(name = "reference_no")
var referenceNumber: String,
@Column(name = "date")
var date: Instant
) : PersistentState()
}
Table name and column name for H2 database.

We create a “order_states” table with five columns: 

seller_name, buyer_name, amount, reference_no and 

date.
Create the Code for State
• Create OrderState class under kotlin-source/src/main/kotlin/com.example/state

package com.example.state
import com.example.contract.OrderContract
import com.example.model.Order
import com.example.schema.OrderSchemaV1
import net.corda.core.contracts.ContractState
import net.corda.core.contracts.LinearState
import net.corda.core.contracts.UniqueIdentifier
import net.corda.core.identity.AbstractParty
import net.corda.core.identity.Party
import net.corda.core.schemas.MappedSchema
import net.corda.core.schemas.PersistentState
import net.corda.core.schemas.QueryableState
import net.corda.core.crypto.keys
import java.security.PublicKey
import java.time.Instant
import java.util.*
data class OrderState(val order: Order,
val seller: Party,
val buyer: Party,
val date: Instant = Instant.now(),
override val linearId: UniqueIdentifier = UniqueIdentifier()
): LinearState, QueryableState {
override val contract get() = OrderContract()
/** The public keys of the involved parties. */
override val participants: List<AbstractParty> get() = listOf(buyer)
/** Tells the vault to track a state if we are one of the parties involved. */
override fun isRelevant(ourKeys: Set<PublicKey>) = ourKeys.intersect(participants.flatMap { it.owningKey.keys }).isNotEmpty()
fun withNewOwner(newOwner: Party) = copy(buyer = newOwner)
override fun generateMappedObject(schema: MappedSchema): PersistentState {
return when (schema) {
is OrderSchemaV1 -> OrderSchemaV1.PersistentBL(
sellerName = this.seller.name.toString(),
buyerName = this.buyer.name.toString(),
referenceNumber = this.order.referenceNumber,
totalAmount = this.order.totalAmount,
date = Instant.now()
)
else -> throw IllegalArgumentException("Unrecognised schema $schema")
}
}
override fun supportedSchemas(): Iterable<MappedSchema> = listOf(OrderSchemaV1)
}
State variables and its data type.
Mapping the database schema to state 

variables.
Got Errors?
Missing class/function, will create a “Contract"
Create the Contract Code
• Create OrderContract class under kotlin-source/src/main/kotlin/com.example/contract

package com.example.contract

import com.example.state.OrderState
import net.corda.core.contracts.*
import net.corda.core.crypto.SecureHash
import net.corda.core.transactions.LedgerTransaction
open class OrderContract : Contract {
override fun verify(tx: LedgerTransaction) {
val command = tx.commands.requireSingleCommand<Commands>()
when (command.value) {
is Commands.Issue -> {
// Issuance verification logic.
requireThat {
// Generic constraints around the order transaction.
"No inputs should be consumed when issuing an order." using (tx.inputs.isEmpty())
"Only one output state should be created." using (tx.outputs.size == 1)
val out = tx.outputsOfType<OrderState>().single()
"The seller and the buyer cannot be the same entity." using (out.seller != out.buyer)
"The amount cannot be 0." using (out.order.totalAmount != 0.0)
"The seller and the buyer must be signers." using (command.signers.containsAll(listOf(out.seller.owningKey, out.buyer.owningKey)))
}
}
is Commands.Move -> {
// Transfer verification logic.
requireThat {
"Only one input should be consumed when move an order." using (tx.inputs.size == 1)
"Only one output state should be created." using (tx.outputs.size == 1)
val input = tx.inputsOfType<OrderState>().single()
val out = tx.outputsOfType<OrderState>().single()
"Buyer must be changed when move an order." using(input.buyer != out.buyer)
}
}
}
}
/**
* This contract implements commands: Issue, Move.
*/
interface Commands : CommandData {
class Issue : TypeOnlyCommandData(), Commands
class Move : TypeOnlyCommandData(), Commands
}
/** This is a reference to the underlying legal contract template and associated parameters. */
override val legalContractReference: SecureHash = SecureHash.sha256("contract template and params")
}
The contract supports issue and transfer (move) operations.
The rules for issue operation, using 

programming logic to represent the legal terms
For the legal contract reference, can put the file name, URL or etc.
Contract Details Example
// Issuance verification logic.
requireThat {
// Generic constraints around the order transaction.
"No inputs should be consumed when issuing an order." using (tx.inputs.isEmpty())
"Only one output state should be created." using (tx.outputs.size == 1)
val out = tx.outputsOfType<OrderState>().single()
"The seller and the buyer cannot be the same entity." using (out.seller != out.buyer)
"The amount cannot be 0." using (out.order.totalAmount != 0.0)
"The seller and the buyer must be signers." using
(command.signers.containsAll(listOf(out.seller.owningKey, out.buyer.owningKey)))
}
•If no transaction input, cannot create the contract.
•After the contract execution, only one output.
•Cannot sell the goods/service to yourself.
•Transaction amount must greater than zero.
•Valid contract requires the signature from Seller and buyer.
Error Disappear
Contract related errors fixed. (From red to black )

The contract controls the data commitment.
Create the Order Flow
Generate the order details
Check the order details follow
the contract or not
Sign the transaction
Pass the contract to counter
party for signature
All parties signed the
transaction, send to notary
for verification
Create the order details based on the required 

data defined by model and state.
Compare the order details and the contract, the 

value must match the contract rules.
If the order match the contract, sign it.
Counter party has to sign the transaction also.
All parties signed the transaction, the notary 

node verify it. If no error, commit to ledger.
Create the Order Flow Code
• Create CreateOrderFlow object under kotlin-source/src/main/kotlin/com.example/flow
package com.example.flow
import co.paralleluniverse.fibers.Suspendable
import com.example.contract.OrderContract
import com.example.flow.CreateOrderFlow.Acceptor
import com.example.flow.CreateOrderFlow.Initiator
import com.example.state.OrderState
import net.corda.core.contracts.Command
import net.corda.core.contracts.TransactionType
import net.corda.core.contracts.requireThat
import net.corda.core.flows.*
import net.corda.core.identity.Party
import net.corda.core.transactions.SignedTransaction
import net.corda.core.transactions.TransactionBuilder
import net.corda.core.utilities.ProgressTracker
object CreateOrderFlow {
@InitiatingFlow
@StartableByRPC
class Initiator(val orderState: OrderState,
val otherParty: Party): FlowLogic<SignedTransaction>() {
/**
* The progress tracker checkpoints each stage of the flow and outputs the specified messages when each
* checkpoint is reached in the code. See the 'progressTracker.currentStep' expressions within the call() function.
*/
companion object {
object GENERATING_TRANSACTION : ProgressTracker.Step("Generating transaction based on new order.")
object VERIFYING_TRANSACTION : ProgressTracker.Step("Verifying contract constraints.")
object SIGNING_TRANSACTION : ProgressTracker.Step("Signing transaction with our private key.")
object GATHERING_SIGS : ProgressTracker.Step("Gathering the counterparty's signature.") {
override fun childProgressTracker() = CollectSignaturesFlow.tracker()
}
object FINALISING_TRANSACTION : ProgressTracker.Step("Obtaining notary signature and recording transaction.") {
override fun childProgressTracker() = FinalityFlow.tracker()
}
fun tracker() = ProgressTracker(
GENERATING_TRANSACTION,
VERIFYING_TRANSACTION,
SIGNING_TRANSACTION,
GATHERING_SIGS,
FINALISING_TRANSACTION
)
}
override val progressTracker = tracker()
/**
* The flow logic is encapsulated within the call() method.
*/
@Suspendable
override fun call(): SignedTransaction {
// Obtain a reference to the notary we want to use.
val notary = serviceHub.networkMapCache.notaryNodes.single().notaryIdentity
// Stage 1.
progressTracker.currentStep = GENERATING_TRANSACTION
// Generate an unsigned transaction.
val txCommand = Command(OrderContract.Commands.Issue(), listOf(orderState.seller.owningKey, orderState.buyer.owningKey))
val txBuilder = TransactionBuilder(TransactionType.General, notary).withItems(orderState, txCommand)
// Stage 2.
progressTracker.currentStep = VERIFYING_TRANSACTION
// Verify that the transaction is valid.
txBuilder.toWireTransaction().toLedgerTransaction(serviceHub).verify()
// Stage 3.
progressTracker.currentStep = SIGNING_TRANSACTION
val partSignedTx = serviceHub.signInitialTransaction(txBuilder)
// Stage 4.
progressTracker.currentStep = GATHERING_SIGS
// Send the state to the counterparty, and receive it back with their signature.
val fullySignedTx = subFlow(CollectSignaturesFlow(partSignedTx, GATHERING_SIGS.childProgressTracker()))
// Stage 5.
progressTracker.currentStep = FINALISING_TRANSACTION
// Notarise and record the transaction in both parties' vaults.
return subFlow(FinalityFlow(fullySignedTx, FINALISING_TRANSACTION.childProgressTracker())).single()
}
}
@InitiatedBy(Initiator::class)
class Acceptor(val otherParty: Party) : FlowLogic<SignedTransaction>() {
@Suspendable
override fun call(): SignedTransaction {
val signTransactionFlow = object : SignTransactionFlow(otherParty) {
override fun checkTransaction(stx: SignedTransaction) = requireThat {
val output = stx.tx.outputs.single().data
"This must be an order transaction." using (output is OrderState)
}
}
return subFlow(signTransactionFlow)
}
}
}
Required steps of the flow.
Steps implementation.
Discuss the flow implementation later.
Required Steps
companion object {
object GENERATING_TRANSACTION : ProgressTracker.Step("Generating transaction based on new order.")
object VERIFYING_TRANSACTION : ProgressTracker.Step("Verifying contract constraints.")
object SIGNING_TRANSACTION : ProgressTracker.Step("Signing transaction with our private key.")
object GATHERING_SIGS : ProgressTracker.Step("Gathering the counterparty's signature.") {
override fun childProgressTracker() = CollectSignaturesFlow.tracker()
}
object FINALISING_TRANSACTION : ProgressTracker.Step("Obtaining notary signature and recording transaction.") {
override fun childProgressTracker() = FinalityFlow.tracker()
}
fun tracker() = ProgressTracker(
GENERATING_TRANSACTION,
VERIFYING_TRANSACTION,
SIGNING_TRANSACTION,
GATHERING_SIGS,
FINALISING_TRANSACTION
)
}
Progress description for ProgressTracker
Progress item
Steps Logic Implementation
@Suspendable
override fun call(): SignedTransaction {
// Obtain a reference to the notary we want to use.
val notary = serviceHub.networkMapCache.notaryNodes.single().notaryIdentity
// Stage 1.
progressTracker.currentStep = GENERATING_TRANSACTION
// Generate an unsigned transaction.
val txCommand = Command(OrderContract.Commands.Issue(), listOf(orderState.seller.owningKey, orderState.buyer.owningKey))
val txBuilder = TransactionBuilder(TransactionType.General, notary).withItems(orderState, txCommand)
// Stage 2.
progressTracker.currentStep = VERIFYING_TRANSACTION
// Verify that the transaction is valid.
txBuilder.toWireTransaction().toLedgerTransaction(serviceHub).verify()
// Stage 3.
progressTracker.currentStep = SIGNING_TRANSACTION
val partSignedTx = serviceHub.signInitialTransaction(txBuilder)
// Stage 4.
progressTracker.currentStep = GATHERING_SIGS
// Send the state to the counterparty, and receive it back with their signature.
val fullySignedTx = subFlow(CollectSignaturesFlow(partSignedTx, GATHERING_SIGS.childProgressTracker()))
// Stage 5.
progressTracker.currentStep = FINALISING_TRANSACTION
// Notarise and record the transaction in both parties' vaults.
return subFlow(FinalityFlow(fullySignedTx, FINALISING_TRANSACTION.childProgressTracker())).single()
}
To initialise the transaction, need to know which transaction 

command and have a transaction builder.
Build the transaction and service hub check it by contract rules.
The party who proposed the transaction sign first.
Other party sign the transaction
Got all signatures, “FinalityFlow" will commit the transaction

to ledger.
Code for Unit Test
• Create an OrderContractTest class under kotlin-sourcesrctestkotlincom.examplecontract and paste the following codes

package com.example.contract
import com.example.flow.CreateOrderFlow
import com.example.model.Order
import com.example.state.OrderState
import net.corda.core.getOrThrow
import net.corda.testing.node.MockNetwork
import org.junit.After
import org.junit.Before
import org.junit.Test
import java.time.Instant
import java.util.*
import kotlin.test.assertEquals
import kotlin.test.assertTrue
import kotlin.test.fail
class OrderContractTest {
lateinit var net: MockNetwork
lateinit var a: MockNetwork.MockNode
lateinit var b: MockNetwork.MockNode
@Before
fun setup() {
net = MockNetwork()
val nodes = net.createSomeNodes(3)
a = nodes.partyNodes[0]
b = nodes.partyNodes[1]
// For real nodes this happens automatically, but we have to manually register the flow for tests
nodes.partyNodes.forEach { it.registerInitiatedFlow(CreateOrderFlow.Acceptor::class.java) }
net.runNetwork()
}
@After
fun tearDown() {
net.stopNodes()
}
@Test
fun `Order amount must greater than zero`(){
val state = OrderState(Order("a01",0.0),
a.info.legalIdentity,
b.info.legalIdentity,
Instant.now()
)
try {
val flow = CreateOrderFlow.Initiator(state, b.info.legalIdentity)
val future = a.services.startFlow(flow).resultFuture
net.runNetwork()
val signedTx = future.getOrThrow()
fail("No exception thrown!!")
} catch(e:Exception){
assertTrue(e.message.toString().contains(Regex("Contract verification failed: Failed requirement")))
}
}
}
Template for Corda Unit
Test Code
• Mock network creation

lateinit var net: MockNetwork
lateinit var a: MockNetwork.MockNode
lateinit var b: MockNetwork.MockNode
@Before
fun setup() {
net = MockNetwork()
val nodes = net.createSomeNodes(2)
a = nodes.partyNodes[0]
b = nodes.partyNodes[1]
// For real nodes this happens automatically, but we have to manually register the flow
for tests
nodes.partyNodes.forEach
{ it.registerInitiatedFlow(CreateOrderFlow.Acceptor::class.java) }
net.runNetwork()
}
@After
fun tearDown() {
net.stopNodes()
}
Create two nodes (a and b) in Corda mock network
Start the nodes before testing
After testing, destroy the mock nodes
Unit Test Example
@Test
fun `Order amount must greater than zero`(){
val state = OrderState(Order("a01",0.0),
a.info.legalIdentity,
b.info.legalIdentity,
Instant.now()
)
try {
val flow = CreateOrderFlow.Initiator(state, b.info.legalIdentity)
val future = a.services.startFlow(flow).resultFuture
net.runNetwork()
val signedTx = future.getOrThrow()
fail("No exception thrown!!")
} catch(e:Exception){
assertTrue(e.message.toString().contains(Regex("Contract verification failed:
Failed requirement")))
}
}
Story: I want to test if the order amount is zero
Propose an order, a have a deal with b, 

the amount is 0
Start the transaction
With an exception is positive, the error has this message string pattern.
If the transaction done, judge the test is fail.
Run the test
• Right click on the OrderContractTest class, click “Run
OrderContractTest”.

• The test should failed with the error message as the
screenshot shown.
Add VM Option
Run > Edit Configuration
-ea -javaagent:../lib/quasar.jar
Test Pass
You can create unit test cases, the code structure/style similar to jUnit.
Create REST API
• Add the following codes to kotlin-source/src/main/kotlin/com.example/api/ExampleApi.kt

• Retrieve all orders (GET method)

@GET
@Path("orders")
@Produces(MediaType.APPLICATION_JSON)
fun getOrders(): List<StateAndRef<OrderState>>{
val vaultStates = services.vaultQueryBy<OrderState>()
return vaultStates.states
}
• Create Order (PUT method)

@PUT
@Path("{seller}/{buyer}/create-order")
fun createOrder(order: Order,
@PathParam("seller") seller: X500Name,
@PathParam("buyer") buyer: X500Name) : Response{
val seller =services.partyFromX500Name(seller)
if (seller == null){
return Response.status(Response.Status.BAD_REQUEST).build()
}
val buyer = services.partyFromX500Name(buyer)
if (buyer == null){
return Response.status(Response.Status.BAD_REQUEST).build()
}
val state = OrderState(
order,
seller,
buyer,
date = Instant.now()
)
val (status, msg) = try {
val flowHandle = services.
startTrackedFlowDynamic(CreateOrderFlow.Initiator::class.java, state, seller)
flowHandle.progress.subscribe { println(">> $it") }
val result = flowHandle.returnValue.getOrThrow()
Response.Status.CREATED to "Transaction id ${result.id} committed to ledger."
} catch (ex: Throwable){
logger.error(ex.message, ex)
Response.Status.BAD_REQUEST to "Transaction failed."
}
return Response.status(status).entity(msg).build()
}
Build Project
• Open the terminal for project in IntelliJ, execute the three
commands

• ./gradlew clean
• ./gradlew build
• ./gradlew deployNodes
Deployment in Dev Mode
• Change working directory to {your project folder}/kotlin-
source/build/nodes

• runnodes (Windows: runnodes.bat Others: runnodes )
1. Run the runnodes script
2. Starting the 4 nodes in terminal 

or CMD windows
depolyNodes Configuration File
• kotlin-source/build.gradle
Node name (X.509 format)
Port numbers for different purposes.
The configuration file defined the nodes’ name 

and ports for communication.
Testing with Browser
localhost:10007
localhost:10007/api/example/me
Implemented APIs from ExampleApi.kt
Test “GET” method, browser is a good choice.

But for PUT or POST methods, POSTMAN or curl is better!
Testing with POSTMAN
Node A (seller) create a order with Node C (buyer), the order number is a00001, amount is 3.14
1. Select PUT method
3. Body tab, raw data, MIME is JSON (application/json)
2. URL is http://localhost:10007/api/example/CN=NodeA,O=NodeA,L=London,C=UK/
CN=NodeC,O=NodeC,L=Paris,C=FR/create-order
4. Enter the value of referenceNumber and totalAmount in JSON format.
5. Click send button.
Result it here. Successful commitment will return a hash string.
Validating the Result
Node C should see the order by GET /orders method.
GET method for http://localhost:10013/api/example/orders

Please note port 10013 is for Node C (from build.gradle file)
Returned result
Entered reference number and amount from Node A.
Seller and buyer information, unix timestamped.

More Related Content

What's hot

20180711 Metamask
20180711 Metamask 20180711 Metamask
20180711 Metamask Hu Kenneth
 
Understanding hd wallets design and implementation
Understanding hd wallets  design and implementationUnderstanding hd wallets  design and implementation
Understanding hd wallets design and implementationArcBlock
 
Non-Fungible Token (NFT) Marketplace Development Service Provider
Non-Fungible Token (NFT) Marketplace Development Service ProviderNon-Fungible Token (NFT) Marketplace Development Service Provider
Non-Fungible Token (NFT) Marketplace Development Service ProviderLinda John
 
Hyperledger Fabric Technical Deep Dive 20190618
Hyperledger Fabric Technical Deep Dive 20190618Hyperledger Fabric Technical Deep Dive 20190618
Hyperledger Fabric Technical Deep Dive 20190618Arnaud Le Hors
 
Blockchain Fundamentals for Beginners - 101 Blockchains
Blockchain Fundamentals for Beginners - 101 BlockchainsBlockchain Fundamentals for Beginners - 101 Blockchains
Blockchain Fundamentals for Beginners - 101 Blockchains101 Blockchains Academy
 
Understanding Proof of Work (PoW) and Proof of Stake (PoS) Algorithms
Understanding Proof of Work (PoW) and Proof of Stake (PoS) AlgorithmsUnderstanding Proof of Work (PoW) and Proof of Stake (PoS) Algorithms
Understanding Proof of Work (PoW) and Proof of Stake (PoS) AlgorithmsGautam Anand
 
A Zero-Knowledge Proof: Improving Privacy on a Blockchain
A Zero-Knowledge Proof:  Improving Privacy on a BlockchainA Zero-Knowledge Proof:  Improving Privacy on a Blockchain
A Zero-Knowledge Proof: Improving Privacy on a BlockchainAltoros
 
Smart contracts using web3.js
Smart contracts using web3.jsSmart contracts using web3.js
Smart contracts using web3.jsFelix Crisan
 
Blockchain Study(1) - What is Blockchain?
Blockchain Study(1) - What is Blockchain?Blockchain Study(1) - What is Blockchain?
Blockchain Study(1) - What is Blockchain?Fermat Jade
 
Hyperledger fabric architecture
Hyperledger fabric architectureHyperledger fabric architecture
Hyperledger fabric architectureCeline George
 
Bitcoin, Ethereum, Smart Contract & Blockchain
Bitcoin, Ethereum, Smart Contract & BlockchainBitcoin, Ethereum, Smart Contract & Blockchain
Bitcoin, Ethereum, Smart Contract & BlockchainJitendra Chittoda
 
The Lightning Network - A gentle introduction
The Lightning Network - A gentle introductionThe Lightning Network - A gentle introduction
The Lightning Network - A gentle introductionRoland Stadler
 
Consensus Algorithms: An Introduction & Analysis
Consensus Algorithms: An Introduction & AnalysisConsensus Algorithms: An Introduction & Analysis
Consensus Algorithms: An Introduction & AnalysisZak Cole
 
Write Smart Contract with Solidity on Ethereum
Write Smart Contract with Solidity on EthereumWrite Smart Contract with Solidity on Ethereum
Write Smart Contract with Solidity on Ethereum劉 維仁
 
Overview of Blockchain Consensus Mechanisms
Overview of Blockchain Consensus MechanismsOverview of Blockchain Consensus Mechanisms
Overview of Blockchain Consensus MechanismsJohannes Ahlmann
 

What's hot (20)

Hyperledger Fabric
Hyperledger FabricHyperledger Fabric
Hyperledger Fabric
 
Erc 721 tokens
Erc 721 tokensErc 721 tokens
Erc 721 tokens
 
20180711 Metamask
20180711 Metamask 20180711 Metamask
20180711 Metamask
 
Understanding hd wallets design and implementation
Understanding hd wallets  design and implementationUnderstanding hd wallets  design and implementation
Understanding hd wallets design and implementation
 
Non-Fungible Token (NFT) Marketplace Development Service Provider
Non-Fungible Token (NFT) Marketplace Development Service ProviderNon-Fungible Token (NFT) Marketplace Development Service Provider
Non-Fungible Token (NFT) Marketplace Development Service Provider
 
Hyperledger Fabric Technical Deep Dive 20190618
Hyperledger Fabric Technical Deep Dive 20190618Hyperledger Fabric Technical Deep Dive 20190618
Hyperledger Fabric Technical Deep Dive 20190618
 
Blockchain Fundamentals for Beginners - 101 Blockchains
Blockchain Fundamentals for Beginners - 101 BlockchainsBlockchain Fundamentals for Beginners - 101 Blockchains
Blockchain Fundamentals for Beginners - 101 Blockchains
 
Understanding Proof of Work (PoW) and Proof of Stake (PoS) Algorithms
Understanding Proof of Work (PoW) and Proof of Stake (PoS) AlgorithmsUnderstanding Proof of Work (PoW) and Proof of Stake (PoS) Algorithms
Understanding Proof of Work (PoW) and Proof of Stake (PoS) Algorithms
 
A Zero-Knowledge Proof: Improving Privacy on a Blockchain
A Zero-Knowledge Proof:  Improving Privacy on a BlockchainA Zero-Knowledge Proof:  Improving Privacy on a Blockchain
A Zero-Knowledge Proof: Improving Privacy on a Blockchain
 
Smart contracts using web3.js
Smart contracts using web3.jsSmart contracts using web3.js
Smart contracts using web3.js
 
Blockchain Study(1) - What is Blockchain?
Blockchain Study(1) - What is Blockchain?Blockchain Study(1) - What is Blockchain?
Blockchain Study(1) - What is Blockchain?
 
Hyperledger fabric architecture
Hyperledger fabric architectureHyperledger fabric architecture
Hyperledger fabric architecture
 
Crypto wallets
Crypto walletsCrypto wallets
Crypto wallets
 
Blockchain for dummies
Blockchain for dummiesBlockchain for dummies
Blockchain for dummies
 
Bitcoin, Ethereum, Smart Contract & Blockchain
Bitcoin, Ethereum, Smart Contract & BlockchainBitcoin, Ethereum, Smart Contract & Blockchain
Bitcoin, Ethereum, Smart Contract & Blockchain
 
The Lightning Network - A gentle introduction
The Lightning Network - A gentle introductionThe Lightning Network - A gentle introduction
The Lightning Network - A gentle introduction
 
Consensus Algorithms: An Introduction & Analysis
Consensus Algorithms: An Introduction & AnalysisConsensus Algorithms: An Introduction & Analysis
Consensus Algorithms: An Introduction & Analysis
 
Write Smart Contract with Solidity on Ethereum
Write Smart Contract with Solidity on EthereumWrite Smart Contract with Solidity on Ethereum
Write Smart Contract with Solidity on Ethereum
 
Blockchain
BlockchainBlockchain
Blockchain
 
Overview of Blockchain Consensus Mechanisms
Overview of Blockchain Consensus MechanismsOverview of Blockchain Consensus Mechanisms
Overview of Blockchain Consensus Mechanisms
 

Viewers also liked

COSCUP 2016 Workshop : 快快樂樂學Neo4j
COSCUP 2016 Workshop : 快快樂樂學Neo4jCOSCUP 2016 Workshop : 快快樂樂學Neo4j
COSCUP 2016 Workshop : 快快樂樂學Neo4jEric Lee
 
Neo4j: JDBC Connection Case Using LibreOffice
Neo4j: JDBC Connection Case Using LibreOfficeNeo4j: JDBC Connection Case Using LibreOffice
Neo4j: JDBC Connection Case Using LibreOfficeEric Lee
 
Python and Neo4j
Python and Neo4jPython and Neo4j
Python and Neo4jEric Lee
 
Introduction to 3rd sequencing
Introduction to 3rd sequencing Introduction to 3rd sequencing
Introduction to 3rd sequencing Eric Lee
 
SNP Detection for Massively Parallel Whole-genome Sequencing
SNP Detection for Massively Parallel Whole-genome SequencingSNP Detection for Massively Parallel Whole-genome Sequencing
SNP Detection for Massively Parallel Whole-genome SequencingEric Lee
 
Introduction to Graph Database
Introduction to Graph DatabaseIntroduction to Graph Database
Introduction to Graph DatabaseEric Lee
 
Google MAP API
Google MAP APIGoogle MAP API
Google MAP APIEric Lee
 

Viewers also liked (7)

COSCUP 2016 Workshop : 快快樂樂學Neo4j
COSCUP 2016 Workshop : 快快樂樂學Neo4jCOSCUP 2016 Workshop : 快快樂樂學Neo4j
COSCUP 2016 Workshop : 快快樂樂學Neo4j
 
Neo4j: JDBC Connection Case Using LibreOffice
Neo4j: JDBC Connection Case Using LibreOfficeNeo4j: JDBC Connection Case Using LibreOffice
Neo4j: JDBC Connection Case Using LibreOffice
 
Python and Neo4j
Python and Neo4jPython and Neo4j
Python and Neo4j
 
Introduction to 3rd sequencing
Introduction to 3rd sequencing Introduction to 3rd sequencing
Introduction to 3rd sequencing
 
SNP Detection for Massively Parallel Whole-genome Sequencing
SNP Detection for Massively Parallel Whole-genome SequencingSNP Detection for Massively Parallel Whole-genome Sequencing
SNP Detection for Massively Parallel Whole-genome Sequencing
 
Introduction to Graph Database
Introduction to Graph DatabaseIntroduction to Graph Database
Introduction to Graph Database
 
Google MAP API
Google MAP APIGoogle MAP API
Google MAP API
 

Similar to Simple Corda Order App Write/Read Flow

Blockchain technology-in-fin tech - Anton Sitnikov
Blockchain technology-in-fin tech - Anton SitnikovBlockchain technology-in-fin tech - Anton Sitnikov
Blockchain technology-in-fin tech - Anton SitnikovDataFest Tbilisi
 
GWT.create 2013: Introduction to GXT
GWT.create 2013: Introduction to GXTGWT.create 2013: Introduction to GXT
GWT.create 2013: Introduction to GXTniloc132
 
Strtio Spark Streaming + Siddhi CEP Engine
Strtio Spark Streaming + Siddhi CEP EngineStrtio Spark Streaming + Siddhi CEP Engine
Strtio Spark Streaming + Siddhi CEP EngineMyung Ho Yun
 
BITM3730 10-17.pptx
BITM3730 10-17.pptxBITM3730 10-17.pptx
BITM3730 10-17.pptxMattMarino13
 
Кирилл Безпалый, .NET Developer, Ciklum
Кирилл Безпалый, .NET Developer, CiklumКирилл Безпалый, .NET Developer, Ciklum
Кирилл Безпалый, .NET Developer, CiklumAlina Vilk
 
Building an api using golang and postgre sql v1.0
Building an api using golang and postgre sql v1.0Building an api using golang and postgre sql v1.0
Building an api using golang and postgre sql v1.0Frost
 
Building Event Driven Services with Kafka Streams
Building Event Driven Services with Kafka StreamsBuilding Event Driven Services with Kafka Streams
Building Event Driven Services with Kafka StreamsBen Stopford
 
Ethereum
EthereumEthereum
EthereumV C
 
Paytm integration in swift
Paytm integration in swiftPaytm integration in swift
Paytm integration in swiftInnovationM
 
VBA API for scriptDB primer
VBA API for scriptDB primerVBA API for scriptDB primer
VBA API for scriptDB primerBruce McPherson
 
Introduction to trader bots with Python
Introduction to trader bots with PythonIntroduction to trader bots with Python
Introduction to trader bots with Pythonroskakori
 
Chapter i c#(console application and programming)
Chapter i c#(console application and programming)Chapter i c#(console application and programming)
Chapter i c#(console application and programming)Chhom Karath
 
Using the Tooling API to Generate Apex SOAP Web Service Clients
Using the Tooling API to Generate Apex SOAP Web Service ClientsUsing the Tooling API to Generate Apex SOAP Web Service Clients
Using the Tooling API to Generate Apex SOAP Web Service ClientsDaniel Ballinger
 
Complex Event Processor 3.0.0 - An overview of upcoming features
Complex Event Processor 3.0.0 - An overview of upcoming features Complex Event Processor 3.0.0 - An overview of upcoming features
Complex Event Processor 3.0.0 - An overview of upcoming features WSO2
 
Concurrency Patterns with MongoDB
Concurrency Patterns with MongoDBConcurrency Patterns with MongoDB
Concurrency Patterns with MongoDBYann Cluchey
 

Similar to Simple Corda Order App Write/Read Flow (20)

Blockchain technology-in-fin tech - Anton Sitnikov
Blockchain technology-in-fin tech - Anton SitnikovBlockchain technology-in-fin tech - Anton Sitnikov
Blockchain technology-in-fin tech - Anton Sitnikov
 
GWT.create 2013: Introduction to GXT
GWT.create 2013: Introduction to GXTGWT.create 2013: Introduction to GXT
GWT.create 2013: Introduction to GXT
 
Introduction to Angular JS
Introduction to Angular JSIntroduction to Angular JS
Introduction to Angular JS
 
Strtio Spark Streaming + Siddhi CEP Engine
Strtio Spark Streaming + Siddhi CEP EngineStrtio Spark Streaming + Siddhi CEP Engine
Strtio Spark Streaming + Siddhi CEP Engine
 
BITM3730 10-17.pptx
BITM3730 10-17.pptxBITM3730 10-17.pptx
BITM3730 10-17.pptx
 
Кирилл Безпалый, .NET Developer, Ciklum
Кирилл Безпалый, .NET Developer, CiklumКирилл Безпалый, .NET Developer, Ciklum
Кирилл Безпалый, .NET Developer, Ciklum
 
Building an api using golang and postgre sql v1.0
Building an api using golang and postgre sql v1.0Building an api using golang and postgre sql v1.0
Building an api using golang and postgre sql v1.0
 
Building Event Driven Services with Kafka Streams
Building Event Driven Services with Kafka StreamsBuilding Event Driven Services with Kafka Streams
Building Event Driven Services with Kafka Streams
 
Ethereum
EthereumEthereum
Ethereum
 
Paytm integration in swift
Paytm integration in swiftPaytm integration in swift
Paytm integration in swift
 
Knative Outro
Knative OutroKnative Outro
Knative Outro
 
VBA API for scriptDB primer
VBA API for scriptDB primerVBA API for scriptDB primer
VBA API for scriptDB primer
 
Introduction to trader bots with Python
Introduction to trader bots with PythonIntroduction to trader bots with Python
Introduction to trader bots with Python
 
Linq
LinqLinq
Linq
 
Javantura v6 - Case Study: Marketplace App with Java and Hyperledger Fabric -...
Javantura v6 - Case Study: Marketplace App with Java and Hyperledger Fabric -...Javantura v6 - Case Study: Marketplace App with Java and Hyperledger Fabric -...
Javantura v6 - Case Study: Marketplace App with Java and Hyperledger Fabric -...
 
Chapter i c#(console application and programming)
Chapter i c#(console application and programming)Chapter i c#(console application and programming)
Chapter i c#(console application and programming)
 
Using the Tooling API to Generate Apex SOAP Web Service Clients
Using the Tooling API to Generate Apex SOAP Web Service ClientsUsing the Tooling API to Generate Apex SOAP Web Service Clients
Using the Tooling API to Generate Apex SOAP Web Service Clients
 
Javascript
JavascriptJavascript
Javascript
 
Complex Event Processor 3.0.0 - An overview of upcoming features
Complex Event Processor 3.0.0 - An overview of upcoming features Complex Event Processor 3.0.0 - An overview of upcoming features
Complex Event Processor 3.0.0 - An overview of upcoming features
 
Concurrency Patterns with MongoDB
Concurrency Patterns with MongoDBConcurrency Patterns with MongoDB
Concurrency Patterns with MongoDB
 

Recently uploaded

The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024Rafal Los
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsMark Billinghurst
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024Scott Keck-Warren
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slidespraypatel2
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxMalak Abu Hammad
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptxHampshireHUG
 
Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Allon Mureinik
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesSinan KOZAK
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationRadu Cotescu
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking MenDelhi Call girls
 
SIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge GraphSIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge GraphNeo4j
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreternaman860154
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure servicePooja Nehwal
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsEnterprise Knowledge
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountPuma Security, LLC
 
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024BookNet Canada
 
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationBeyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationSafe Software
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking MenDelhi Call girls
 
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...shyamraj55
 
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | DelhiFULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhisoniya singh
 

Recently uploaded (20)

The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR Systems
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slides
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptx
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
 
Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen Frames
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 
SIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge GraphSIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge Graph
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path Mount
 
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
 
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationBeyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
 
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | DelhiFULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
 

Simple Corda Order App Write/Read Flow

  • 1. A Simple Write/Read Example with R3 Corda Eric Lee cheng-yu.eric.lee@accenture.com
  • 2. Objectives • Define a database schema in Corda “State” • Define the contract rules and data flows • Unit test design • Create REST API to write and read the data • Test with POSTMAN
  • 3. Preparation • Install Oracle Java JDK 8 (Build >139) • Install IntelliJ 2017.2 • Clone example code from git repository
  • 4. Clone the Example From Git git clone https://github.com/DAYUCS/cordapp-bill-of-lading.git *M14 based
  • 5. Define the Schema date seller buyer referenceNumber totalAmount I want to record this five columns to ledger as order information.
  • 6. Open the Cloned Project by IntelliJ 2017.02 1 2 3 4 From File menu, click “Open” Browse the cloned folder and open Click “Import Gradle Project” Apply default configuration, click “OK” button
  • 7. Add IDE Panels View > Tool Windows > Project Can see the folder structure now. You can add “Terminal” panel too.
  • 8. Modelling the Solution with Corda • Define the State
 The data model, the record you want to store in the ledger, define the table schema. • Define the Contract
 The relationships between participants, obligations and the rules. • Define the Flow
 The workflow for data commitment.
  • 9. State Related Files (Classes) • Model
 Data structure for participants. REST API requires these fields for JSON data submission. • Schema
 Column name definition for H2 database. • State
 Data class for state, invoked the Model and Schema classes.
  • 10. Create Order class in model 1. Right click on kotlin-source/src/main/kotlin/com.example/model ,
 New > Kotlin Files/Class 2. Name is Order, Kind is Class. 3. Add this new file(class) to git or not?
  • 11. Edit the Code for Order.kt package com.example.model
 
 import net.corda.core.serialization.CordaSerializable
 
 @CordaSerializable 
 data class Order(val referenceNumber: String, val totalAmount: Double) Field name is referenceNumber, data type is string. Field name is totalAmount, data type is double.
  • 12. Create the Code for Schema •Create OrderSchema.kt under kotlin-source/src/main/kotlin/ com.example/schema package com.example.schema import net.corda.core.schemas.MappedSchema import net.corda.core.schemas.PersistentState import java.time.Instant import java.util.* import javax.persistence.Column import javax.persistence.Entity import javax.persistence.Table object OrderSchema object OrderSchemaV1 : MappedSchema( schemaFamily = OrderSchema.javaClass, version = 1, mappedTypes = listOf(PersistentBL::class.java)) { @Entity @Table(name = "order_states") class PersistentBL( @Column(name = "seller_name") var sellerName: String, @Column(name = "buyer_name") var buyerName: String, @Column(name = "amount") var totalAmount: Double, @Column(name = "reference_no") var referenceNumber: String, @Column(name = "date") var date: Instant ) : PersistentState() } Table name and column name for H2 database.
 We create a “order_states” table with five columns: 
 seller_name, buyer_name, amount, reference_no and 
 date.
  • 13. Create the Code for State • Create OrderState class under kotlin-source/src/main/kotlin/com.example/state package com.example.state import com.example.contract.OrderContract import com.example.model.Order import com.example.schema.OrderSchemaV1 import net.corda.core.contracts.ContractState import net.corda.core.contracts.LinearState import net.corda.core.contracts.UniqueIdentifier import net.corda.core.identity.AbstractParty import net.corda.core.identity.Party import net.corda.core.schemas.MappedSchema import net.corda.core.schemas.PersistentState import net.corda.core.schemas.QueryableState import net.corda.core.crypto.keys import java.security.PublicKey import java.time.Instant import java.util.* data class OrderState(val order: Order, val seller: Party, val buyer: Party, val date: Instant = Instant.now(), override val linearId: UniqueIdentifier = UniqueIdentifier() ): LinearState, QueryableState { override val contract get() = OrderContract() /** The public keys of the involved parties. */ override val participants: List<AbstractParty> get() = listOf(buyer) /** Tells the vault to track a state if we are one of the parties involved. */ override fun isRelevant(ourKeys: Set<PublicKey>) = ourKeys.intersect(participants.flatMap { it.owningKey.keys }).isNotEmpty() fun withNewOwner(newOwner: Party) = copy(buyer = newOwner) override fun generateMappedObject(schema: MappedSchema): PersistentState { return when (schema) { is OrderSchemaV1 -> OrderSchemaV1.PersistentBL( sellerName = this.seller.name.toString(), buyerName = this.buyer.name.toString(), referenceNumber = this.order.referenceNumber, totalAmount = this.order.totalAmount, date = Instant.now() ) else -> throw IllegalArgumentException("Unrecognised schema $schema") } } override fun supportedSchemas(): Iterable<MappedSchema> = listOf(OrderSchemaV1) } State variables and its data type. Mapping the database schema to state 
 variables.
  • 14. Got Errors? Missing class/function, will create a “Contract"
  • 15. Create the Contract Code • Create OrderContract class under kotlin-source/src/main/kotlin/com.example/contract package com.example.contract import com.example.state.OrderState import net.corda.core.contracts.* import net.corda.core.crypto.SecureHash import net.corda.core.transactions.LedgerTransaction open class OrderContract : Contract { override fun verify(tx: LedgerTransaction) { val command = tx.commands.requireSingleCommand<Commands>() when (command.value) { is Commands.Issue -> { // Issuance verification logic. requireThat { // Generic constraints around the order transaction. "No inputs should be consumed when issuing an order." using (tx.inputs.isEmpty()) "Only one output state should be created." using (tx.outputs.size == 1) val out = tx.outputsOfType<OrderState>().single() "The seller and the buyer cannot be the same entity." using (out.seller != out.buyer) "The amount cannot be 0." using (out.order.totalAmount != 0.0) "The seller and the buyer must be signers." using (command.signers.containsAll(listOf(out.seller.owningKey, out.buyer.owningKey))) } } is Commands.Move -> { // Transfer verification logic. requireThat { "Only one input should be consumed when move an order." using (tx.inputs.size == 1) "Only one output state should be created." using (tx.outputs.size == 1) val input = tx.inputsOfType<OrderState>().single() val out = tx.outputsOfType<OrderState>().single() "Buyer must be changed when move an order." using(input.buyer != out.buyer) } } } } /** * This contract implements commands: Issue, Move. */ interface Commands : CommandData { class Issue : TypeOnlyCommandData(), Commands class Move : TypeOnlyCommandData(), Commands } /** This is a reference to the underlying legal contract template and associated parameters. */ override val legalContractReference: SecureHash = SecureHash.sha256("contract template and params") } The contract supports issue and transfer (move) operations. The rules for issue operation, using 
 programming logic to represent the legal terms For the legal contract reference, can put the file name, URL or etc.
  • 16. Contract Details Example // Issuance verification logic. requireThat { // Generic constraints around the order transaction. "No inputs should be consumed when issuing an order." using (tx.inputs.isEmpty()) "Only one output state should be created." using (tx.outputs.size == 1) val out = tx.outputsOfType<OrderState>().single() "The seller and the buyer cannot be the same entity." using (out.seller != out.buyer) "The amount cannot be 0." using (out.order.totalAmount != 0.0) "The seller and the buyer must be signers." using (command.signers.containsAll(listOf(out.seller.owningKey, out.buyer.owningKey))) } •If no transaction input, cannot create the contract. •After the contract execution, only one output. •Cannot sell the goods/service to yourself. •Transaction amount must greater than zero. •Valid contract requires the signature from Seller and buyer.
  • 17. Error Disappear Contract related errors fixed. (From red to black )
 The contract controls the data commitment.
  • 18. Create the Order Flow Generate the order details Check the order details follow the contract or not Sign the transaction Pass the contract to counter party for signature All parties signed the transaction, send to notary for verification Create the order details based on the required 
 data defined by model and state. Compare the order details and the contract, the 
 value must match the contract rules. If the order match the contract, sign it. Counter party has to sign the transaction also. All parties signed the transaction, the notary 
 node verify it. If no error, commit to ledger.
  • 19. Create the Order Flow Code • Create CreateOrderFlow object under kotlin-source/src/main/kotlin/com.example/flow package com.example.flow import co.paralleluniverse.fibers.Suspendable import com.example.contract.OrderContract import com.example.flow.CreateOrderFlow.Acceptor import com.example.flow.CreateOrderFlow.Initiator import com.example.state.OrderState import net.corda.core.contracts.Command import net.corda.core.contracts.TransactionType import net.corda.core.contracts.requireThat import net.corda.core.flows.* import net.corda.core.identity.Party import net.corda.core.transactions.SignedTransaction import net.corda.core.transactions.TransactionBuilder import net.corda.core.utilities.ProgressTracker object CreateOrderFlow { @InitiatingFlow @StartableByRPC class Initiator(val orderState: OrderState, val otherParty: Party): FlowLogic<SignedTransaction>() { /** * The progress tracker checkpoints each stage of the flow and outputs the specified messages when each * checkpoint is reached in the code. See the 'progressTracker.currentStep' expressions within the call() function. */ companion object { object GENERATING_TRANSACTION : ProgressTracker.Step("Generating transaction based on new order.") object VERIFYING_TRANSACTION : ProgressTracker.Step("Verifying contract constraints.") object SIGNING_TRANSACTION : ProgressTracker.Step("Signing transaction with our private key.") object GATHERING_SIGS : ProgressTracker.Step("Gathering the counterparty's signature.") { override fun childProgressTracker() = CollectSignaturesFlow.tracker() } object FINALISING_TRANSACTION : ProgressTracker.Step("Obtaining notary signature and recording transaction.") { override fun childProgressTracker() = FinalityFlow.tracker() } fun tracker() = ProgressTracker( GENERATING_TRANSACTION, VERIFYING_TRANSACTION, SIGNING_TRANSACTION, GATHERING_SIGS, FINALISING_TRANSACTION ) } override val progressTracker = tracker() /** * The flow logic is encapsulated within the call() method. */ @Suspendable override fun call(): SignedTransaction { // Obtain a reference to the notary we want to use. val notary = serviceHub.networkMapCache.notaryNodes.single().notaryIdentity // Stage 1. progressTracker.currentStep = GENERATING_TRANSACTION // Generate an unsigned transaction. val txCommand = Command(OrderContract.Commands.Issue(), listOf(orderState.seller.owningKey, orderState.buyer.owningKey)) val txBuilder = TransactionBuilder(TransactionType.General, notary).withItems(orderState, txCommand) // Stage 2. progressTracker.currentStep = VERIFYING_TRANSACTION // Verify that the transaction is valid. txBuilder.toWireTransaction().toLedgerTransaction(serviceHub).verify() // Stage 3. progressTracker.currentStep = SIGNING_TRANSACTION val partSignedTx = serviceHub.signInitialTransaction(txBuilder) // Stage 4. progressTracker.currentStep = GATHERING_SIGS // Send the state to the counterparty, and receive it back with their signature. val fullySignedTx = subFlow(CollectSignaturesFlow(partSignedTx, GATHERING_SIGS.childProgressTracker())) // Stage 5. progressTracker.currentStep = FINALISING_TRANSACTION // Notarise and record the transaction in both parties' vaults. return subFlow(FinalityFlow(fullySignedTx, FINALISING_TRANSACTION.childProgressTracker())).single() } } @InitiatedBy(Initiator::class) class Acceptor(val otherParty: Party) : FlowLogic<SignedTransaction>() { @Suspendable override fun call(): SignedTransaction { val signTransactionFlow = object : SignTransactionFlow(otherParty) { override fun checkTransaction(stx: SignedTransaction) = requireThat { val output = stx.tx.outputs.single().data "This must be an order transaction." using (output is OrderState) } } return subFlow(signTransactionFlow) } } } Required steps of the flow. Steps implementation. Discuss the flow implementation later.
  • 20. Required Steps companion object { object GENERATING_TRANSACTION : ProgressTracker.Step("Generating transaction based on new order.") object VERIFYING_TRANSACTION : ProgressTracker.Step("Verifying contract constraints.") object SIGNING_TRANSACTION : ProgressTracker.Step("Signing transaction with our private key.") object GATHERING_SIGS : ProgressTracker.Step("Gathering the counterparty's signature.") { override fun childProgressTracker() = CollectSignaturesFlow.tracker() } object FINALISING_TRANSACTION : ProgressTracker.Step("Obtaining notary signature and recording transaction.") { override fun childProgressTracker() = FinalityFlow.tracker() } fun tracker() = ProgressTracker( GENERATING_TRANSACTION, VERIFYING_TRANSACTION, SIGNING_TRANSACTION, GATHERING_SIGS, FINALISING_TRANSACTION ) } Progress description for ProgressTracker Progress item
  • 21. Steps Logic Implementation @Suspendable override fun call(): SignedTransaction { // Obtain a reference to the notary we want to use. val notary = serviceHub.networkMapCache.notaryNodes.single().notaryIdentity // Stage 1. progressTracker.currentStep = GENERATING_TRANSACTION // Generate an unsigned transaction. val txCommand = Command(OrderContract.Commands.Issue(), listOf(orderState.seller.owningKey, orderState.buyer.owningKey)) val txBuilder = TransactionBuilder(TransactionType.General, notary).withItems(orderState, txCommand) // Stage 2. progressTracker.currentStep = VERIFYING_TRANSACTION // Verify that the transaction is valid. txBuilder.toWireTransaction().toLedgerTransaction(serviceHub).verify() // Stage 3. progressTracker.currentStep = SIGNING_TRANSACTION val partSignedTx = serviceHub.signInitialTransaction(txBuilder) // Stage 4. progressTracker.currentStep = GATHERING_SIGS // Send the state to the counterparty, and receive it back with their signature. val fullySignedTx = subFlow(CollectSignaturesFlow(partSignedTx, GATHERING_SIGS.childProgressTracker())) // Stage 5. progressTracker.currentStep = FINALISING_TRANSACTION // Notarise and record the transaction in both parties' vaults. return subFlow(FinalityFlow(fullySignedTx, FINALISING_TRANSACTION.childProgressTracker())).single() } To initialise the transaction, need to know which transaction 
 command and have a transaction builder. Build the transaction and service hub check it by contract rules. The party who proposed the transaction sign first. Other party sign the transaction Got all signatures, “FinalityFlow" will commit the transaction
 to ledger.
  • 22. Code for Unit Test • Create an OrderContractTest class under kotlin-sourcesrctestkotlincom.examplecontract and paste the following codes package com.example.contract import com.example.flow.CreateOrderFlow import com.example.model.Order import com.example.state.OrderState import net.corda.core.getOrThrow import net.corda.testing.node.MockNetwork import org.junit.After import org.junit.Before import org.junit.Test import java.time.Instant import java.util.* import kotlin.test.assertEquals import kotlin.test.assertTrue import kotlin.test.fail class OrderContractTest { lateinit var net: MockNetwork lateinit var a: MockNetwork.MockNode lateinit var b: MockNetwork.MockNode @Before fun setup() { net = MockNetwork() val nodes = net.createSomeNodes(3) a = nodes.partyNodes[0] b = nodes.partyNodes[1] // For real nodes this happens automatically, but we have to manually register the flow for tests nodes.partyNodes.forEach { it.registerInitiatedFlow(CreateOrderFlow.Acceptor::class.java) } net.runNetwork() } @After fun tearDown() { net.stopNodes() } @Test fun `Order amount must greater than zero`(){ val state = OrderState(Order("a01",0.0), a.info.legalIdentity, b.info.legalIdentity, Instant.now() ) try { val flow = CreateOrderFlow.Initiator(state, b.info.legalIdentity) val future = a.services.startFlow(flow).resultFuture net.runNetwork() val signedTx = future.getOrThrow() fail("No exception thrown!!") } catch(e:Exception){ assertTrue(e.message.toString().contains(Regex("Contract verification failed: Failed requirement"))) } } }
  • 23. Template for Corda Unit Test Code • Mock network creation
 lateinit var net: MockNetwork lateinit var a: MockNetwork.MockNode lateinit var b: MockNetwork.MockNode @Before fun setup() { net = MockNetwork() val nodes = net.createSomeNodes(2) a = nodes.partyNodes[0] b = nodes.partyNodes[1] // For real nodes this happens automatically, but we have to manually register the flow for tests nodes.partyNodes.forEach { it.registerInitiatedFlow(CreateOrderFlow.Acceptor::class.java) } net.runNetwork() } @After fun tearDown() { net.stopNodes() } Create two nodes (a and b) in Corda mock network Start the nodes before testing After testing, destroy the mock nodes
  • 24. Unit Test Example @Test fun `Order amount must greater than zero`(){ val state = OrderState(Order("a01",0.0), a.info.legalIdentity, b.info.legalIdentity, Instant.now() ) try { val flow = CreateOrderFlow.Initiator(state, b.info.legalIdentity) val future = a.services.startFlow(flow).resultFuture net.runNetwork() val signedTx = future.getOrThrow() fail("No exception thrown!!") } catch(e:Exception){ assertTrue(e.message.toString().contains(Regex("Contract verification failed: Failed requirement"))) } } Story: I want to test if the order amount is zero Propose an order, a have a deal with b, 
 the amount is 0 Start the transaction With an exception is positive, the error has this message string pattern. If the transaction done, judge the test is fail.
  • 25. Run the test • Right click on the OrderContractTest class, click “Run OrderContractTest”. • The test should failed with the error message as the screenshot shown.
  • 26. Add VM Option Run > Edit Configuration -ea -javaagent:../lib/quasar.jar
  • 27. Test Pass You can create unit test cases, the code structure/style similar to jUnit.
  • 28. Create REST API • Add the following codes to kotlin-source/src/main/kotlin/com.example/api/ExampleApi.kt • Retrieve all orders (GET method) @GET @Path("orders") @Produces(MediaType.APPLICATION_JSON) fun getOrders(): List<StateAndRef<OrderState>>{ val vaultStates = services.vaultQueryBy<OrderState>() return vaultStates.states } • Create Order (PUT method) @PUT @Path("{seller}/{buyer}/create-order") fun createOrder(order: Order, @PathParam("seller") seller: X500Name, @PathParam("buyer") buyer: X500Name) : Response{ val seller =services.partyFromX500Name(seller) if (seller == null){ return Response.status(Response.Status.BAD_REQUEST).build() } val buyer = services.partyFromX500Name(buyer) if (buyer == null){ return Response.status(Response.Status.BAD_REQUEST).build() } val state = OrderState( order, seller, buyer, date = Instant.now() ) val (status, msg) = try { val flowHandle = services. startTrackedFlowDynamic(CreateOrderFlow.Initiator::class.java, state, seller) flowHandle.progress.subscribe { println(">> $it") } val result = flowHandle.returnValue.getOrThrow() Response.Status.CREATED to "Transaction id ${result.id} committed to ledger." } catch (ex: Throwable){ logger.error(ex.message, ex) Response.Status.BAD_REQUEST to "Transaction failed." } return Response.status(status).entity(msg).build() }
  • 29. Build Project • Open the terminal for project in IntelliJ, execute the three commands • ./gradlew clean • ./gradlew build • ./gradlew deployNodes
  • 30. Deployment in Dev Mode • Change working directory to {your project folder}/kotlin- source/build/nodes • runnodes (Windows: runnodes.bat Others: runnodes ) 1. Run the runnodes script 2. Starting the 4 nodes in terminal 
 or CMD windows
  • 31. depolyNodes Configuration File • kotlin-source/build.gradle Node name (X.509 format) Port numbers for different purposes. The configuration file defined the nodes’ name 
 and ports for communication.
  • 32. Testing with Browser localhost:10007 localhost:10007/api/example/me Implemented APIs from ExampleApi.kt Test “GET” method, browser is a good choice.
 But for PUT or POST methods, POSTMAN or curl is better!
  • 33. Testing with POSTMAN Node A (seller) create a order with Node C (buyer), the order number is a00001, amount is 3.14 1. Select PUT method 3. Body tab, raw data, MIME is JSON (application/json) 2. URL is http://localhost:10007/api/example/CN=NodeA,O=NodeA,L=London,C=UK/ CN=NodeC,O=NodeC,L=Paris,C=FR/create-order 4. Enter the value of referenceNumber and totalAmount in JSON format. 5. Click send button. Result it here. Successful commitment will return a hash string.
  • 34. Validating the Result Node C should see the order by GET /orders method. GET method for http://localhost:10013/api/example/orders
 Please note port 10013 is for Node C (from build.gradle file) Returned result Entered reference number and amount from Node A. Seller and buyer information, unix timestamped.