mirror of
https://github.com/corda/corda.git
synced 2024-12-19 04:57:58 +00:00
Updates tutorials (general fixes, link to solutions repos)
* Updates tutorial to make imports to be added clearer, and to reflect new repo structure. * Adds links to the solution repos for tut 1. * Further fixes based on dry-run.
This commit is contained in:
parent
d1ea881aef
commit
929341e7ee
@ -33,6 +33,7 @@ dependencies {
|
||||
compile project(':core')
|
||||
compile project(':client:jfx')
|
||||
compile project(':node-driver')
|
||||
compile project(':webserver')
|
||||
testCompile project(':verifier')
|
||||
testCompile project(':test-utils')
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
package net.corda.docs.java.tutorial.helloworld;
|
||||
package com.template;
|
||||
|
||||
import net.corda.core.contracts.CommandData;
|
||||
import net.corda.core.contracts.Contract;
|
@ -1,17 +1,21 @@
|
||||
package net.corda.docs.java.tutorial.helloworld;
|
||||
|
||||
// DOCSTART 01
|
||||
import co.paralleluniverse.fibers.Suspendable;
|
||||
import com.template.TemplateContract;
|
||||
import net.corda.core.flows.*;
|
||||
|
||||
// DOCSTART 01
|
||||
// Add these imports:
|
||||
import net.corda.core.contracts.Command;
|
||||
import net.corda.core.contracts.CommandData;
|
||||
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;
|
||||
|
||||
import static net.corda.docs.java.tutorial.helloworld.TemplateContract.TEMPLATE_CONTRACT_ID;
|
||||
import static com.template.TemplateContract.TEMPLATE_CONTRACT_ID;
|
||||
|
||||
// Replace TemplateFlow's definition with:
|
||||
@InitiatingFlow
|
||||
@StartableByRPC
|
||||
public class IOUFlow extends FlowLogic<Void> {
|
||||
|
@ -1,13 +1,15 @@
|
||||
package net.corda.docs.java.tutorial.helloworld;
|
||||
|
||||
// DOCSTART 01
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import net.corda.core.contracts.ContractState;
|
||||
import net.corda.core.identity.AbstractParty;
|
||||
import net.corda.core.identity.Party;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
// DOCSTART 01
|
||||
// Add these imports:
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import net.corda.core.identity.Party;
|
||||
|
||||
// Replace TemplateState's definition with:
|
||||
public class IOUState implements ContractState {
|
||||
private final int value;
|
||||
private final Party lender;
|
||||
|
@ -1,20 +1,25 @@
|
||||
package net.corda.docs.java.tutorial.twoparty;
|
||||
|
||||
// DOCSTART 01
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import net.corda.core.contracts.CommandData;
|
||||
import net.corda.core.contracts.CommandWithParties;
|
||||
import net.corda.core.contracts.Contract;
|
||||
import net.corda.core.identity.Party;
|
||||
import net.corda.core.transactions.LedgerTransaction;
|
||||
|
||||
// DOCSTART 01
|
||||
// Add these imports:
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import net.corda.core.contracts.CommandWithParties;
|
||||
import net.corda.core.identity.Party;
|
||||
|
||||
import java.security.PublicKey;
|
||||
import java.util.List;
|
||||
|
||||
import static net.corda.core.contracts.ContractsDSL.requireSingleCommand;
|
||||
import static net.corda.core.contracts.ContractsDSL.requireThat;
|
||||
|
||||
// Replace TemplateContract's definition with:
|
||||
public class IOUContract implements Contract {
|
||||
public static final String IOU_CONTRACT_ID = "com.template.IOUContract";
|
||||
|
||||
// Our Create command.
|
||||
public static class Create implements CommandData {
|
||||
}
|
||||
|
@ -45,15 +45,14 @@ public class IOUFlow extends FlowLogic<Void> {
|
||||
// We retrieve the notary identity from the network map.
|
||||
final Party notary = getServiceHub().getNetworkMapCache().getNotaryIdentities().get(0);
|
||||
|
||||
// DOCSTART 02
|
||||
// We create a transaction builder.
|
||||
final TransactionBuilder txBuilder = new TransactionBuilder();
|
||||
txBuilder.setNotary(notary);
|
||||
|
||||
// DOCSTART 02
|
||||
// We create the transaction components.
|
||||
IOUState outputState = new IOUState(iouValue, getOurIdentity(), otherParty);
|
||||
String outputContract = IOUContract.class.getName();
|
||||
StateAndContract outputContractAndState = new StateAndContract(outputState, outputContract);
|
||||
StateAndContract outputContractAndState = new StateAndContract(outputState, IOUContract.IOU_CONTRACT_ID);
|
||||
List<PublicKey> requiredSigners = ImmutableList.of(getOurIdentity().getOwningKey(), otherParty.getOwningKey());
|
||||
Command cmd = new Command<>(new IOUContract.Create(), requiredSigners);
|
||||
|
||||
|
@ -1,16 +1,16 @@
|
||||
package net.corda.docs.java.tutorial.twoparty;
|
||||
|
||||
// DOCSTART 01
|
||||
// Add these imports:
|
||||
import co.paralleluniverse.fibers.Suspendable;
|
||||
import net.corda.core.contracts.ContractState;
|
||||
import net.corda.core.flows.*;
|
||||
import net.corda.core.transactions.SignedTransaction;
|
||||
import net.corda.core.utilities.ProgressTracker;
|
||||
import net.corda.docs.java.tutorial.helloworld.IOUFlow;
|
||||
import net.corda.docs.java.tutorial.helloworld.IOUState;
|
||||
|
||||
import static net.corda.core.contracts.ContractsDSL.requireThat;
|
||||
|
||||
// Define IOUFlowResponder:
|
||||
@InitiatedBy(IOUFlow.class)
|
||||
public class IOUFlowResponder extends FlowLogic<Void> {
|
||||
private final FlowSession otherPartySession;
|
||||
|
@ -1,16 +1,19 @@
|
||||
package net.corda.docs.tutorial.helloworld
|
||||
|
||||
// DOCSTART 01
|
||||
import co.paralleluniverse.fibers.Suspendable
|
||||
import net.corda.core.contracts.Command
|
||||
import net.corda.core.flows.FinalityFlow
|
||||
import net.corda.core.flows.FlowLogic
|
||||
import net.corda.core.flows.InitiatingFlow
|
||||
import net.corda.core.flows.StartableByRPC
|
||||
|
||||
// DOCSTART 01
|
||||
// Add these imports:
|
||||
import net.corda.core.contracts.Command
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.transactions.TransactionBuilder
|
||||
import net.corda.core.utilities.ProgressTracker
|
||||
|
||||
// Replace TemplateFlow's definition with:
|
||||
@InitiatingFlow
|
||||
@StartableByRPC
|
||||
class IOUFlow(val iouValue: Int,
|
||||
|
@ -1,9 +1,12 @@
|
||||
package net.corda.docs.tutorial.helloworld
|
||||
|
||||
// DOCSTART 01
|
||||
import net.corda.core.contracts.ContractState
|
||||
|
||||
// DOCSTART 01
|
||||
// Add these imports:
|
||||
import net.corda.core.identity.Party
|
||||
|
||||
// Replace TemplateState's definition with:
|
||||
class IOUState(val value: Int,
|
||||
val lender: Party,
|
||||
val borrower: Party) : ContractState {
|
||||
|
@ -1,12 +1,16 @@
|
||||
package net.corda.docs.tutorial.twoparty
|
||||
|
||||
// DOCSTART 01
|
||||
import net.corda.core.contracts.CommandData
|
||||
import net.corda.core.contracts.Contract
|
||||
import net.corda.core.contracts.requireSingleCommand
|
||||
import net.corda.core.contracts.requireThat
|
||||
import net.corda.core.transactions.LedgerTransaction
|
||||
|
||||
// DOCSTART 01
|
||||
// Add these imports:
|
||||
import net.corda.core.contracts.*
|
||||
|
||||
// Replace IOUContract's contract ID and definition with:
|
||||
val IOU_CONTRACT_ID = "com.template.IOUContract"
|
||||
|
||||
class IOUContract : Contract {
|
||||
// Our Create command.
|
||||
class Create : CommandData
|
||||
@ -20,7 +24,7 @@ class IOUContract : Contract {
|
||||
"There should be one output state of type IOUState." using (tx.outputs.size == 1)
|
||||
|
||||
// IOU-specific constraints.
|
||||
val out = tx.outputsOfType<net.corda.docs.tutorial.helloworld.IOUState>().single()
|
||||
val out = tx.outputsOfType<IOUState>().single()
|
||||
"The IOU's value must be non-negative." using (out.value > 0)
|
||||
"The lender and the borrower cannot be the same entity." using (out.lender != out.borrower)
|
||||
|
||||
|
@ -6,9 +6,17 @@ import net.corda.core.contracts.Command
|
||||
import net.corda.core.contracts.StateAndContract
|
||||
import net.corda.core.flows.*
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.messaging.CordaRPCOps
|
||||
import net.corda.core.serialization.SerializationWhitelist
|
||||
import net.corda.core.transactions.TransactionBuilder
|
||||
import net.corda.core.utilities.ProgressTracker
|
||||
import kotlin.reflect.jvm.jvmName
|
||||
import net.corda.webserver.services.WebServerPluginRegistry
|
||||
import java.util.function.Function
|
||||
import javax.ws.rs.GET
|
||||
import javax.ws.rs.Path
|
||||
import javax.ws.rs.Produces
|
||||
import javax.ws.rs.core.MediaType
|
||||
import javax.ws.rs.core.Response
|
||||
// DOCEND 01
|
||||
|
||||
@InitiatingFlow
|
||||
@ -25,14 +33,13 @@ class IOUFlow(val iouValue: Int,
|
||||
// We retrieve the notary identity from the network map.
|
||||
val notary = serviceHub.networkMapCache.notaryIdentities[0]
|
||||
|
||||
// We create a transaction builder
|
||||
// DOCSTART 02
|
||||
// We create a transaction builder.
|
||||
val txBuilder = TransactionBuilder(notary = notary)
|
||||
|
||||
// DOCSTART 02
|
||||
// We create the transaction components.
|
||||
val outputState = IOUState(iouValue, ourIdentity, otherParty)
|
||||
val outputContract = IOUContract::class.jvmName
|
||||
val outputContractAndState = StateAndContract(outputState, outputContract)
|
||||
val outputContractAndState = StateAndContract(outputState, IOU_CONTRACT_ID)
|
||||
val cmd = Command(IOUContract.Create(), listOf(ourIdentity.owningKey, otherParty.owningKey))
|
||||
|
||||
// We add the items to the builder.
|
||||
|
@ -1,16 +1,19 @@
|
||||
package net.corda.docs.tutorial.twoparty
|
||||
|
||||
// DOCSTART 01
|
||||
import co.paralleluniverse.fibers.Suspendable
|
||||
import net.corda.core.contracts.requireThat
|
||||
import net.corda.core.flows.FlowLogic
|
||||
import net.corda.core.flows.FlowSession
|
||||
import net.corda.core.flows.InitiatedBy
|
||||
import net.corda.core.flows.SignTransactionFlow
|
||||
import net.corda.core.transactions.SignedTransaction
|
||||
import net.corda.docs.tutorial.helloworld.IOUFlow
|
||||
import net.corda.docs.tutorial.helloworld.IOUState
|
||||
|
||||
// DOCSTART 01
|
||||
// Add these imports:
|
||||
import net.corda.core.contracts.requireThat
|
||||
import net.corda.core.transactions.SignedTransaction
|
||||
|
||||
// Define IOUFlowResponder:
|
||||
@InitiatedBy(IOUFlow::class)
|
||||
class IOUFlowResponder(val otherPartySession: FlowSession) : FlowLogic<Unit>() {
|
||||
@Suspendable
|
||||
|
@ -6,8 +6,8 @@
|
||||
|
||||
Writing the flow
|
||||
================
|
||||
A flow encodes a sequence of steps that a node can run to achieve a specific ledger update. By installing new flows on
|
||||
a node, we allow the node to handle new business processes. The flow we define will allow a node to issue an
|
||||
A flow encodes a sequence of steps that a node can perform to achieve a specific ledger update. By installing new flows
|
||||
on a node, we allow the node to handle new business processes. The flow we define will allow a node to issue an
|
||||
``IOUState`` onto the ledger.
|
||||
|
||||
Flow outline
|
||||
@ -40,8 +40,8 @@ FlowLogic
|
||||
---------
|
||||
All flows must subclass ``FlowLogic``. You then define the steps taken by the flow by overriding ``FlowLogic.call``.
|
||||
|
||||
Let's define our ``IOUFlow`` in either ``TemplateFlow.java`` or ``App.kt``. Delete both the existing flows in the
|
||||
template, and replace them with the following:
|
||||
Let's define our ``IOUFlow`` in either ``TemplateFlow.java`` or ``App.kt``. Delete the two existing flows in the
|
||||
template (``Initiator`` and ``Responder``), and replace them with the following:
|
||||
|
||||
.. container:: codeset
|
||||
|
||||
|
@ -107,9 +107,15 @@ commands.
|
||||
|
||||
We want to create an IOU of 100 with PartyB. We start the ``IOUFlow`` by typing:
|
||||
|
||||
.. code:: bash
|
||||
.. container:: codeset
|
||||
|
||||
start IOUFlow iouValue: 99, otherParty: "O=PartyB,L=New York,C=US"
|
||||
.. code-block:: java
|
||||
|
||||
start IOUFlow arg0: 99, arg1: "O=PartyB,L=New York,C=US"
|
||||
|
||||
.. code-block:: kotlin
|
||||
|
||||
start IOUFlow iouValue: 99, otherParty: "O=PartyB,L=New York,C=US"
|
||||
|
||||
This single command will cause PartyA and PartyB to automatically agree an IOU. This is one of the great advantages of
|
||||
the flow framework - it allows you to reduce complex negotiation and update processes into a single function call.
|
||||
@ -118,13 +124,7 @@ If the flow worked, it should have recorded a new IOU in the vaults of both Part
|
||||
|
||||
We can check the contents of each node's vault by running:
|
||||
|
||||
.. container:: codeset
|
||||
|
||||
.. code-block:: java
|
||||
|
||||
run vaultQuery contractStateType: com.template.state.IOUState
|
||||
|
||||
.. code-block:: kotlin
|
||||
.. code-block:: base
|
||||
|
||||
run vaultQuery contractStateType: com.template.IOUState
|
||||
|
||||
@ -174,6 +174,11 @@ parts:
|
||||
* The ``IOUState``, representing IOUs on the ledger
|
||||
* The ``IOUFlow``, orchestrating the process of agreeing the creation of an IOU on-ledger
|
||||
|
||||
After completing this tutorial, your CorDapp should look like this:
|
||||
|
||||
* Java: https://github.com/corda/corda-tut1-solution-java
|
||||
* Kotlin: https://github.com/corda/corda-tut1-solution-kotlin
|
||||
|
||||
Next steps
|
||||
----------
|
||||
There are a number of improvements we could make to this CorDapp:
|
||||
@ -183,4 +188,4 @@ There are a number of improvements we could make to this CorDapp:
|
||||
* We could add an API, to make it easier to interact with the CorDapp
|
||||
|
||||
But for now, the biggest priority is to add an ``IOUContract`` imposing constraints on the evolution of each
|
||||
``IOUState`` over time. This will be the focus of our next tutorial.
|
||||
``IOUState`` over time. This will be the focus of our next tutorial.
|
@ -24,7 +24,6 @@ interface is defined as follows:
|
||||
val participants: List<AbstractParty>
|
||||
}
|
||||
|
||||
<<<<<<< HEAD
|
||||
The first thing you'll probably notice about this interface declaration is that its not written in Java or another
|
||||
common language. The core Corda platform, including the interface declaration above, is entirely written in Kotlin.
|
||||
|
||||
@ -70,7 +69,7 @@ later is often as simple as adding an additional property to your class definiti
|
||||
|
||||
Defining IOUState
|
||||
-----------------
|
||||
Let's get started by opening ``TemplateState.java`` (for Java) or ``App.kt`` (for Kotlin) and updating
|
||||
Let's get started by opening ``TemplateState.java`` (for Java) or ``StatesAndContracts.kt`` (for Kotlin) and updating
|
||||
``TemplateState`` to define an ``IOUState``:
|
||||
|
||||
.. container:: codeset
|
||||
|
@ -41,34 +41,33 @@ https://docs.corda.net/tutorial-cordapp.html#opening-the-example-cordapp-in-inte
|
||||
|
||||
Template structure
|
||||
------------------
|
||||
The template has a number of files, but we can ignore most of them. To implement our IOU CorDapp in Java, we'll only
|
||||
need to modify two files. For Kotlin, we'll simply be modifying the ``App.kt`` file:
|
||||
The template has a number of files, but we can ignore most of them. We will only be modifying the following files:
|
||||
|
||||
.. container:: codeset
|
||||
|
||||
.. code-block:: java
|
||||
|
||||
// 1. The state
|
||||
src/main/java/com/template/TemplateState.java
|
||||
cordapp-contracts-states/src/main/java/com/template/TemplateState.java
|
||||
|
||||
// 2. The flow
|
||||
src/main/java/com/template/TemplateFlow.java
|
||||
cordapp/src/main/java/com/template/TemplateFlow.java
|
||||
|
||||
.. code-block:: kotlin
|
||||
|
||||
src/main/kotlin/com/template/App.kt
|
||||
// 1. The state
|
||||
cordapp-contracts-states/src/main/kotlin/com/template/StatesAndContracts.kt
|
||||
|
||||
// 2. The flow
|
||||
cordapp/src/main/kotlin/com/template/App.kt
|
||||
|
||||
Clean up
|
||||
--------
|
||||
To prevent build errors later on, we should delete the following files before we begin:
|
||||
|
||||
* Java:
|
||||
* ``src/main/java/com/template/TemplateClient.java``
|
||||
* ``src/test/java/com/template/FlowTests.java``
|
||||
* Java: ``cordapp/src/main/java/com/template/TemplateClient.java``
|
||||
|
||||
* Kotlin:
|
||||
* ``src/main/kotlin/com/template/TemplateClient.kt``
|
||||
* ``src/test/kotlin/com/template/FlowTests.kt``
|
||||
* Kotlin: ``cordapp/src/main/kotlin/com/template/TemplateClient.kt``
|
||||
|
||||
Progress so far
|
||||
---------------
|
||||
|
@ -77,7 +77,7 @@ We can picture this transaction as follows:
|
||||
Defining IOUContract
|
||||
--------------------
|
||||
Let's write a contract that enforces these constraints. We'll do this by modifying either ``TemplateContract.java`` or
|
||||
``App.kt`` and updating ``TemplateContract`` to define an ``IOUContract``:
|
||||
``StatesAndContracts.kt`` and updating ``TemplateContract`` to define an ``IOUContract``:
|
||||
|
||||
.. container:: codeset
|
||||
|
||||
|
@ -17,7 +17,7 @@ We'll do this by modifying the flow we wrote in the previous tutorial.
|
||||
|
||||
Verifying the transaction
|
||||
-------------------------
|
||||
In ``IOUFlow.java``/``IOUFlow.kt``, change the imports block to the following:
|
||||
In ``IOUFlow.java``/``App.kt``, change the imports block to the following:
|
||||
|
||||
.. container:: codeset
|
||||
|
||||
@ -31,7 +31,8 @@ In ``IOUFlow.java``/``IOUFlow.kt``, change the imports block to the following:
|
||||
:start-after: DOCSTART 01
|
||||
:end-before: DOCEND 01
|
||||
|
||||
And update ``IOUFlow.call`` by changing the code following the creation of the ``TransactionBuilder`` as follows:
|
||||
And update ``IOUFlow.call`` by changing the code following the retrieval of the notary's identity from the network as
|
||||
follows:
|
||||
|
||||
.. container:: codeset
|
||||
|
||||
@ -138,6 +139,11 @@ Our CorDapp now imposes restrictions on the issuance of IOUs. Most importantly,
|
||||
from both the lender and the borrower before an IOU can be created on the ledger. This prevents either the lender or
|
||||
the borrower from unilaterally updating the ledger in a way that only benefits themselves.
|
||||
|
||||
After completing this tutorial, your CorDapp should look like this:
|
||||
|
||||
* Java: https://github.com/corda/corda-tut2-solution-java
|
||||
* Kotlin: https://github.com/corda/corda-tut2-solution-kotlin
|
||||
|
||||
You should now be ready to develop your own CorDapps. You can also find a list of sample CorDapps
|
||||
`here <https://www.corda.net/samples/>`_. As you write CorDapps, you'll also want to learn more about the
|
||||
:doc:`Corda API <corda-api>`.
|
||||
|
Loading…
Reference in New Issue
Block a user