diff --git a/docs/source/hello-world-contract.rst b/docs/source/hello-world-contract.rst index 31bebc2495..253020441e 100644 --- a/docs/source/hello-world-contract.rst +++ b/docs/source/hello-world-contract.rst @@ -79,18 +79,19 @@ Defining IOUContract -------------------- Let's write a contract that enforces these constraints. We'll do this by modifying either ``TemplateContract.java`` or -``TemplateContract.kt`` and updating ``TemplateContract`` to define an ``IOUContract``: +``App.kt`` and updating ``TemplateContract`` to define an ``IOUContract``: .. container:: codeset .. code-block:: kotlin - package com.iou + ... import net.corda.core.contracts.* - import net.corda.core.crypto.SecureHash - open class IOUContract : Contract { + ... + + class IOUContract : Contract { // Our Create command. class Create : CommandData @@ -109,7 +110,7 @@ Let's write a contract that enforces these constraints. We'll do this by modifyi // Constraints on the signers. "There must only be one signer." using (command.signers.toSet().size == 1) - "The signer must be the borrower." using (command.signers.contains(out.borrower.owningKey)) + "The signer must be the lender." using (command.signers.contains(out.lender.owningKey)) } } @@ -119,9 +120,10 @@ Let's write a contract that enforces these constraints. We'll do this by modifyi .. code-block:: java - package com.iou; + package com.template.contract; import com.google.common.collect.ImmutableSet; + import com.template.state.IOUState; import net.corda.core.contracts.AuthenticatedObject; import net.corda.core.contracts.CommandData; import net.corda.core.contracts.Contract; @@ -146,7 +148,7 @@ Let's write a contract that enforces these constraints. We'll do this by modifyi check.using("There should be one output state of type IOUState.", tx.getOutputs().size() == 1); // IOU-specific constraints. - final IOUState out = (IOUState) tx.getOutputs().getData().get(0); + final IOUState out = (IOUState) tx.getOutputs().get(0).getData(); final Party lender = out.getLender(); final Party borrower = out.getBorrower(); check.using("The IOU's value must be non-negative.",out.getValue() > 0); @@ -154,7 +156,7 @@ Let's write a contract that enforces these constraints. We'll do this by modifyi // Constraints on the signers. check.using("There must only be one signer.", ImmutableSet.of(command.getSigners()).size() == 1); - check.using("The signer must be the borrower.", command.getSigners().contains(borrower.getOwningKey())); + check.using("The signer must be the lender.", command.getSigners().contains(lender.getOwningKey())); return null; }); @@ -165,6 +167,8 @@ Let's write a contract that enforces these constraints. We'll do this by modifyi @Override public final SecureHash getLegalContractReference() { return legalContractReference; } } +If you're following along in Java, you'll also need to rename ``TemplateContract.java`` to ``IOUContract.java``. + Let's walk through this code step by step. The Create command @@ -254,7 +258,7 @@ other statements - in this case, we're extracting the transaction's single ``IOU Signer constraints ~~~~~~~~~~~~~~~~~~ -Finally, we require the borrower's signature on the transaction. A transaction's required signers is equal to the union +Finally, we require the lender's signature on the transaction. A transaction's required signers is equal to the union of all the signers listed on the commands. We therefore extract the signers from the ``Create`` command we retrieved earlier. diff --git a/docs/source/hello-world-flow.rst b/docs/source/hello-world-flow.rst index b23a61b30d..1adb34a1e5 100644 --- a/docs/source/hello-world-flow.rst +++ b/docs/source/hello-world-flow.rst @@ -33,24 +33,20 @@ FlowLogic Flows are implemented as ``FlowLogic`` subclasses. You define the steps taken by the flow by overriding ``FlowLogic.call``. -We'll write our flow in either ``TemplateFlow.java`` or ``TemplateFlow.kt``. Overwrite the existing template code with -the following: +We'll write our flow in either ``TemplateFlow.java`` or ``App.kt``. Overwrite both the existing flows in the template +with the following: .. container:: codeset .. code-block:: kotlin - package com.iou + ... - import co.paralleluniverse.fibers.Suspendable - import net.corda.core.contracts.Command - import net.corda.core.flows.FlowLogic - import net.corda.core.flows.InitiatingFlow - import net.corda.core.flows.StartableByRPC - import net.corda.core.identity.Party - import net.corda.core.transactions.TransactionBuilder import net.corda.core.utilities.ProgressTracker - import net.corda.core.flows.FinalityFlow + import net.corda.core.transactions.TransactionBuilder + import net.corda.core.flows.* + + ... @InitiatingFlow @StartableByRPC @@ -88,19 +84,17 @@ the following: .. code-block:: java - package com.iou; + package com.template.flow; import co.paralleluniverse.fibers.Suspendable; + import com.template.contract.IOUContract; + import com.template.state.IOUState; import net.corda.core.contracts.Command; - import net.corda.core.flows.FlowException; - import net.corda.core.flows.FlowLogic; - import net.corda.core.flows.InitiatingFlow; - import net.corda.core.flows.StartableByRPC; + 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 net.corda.flows.FinalityFlow; @InitiatingFlow @StartableByRPC @@ -118,6 +112,11 @@ the following: this.otherParty = otherParty; } + @Override + public ProgressTracker getProgressTracker() { + return progressTracker; + } + /** * The flow logic is encapsulated within the call() method. */ @@ -128,7 +127,7 @@ the following: final Party me = getServiceHub().getMyInfo().getLegalIdentity(); final Party notary = getServiceHub().getNetworkMapCache().getAnyNotary(null); - // We create a transaction builder + // We create a transaction builder. final TransactionBuilder txBuilder = new TransactionBuilder(); txBuilder.setNotary(notary); @@ -150,6 +149,8 @@ the following: } } +If you're following along in Java, you'll also need to rename ``TemplateFlow.java`` to ``IOUFlow.java``. + We now have our own ``FlowLogic`` subclass that overrides ``FlowLogic.call``. There's a few things to note: * ``FlowLogic.call`` has a return type that matches the type parameter passed to ``FlowLogic`` - this is type returned @@ -163,6 +164,9 @@ We now have our own ``FlowLogic`` subclass that overrides ``FlowLogic.call``. Th * ``@InitiatingFlow`` means that this flow can be started directly by the node * ``StartableByRPC`` allows the node owner to start this flow via an RPC call +* We override the progress tracker, even though we are not providing any progress tracker steps yet. The progress + tracker is required for the node shell to establish when the flow has ended + Let's walk through the steps of ``FlowLogic.call`` one-by-one: Retrieving participant information @@ -229,7 +233,7 @@ Signing the transaction Now that we have a valid transaction proposal, we need to sign it. Once the transaction is signed, no-one will be able to modify the transaction without invalidating our signature, effectively making the transaction immutable. -The call to ``ServiceHub.signInitialTransaction`` returns a ``SignedTransaction`` - an object that pairs the +The call to ``ServiceHub.toSignedTransaction`` returns a ``SignedTransaction`` - an object that pairs the transaction itself with a list of signatures over that transaction. Finalising the transaction diff --git a/docs/source/hello-world-running.rst b/docs/source/hello-world-running.rst index b71eefd867..2696af6b23 100644 --- a/docs/source/hello-world-running.rst +++ b/docs/source/hello-world-running.rst @@ -9,6 +9,11 @@ Running our CorDapp Now that we've written a CorDapp, it's time to test it by running it on some real Corda nodes. +Clean up +-------- +Before running our node, delete the ``client/TemplateClient.java`` (for Java) or ``client/TemplateClient.kt`` (for +Kotlin) file. We won't be using it, and it will cause build errors unless we remove it. + Deploying our CorDapp --------------------- Let's take a look at the nodes we're going to deploy. Open the project's build file under ``java-source/build.gradle`` diff --git a/docs/source/hello-world-state.rst b/docs/source/hello-world-state.rst index b677366a08..a4ba0ef205 100644 --- a/docs/source/hello-world-state.rst +++ b/docs/source/hello-world-state.rst @@ -64,31 +64,26 @@ you wish to add them later, its as simple as adding an additional property to yo Defining IOUState ----------------- -Let's open ``TemplateState.java`` (for Java) or ``TemplateState.kt`` (for Kotlin) and update ``TemplateState`` to +Let's open ``TemplateState.java`` (for Java) or ``App.kt`` (for Kotlin) and update ``TemplateState`` to define an ``IOUState``: .. container:: codeset .. code-block:: kotlin - package com.iou - - import net.corda.core.contracts.ContractState - import net.corda.core.identity.Party - class IOUState(val value: Int, val lender: Party, val borrower: Party) : ContractState { - override val contract: IOUContract = IOUContract() - + override val contract = TemplateContract() override val participants get() = listOf(lender, borrower) } .. code-block:: java - package com.iou; + package com.template.state; import com.google.common.collect.ImmutableList; + import com.template.contract.TemplateContract; import net.corda.core.contracts.ContractState; import net.corda.core.identity.AbstractParty; import net.corda.core.identity.Party; @@ -99,7 +94,7 @@ define an ``IOUState``: private final int value; private final Party lender; private final Party borrower; - private final IOUContract contract = new IOUContract(); + private final TemplateContract contract = new TemplateContract(); public IOUState(int value, Party lender, Party borrower) { this.value = value; @@ -121,7 +116,7 @@ define an ``IOUState``: @Override // TODO: Once we've defined IOUContract, come back and update this. - public IOUContract getContract() { + public TemplateContract getContract() { return contract; } @@ -131,6 +126,8 @@ define an ``IOUState``: } } +If you're following along in Java, you'll also need to rename ``TemplateState.java`` to ``IOUState.java``. + We've made the following changes: * We've renamed ``TemplateState`` to ``IOUState`` @@ -153,4 +150,4 @@ We've defined an ``IOUState`` that can be used to represent IOUs as shared facts Corda are simply JVM classes that implement the ``ContractState`` interface. They can have any additional properties and methods you like. -Next, we'll be writing our ``IOUContract`` to control the evolution of these shared facts over time. \ No newline at end of file +Next, we'll be writing our ``IOUContract`` to control the evolution of these shared facts over time. diff --git a/docs/source/hello-world-template.rst b/docs/source/hello-world-template.rst index aac84d483d..6ef1be4905 100644 --- a/docs/source/hello-world-template.rst +++ b/docs/source/hello-world-template.rst @@ -8,8 +8,9 @@ The CorDapp Template ==================== When writing a new CorDapp, you’ll generally want to base it on the -`Cordapp Template `_. The Cordapp Template allows you to quickly deploy -your CorDapp onto a local test network of dummy nodes to evaluate its functionality. +`Java Cordapp Template `_ or the equivalent +`Kotlin Cordapp Template `_. The Cordapp Template allows you to +quickly deploy your CorDapp onto a local test network of dummy nodes to evaluate its functionality. Note that there's no need to download and install Corda itself. As long as you're working from a stable Milestone branch, the required libraries will be downloaded automatically from an online repository. @@ -24,7 +25,11 @@ Open a terminal window in the directory where you want to download the CorDapp t .. code-block:: text # Clone the template from GitHub: - git clone https://github.com/corda/cordapp-template.git ; cd cordapp-template + git clone https://github.com/corda/cordapp-template-java.git ; cd cordapp-template-java + + *or* + + git clone https://github.com/corda/cordapp-template-kotlin.git ; cd cordapp-template-kotlin # Retrieve a list of the stable Milestone branches using: git branch -a --list *release-M* @@ -34,11 +39,8 @@ Open a terminal window in the directory where you want to download the CorDapp t Template structure ------------------ -We can write our CorDapp in either Java or Kotlin, and will be providing the code in both languages throughout. If -you want to write the CorDapp in Java, you'll be modifying the files under ``java-source``. If you prefer to use -Kotlin, you'll be modifying the files under ``kotlin-source``. - -To implement our IOU CorDapp, we'll only need to modify three files: +We can write our CorDapp in either Java or Kotlin, and will be providing the code in both languages throughout. To +implement our IOU CorDapp in Java, we'll only need to modify three files: .. container:: codeset @@ -53,16 +55,7 @@ To implement our IOU CorDapp, we'll only need to modify three files: // 3. The flow java-source/src/main/java/com/template/flow/TemplateFlow.java - .. code-block:: kotlin - - // 1. The state - kotlin-source/src/main/kotlin/com/template/state/TemplateState.kt - - // 2. The contract - kotlin-source/src/main/kotlin/com/template/contract/TemplateContract.kt - - // 3. The flow - kotlin-source/src/main/kotlin/com/template/flow/TemplateFlow.kt +For Kotlin, we'll simply be modifying the ``App.kt`` file. Progress so far ---------------