diff --git a/.gitignore b/.gitignore
index 19409419..d08af3e7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,5 +8,6 @@
**/.vscode/*
**/out/
**/logs/
+**/node_modules/
corda-nodeinfo/corda-nodeinfo.iml
*~*
diff --git a/Accounts/README.md b/Accounts/README.md
index fde3c3ba..f304320a 100644
--- a/Accounts/README.md
+++ b/Accounts/README.md
@@ -1,18 +1,21 @@
-## samples-java/Accounts
+## Accounts CorDapp Samples
This folder features Corda Accounts sample projects. Learn more about [Accounts](https://training.corda.net/libraries/accounts-lib/).
### [Supply Chain](./supplychain):
This CorDapp mimics a supply chain transaction, where the deal is incorporated among different teams in the companies on both side of the trade.
-[
](https://ide.corda.net/?folder=/home/coder/samples-java/Accounts/supplychain)
+
+
+
### [Tic Tac Thor](./tictacthor):
-This CorDapp recreates the game of Tic Tac Toe via Corda. It primarily demonstrates how you can have [LinearState](https://docs.corda.net/docs/corda-os/api-states.html#linearstate) transactions between cross-node accounts.
-[
](https://ide.corda.net/?folder=/home/coder/samples-java/Accounts/tictacthor)
+This CorDapp recreates the game of Tic Tac Toe via Corda. It primarily demonstrates how you can have LinearState transactions between cross-node accounts.
+
+
+
-### [Worldcup Ticket Booking](./worldcupticketbooking):
-This CorDapp demonstrates an ticket booking system with a collaboration of Corda [Accounts](https://training.corda.net/libraries/accounts-lib/) and [Tokens](https://training.corda.net/libraries/tokens-sdk/).
-[
](https://ide.corda.net/?folder=/home/coder/samples-java/Accounts/worldcupticketbooking)
+### [World Cup Ticket Booking](./worldcupticketbooking):
+This sample shows you how to integrate accounts and tokens. This sample talks about a scenario where typically when the Cricket season starts, BCCI (Board of Control for Cricket) starts selling tickets. As of now there are multiple dealers whom the BCCI issues tickets and further these dealers sell tickets to their client. We are trying to simulate similar functionality maintaining the entire issuance and selling of the tickets on Corda Platform.
\ No newline at end of file
diff --git a/Accounts/constants.properties b/Accounts/constants.properties
index 2cd5a28c..adcdb361 100644
--- a/Accounts/constants.properties
+++ b/Accounts/constants.properties
@@ -1,12 +1,12 @@
cordaReleaseGroup=net.corda
cordaCoreReleaseGroup=net.corda
-cordaVersion=4.6
-cordaCoreVersion=4.6
+cordaVersion=4.10
+cordaCoreVersion=4.10
gradlePluginsVersion=5.0.12
kotlinVersion=1.2.71
junitVersion=4.12
quasarVersion=0.7.10
-log4jVersion =2.11.2
-platformVersion=8
+log4jVersion =2.17.1
+platformVersion=12
slf4jVersion=1.7.25
nettyVersion=4.1.22.Final
diff --git a/Accounts/supplychain/Business Flow.png b/Accounts/supplychain/Business_Flow.png
similarity index 100%
rename from Accounts/supplychain/Business Flow.png
rename to Accounts/supplychain/Business_Flow.png
diff --git a/Accounts/supplychain/README.md b/Accounts/supplychain/README.md
index 0cf08e9a..87168170 100644
--- a/Accounts/supplychain/README.md
+++ b/Accounts/supplychain/README.md
@@ -1,6 +1,6 @@
-# Accounts_SupplyChain [
](https://ide.corda.net/?folder=/home/coder/samples-java/Accounts/supplychain)
+# Accounts_SupplyChain
-For More information regarding the Accounts Library, please read at: https://github.com/corda/accounts/blob/master/docs.md
+For more information regarding the Accounts Library, please read at: https://github.com/corda/accounts/blob/master/docs.md
This sample describes a mock/simple supply chain business flow.
@@ -10,10 +10,15 @@ This sample describes a mock/simple supply chain business flow.
From the above chart, you can see the flow is going back and forth between different parties' accounts. Please follow the instruction below to experience the [Accounts](https://training.corda.net/libraries/accounts-lib/) library.
-# Setting up
+
+## Pre-Requisites
+
+For development environment setup, please refer to: [Setup Guide](https://docs.r3.com/en/platform/corda/4.9/community/getting-set-up.html).
+
+## Runnning the nodes
Go into the project directory and build the project
```
-./gradlew clean deployNodes
+./gradlew clean build deployNodes
```
Run the project
```
@@ -21,7 +26,7 @@ Run the project
```
Now, you should have four Corda terminals opened automatically.
-# Shell Instructions (Part 1) - Creating & Sharing Accounts
+## Shell Instructions (Part 1) - Creating & Sharing Accounts
Go to the Buyer's node terminal and paste in the following code: (You can select all 7 lines and copy to the terminal all at once)
```
flow start CreateNewAccount acctName: BuyerProcurement
@@ -33,7 +38,7 @@ flow start ShareAccountTo acctNameShared: BuyerFinance, shareTo: Seller
flow start ShareAccountTo acctNameShared: BuyerWarehouse, shareTo: ShippingCo
flow start ShareAccountTo acctNameShared: BuyerWarehouse, shareTo: Seller
```
-This is creating 3 accounts under Buyer's node and sharing with their specific conterpartie's node or account.
+This is creating 3 accounts under Buyer's node and sharing with their specific counterparty's node or account.
Go to the Seller's node terminal and paste in the following code:
```
@@ -45,14 +50,14 @@ flow start ShareAccountTo acctNameShared: SellerSales, shareTo: Buyer
flow start ShareAccountTo acctNameShared: SellerFinance, shareTo: Buyer
flow start ShareAccountTo acctNameShared: SellerInventory, shareTo: ShippingCo
```
-This is creating 3 accounts under Seller's node and sharing with their specific conterparty's node or account.
+This is creating 3 accounts under Seller's node and sharing with their specific counterparty's node or account.
[Optional]: You can run a vaultQuery to see the [AccountInfo](https://training.corda.net/libraries/accounts-lib/#design) that been stored at each node by using:
```
run vaultQuery contractStateType: com.r3.corda.lib.accounts.contracts.states.AccountInfo
```
-# Shell Instructions (Part 2) - Executing Business Flows
-## Step 1: Seller's sales team send inovice of $500 to Buyer's procurement team
+## Shell Instructions (Part 2) - Executing Business Flows
+### Step 1: Seller's sales team send invoice for $500 to Buyer's procurement team
navigate to Seller's node terminal and run
```
flow start SendInvoice whoAmI: SellerSales, whereTo: BuyerProcurement, amount: 500
@@ -63,42 +68,42 @@ flow start ViewInboxByAccount acctname: BuyerProcurement
```
You see that the invoice state amount 500 is returned. You can also replace the BuyerProcurement with BuyerWarehouse to see that the non-relevant accounts has no visiblity about the invoice state.
-## Step 2: Buyer's procurement team will send an internal message to Buyer's Buyer's finance team
+### Step 2: Buyer's procurement team will send an internal message to Buyer's Buyer's finance team
Navigate to Buyer's node terminal and type in:
```
flow start InternalMessage fromWho: BuyerProcurement, whereTo: BuyerFinance, message: Send 500 to SellerFinance
```
[Optional verification]: run ```flow start ViewInboxByAccount acctname: BuyerFinance``` at Buyer' node terminal
-## Step 3: Buyer's finance team send a payment to Seller's finance team
+### Step 3: Buyer's finance team send a payment to Seller's finance team
Navigate to Buyer's node terminal and type in:
```
flow start SendPayment whoAmI: BuyerFinance, whereTo: SellerFinance, amount: 500
```
[Optional verification]: run ```flow start ViewInboxByAccount acctname: SellerFinance``` at Seller's node terminal
-## Step 4: Seller's finance team send an internal message to Seller's inventory team to instruct them to send the cargo
+### Step 4: Seller's finance team send an internal message to Seller's inventory team to instruct them to send the cargo
Navigate to Seller's node terminal and type in
```
flow start InternalMessage fromWho: SellerFinance, whereTo: SellerInventory, message: send Cargo to Buyer
```
[Optional verification]: run ```flow start ViewInboxByAccount acctname: SellerInventory``` at Seller's node terminal
-## step 5: Seller's inventory team send a shipping work order for shipping company
+### step 5: Seller's inventory team send a shipping work order for shipping company
Navigate to Seller's node terminal and type in
```
flow start SendShippingRequest whoAmI: SellerInventory, whereTo: BuyerWarehouse, shipper: ShippingCo, Cargo: 10 boxes of Books
```
-[Optional verification]: run ```run vaultQuery contractStateType: com.accounts_SupplyChain.states.ShippingRequestState``` at ShippingCo's node terminal
+[Optional verification]: run ```run vaultQuery contractStateType: ShippingRequestState``` at ShippingCo's node terminal
-## Step 6: Shipping company sends the cargo to Buyer's warehouse
+### Step 6: Shipping company sends the cargo to Buyer's warehouse
Navigate to ShippingCo's node terminal and type in
```
flow start SendCargo pickupFrom: SellerInventory, shipTo: BuyerWarehouse, cargo: Books
```
[Optional verification]: run ```flow start ViewInboxByAccount acctname: BuyerWarehouse``` at Buyer's node terminal
-## Now, the entire business chain is completed.
+### Now, the entire business chain is completed.
diff --git a/Accounts/supplychain/build.gradle b/Accounts/supplychain/build.gradle
index fed4c3bd..4d70ff49 100644
--- a/Accounts/supplychain/build.gradle
+++ b/Accounts/supplychain/build.gradle
@@ -3,7 +3,6 @@ buildscript {
file("$projectDir/../constants.properties").withInputStream { constants.load(it) }
ext {
-
corda_release_group = constants.getProperty("cordaReleaseGroup")
corda_core_release_group = constants.getProperty("cordaCoreReleaseGroup")
corda_release_version = constants.getProperty("cordaVersion")
@@ -15,9 +14,11 @@ buildscript {
log4j_version = constants.getProperty("log4jVersion")
slf4j_version = constants.getProperty("slf4jVersion")
corda_platform_version = constants.getProperty("platformVersion").toInteger()
- //accounts
- accounts_release_version = '1.0'
+
+ //account
accounts_release_group = 'com.r3.corda.lib.accounts'
+ accounts_release_version = '1.0'
+ //CI
confidential_id_release_group = "com.r3.corda.lib.ci"
confidential_id_release_version = "1.0"
}
@@ -25,8 +26,7 @@ buildscript {
repositories {
mavenLocal()
mavenCentral()
- jcenter()
- maven { url 'https://ci-artifactory.corda.r3cev.com/artifactory/corda-releases' }
+ maven { url 'https://download.corda.net/maven/corda-releases' }
}
dependencies {
@@ -42,12 +42,14 @@ allprojects {
repositories {
mavenLocal()
- jcenter()
+
mavenCentral()
- maven { url 'https://ci-artifactory.corda.r3cev.com/artifactory/corda' }
- maven { url 'https://ci-artifactory.corda.r3cev.com/artifactory/corda-lib' }
- maven { url 'https://ci-artifactory.corda.r3cev.com/artifactory/corda-lib-dev' }
- maven { url "https://repo.gradle.org/gradle/libs-releases-local" }
+ maven { url 'https://download.corda.net/maven/corda-dependencies' }
+ maven { url 'https://jitpack.io' }
+ //SDK lib
+ maven { url 'https://download.corda.net/maven/corda-lib' }
+ //Gradle Plugins
+ maven { url 'https://repo.gradle.org/gradle/libs-releases' }
}
tasks.withType(JavaCompile) {
@@ -62,9 +64,6 @@ allprojects {
}
}
-
-
-
apply plugin: 'net.corda.plugins.cordapp'
apply plugin: 'net.corda.plugins.cordformation'
apply plugin: 'net.corda.plugins.quasar-utils'
@@ -90,6 +89,8 @@ dependencies {
cordaCompile "org.apache.logging.log4j:log4j-slf4j-impl:${log4j_version}"
cordaCompile "org.apache.logging.log4j:log4j-web:${log4j_version}"
cordaCompile "org.slf4j:jul-to-slf4j:$slf4j_version"
+ cordaDriver "net.corda:corda-shell:4.10"
+
//accounts
cordapp "$accounts_release_group:accounts-contracts:$accounts_release_version"
@@ -97,29 +98,6 @@ dependencies {
cordapp "$accounts_release_group:accounts-workflows:$accounts_release_version"
}
-cordapp {
- info {
- name "CorDapp supplychain"
- vendor "Corda Open Source"
- targetPlatformVersion corda_platform_version
- minimumPlatformVersion corda_platform_version
- }
-}
-
-task ganache {
- subprojects {
- if (it.project.name != "clients") {
- dependsOn jar
- doLast {
- copy {
- from "${buildDir}/libs"
- into "${rootDir}/build/libs"
- }
- }
- }
- }
-}
-
task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar']) {
nodeDefaults {
projectCordapp {
diff --git a/Accounts/supplychain/contracts/src/main/java/com/supplychain/contracts/InvoiceStateContract.java b/Accounts/supplychain/contracts/src/main/java/com/supplychain/contracts/InvoiceStateContract.java
deleted file mode 100644
index e0f94689..00000000
--- a/Accounts/supplychain/contracts/src/main/java/com/supplychain/contracts/InvoiceStateContract.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package com.supplychain.contracts;
-
-import net.corda.core.contracts.CommandData;
-import net.corda.core.contracts.Contract;
-import net.corda.core.transactions.LedgerTransaction;
-
-// ************
-// * Contract *
-// ************
-public class InvoiceStateContract implements Contract {
- // This is used to identify our contract when building a transaction.
- public static final String ID = "com.supplychain.contracts.InvoiceStateContract";
-
- // A transaction is valid if the verify() function of the contract of all the transaction's input and output states
- // does not throw an exception.
- @Override
- public void verify(LedgerTransaction tx) {}
-
- // Used to indicate the transaction's intent.
- public interface Commands extends CommandData {
- class Create implements Commands {}
- }
-}
\ No newline at end of file
diff --git a/Accounts/supplychain/contracts/src/main/java/com/supplychain/states/InvoiceState.java b/Accounts/supplychain/contracts/src/main/java/com/supplychain/states/InvoiceState.java
deleted file mode 100644
index 164111f6..00000000
--- a/Accounts/supplychain/contracts/src/main/java/com/supplychain/states/InvoiceState.java
+++ /dev/null
@@ -1,71 +0,0 @@
-package com.supplychain.states;
-
-import com.supplychain.contracts.InvoiceStateContract;
-import net.corda.core.contracts.BelongsToContract;
-import net.corda.core.contracts.ContractState;
-import net.corda.core.identity.AbstractParty;
-import net.corda.core.identity.AnonymousParty;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.UUID;
-
-// *********
-// * State *
-// *********
-@BelongsToContract(InvoiceStateContract.class)
-public class InvoiceState implements ContractState {
-
- private int amount;
- private AnonymousParty sender;
- private AnonymousParty recipient;
- private UUID invoiceID;
- private List participants;
-
- public InvoiceState(int amount, AnonymousParty sender, AnonymousParty recipient, UUID invoiceID) {
- this.amount = amount;
- this.sender = sender;
- this.recipient = recipient;
- this.invoiceID = invoiceID;
- this.participants = new ArrayList();
- participants.add(recipient);
- participants.add(sender);
- }
-
- public int getAmount() {
- return amount;
- }
-
- public void setAmount(int amount) {
- this.amount = amount;
- }
-
- public AnonymousParty getSender() {
- return sender;
- }
-
- public void setSender(AnonymousParty sender) {
- this.sender = sender;
- }
-
- public AnonymousParty getRecipient() {
- return recipient;
- }
-
- public void setRecipient(AnonymousParty recipient) {
- this.recipient = recipient;
- }
-
- public UUID getInvoiceID() {
- return invoiceID;
- }
-
- public void setInvoiceID(UUID invoiceID) {
- this.invoiceID = invoiceID;
- }
-
- @Override
- public List getParticipants() {
- return this.participants;
- }
-}
\ No newline at end of file
diff --git a/Accounts/supplychain/contracts/src/main/java/com/supplychain/contracts/CargoStateContract.java b/Accounts/supplychain/contracts/src/main/java/net/corda/samples/supplychain/contracts/CargoStateContract.java
similarity index 82%
rename from Accounts/supplychain/contracts/src/main/java/com/supplychain/contracts/CargoStateContract.java
rename to Accounts/supplychain/contracts/src/main/java/net/corda/samples/supplychain/contracts/CargoStateContract.java
index 741765fe..6a2a704c 100644
--- a/Accounts/supplychain/contracts/src/main/java/com/supplychain/contracts/CargoStateContract.java
+++ b/Accounts/supplychain/contracts/src/main/java/net/corda/samples/supplychain/contracts/CargoStateContract.java
@@ -1,4 +1,4 @@
-package com.supplychain.contracts;
+package net.corda.samples.supplychain.contracts;
import net.corda.core.contracts.CommandData;
import net.corda.core.contracts.Contract;
@@ -9,7 +9,7 @@
// ************
public class CargoStateContract implements Contract {
// This is used to identify our contract when building a transaction.
- public static final String ID = "com.supplychain.contracts.CargoStateContract";
+ public static final String ID = "net.corda.samples.supplychain.contracts.CargoStateContract";
// A transaction is valid if the verify() function of the contract of all the transaction's input and output states
// does not throw an exception.
diff --git a/Accounts/supplychain/contracts/src/main/java/com/supplychain/contracts/InternalMessageStateContract.java b/Accounts/supplychain/contracts/src/main/java/net/corda/samples/supplychain/contracts/InternalMessageStateContract.java
similarity index 81%
rename from Accounts/supplychain/contracts/src/main/java/com/supplychain/contracts/InternalMessageStateContract.java
rename to Accounts/supplychain/contracts/src/main/java/net/corda/samples/supplychain/contracts/InternalMessageStateContract.java
index 6550d8a6..bc99bb7b 100644
--- a/Accounts/supplychain/contracts/src/main/java/com/supplychain/contracts/InternalMessageStateContract.java
+++ b/Accounts/supplychain/contracts/src/main/java/net/corda/samples/supplychain/contracts/InternalMessageStateContract.java
@@ -1,4 +1,4 @@
-package com.supplychain.contracts;
+package net.corda.samples.supplychain.contracts;
import net.corda.core.contracts.CommandData;
import net.corda.core.contracts.Contract;
@@ -9,7 +9,7 @@
// ************
public class InternalMessageStateContract implements Contract {
// This is used to identify our contract when building a transaction.
- public static final String ID = "com.supplychain.contracts.InternalMessageStateContract";
+ public static final String ID = "net.corda.samples.supplychain.contracts.InternalMessageStateContract";
// A transaction is valid if the verify() function of the contract of all the transaction's input and output states
// does not throw an exception.
diff --git a/Accounts/supplychain/contracts/src/main/java/net/corda/samples/supplychain/contracts/InvoiceStateContract.java b/Accounts/supplychain/contracts/src/main/java/net/corda/samples/supplychain/contracts/InvoiceStateContract.java
new file mode 100644
index 00000000..4336423f
--- /dev/null
+++ b/Accounts/supplychain/contracts/src/main/java/net/corda/samples/supplychain/contracts/InvoiceStateContract.java
@@ -0,0 +1,56 @@
+package net.corda.samples.supplychain.contracts;
+
+import net.corda.core.contracts.CommandData;
+import net.corda.core.contracts.CommandWithParties;
+import net.corda.core.contracts.Contract;
+import net.corda.core.contracts.ContractState;
+import net.corda.core.transactions.LedgerTransaction;
+import net.corda.samples.supplychain.states.InvoiceState;
+
+import java.util.List;
+
+import static net.corda.core.contracts.ContractsDSL.requireSingleCommand;
+import static net.corda.core.contracts.ContractsDSL.requireThat;
+
+// ************
+// * Contract *
+// ************
+public class InvoiceStateContract implements Contract {
+ // This is used to identify our contract when building a transaction.
+ public static final String ID = "net.corda.samples.supplychain.contracts.InvoiceStateContract";
+
+ // A transaction is valid if the verify() function of the contract of all the transaction's input and output states
+ // does not throw an exception.
+ @Override
+ public void verify(LedgerTransaction tx) throws IllegalArgumentException {
+ /*
+ * We can use the requireSingleCommand function to extract command data from transaction.
+ * However, it is possible to have multiple commands in a signle transaction.
+ */
+ final CommandWithParties command = requireSingleCommand(tx.getCommands(), InvoiceStateContract.Commands.class);
+
+ List inputs = tx.getInputStates();
+ List outputs = tx.getOutputStates();
+
+ if (command.getValue() instanceof InvoiceStateContract.Commands.Create) {
+
+ // Using Corda DSL function requireThat to replicate conditions-checks
+ requireThat(require -> {
+ require.using("No inputs should be consumed when creating a new Invoice State.", inputs.isEmpty());
+ require.using("Transaction must have exactly one output.", outputs.size() == 1);
+ InvoiceState output = (InvoiceState) outputs.get(0);
+ require.using("Invoice amount must be a valid number (Greater than zero)", output.getAmount() > 0);
+ return null;
+ });
+
+ } else {
+ throw new IllegalArgumentException("Command not found!");
+ }
+
+ }
+
+ // Used to indicate the transaction's intent.
+ public interface Commands extends CommandData {
+ class Create implements Commands {}
+ }
+}
\ No newline at end of file
diff --git a/Accounts/supplychain/contracts/src/main/java/com/supplychain/contracts/PaymentStateContract.java b/Accounts/supplychain/contracts/src/main/java/net/corda/samples/supplychain/contracts/PaymentStateContract.java
similarity index 82%
rename from Accounts/supplychain/contracts/src/main/java/com/supplychain/contracts/PaymentStateContract.java
rename to Accounts/supplychain/contracts/src/main/java/net/corda/samples/supplychain/contracts/PaymentStateContract.java
index acbe7986..81a7b16d 100644
--- a/Accounts/supplychain/contracts/src/main/java/com/supplychain/contracts/PaymentStateContract.java
+++ b/Accounts/supplychain/contracts/src/main/java/net/corda/samples/supplychain/contracts/PaymentStateContract.java
@@ -1,4 +1,4 @@
-package com.supplychain.contracts;
+package net.corda.samples.supplychain.contracts;
import net.corda.core.contracts.CommandData;
import net.corda.core.contracts.Contract;
@@ -9,7 +9,7 @@
// ************
public class PaymentStateContract implements Contract {
// This is used to identify our contract when building a transaction.
- public static final String ID = "com.supplychain.contracts.PaymentStateContract";
+ public static final String ID = "net.corda.samples.supplychain.contracts.PaymentStateContract";
// A transaction is valid if the verify() function of the contract of all the transaction's input and output states
// does not throw an exception.
diff --git a/Accounts/supplychain/contracts/src/main/java/com/supplychain/contracts/ShippingRequestStateContract.java b/Accounts/supplychain/contracts/src/main/java/net/corda/samples/supplychain/contracts/ShippingRequestStateContract.java
similarity index 81%
rename from Accounts/supplychain/contracts/src/main/java/com/supplychain/contracts/ShippingRequestStateContract.java
rename to Accounts/supplychain/contracts/src/main/java/net/corda/samples/supplychain/contracts/ShippingRequestStateContract.java
index e9dcb906..ab0c0cfa 100644
--- a/Accounts/supplychain/contracts/src/main/java/com/supplychain/contracts/ShippingRequestStateContract.java
+++ b/Accounts/supplychain/contracts/src/main/java/net/corda/samples/supplychain/contracts/ShippingRequestStateContract.java
@@ -1,4 +1,4 @@
-package com.supplychain.contracts;
+package net.corda.samples.supplychain.contracts;
import net.corda.core.contracts.CommandData;
import net.corda.core.contracts.Contract;
@@ -9,7 +9,7 @@
// ************
public class ShippingRequestStateContract implements Contract {
// This is used to identify our contract when building a transaction.
- public static final String ID = "com.supplychain.contracts.ShippingRequestStateContract";
+ public static final String ID = "net.corda.samples.supplychain.contracts.ShippingRequestStateContract";
// A transaction is valid if the verify() function of the contract of all the transaction's input and output states
// does not throw an exception.
diff --git a/Accounts/supplychain/contracts/src/main/java/com/supplychain/states/CargoState.java b/Accounts/supplychain/contracts/src/main/java/net/corda/samples/supplychain/states/CargoState.java
similarity index 93%
rename from Accounts/supplychain/contracts/src/main/java/com/supplychain/states/CargoState.java
rename to Accounts/supplychain/contracts/src/main/java/net/corda/samples/supplychain/states/CargoState.java
index 13e71b3f..38ac721a 100644
--- a/Accounts/supplychain/contracts/src/main/java/com/supplychain/states/CargoState.java
+++ b/Accounts/supplychain/contracts/src/main/java/net/corda/samples/supplychain/states/CargoState.java
@@ -1,6 +1,6 @@
-package com.supplychain.states;
+package net.corda.samples.supplychain.states;
-import com.supplychain.contracts.CargoStateContract;
+import net.corda.samples.supplychain.contracts.CargoStateContract;
import net.corda.core.contracts.BelongsToContract;
import net.corda.core.contracts.ContractState;
import net.corda.core.identity.AbstractParty;
diff --git a/Accounts/supplychain/contracts/src/main/java/com/supplychain/states/InternalMessageState.java b/Accounts/supplychain/contracts/src/main/java/net/corda/samples/supplychain/states/InternalMessageState.java
similarity index 91%
rename from Accounts/supplychain/contracts/src/main/java/com/supplychain/states/InternalMessageState.java
rename to Accounts/supplychain/contracts/src/main/java/net/corda/samples/supplychain/states/InternalMessageState.java
index 29c5713e..5d7a34a3 100644
--- a/Accounts/supplychain/contracts/src/main/java/com/supplychain/states/InternalMessageState.java
+++ b/Accounts/supplychain/contracts/src/main/java/net/corda/samples/supplychain/states/InternalMessageState.java
@@ -1,6 +1,6 @@
-package com.supplychain.states;
+package net.corda.samples.supplychain.states;
-import com.supplychain.contracts.InternalMessageStateContract;
+import net.corda.samples.supplychain.contracts.InternalMessageStateContract;
import net.corda.core.contracts.BelongsToContract;
import net.corda.core.contracts.ContractState;
import net.corda.core.identity.AbstractParty;
diff --git a/Accounts/supplychain/contracts/src/main/java/net/corda/samples/supplychain/states/InvoiceState.java b/Accounts/supplychain/contracts/src/main/java/net/corda/samples/supplychain/states/InvoiceState.java
new file mode 100644
index 00000000..699cc532
--- /dev/null
+++ b/Accounts/supplychain/contracts/src/main/java/net/corda/samples/supplychain/states/InvoiceState.java
@@ -0,0 +1,71 @@
+package net.corda.samples.supplychain.states;
+
+import net.corda.samples.supplychain.contracts.InvoiceStateContract;
+import net.corda.core.contracts.BelongsToContract;
+import net.corda.core.contracts.ContractState;
+import net.corda.core.identity.AbstractParty;
+import net.corda.core.identity.AnonymousParty;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+// *********
+// * State *
+// *********
+@BelongsToContract(InvoiceStateContract.class)
+public class InvoiceState implements ContractState {
+
+ private int amount;
+ private AnonymousParty sender;
+ private AnonymousParty recipient;
+ private UUID invoiceID;
+ private List participants;
+
+ public InvoiceState(int amount, AnonymousParty sender, AnonymousParty recipient, UUID invoiceID) {
+ this.amount = amount;
+ this.sender = sender;
+ this.recipient = recipient;
+ this.invoiceID = invoiceID;
+ this.participants = new ArrayList();
+ participants.add(recipient);
+ participants.add(sender);
+ }
+
+ public int getAmount() {
+ return amount;
+ }
+
+ public void setAmount(int amount) {
+ this.amount = amount;
+ }
+
+ public AnonymousParty getSender() {
+ return sender;
+ }
+
+ public void setSender(AnonymousParty sender) {
+ this.sender = sender;
+ }
+
+ public AnonymousParty getRecipient() {
+ return recipient;
+ }
+
+ public void setRecipient(AnonymousParty recipient) {
+ this.recipient = recipient;
+ }
+
+ public UUID getInvoiceID() {
+ return invoiceID;
+ }
+
+ public void setInvoiceID(UUID invoiceID) {
+ this.invoiceID = invoiceID;
+ }
+
+ @Override
+ public List getParticipants() {
+ return this.participants;
+ }
+}
\ No newline at end of file
diff --git a/Accounts/supplychain/contracts/src/main/java/com/supplychain/states/PaymentState.java b/Accounts/supplychain/contracts/src/main/java/net/corda/samples/supplychain/states/PaymentState.java
similarity index 92%
rename from Accounts/supplychain/contracts/src/main/java/com/supplychain/states/PaymentState.java
rename to Accounts/supplychain/contracts/src/main/java/net/corda/samples/supplychain/states/PaymentState.java
index 9e75a41b..00d3531e 100644
--- a/Accounts/supplychain/contracts/src/main/java/com/supplychain/states/PaymentState.java
+++ b/Accounts/supplychain/contracts/src/main/java/net/corda/samples/supplychain/states/PaymentState.java
@@ -1,6 +1,6 @@
-package com.supplychain.states;
+package net.corda.samples.supplychain.states;
-import com.supplychain.contracts.PaymentStateContract;
+import net.corda.samples.supplychain.contracts.PaymentStateContract;
import net.corda.core.contracts.BelongsToContract;
import net.corda.core.contracts.ContractState;
import net.corda.core.identity.AbstractParty;
diff --git a/Accounts/supplychain/contracts/src/main/java/com/supplychain/states/ShippingRequestState.java b/Accounts/supplychain/contracts/src/main/java/net/corda/samples/supplychain/states/ShippingRequestState.java
similarity index 93%
rename from Accounts/supplychain/contracts/src/main/java/com/supplychain/states/ShippingRequestState.java
rename to Accounts/supplychain/contracts/src/main/java/net/corda/samples/supplychain/states/ShippingRequestState.java
index 3ff5ee22..ebfd2cf1 100644
--- a/Accounts/supplychain/contracts/src/main/java/com/supplychain/states/ShippingRequestState.java
+++ b/Accounts/supplychain/contracts/src/main/java/net/corda/samples/supplychain/states/ShippingRequestState.java
@@ -1,6 +1,6 @@
-package com.supplychain.states;
+package net.corda.samples.supplychain.states;
-import com.supplychain.contracts.ShippingRequestStateContract;
+import net.corda.samples.supplychain.contracts.ShippingRequestStateContract;
import net.corda.core.contracts.BelongsToContract;
import net.corda.core.contracts.ContractState;
import net.corda.core.identity.AbstractParty;
diff --git a/Accounts/supplychain/contracts/src/test/java/com/supplychain/contracts/ContractTests.java b/Accounts/supplychain/contracts/src/test/java/com/supplychain/contracts/ContractTests.java
deleted file mode 100644
index 63beb3ba..00000000
--- a/Accounts/supplychain/contracts/src/test/java/com/supplychain/contracts/ContractTests.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package com.supplychain.contracts;
-
-import net.corda.testing.node.MockServices;
-import org.junit.Test;
-
-public class ContractTests {
- private final MockServices ledgerServices = new MockServices();
-
- @Test
- public void dummyTest() {
-
- }
-}
\ No newline at end of file
diff --git a/Accounts/supplychain/contracts/src/test/java/net/corda/samples/supplychain/contracts/ContractTests.java b/Accounts/supplychain/contracts/src/test/java/net/corda/samples/supplychain/contracts/ContractTests.java
new file mode 100644
index 00000000..f40dd8f7
--- /dev/null
+++ b/Accounts/supplychain/contracts/src/test/java/net/corda/samples/supplychain/contracts/ContractTests.java
@@ -0,0 +1,38 @@
+package net.corda.samples.supplychain.contracts;
+
+import net.corda.core.contracts.UniqueIdentifier;
+import net.corda.core.identity.AnonymousParty;
+import net.corda.core.identity.CordaX500Name;
+import net.corda.samples.supplychain.states.InvoiceState;
+import net.corda.testing.core.TestIdentity;
+import net.corda.testing.node.MockServices;
+import org.junit.Test;
+
+import java.util.UUID;
+
+import static net.corda.testing.node.NodeTestUtils.ledger;
+
+public class ContractTests {
+ private final MockServices ledgerServices = new MockServices();
+ TestIdentity Operator = new TestIdentity(new CordaX500Name("Alice", "TestLand", "US"));
+ TestIdentity Operator2 = new TestIdentity(new CordaX500Name("Bob", "TestLand", "US"));
+
+ @Test
+ public void InvoiceAmountMustBeGreaterThanZero() {
+ InvoiceState tokenPass = new InvoiceState(10, new AnonymousParty(Operator.getPublicKey()),new AnonymousParty(Operator2.getPublicKey()),new UniqueIdentifier().getId());
+ InvoiceState tokenfail = new InvoiceState(-1, new AnonymousParty(Operator.getPublicKey()),new AnonymousParty(Operator2.getPublicKey()),new UniqueIdentifier().getId());
+ ledger(ledgerServices, l -> {
+ l.transaction(tx -> {
+ tx.output(InvoiceStateContract.ID, tokenfail);
+ tx.command(Operator.getPublicKey(), new InvoiceStateContract.Commands.Create()); // Wrong type.
+ return tx.fails();
+ });
+ l.transaction(tx -> {
+ tx.output(InvoiceStateContract.ID, tokenPass);
+ tx.command(Operator.getPublicKey(), new InvoiceStateContract.Commands.Create()); // Wrong type.
+ return tx.verifies();
+ });
+ return null;
+ });
+ }
+}
\ No newline at end of file
diff --git a/Accounts/supplychain/contracts/src/test/java/net/corda/samples/supplychain/contracts/StateTests.java b/Accounts/supplychain/contracts/src/test/java/net/corda/samples/supplychain/contracts/StateTests.java
new file mode 100644
index 00000000..5031f6be
--- /dev/null
+++ b/Accounts/supplychain/contracts/src/test/java/net/corda/samples/supplychain/contracts/StateTests.java
@@ -0,0 +1,17 @@
+package net.corda.samples.supplychain.contracts;
+
+import net.corda.samples.supplychain.states.InvoiceState;
+import net.corda.testing.node.MockServices;
+import org.junit.Test;
+
+public class StateTests {
+ private final MockServices ledgerServices = new MockServices();
+
+ @Test
+ public void hasAmountFieldOfCorrectType() throws NoSuchFieldException {
+ // Does the message field exist?
+ InvoiceState.class.getDeclaredField("amount");
+ // Is the message field of the correct type?
+ assert(InvoiceState.class.getDeclaredField("amount").getType().equals(int.class));
+ }
+}
\ No newline at end of file
diff --git a/Accounts/supplychain/gradle.properties b/Accounts/supplychain/gradle.properties
index 834d4552..6b3850f8 100644
--- a/Accounts/supplychain/gradle.properties
+++ b/Accounts/supplychain/gradle.properties
@@ -1,3 +1,3 @@
-name=Test
+name=Supplychain Cordapp
group=com.supplychain
-version=0.1
\ No newline at end of file
+version=1.0
\ No newline at end of file
diff --git a/Accounts/supplychain/gradle/wrapper/gradle-wrapper.properties b/Accounts/supplychain/gradle/wrapper/gradle-wrapper.properties
index 2a2a3a8e..ae01072d 100644
--- a/Accounts/supplychain/gradle/wrapper/gradle-wrapper.properties
+++ b/Accounts/supplychain/gradle/wrapper/gradle-wrapper.properties
@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip
diff --git a/Accounts/supplychain/repositories.gradle b/Accounts/supplychain/repositories.gradle
index 2874c2ab..9797c0ea 100644
--- a/Accounts/supplychain/repositories.gradle
+++ b/Accounts/supplychain/repositories.gradle
@@ -1,8 +1,7 @@
repositories {
mavenLocal()
mavenCentral()
- jcenter()
maven { url 'https://jitpack.io' }
- maven { url 'https://ci-artifactory.corda.r3cev.com/artifactory/corda' }
+ maven { url 'https://download.corda.net/maven/corda-dependencies' }
maven { url 'https://repo.gradle.org/gradle/libs-releases' }
}
diff --git a/Accounts/supplychain/workflows/src/integrationTest/java/com/supplychain/DriverBasedTest.java b/Accounts/supplychain/workflows/src/integrationTest/java/com/supplychain/DriverBasedTest.java
deleted file mode 100644
index a6bc2380..00000000
--- a/Accounts/supplychain/workflows/src/integrationTest/java/com/supplychain/DriverBasedTest.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package com.supplychain;
-
-import com.google.common.collect.ImmutableList;
-import net.corda.core.concurrent.CordaFuture;
-import net.corda.core.identity.CordaX500Name;
-import net.corda.testing.core.TestIdentity;
-import net.corda.testing.driver.DriverParameters;
-import net.corda.testing.driver.NodeHandle;
-import net.corda.testing.driver.NodeParameters;
-import org.junit.Test;
-
-import java.util.List;
-
-import static net.corda.testing.driver.Driver.driver;
-import static org.junit.Assert.assertEquals;
-
-public class DriverBasedTest {
- private final TestIdentity bankA = new TestIdentity(new CordaX500Name("BankA", "", "GB"));
- private final TestIdentity bankB = new TestIdentity(new CordaX500Name("BankB", "", "US"));
-
- @Test
- public void nodeTest() {
- driver(new DriverParameters().withIsDebug(true).withStartNodesInProcess(true), dsl -> {
- // Start a pair of nodes and wait for them both to be ready.
- List> handleFutures = ImmutableList.of(
- dsl.startNode(new NodeParameters().withProvidedName(bankA.getName())),
- dsl.startNode(new NodeParameters().withProvidedName(bankB.getName()))
- );
-
- try {
- NodeHandle partyAHandle = handleFutures.get(0).get();
- NodeHandle partyBHandle = handleFutures.get(1).get();
-
- // From each node, make an RPC call to retrieve another node's name from the network map, to verify that the
- // nodes have started and can communicate.
-
- // This is a very basic test: in practice tests would be starting flows, and verifying the states in the vault
- // and other important metrics to ensure that your CorDapp is working as intended.
- assertEquals(partyAHandle.getRpc().wellKnownPartyFromX500Name(bankB.getName()).getName(), bankB.getName());
- assertEquals(partyBHandle.getRpc().wellKnownPartyFromX500Name(bankA.getName()).getName(), bankA.getName());
- } catch (Exception e) {
- throw new RuntimeException("Caught exception during test: ", e);
- }
-
- return null;
- });
- }
-}
\ No newline at end of file
diff --git a/Accounts/supplychain/workflows/src/integrationTest/java/net/corda/samples/supplychain/DriverBasedTest.java b/Accounts/supplychain/workflows/src/integrationTest/java/net/corda/samples/supplychain/DriverBasedTest.java
new file mode 100644
index 00000000..0a6262ef
--- /dev/null
+++ b/Accounts/supplychain/workflows/src/integrationTest/java/net/corda/samples/supplychain/DriverBasedTest.java
@@ -0,0 +1,48 @@
+package net.corda.samples.supplychain;
+
+import com.google.common.collect.ImmutableList;
+import net.corda.core.concurrent.CordaFuture;
+import net.corda.core.identity.CordaX500Name;
+import net.corda.testing.core.TestIdentity;
+import net.corda.testing.driver.DriverParameters;
+import net.corda.testing.driver.NodeHandle;
+import net.corda.testing.driver.NodeParameters;
+import org.junit.Test;
+
+import java.util.List;
+
+import static net.corda.testing.driver.Driver.driver;
+import static org.junit.Assert.assertEquals;
+
+public class DriverBasedTest {
+ private final TestIdentity bankA = new TestIdentity(new CordaX500Name("BankA", "", "GB"));
+ private final TestIdentity bankB = new TestIdentity(new CordaX500Name("BankB", "", "US"));
+
+ @Test
+ public void nodeTest() {
+ driver(new DriverParameters().withIsDebug(true).withStartNodesInProcess(true), dsl -> {
+ // Start a pair of nodes and wait for them both to be ready.
+ List> handleFutures = ImmutableList.of(
+ dsl.startNode(new NodeParameters().withProvidedName(bankA.getName())),
+ dsl.startNode(new NodeParameters().withProvidedName(bankB.getName()))
+ );
+
+ try {
+ NodeHandle partyAHandle = handleFutures.get(0).get();
+ NodeHandle partyBHandle = handleFutures.get(1).get();
+
+ // From each node, make an RPC call to retrieve another node's name from the network map, to verify that the
+ // nodes have started and can communicate.
+
+ // This is a very basic test: in practice tests would be starting flows, and verifying the states in the vault
+ // and other important metrics to ensure that your CorDapp is working as intended.
+ assertEquals(partyAHandle.getRpc().wellKnownPartyFromX500Name(bankB.getName()).getName(), bankB.getName());
+ assertEquals(partyBHandle.getRpc().wellKnownPartyFromX500Name(bankA.getName()).getName(), bankA.getName());
+ } catch (Exception e) {
+ throw new RuntimeException("Caught exception during test: ", e);
+ }
+
+ return null;
+ });
+ }
+}
\ No newline at end of file
diff --git a/Accounts/supplychain/workflows/src/main/java/com/supplychain/accountUtilities/CreateNewAccount.java b/Accounts/supplychain/workflows/src/main/java/com/supplychain/accountUtilities/CreateNewAccount.java
deleted file mode 100644
index eb3d275c..00000000
--- a/Accounts/supplychain/workflows/src/main/java/com/supplychain/accountUtilities/CreateNewAccount.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package com.supplychain.accountUtilities;
-
-import com.r3.corda.lib.accounts.contracts.states.AccountInfo;
-import com.r3.corda.lib.accounts.workflows.*;
-import com.r3.corda.lib.accounts.workflows.services.KeyManagementBackedAccountService;
-import net.corda.core.contracts.StateAndRef;
-import net.corda.core.flows.*;
-import co.paralleluniverse.fibers.Suspendable;
-import com.r3.corda.lib.accounts.workflows.services.AccountService;
-import net.corda.core.flows.FlowLogic;;
-import net.corda.core.flows.StartableByRPC;
-
-import java.util.UUID;
-
-@StartableByRPC
-@StartableByService
-@InitiatingFlow
-public class CreateNewAccount extends FlowLogic{
-
- private String acctName;
-
- public CreateNewAccount(String acctName) {
- this.acctName = acctName;
- }
-
-
- @Override
- public String call() throws FlowException {
- StateAndRef newAccount = null;
- try {
- newAccount = getServiceHub().cordaService(KeyManagementBackedAccountService.class).createAccount(acctName).get();
- } catch (Exception e) {
- e.printStackTrace();
- }
- AccountInfo acct = newAccount.getState().getData();
- return "" + acct.getName() + " team's account was created. UUID is : " + acct.getIdentifier();
- }
-}
diff --git a/Accounts/supplychain/workflows/src/main/java/com/supplychain/accountUtilities/NewKeyForAccount.java b/Accounts/supplychain/workflows/src/main/java/com/supplychain/accountUtilities/NewKeyForAccount.java
deleted file mode 100644
index 83e2c5e6..00000000
--- a/Accounts/supplychain/workflows/src/main/java/com/supplychain/accountUtilities/NewKeyForAccount.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package com.supplychain.accountUtilities;
-
-import co.paralleluniverse.fibers.Suspendable;
-import net.corda.core.flows.FlowException;
-import net.corda.core.flows.FlowLogic;
-import net.corda.core.flows.StartableByRPC;
-import net.corda.core.flows.StartableByService;
-import net.corda.core.identity.PartyAndCertificate;
-import java.util.*;
-
-@StartableByRPC
-@StartableByService
-public class NewKeyForAccount extends FlowLogic{
-
- private final UUID accountID;
-
- public NewKeyForAccount(UUID accountID) {
- this.accountID = accountID;
- }
-
- @Override
- @Suspendable
- public PartyAndCertificate call() throws FlowException {
- return getServiceHub().getKeyManagementService().freshKeyAndCert(getOurIdentityAndCert(), false, accountID);
- }
-}
\ No newline at end of file
diff --git a/Accounts/supplychain/workflows/src/main/java/com/supplychain/accountUtilities/ShareAccountTo.java b/Accounts/supplychain/workflows/src/main/java/com/supplychain/accountUtilities/ShareAccountTo.java
deleted file mode 100644
index c828a0c9..00000000
--- a/Accounts/supplychain/workflows/src/main/java/com/supplychain/accountUtilities/ShareAccountTo.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package com.supplychain.accountUtilities;
-
-import co.paralleluniverse.fibers.Suspendable;
-import com.r3.corda.lib.accounts.contracts.states.AccountInfo;
-import com.r3.corda.lib.accounts.workflows.flows.AccountInfoByName;
-import com.r3.corda.lib.accounts.workflows.services.KeyManagementBackedAccountService;
-import net.corda.core.contracts.StateAndRef;
-import net.corda.core.flows.FlowException;
-import net.corda.core.flows.FlowLogic;
-import net.corda.core.flows.StartableByRPC;
-import net.corda.core.flows.StartableByService;
-import net.corda.core.identity.Party;
-import com.r3.corda.lib.accounts.workflows.flows.ShareAccountInfo;
-import java.util.*;
-
-@StartableByRPC
-@StartableByService
-public class ShareAccountTo extends FlowLogic{
-
- private final Party shareTo;
- private final String acctNameShared;
-
- public ShareAccountTo(String acctNameShared, Party shareTo) {
- this.acctNameShared = acctNameShared;
- this.shareTo = shareTo;
- }
-
- @Override
- @Suspendable
- public String call() throws FlowException {
- List> allmyAccounts = getServiceHub().cordaService(KeyManagementBackedAccountService.class).ourAccounts();
- StateAndRef SharedAccount = allmyAccounts.stream()
- .filter(it -> it.getState().getData().getName().equals(acctNameShared))
- .findAny().get();
-
- subFlow(new ShareAccountInfo(SharedAccount, Arrays.asList(shareTo)));
- return "Shared " + acctNameShared + " with " + shareTo.getName().getOrganisation();
- }
-}
\ No newline at end of file
diff --git a/Accounts/supplychain/workflows/src/main/java/net/corda/samples/supplychain/accountUtilities/CreateNewAccount.java b/Accounts/supplychain/workflows/src/main/java/net/corda/samples/supplychain/accountUtilities/CreateNewAccount.java
new file mode 100644
index 00000000..1e79bf3f
--- /dev/null
+++ b/Accounts/supplychain/workflows/src/main/java/net/corda/samples/supplychain/accountUtilities/CreateNewAccount.java
@@ -0,0 +1,38 @@
+package net.corda.samples.supplychain.accountUtilities;
+
+import com.r3.corda.lib.accounts.contracts.states.AccountInfo;
+import com.r3.corda.lib.accounts.workflows.*;
+import com.r3.corda.lib.accounts.workflows.services.KeyManagementBackedAccountService;
+import net.corda.core.contracts.StateAndRef;
+import net.corda.core.flows.*;
+import co.paralleluniverse.fibers.Suspendable;
+import com.r3.corda.lib.accounts.workflows.services.AccountService;
+import net.corda.core.flows.FlowLogic;;
+import net.corda.core.flows.StartableByRPC;
+
+import java.util.UUID;
+
+@StartableByRPC
+@StartableByService
+@InitiatingFlow
+public class CreateNewAccount extends FlowLogic{
+
+ private String acctName;
+
+ public CreateNewAccount(String acctName) {
+ this.acctName = acctName;
+ }
+
+
+ @Override
+ public String call() throws FlowException {
+ StateAndRef newAccount = null;
+ try {
+ newAccount = getServiceHub().cordaService(KeyManagementBackedAccountService.class).createAccount(acctName).get();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ AccountInfo acct = newAccount.getState().getData();
+ return "" + acct.getName() + " team's account was created. UUID is : " + acct.getIdentifier();
+ }
+}
diff --git a/Accounts/supplychain/workflows/src/main/java/net/corda/samples/supplychain/accountUtilities/NewKeyForAccount.java b/Accounts/supplychain/workflows/src/main/java/net/corda/samples/supplychain/accountUtilities/NewKeyForAccount.java
new file mode 100644
index 00000000..1d057192
--- /dev/null
+++ b/Accounts/supplychain/workflows/src/main/java/net/corda/samples/supplychain/accountUtilities/NewKeyForAccount.java
@@ -0,0 +1,26 @@
+package net.corda.samples.supplychain.accountUtilities;
+
+import co.paralleluniverse.fibers.Suspendable;
+import net.corda.core.flows.FlowException;
+import net.corda.core.flows.FlowLogic;
+import net.corda.core.flows.StartableByRPC;
+import net.corda.core.flows.StartableByService;
+import net.corda.core.identity.PartyAndCertificate;
+import java.util.*;
+
+@StartableByRPC
+@StartableByService
+public class NewKeyForAccount extends FlowLogic{
+
+ private final UUID accountID;
+
+ public NewKeyForAccount(UUID accountID) {
+ this.accountID = accountID;
+ }
+
+ @Override
+ @Suspendable
+ public PartyAndCertificate call() throws FlowException {
+ return getServiceHub().getKeyManagementService().freshKeyAndCert(getOurIdentityAndCert(), false, accountID);
+ }
+}
\ No newline at end of file
diff --git a/Accounts/supplychain/workflows/src/main/java/net/corda/samples/supplychain/accountUtilities/ShareAccountTo.java b/Accounts/supplychain/workflows/src/main/java/net/corda/samples/supplychain/accountUtilities/ShareAccountTo.java
new file mode 100644
index 00000000..415dbcf5
--- /dev/null
+++ b/Accounts/supplychain/workflows/src/main/java/net/corda/samples/supplychain/accountUtilities/ShareAccountTo.java
@@ -0,0 +1,39 @@
+package net.corda.samples.supplychain.accountUtilities;
+
+import co.paralleluniverse.fibers.Suspendable;
+import com.r3.corda.lib.accounts.contracts.states.AccountInfo;
+import com.r3.corda.lib.accounts.workflows.flows.AccountInfoByName;
+import com.r3.corda.lib.accounts.workflows.services.KeyManagementBackedAccountService;
+import net.corda.core.contracts.StateAndRef;
+import net.corda.core.flows.FlowException;
+import net.corda.core.flows.FlowLogic;
+import net.corda.core.flows.StartableByRPC;
+import net.corda.core.flows.StartableByService;
+import net.corda.core.identity.Party;
+import com.r3.corda.lib.accounts.workflows.flows.ShareAccountInfo;
+import java.util.*;
+
+@StartableByRPC
+@StartableByService
+public class ShareAccountTo extends FlowLogic{
+
+ private final Party shareTo;
+ private final String acctNameShared;
+
+ public ShareAccountTo(String acctNameShared, Party shareTo) {
+ this.acctNameShared = acctNameShared;
+ this.shareTo = shareTo;
+ }
+
+ @Override
+ @Suspendable
+ public String call() throws FlowException {
+ List> allmyAccounts = getServiceHub().cordaService(KeyManagementBackedAccountService.class).ourAccounts();
+ StateAndRef SharedAccount = allmyAccounts.stream()
+ .filter(it -> it.getState().getData().getName().equals(acctNameShared))
+ .findAny().get();
+
+ subFlow(new ShareAccountInfo(SharedAccount, Arrays.asList(shareTo)));
+ return "Shared " + acctNameShared + " with " + shareTo.getName().getOrganisation();
+ }
+}
\ No newline at end of file
diff --git a/Accounts/supplychain/workflows/src/main/java/com/supplychain/accountUtilities/ViewInboxByAccount.java b/Accounts/supplychain/workflows/src/main/java/net/corda/samples/supplychain/accountUtilities/ViewInboxByAccount.java
similarity index 88%
rename from Accounts/supplychain/workflows/src/main/java/com/supplychain/accountUtilities/ViewInboxByAccount.java
rename to Accounts/supplychain/workflows/src/main/java/net/corda/samples/supplychain/accountUtilities/ViewInboxByAccount.java
index d293539d..b97062bb 100644
--- a/Accounts/supplychain/workflows/src/main/java/com/supplychain/accountUtilities/ViewInboxByAccount.java
+++ b/Accounts/supplychain/workflows/src/main/java/net/corda/samples/supplychain/accountUtilities/ViewInboxByAccount.java
@@ -1,19 +1,14 @@
-package com.supplychain.accountUtilities;
+package net.corda.samples.supplychain.accountUtilities;
-import co.paralleluniverse.fibers.Suspendable;
import com.r3.corda.lib.accounts.contracts.states.AccountInfo;
-import com.r3.corda.lib.accounts.workflows.flows.AccountInfoByName;
import com.r3.corda.lib.accounts.workflows.services.AccountService;
import com.r3.corda.lib.accounts.workflows.services.KeyManagementBackedAccountService;
-import com.supplychain.states.*;
-import net.corda.core.contracts.StateAndRef;
import net.corda.core.flows.FlowException;
import net.corda.core.flows.FlowLogic;
import net.corda.core.flows.StartableByRPC;
import net.corda.core.flows.StartableByService;
-import net.corda.core.identity.Party;
-import com.r3.corda.lib.accounts.workflows.flows.ShareAccountInfo;
import net.corda.core.node.services.vault.QueryCriteria;
+import net.corda.samples.supplychain.states.*;
import java.util.*;
import java.util.stream.Collectors;
diff --git a/Accounts/supplychain/workflows/src/main/java/com/supplychain/flows/InternalMessage.java b/Accounts/supplychain/workflows/src/main/java/net/corda/samples/supplychain/flows/InternalMessage.java
similarity index 84%
rename from Accounts/supplychain/workflows/src/main/java/com/supplychain/flows/InternalMessage.java
rename to Accounts/supplychain/workflows/src/main/java/net/corda/samples/supplychain/flows/InternalMessage.java
index f4be9f4e..eadf9f59 100644
--- a/Accounts/supplychain/workflows/src/main/java/com/supplychain/flows/InternalMessage.java
+++ b/Accounts/supplychain/workflows/src/main/java/net/corda/samples/supplychain/flows/InternalMessage.java
@@ -1,4 +1,4 @@
-package com.supplychain.flows;
+package net.corda.samples.supplychain.flows;
import co.paralleluniverse.fibers.Suspendable;
import com.r3.corda.lib.accounts.contracts.states.AccountInfo;
@@ -6,11 +6,10 @@
import com.r3.corda.lib.accounts.workflows.flows.RequestKeyForAccount;
import com.r3.corda.lib.accounts.workflows.services.KeyManagementBackedAccountService;
import com.sun.istack.NotNull;
-import com.supplychain.accountUtilities.NewKeyForAccount;
-import com.supplychain.contracts.InternalMessageStateContract;
-import com.supplychain.contracts.InvoiceStateContract;
-import com.supplychain.states.InternalMessageState;
-import com.supplychain.states.InvoiceState;
+import net.corda.core.identity.CordaX500Name;
+import net.corda.samples.supplychain.accountUtilities.NewKeyForAccount;
+import net.corda.samples.supplychain.contracts.InternalMessageStateContract;
+import net.corda.samples.supplychain.states.InternalMessageState;
import net.corda.core.crypto.TransactionSignature;
import net.corda.core.flows.*;
import net.corda.core.identity.AnonymousParty;
@@ -22,8 +21,6 @@
import java.security.PublicKey;
import java.util.Arrays;
import java.util.List;
-import java.util.UUID;
-import java.util.stream.Collectors;
// ******************
@@ -85,13 +82,8 @@ public String call() throws FlowException {
InternalMessageState output = new InternalMessageState(message,new AnonymousParty(myKey),targetAcctAnonymousParty);
// Obtain a reference to a notary we wish to use.
- /** METHOD 1: Take first notary on network, WARNING: use for test, non-prod environments, and single-notary networks only!*
- * METHOD 2: Explicit selection of notary by CordaX500Name - argument can by coded in flow or parsed from config (Preferred)
- *
- * * - For production you always want to use Method 2 as it guarantees the expected notary is returned.
- */
- final Party notary = getServiceHub().getNetworkMapCache().getNotaryIdentities().get(0); // METHOD 1
- // final Party notary = getServiceHub().getNetworkMapCache().getNotary(CordaX500Name.parse("O=Notary,L=London,C=GB")); // METHOD 2
+ /** Explicit selection of notary by CordaX500Name - argument can by coded in flows or parsed from config (Preferred)*/
+ final Party notary = getServiceHub().getNetworkMapCache().getNotary(CordaX500Name.parse("O=Notary,L=London,C=GB"));
TransactionBuilder txbuilder = new TransactionBuilder(notary)
.addOutputState(output)
diff --git a/Accounts/supplychain/workflows/src/main/java/com/supplychain/flows/SendCargo.java b/Accounts/supplychain/workflows/src/main/java/net/corda/samples/supplychain/flows/SendCargo.java
similarity index 84%
rename from Accounts/supplychain/workflows/src/main/java/com/supplychain/flows/SendCargo.java
rename to Accounts/supplychain/workflows/src/main/java/net/corda/samples/supplychain/flows/SendCargo.java
index 25029adc..d51f2527 100644
--- a/Accounts/supplychain/workflows/src/main/java/com/supplychain/flows/SendCargo.java
+++ b/Accounts/supplychain/workflows/src/main/java/net/corda/samples/supplychain/flows/SendCargo.java
@@ -1,4 +1,4 @@
-package com.supplychain.flows;
+package net.corda.samples.supplychain.flows;
import co.paralleluniverse.fibers.Suspendable;
import com.r3.corda.lib.accounts.contracts.states.AccountInfo;
@@ -6,15 +6,17 @@
import com.r3.corda.lib.accounts.workflows.flows.RequestKeyForAccount;
import com.r3.corda.lib.accounts.workflows.services.KeyManagementBackedAccountService;
import com.sun.istack.NotNull;
-import com.supplychain.accountUtilities.NewKeyForAccount;
-import com.supplychain.contracts.CargoStateContract;
-import com.supplychain.states.CargoState;
+import net.corda.core.identity.CordaX500Name;
+import net.corda.samples.supplychain.accountUtilities.NewKeyForAccount;
+import net.corda.samples.supplychain.contracts.CargoStateContract;
+import net.corda.samples.supplychain.states.CargoState;
import net.corda.core.crypto.TransactionSignature;
import net.corda.core.flows.*;
import net.corda.core.identity.AnonymousParty;
import net.corda.core.identity.Party;
import net.corda.core.transactions.SignedTransaction;
import net.corda.core.transactions.TransactionBuilder;
+
import java.security.PublicKey;
import java.util.Arrays;
import java.util.List;
@@ -57,13 +59,8 @@ public String call() throws FlowException {
CargoState output = new CargoState(new AnonymousParty(myKey),targetAcctAnonymousParty,cargo,getOurIdentity());
// Obtain a reference to a notary we wish to use.
- /** METHOD 1: Take first notary on network, WARNING: use for test, non-prod environments, and single-notary networks only!*
- * METHOD 2: Explicit selection of notary by CordaX500Name - argument can by coded in flow or parsed from config (Preferred)
- *
- * * - For production you always want to use Method 2 as it guarantees the expected notary is returned.
- */
- final Party notary = getServiceHub().getNetworkMapCache().getNotaryIdentities().get(0); // METHOD 1
- // final Party notary = getServiceHub().getNetworkMapCache().getNotary(CordaX500Name.parse("O=Notary,L=London,C=GB")); // METHOD 2
+ /** Explicit selection of notary by CordaX500Name - argument can by coded in flows or parsed from config (Preferred)*/
+ final Party notary = getServiceHub().getNetworkMapCache().getNotary(CordaX500Name.parse("O=Notary,L=London,C=GB"));
TransactionBuilder txbuilder = new TransactionBuilder(notary)
.addOutputState(output)
diff --git a/Accounts/supplychain/workflows/src/main/java/com/supplychain/flows/SendInvoice.java b/Accounts/supplychain/workflows/src/main/java/net/corda/samples/supplychain/flows/SendInvoice.java
similarity index 84%
rename from Accounts/supplychain/workflows/src/main/java/com/supplychain/flows/SendInvoice.java
rename to Accounts/supplychain/workflows/src/main/java/net/corda/samples/supplychain/flows/SendInvoice.java
index 3ac0cb2a..5d17627c 100644
--- a/Accounts/supplychain/workflows/src/main/java/com/supplychain/flows/SendInvoice.java
+++ b/Accounts/supplychain/workflows/src/main/java/net/corda/samples/supplychain/flows/SendInvoice.java
@@ -1,4 +1,4 @@
-package com.supplychain.flows;
+package net.corda.samples.supplychain.flows;
import co.paralleluniverse.fibers.Suspendable;
import com.r3.corda.lib.accounts.contracts.states.AccountInfo;
@@ -6,15 +6,17 @@
import com.r3.corda.lib.accounts.workflows.flows.RequestKeyForAccount;
import com.r3.corda.lib.accounts.workflows.services.KeyManagementBackedAccountService;
import com.sun.istack.NotNull;
-import com.supplychain.accountUtilities.NewKeyForAccount;
-import com.supplychain.contracts.InvoiceStateContract;
-import com.supplychain.states.InvoiceState;
+import net.corda.core.identity.CordaX500Name;
+import net.corda.samples.supplychain.accountUtilities.NewKeyForAccount;
+import net.corda.samples.supplychain.contracts.InvoiceStateContract;
+import net.corda.samples.supplychain.states.InvoiceState;
import net.corda.core.crypto.TransactionSignature;
import net.corda.core.flows.*;
import net.corda.core.identity.AnonymousParty;
import net.corda.core.identity.Party;
import net.corda.core.transactions.SignedTransaction;
import net.corda.core.transactions.TransactionBuilder;
+
import java.security.PublicKey;
import java.util.Arrays;
import java.util.List;
@@ -57,13 +59,8 @@ public String call() throws FlowException {
InvoiceState output = new InvoiceState(amount,new AnonymousParty(myKey),targetAcctAnonymousParty, UUID.randomUUID());
// Obtain a reference to a notary we wish to use.
- /** METHOD 1: Take first notary on network, WARNING: use for test, non-prod environments, and single-notary networks only!*
- * METHOD 2: Explicit selection of notary by CordaX500Name - argument can by coded in flow or parsed from config (Preferred)
- *
- * * - For production you always want to use Method 2 as it guarantees the expected notary is returned.
- */
- final Party notary = getServiceHub().getNetworkMapCache().getNotaryIdentities().get(0); // METHOD 1
- // final Party notary = getServiceHub().getNetworkMapCache().getNotary(CordaX500Name.parse("O=Notary,L=London,C=GB")); // METHOD 2
+ /** Explicit selection of notary by CordaX500Name - argument can by coded in flows or parsed from config (Preferred)*/
+ final Party notary = getServiceHub().getNetworkMapCache().getNotary(CordaX500Name.parse("O=Notary,L=London,C=GB"));
TransactionBuilder txbuilder = new TransactionBuilder(notary)
.addOutputState(output)
diff --git a/Accounts/supplychain/workflows/src/main/java/com/supplychain/flows/SendPayment.java b/Accounts/supplychain/workflows/src/main/java/net/corda/samples/supplychain/flows/SendPayment.java
similarity index 83%
rename from Accounts/supplychain/workflows/src/main/java/com/supplychain/flows/SendPayment.java
rename to Accounts/supplychain/workflows/src/main/java/net/corda/samples/supplychain/flows/SendPayment.java
index 79e3f392..9a65d6df 100644
--- a/Accounts/supplychain/workflows/src/main/java/com/supplychain/flows/SendPayment.java
+++ b/Accounts/supplychain/workflows/src/main/java/net/corda/samples/supplychain/flows/SendPayment.java
@@ -1,4 +1,4 @@
-package com.supplychain.flows;
+package net.corda.samples.supplychain.flows;
import co.paralleluniverse.fibers.Suspendable;
import com.r3.corda.lib.accounts.contracts.states.AccountInfo;
@@ -6,19 +6,20 @@
import com.r3.corda.lib.accounts.workflows.flows.RequestKeyForAccount;
import com.r3.corda.lib.accounts.workflows.services.KeyManagementBackedAccountService;
import com.sun.istack.NotNull;
-import com.supplychain.accountUtilities.NewKeyForAccount;
-import com.supplychain.contracts.PaymentStateContract;
-import com.supplychain.states.PaymentState;
+import net.corda.core.identity.CordaX500Name;
+import net.corda.samples.supplychain.accountUtilities.NewKeyForAccount;
+import net.corda.samples.supplychain.contracts.PaymentStateContract;
+import net.corda.samples.supplychain.states.PaymentState;
import net.corda.core.crypto.TransactionSignature;
import net.corda.core.flows.*;
import net.corda.core.identity.AnonymousParty;
import net.corda.core.identity.Party;
import net.corda.core.transactions.SignedTransaction;
import net.corda.core.transactions.TransactionBuilder;
+
import java.security.PublicKey;
import java.util.Arrays;
import java.util.List;
-import java.util.UUID;
import java.util.stream.Collectors;
@@ -57,13 +58,8 @@ public String call() throws FlowException {
PaymentState output = new PaymentState(amount,new AnonymousParty(myKey),targetAcctAnonymousParty);
// Obtain a reference to a notary we wish to use.
- /** METHOD 1: Take first notary on network, WARNING: use for test, non-prod environments, and single-notary networks only!*
- * METHOD 2: Explicit selection of notary by CordaX500Name - argument can by coded in flow or parsed from config (Preferred)
- *
- * * - For production you always want to use Method 2 as it guarantees the expected notary is returned.
- */
- final Party notary = getServiceHub().getNetworkMapCache().getNotaryIdentities().get(0); // METHOD 1
- // final Party notary = getServiceHub().getNetworkMapCache().getNotary(CordaX500Name.parse("O=Notary,L=London,C=GB")); // METHOD 2
+ /** Explicit selection of notary by CordaX500Name - argument can by coded in flows or parsed from config (Preferred)*/
+ final Party notary = getServiceHub().getNetworkMapCache().getNotary(CordaX500Name.parse("O=Notary,L=London,C=GB"));
TransactionBuilder txbuilder = new TransactionBuilder(notary)
.addOutputState(output)
diff --git a/Accounts/supplychain/workflows/src/main/java/com/supplychain/flows/SendShippingRequest.java b/Accounts/supplychain/workflows/src/main/java/net/corda/samples/supplychain/flows/SendShippingRequest.java
similarity index 83%
rename from Accounts/supplychain/workflows/src/main/java/com/supplychain/flows/SendShippingRequest.java
rename to Accounts/supplychain/workflows/src/main/java/net/corda/samples/supplychain/flows/SendShippingRequest.java
index 9500bbc0..962770ee 100644
--- a/Accounts/supplychain/workflows/src/main/java/com/supplychain/flows/SendShippingRequest.java
+++ b/Accounts/supplychain/workflows/src/main/java/net/corda/samples/supplychain/flows/SendShippingRequest.java
@@ -1,17 +1,14 @@
-package com.supplychain.flows;
+package net.corda.samples.supplychain.flows;
import co.paralleluniverse.fibers.Suspendable;
import com.r3.corda.lib.accounts.contracts.states.AccountInfo;
import com.r3.corda.lib.accounts.workflows.services.AccountService;
-import com.r3.corda.lib.accounts.workflows.flows.RequestKeyForAccount;
import com.r3.corda.lib.accounts.workflows.services.KeyManagementBackedAccountService;
import com.sun.istack.NotNull;
-import com.supplychain.accountUtilities.NewKeyForAccount;
-import com.supplychain.contracts.InvoiceStateContract;
-import com.supplychain.contracts.ShippingRequestStateContract;
-import com.supplychain.states.InvoiceState;
-import com.supplychain.states.PaymentState;
-import com.supplychain.states.ShippingRequestState;
+import net.corda.core.identity.CordaX500Name;
+import net.corda.samples.supplychain.accountUtilities.NewKeyForAccount;
+import net.corda.samples.supplychain.contracts.ShippingRequestStateContract;
+import net.corda.samples.supplychain.states.ShippingRequestState;
import net.corda.core.crypto.TransactionSignature;
import net.corda.core.flows.*;
import net.corda.core.identity.AnonymousParty;
@@ -23,7 +20,6 @@
import java.security.PublicKey;
import java.util.Arrays;
import java.util.List;
-import java.util.UUID;
import java.util.stream.Collectors;
@@ -89,13 +85,8 @@ public String call() throws FlowException {
ShippingRequestState output = new ShippingRequestState(new AnonymousParty(myKey),whereTo,shipper,cargo);
// Obtain a reference to a notary we wish to use.
- /** METHOD 1: Take first notary on network, WARNING: use for test, non-prod environments, and single-notary networks only!*
- * METHOD 2: Explicit selection of notary by CordaX500Name - argument can by coded in flow or parsed from config (Preferred)
- *
- * * - For production you always want to use Method 2 as it guarantees the expected notary is returned.
- */
- final Party notary = getServiceHub().getNetworkMapCache().getNotaryIdentities().get(0); // METHOD 1
- // final Party notary = getServiceHub().getNetworkMapCache().getNotary(CordaX500Name.parse("O=Notary,L=London,C=GB")); // METHOD 2
+ /** Explicit selection of notary by CordaX500Name - argument can by coded in flows or parsed from config (Preferred)*/
+ final Party notary = getServiceHub().getNetworkMapCache().getNotary(CordaX500Name.parse("O=Notary,L=London,C=GB"));
TransactionBuilder txbuilder = new TransactionBuilder(notary)
.addOutputState(output)
diff --git a/Accounts/supplychain/workflows/src/test/java/com/supplychain/ContractTests.java b/Accounts/supplychain/workflows/src/test/java/com/supplychain/ContractTests.java
deleted file mode 100644
index e0a55a0d..00000000
--- a/Accounts/supplychain/workflows/src/test/java/com/supplychain/ContractTests.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package com.supplychain;
-
-import net.corda.testing.node.MockServices;
-import org.junit.Test;
-
-public class ContractTests {
- private final MockServices ledgerServices = new MockServices();
-
- @Test
- public void dummyTest() {
-
- }
-}
\ No newline at end of file
diff --git a/Accounts/supplychain/workflows/src/test/java/com/supplychain/FlowTests.java b/Accounts/supplychain/workflows/src/test/java/com/supplychain/FlowTests.java
deleted file mode 100644
index ea71fc74..00000000
--- a/Accounts/supplychain/workflows/src/test/java/com/supplychain/FlowTests.java
+++ /dev/null
@@ -1,37 +0,0 @@
-package com.supplychain;
-
-import com.google.common.collect.ImmutableList;
-import net.corda.testing.node.MockNetwork;
-import net.corda.testing.node.MockNetworkParameters;
-import net.corda.testing.node.StartedMockNode;
-import net.corda.testing.node.TestCordapp;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-public class FlowTests {
- private final MockNetwork network = new MockNetwork(new MockNetworkParameters(ImmutableList.of(
- TestCordapp.findCordapp("com.supplychain.contracts"),
- TestCordapp.findCordapp("com.supplychain.flows")
- )));
- private final StartedMockNode a = network.createNode();
- private final StartedMockNode b = network.createNode();
-
- public FlowTests() {
- }
-
- @Before
- public void setup() {
- network.runNetwork();
- }
-
- @After
- public void tearDown() {
- network.stopNodes();
- }
-
- @Test
- public void dummyTest() {
-
- }
-}
diff --git a/Accounts/supplychain/workflows/src/test/java/com/supplychain/NodeDriver.java b/Accounts/supplychain/workflows/src/test/java/com/supplychain/NodeDriver.java
deleted file mode 100644
index ef32c93e..00000000
--- a/Accounts/supplychain/workflows/src/test/java/com/supplychain/NodeDriver.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package com.supplychain;
-
-import com.google.common.collect.ImmutableList;
-import net.corda.core.identity.CordaX500Name;
-import net.corda.testing.driver.DriverParameters;
-import net.corda.testing.driver.NodeParameters;
-import net.corda.testing.node.User;
-import com.google.common.collect.ImmutableSet;
-
-import java.util.List;
-import static net.corda.testing.driver.Driver.driver;
-
-/**
- * Allows you to run your nodes through an IDE (as opposed to using deployNodes). Do not use in a production
- * environment.
- */
-public class NodeDriver {
- public static void main(String[] args) {
- final List rpcUsers =
- ImmutableList.of(new User("user1", "test", ImmutableSet.of("ALL")));
-
- driver(new DriverParameters().withStartNodesInProcess(true).withWaitForAllNodesToFinish(true), dsl -> {
- try {
- dsl.startNode(new NodeParameters()
- .withProvidedName(new CordaX500Name("PartyA", "London", "GB"))
- .withRpcUsers(rpcUsers)).get();
- dsl.startNode(new NodeParameters()
- .withProvidedName(new CordaX500Name("PartyB", "New York", "US"))
- .withRpcUsers(rpcUsers)).get();
- } catch (Throwable e) {
- System.err.println("Encountered exception in node startup: " + e.getMessage());
- e.printStackTrace();
- }
-
- return null;
- }
- );
- }
-}
diff --git a/Accounts/supplychain/workflows/src/test/java/net/corda/samples/supplychain/FlowTests.java b/Accounts/supplychain/workflows/src/test/java/net/corda/samples/supplychain/FlowTests.java
new file mode 100644
index 00000000..5332c1fb
--- /dev/null
+++ b/Accounts/supplychain/workflows/src/test/java/net/corda/samples/supplychain/FlowTests.java
@@ -0,0 +1,99 @@
+package net.corda.samples.supplychain;
+
+import com.google.common.collect.ImmutableList;
+import com.r3.corda.lib.accounts.contracts.states.AccountInfo;
+import com.r3.corda.lib.accounts.workflows.services.AccountService;
+import com.r3.corda.lib.accounts.workflows.services.KeyManagementBackedAccountService;
+import net.corda.core.contracts.StateAndRef;
+import net.corda.core.contracts.UniqueIdentifier;
+import net.corda.core.identity.CordaX500Name;
+import net.corda.core.node.NetworkParameters;
+import net.corda.core.node.services.Vault;
+import net.corda.core.node.services.vault.QueryCriteria;
+import net.corda.samples.supplychain.accountUtilities.CreateNewAccount;
+import net.corda.samples.supplychain.accountUtilities.ShareAccountTo;
+import net.corda.samples.supplychain.flows.SendInvoice;
+import net.corda.samples.supplychain.states.InvoiceState;
+import net.corda.testing.node.*;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.*;
+import java.time.Instant;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import java.util.stream.Collectors;
+
+public class FlowTests {
+ private MockNetwork network;
+ private StartedMockNode a;
+ private StartedMockNode b;
+
+
+ private NetworkParameters testNetworkParameters =
+ new NetworkParameters(4, Arrays.asList(), 10485760, (10485760 * 5), Instant.now(),1, new LinkedHashMap<>());
+
+ @Before
+ public void setup() {
+
+ network = new MockNetwork(new MockNetworkParameters().withCordappsForAllNodes(ImmutableList.of(
+ TestCordapp.findCordapp("net.corda.samples.supplychain.contracts"),
+ TestCordapp.findCordapp("net.corda.samples.supplychain.flows"),
+ TestCordapp.findCordapp("com.r3.corda.lib.accounts.contracts"),
+ TestCordapp.findCordapp("com.r3.corda.lib.accounts.workflows"))).withNetworkParameters(testNetworkParameters)
+ .withNotarySpecs(ImmutableList.of(new MockNetworkNotarySpec(CordaX500Name.parse("O=Notary,L=London,C=GB"))))
+ );
+ a = network.createPartyNode(null);
+ b = network.createPartyNode(null);
+ network.runNetwork();
+ }
+
+ @After
+ public void tearDown() {
+ network.stopNodes();
+ }
+
+ @Test
+ public void AccountCreation() throws ExecutionException, InterruptedException {
+ CreateNewAccount createAcct = new CreateNewAccount("TestAccountA");
+ Future future = a.startFlow(createAcct);
+ network.runNetwork();
+ AccountService accountService = a.getServices().cordaService(KeyManagementBackedAccountService.class);
+ List> myAccount = accountService.accountInfo("TestAccountA");
+ assert (myAccount.size() != 0);
+ }
+
+ @Test
+ public void InvoiceFlowTest() throws ExecutionException, InterruptedException {
+ CreateNewAccount createAcct = new CreateNewAccount("TestAccountA");
+ Future future = a.startFlow(createAcct);
+ network.runNetwork();
+ ShareAccountTo shareAToB = new ShareAccountTo("TestAccountA",b.getInfo().getLegalIdentities().get(0));
+ Future future2 = a.startFlow(shareAToB);
+ network.runNetwork();
+
+ CreateNewAccount createAcct2 = new CreateNewAccount("TestAccountB");
+ Future future3 = b.startFlow(createAcct2);
+ network.runNetwork();
+
+ ShareAccountTo shareBToA = new ShareAccountTo("TestAccountB",a.getInfo().getLegalIdentities().get(0));
+ Future future4 = b.startFlow(shareBToA);
+ network.runNetwork();
+
+ SendInvoice invoiceflow = new SendInvoice("TestAccountA","TestAccountB",20);
+ Future future5 = a.startFlow(invoiceflow);
+ network.runNetwork();
+
+ //retrieve
+ AccountService accountService = b.getServices().cordaService(KeyManagementBackedAccountService.class);
+ AccountInfo myAccount = accountService.accountInfo("TestAccountB").get(0).getState().getData();
+ QueryCriteria.VaultQueryCriteria criteria = new QueryCriteria.VaultQueryCriteria()
+ .withExternalIds(Arrays.asList(myAccount.getIdentifier().getId()));
+ InvoiceState storedState = b.getServices().getVaultService().queryBy(InvoiceState.class,criteria).getStates()
+ .get(0).getState().getData();
+ assert (storedState.getAmount() == 20);
+ }
+
+
+}
diff --git a/Accounts/tictacthor/README.md b/Accounts/tictacthor/README.md
index 3d3f0416..5c388345 100644
--- a/Accounts/tictacthor/README.md
+++ b/Accounts/tictacthor/README.md
@@ -1,31 +1,36 @@
-# Tic Tac Thor [
](https://ide.corda.net/?folder=/home/coder/samples-java/Accounts/tictacthor)
-This CorDapp recreates the game of Tic Tac Toe via Corda. It primarilly demonstrates how you can have [LinearState](https://docs.corda.net/docs/corda-os/api-states.html#linearstate) transactions between cross-node accounts.
+# Tic Tac Thor
+This CorDapp recreates the game of Tic Tac Toe via Corda. It primarily demonstrates how you can have [LinearState](https://docs.corda.net/docs/corda-os/api-states.html#linearstate) transactions between cross-node accounts.
+
+## Pre-Requisites
+
+For development environment setup, please refer to: [Setup Guide](https://docs.r3.com/en/platform/corda/4.9/community/getting-set-up.html).
+
## Running the sample
Deploy and run the nodes by:
```
-./gradlew deployNodes
+./gradlew clean build deployNodes
./build/nodes/runnodes
```
-Then you will need to also start the spring server for the Cordapp by running the following commands seperately:
+Then you will need to also start the spring server for the CorDapp by running the following commands separately:
`./gradlew bootRunDevRel`will have the DevRel server running on 8080 port
, and `./gradlew bootRunSOE`will start the Solution Engineering server on 8090 port
-## Operating the Cordapp
-Now go to postman and excute the following in order: (All of the API are POST request!)
+## Operating the CorDapp
+Now go to postman and execute the following in order: (All the APIs are POST requests!)
1. Create an account on DevRel node: `http://localhost:8080/createAccount/PeterLi`
2. Create an account on SoE node: `http://localhost:8090/createAccount/DavidWinner`
3. Peter now requests game with David: `http://localhost:8080/requestGameWith/PeterLi/SolutionEng/DavidWinner`
-4. David has to accept the challenege: `http://localhost:8090/acceptGameInvite/DavidWinner/DevRel/PeterLi`
+4. David has to accept the challenge: `http://localhost:8090/acceptGameInvite/DavidWinner/DevRel/PeterLi`
5. Game Starts, and Peter makes the first move: `http://localhost:8080/startGameAndFirstMove/PeterLi/DavidWinner/0`
6. David's turn: `http://localhost:8090/submitMove/DavidWinner/PeterLi/4`
API Syntax: `http://localhost:8080/submitMove/WHO-AM-I/MY-COUNTERPART/POSITION`
-From here, you can start play the game by changing the very last number from the `submitMove`API call. The game board is representated by an 1-D array: What we just ran can transfer into a tic-tac-toe game board like the one we see on the right.
+From here, you can start play the game by changing the very last number from the `submitMove`API call. The game board is represented by an 1-D array: What we just ran can transfer into a tic-tac-toe game board like the one we see on the right.
```
│0│1│2│ │O│ │ │
│3│4│5│ -> │ │X│ │
@@ -34,7 +39,7 @@ From here, you can start play the game by changing the very last number from the
The Game will automatically end when one player wins the game.
You can also run `run vaultQuery contractStateType: net.corda.samples.tictacthor.states.BoardState` at any given time to see the board games stored in vault.
-now if you want to fast forward the game, Play the following moves in order:
+now if you want to fast-forward the game, Play the following moves in order:
According to syntax: we should have `http://localhost:8080/submitMove/PeterLi/DavidWinner/3` for the first move below.
```
* Peter: 3 │O│ │ │
@@ -49,7 +54,7 @@ We can play a bit more about the accounts. Now let's create two accounts, a new
* Create an account on SoE node: `http://localhost:8090/createAccount/ThorG`
Now, try to have Anthony play a game with Thor while start a new game between Peter and David. It worked!
-One key feature about account is that, each account's data is segregated, meaning that it can be enforced that each account will not be able to see other account's data. In this sample cordapp, the game is queried by account name. Therefore, we see that each account only knows about the game that he participated. Account Peter doesn't know anything about the game between Thor and Anthony.
+One key feature about account is that, each account's data is segregated, meaning that it can be enforced that each account will not be able to see other account's data. In this sample CorDapp, the game is queried by account name. Therefore, we see that each account only knows about the game that he participated. Account Peter doesn't know anything about the game between Thor and Anthony.
## Credit
This project is inspired and evolved from a simple [tic-tac-toe](https://github.com/thorgilman/tictactoe) game on Corda by Thor Gilman.
diff --git a/Accounts/tictacthor/build.gradle b/Accounts/tictacthor/build.gradle
index 1d646909..b33c32b0 100644
--- a/Accounts/tictacthor/build.gradle
+++ b/Accounts/tictacthor/build.gradle
@@ -15,9 +15,11 @@ buildscript {
log4j_version = constants.getProperty("log4jVersion")
slf4j_version = constants.getProperty("slf4jVersion")
corda_platform_version = constants.getProperty("platformVersion").toInteger()
+
//springboot
spring_boot_version = '2.0.2.RELEASE'
spring_boot_gradle_plugin_version = '2.0.2.RELEASE'
+
//account
accounts_release_group = 'com.r3.corda.lib.accounts'
accounts_release_version = '1.0'
@@ -29,12 +31,8 @@ buildscript {
repositories {
mavenLocal()
mavenCentral()
- jcenter()
- maven { url 'http://ci-artifactory.corda.r3cev.com/artifactory/corda-lib-dev' }
- maven { url 'http://ci-artifactory.corda.r3cev.com/artifactory/corda-lib' }
- maven { url 'https://ci-artifactory.corda.r3cev.com/artifactory/corda' }
- // Corda dependencies for the patched Quasar version
- maven { url "https://software.r3.com/artifactory/corda-dependencies" } // access to the patched Quasar version
+
+ maven { url 'https://download.corda.net/maven/corda-releases' }
}
dependencies {
@@ -52,14 +50,14 @@ allprojects {
repositories {
mavenLocal()
- jcenter()
+
mavenCentral()
- maven { url 'https://ci-artifactory.corda.r3cev.com/artifactory/corda' }
- // Can be removed post-release - used to get nightly snapshot build.
- maven { url 'https://ci-artifactory.corda.r3cev.com/artifactory/corda-lib' }
- maven { url 'https://ci-artifactory.corda.r3cev.com/artifactory/corda-lib-dev' }
+ maven { url 'https://download.corda.net/maven/corda-dependencies' }
maven { url 'https://jitpack.io' }
- maven { url "https://repo.gradle.org/gradle/libs-releases-local" }
+ //SDK lib
+ maven { url 'https://download.corda.net/maven/corda-lib' }
+ //Gradle Plugins
+ maven { url 'https://repo.gradle.org/gradle/libs-releases' }
}
tasks.withType(JavaCompile) {
@@ -102,6 +100,7 @@ dependencies {
cordaCompile "org.apache.logging.log4j:log4j-slf4j-impl:${log4j_version}"
cordaCompile "org.apache.logging.log4j:log4j-web:${log4j_version}"
cordaCompile "org.slf4j:jul-to-slf4j:$slf4j_version"
+ cordaDriver "net.corda:corda-shell:4.10"
//Account lib
cordapp "$confidential_id_release_group:ci-workflows:$confidential_id_release_version"
@@ -109,30 +108,6 @@ dependencies {
cordapp "$accounts_release_group:accounts-workflows:$accounts_release_version"
}
-cordapp {
- info {
- name "CorDapp tictacthor"
- vendor "Corda Open Source"
- targetPlatformVersion corda_platform_version
- minimumPlatformVersion corda_platform_version
- }
-}
-
-task ganache {
- subprojects {
- if (it.project.name != "clients") {
- dependsOn jar
- doLast {
- copy {
- from "${buildDir}/libs"
- into "${rootDir}/build/libs"
- }
- }
- }
- }
-}
-
-
task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar']) {
nodeDefaults {
projectCordapp {
@@ -143,7 +118,7 @@ task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar']) {
cordapp("$confidential_id_release_group:ci-workflows:$confidential_id_release_version")
cordapp("$accounts_release_group:accounts-contracts:$accounts_release_version")
cordapp("$accounts_release_group:accounts-workflows:$accounts_release_version")
- runSchemaMigration = true
+ runSchemaMigration = true
}
node {
name "O=Notary,L=London,C=GB"
@@ -173,15 +148,6 @@ task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar']) {
}
rpcUsers = [[ user: "user1", "password": "test", "permissions": ["ALL"]]]
}
-// node {
-// name "O=Observer,L=Chicago,C=US,CN=John"
-// p2pPort 10011
-// rpcSettings {
-// address("localhost:10010")
-// adminAddress("localhost:10050")
-// }
-// rpcUsers = [[ user: "user1", "password": "test", "permissions": ["ALL"]]]
-// }
}
task installQuasar(type: Copy) {
diff --git a/Accounts/tictacthor/clients/build.gradle b/Accounts/tictacthor/clients/build.gradle
index b17168b1..bbba1aea 100644
--- a/Accounts/tictacthor/clients/build.gradle
+++ b/Accounts/tictacthor/clients/build.gradle
@@ -8,6 +8,12 @@ sourceSets {
}
}
+configurations {
+ all {
+ exclude group: 'ch.qos.logback', module: 'logback-classic'
+ }
+}
+
dependencies {
// Corda dependencies.
compile "$corda_release_group:corda-rpc:$corda_release_version"
@@ -27,17 +33,17 @@ dependencies {
}
springBoot {
- mainClassName = "com.tictacthor.webserver.Server"
+ mainClassName = "net.corda.samples.tictacthor.webserver"
}
task bootRunDevRel(type: JavaExec, dependsOn: jar) {
classpath = sourceSets.main.runtimeClasspath
- main = 'com.tictacthor.webserver.Starter'
+ main = 'net.corda.samples.tictacthor.webserver.Starter'
args '--server.port=8080', '--config.rpc.host=localhost', '--config.rpc.port=10006', '--config.rpc.username=user1', '--config.rpc.password=test'
}
task bootRunSOE(type: JavaExec, dependsOn: jar) {
classpath = sourceSets.main.runtimeClasspath
- main = 'com.tictacthor.webserver.Starter'
+ main = 'net.corda.samples.tictacthor.webserver.Starter'
args '--server.port=8090', '--config.rpc.host=localhost', '--config.rpc.port=10009', '--config.rpc.username=user1', '--config.rpc.password=test'
}
\ No newline at end of file
diff --git a/Accounts/tictacthor/clients/src/main/java/com/tictacthor/Client.java b/Accounts/tictacthor/clients/src/main/java/com/tictacthor/Client.java
deleted file mode 100644
index 892d7a17..00000000
--- a/Accounts/tictacthor/clients/src/main/java/com/tictacthor/Client.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package com.tictacthor;
-
-import net.corda.client.rpc.CordaRPCClient;
-import net.corda.core.messaging.CordaRPCOps;
-import net.corda.core.node.NodeInfo;
-import net.corda.core.utilities.NetworkHostAndPort;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.List;
-
-import static net.corda.core.utilities.NetworkHostAndPort.parse;
-
-/**
- * Connects to a Corda node via RPC and performs RPC operations on the node.
- *
- * The RPC connection is configured using command line arguments.
- */
-public class Client {
- private static final Logger logger = LoggerFactory.getLogger(Client.class);
-
- public static void main(String[] args) {
- // Create an RPC connection to the node.
- if (args.length != 3) throw new IllegalArgumentException("Usage: Client ");
- final NetworkHostAndPort nodeAddress = parse(args[0]);
- final String rpcUsername = args[1];
- final String rpcPassword = args[2];
- final CordaRPCClient client = new CordaRPCClient(nodeAddress);
- final CordaRPCOps proxy = client.start(rpcUsername, rpcPassword).getProxy();
-
- // Interact with the node.
- // For example, here we print the nodes on the network.
- final List nodes = proxy.networkMapSnapshot();
- logger.info("{}", nodes);
- }
-}
\ No newline at end of file
diff --git a/Accounts/tictacthor/clients/src/main/java/com/tictacthor/webserver/Controller.java b/Accounts/tictacthor/clients/src/main/java/com/tictacthor/webserver/Controller.java
deleted file mode 100644
index 77ab2a0a..00000000
--- a/Accounts/tictacthor/clients/src/main/java/com/tictacthor/webserver/Controller.java
+++ /dev/null
@@ -1,218 +0,0 @@
-package com.tictacthor.webserver;
-
-
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.tictacthor.accountUtilities.CreateNewAccount;
-import com.tictacthor.accountUtilities.ShareAccountTo;
-import com.tictacthor.accountUtilities.myGame;
-import com.tictacthor.flows.EndGameFlow;
-import com.tictacthor.flows.StartGameFlow;
-import com.tictacthor.flows.SubmitTurnFlow;
-import com.tictacthor.states.BoardState;
-import net.corda.client.jackson.JacksonSupport;
-import net.corda.core.contracts.UniqueIdentifier;
-import net.corda.core.identity.CordaX500Name;
-import net.corda.core.identity.Party;
-import net.corda.core.messaging.CordaRPCOps;
-import net.corda.core.node.NodeInfo;
-import java.util.*;
-import org.bouncycastle.asn1.x500.X500Name;
-import org.bouncycastle.asn1.x500.style.BCStyle;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.http.HttpStatus;
-import org.springframework.http.ResponseEntity;
-import org.springframework.web.bind.annotation.*;
-
-import java.util.stream.Collectors;
-import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
-
-/**
- * Define your API endpoints here.
- */
-@RestController
-@RequestMapping("/") // The paths for HTTP requests are relative to this base path.
-public class Controller {
- private static final Logger logger = LoggerFactory.getLogger(RestController.class);
- private final CordaRPCOps proxy;
- private final CordaX500Name me;
-
- public Controller(NodeRPCConnection rpc) {
- this.proxy = rpc.proxy;
- this.me = proxy.nodeInfo().getLegalIdentities().get(0).getName();
-
- }
-
- /** Helpers for filtering the network map cache. */
- public String toDisplayString(X500Name name){
- return BCStyle.INSTANCE.toString(name);
- }
-
- private boolean isNotary(NodeInfo nodeInfo) {
- return !proxy.notaryIdentities()
- .stream().filter(el -> nodeInfo.isLegalIdentity(el))
- .collect(Collectors.toList()).isEmpty();
- }
-
- private boolean isMe(NodeInfo nodeInfo){
- return nodeInfo.getLegalIdentities().get(0).getName().equals(me);
- }
-
- private boolean isNetworkMap(NodeInfo nodeInfo){
- return nodeInfo.getLegalIdentities().get(0).getName().getOrganisation().equals("Network Map Service");
- }
-
- @Configuration
- class Plugin {
- @Bean
- public ObjectMapper registerModule() {
- return JacksonSupport.createNonRpcMapper();
- }
- }
-
- @GetMapping(value = "/me",produces = APPLICATION_JSON_VALUE)
- private HashMap whoami(){
- HashMap myMap = new HashMap<>();
- myMap.put("me", me.toString());
- return myMap;
- }
-
- @PostMapping(value = "createAccount/{acctName}")
- private ResponseEntity createAccount(@PathVariable String acctName){
- try{
- String result = proxy.startTrackedFlowDynamic(CreateNewAccount.class,acctName).getReturnValue().get();
- return ResponseEntity.status(HttpStatus.CREATED).body("Account "+acctName+" Created");
-
- }catch (Exception e) {
- return ResponseEntity
- .status(HttpStatus.BAD_REQUEST)
- .body(e.getMessage());
- }
- }
-
- @PostMapping(value = "requestGameWith/{whoAmI}/{team}/{competeWith}")
- private ResponseEntity requestGameWith(@PathVariable String whoAmI,@PathVariable String team, @PathVariable String competeWith){
- Set matchingPasties = proxy.partiesFromName(team,false);
- try{
-
- Iterator iter = matchingPasties.iterator();
- String result = proxy.startTrackedFlowDynamic(ShareAccountTo.class,whoAmI,iter.next()).getReturnValue().get();
- return ResponseEntity.status(HttpStatus.CREATED).body("Game Request has Sent. When "+competeWith+" accepts your challenge, the game will start!");
-
- }catch (Exception e) {
- return ResponseEntity
- .status(HttpStatus.BAD_REQUEST)
- .body(e.getMessage());
- }
- }
-
- @PostMapping(value = "acceptGameInvite/{whoAmI}/{team}/{competeWith}")
- private ResponseEntity acceptGameInvite(@PathVariable String whoAmI,@PathVariable String team, @PathVariable String competeWith){
- Set matchingPasties = proxy.partiesFromName(team,false);
- try{
-
- Iterator iter = matchingPasties.iterator();
- String result = proxy.startTrackedFlowDynamic(ShareAccountTo.class,whoAmI,iter.next()).getReturnValue().get();
- return ResponseEntity.status(HttpStatus.CREATED).body("I, "+whoAmI+" accepts "+competeWith+"'s challenge. Let's play!");
-
- }catch (Exception e) {
- return ResponseEntity
- .status(HttpStatus.BAD_REQUEST)
- .body(e.getMessage());
- }
- }
-
- @PostMapping(value = "startGameAndFirstMove/{whoAmI}/{competeWith}/{position}")
- private ResponseEntity startGameAndFirstMove(@PathVariable String whoAmI,
- @PathVariable String competeWith,
- @PathVariable String position){
- int x = -1;
- int y = -1;
- int pos = Integer.parseInt(position);
- if(pos == 0) {
- x=0;y=0;
- }else if(pos == 1){
- x=0;y=1;
- }else if(pos == 2){
- x=0;y=2;
- }else if(pos == 3){
- x=1;y=0;
- }else if(pos == 4){
- x=1;y=1;
- }else if(pos == 5){
- x=1;y=2;
- }else if(pos == 6){
- x=2;y=0;
- }else if(pos == 7){
- x=2;y=1;
- }else if(pos == 8){
- x=2;y=2;
- }
- try{
- UniqueIdentifier gameId = proxy.startTrackedFlowDynamic(StartGameFlow.class,whoAmI,competeWith).getReturnValue().get();
- String submitTurn = proxy.startTrackedFlowDynamic(SubmitTurnFlow.class, gameId, whoAmI,competeWith,x,y).getReturnValue().get();
- return ResponseEntity.status(HttpStatus.CREATED).body("Game Id Created: "+gameId+", "+whoAmI+" made the first move on position ["+x+","+y+"].");
-
- }catch (Exception e) {
- return ResponseEntity
- .status(HttpStatus.BAD_REQUEST)
- .body(e.getMessage());
- }
- }
-
- @PostMapping(value = "submitMove/{whoAmI}/{competeWith}/{position}")
- private ResponseEntity submitMove(@PathVariable String whoAmI,
- @PathVariable String competeWith,
- @PathVariable String position) {
- int x = -1;
- int y = -1;
- int pos = Integer.parseInt(position);
- if(pos == 0) {
- x=0;y=0;
- }else if(pos == 1){
- x=0;y=1;
- }else if(pos == 2){
- x=0;y=2;
- }else if(pos == 3){
- x=1;y=0;
- }else if(pos == 4){
- x=1;y=1;
- }else if(pos == 5){
- x=1;y=2;
- }else if(pos == 6){
- x=2;y=0;
- }else if(pos == 7){
- x=2;y=1;
- }else if(pos == 8){
- x=2;y=2;
- }
- try{
- UniqueIdentifier gameId = proxy.startTrackedFlowDynamic(myGame.class,whoAmI).getReturnValue().get().getLinearId();
- String submitTurn = proxy.startTrackedFlowDynamic(SubmitTurnFlow.class, gameId, whoAmI,competeWith,x,y).getReturnValue().get();
-
- if(isGameOver(whoAmI)){
- proxy.startTrackedFlowDynamic(EndGameFlow.class, gameId, whoAmI,competeWith).getReturnValue().get();
- return ResponseEntity.status(HttpStatus.CREATED).body(""+whoAmI+" made the move on position ["+x+","+y+"], and Game Over");
- }else{
- return ResponseEntity.status(HttpStatus.CREATED).body(""+whoAmI+"+ made the move on position ["+x+","+y+"]");
- }
- }catch (Exception e) {
- return ResponseEntity
- .status(HttpStatus.BAD_REQUEST)
- .body(e.getMessage());
- }
- }
-
- private Boolean isGameOver(String whoAmI){
- //If the game is over, the Status should be a null variable
- //So if the status returned is GAME_IN_PROGRESS, it means the game is not over.
- try{
- BoardState.Status gameStatus = proxy.startTrackedFlowDynamic(myGame.class,whoAmI).getReturnValue().get().getStatus();
- return gameStatus != BoardState.Status.GAME_IN_PROGRESS;
- }catch (Exception e) {
- throw new IllegalArgumentException("No board");
- }
- }
-}
\ No newline at end of file
diff --git a/Accounts/tictacthor/clients/src/main/java/com/tictacthor/webserver/NodeRPCConnection.java b/Accounts/tictacthor/clients/src/main/java/com/tictacthor/webserver/NodeRPCConnection.java
deleted file mode 100644
index bea1e18a..00000000
--- a/Accounts/tictacthor/clients/src/main/java/com/tictacthor/webserver/NodeRPCConnection.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package com.tictacthor.webserver;
-
-import net.corda.client.rpc.CordaRPCClient;
-import net.corda.client.rpc.CordaRPCConnection;
-import net.corda.core.messaging.CordaRPCOps;
-import net.corda.core.utilities.NetworkHostAndPort;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.stereotype.Component;
-
-import javax.annotation.PostConstruct;
-import javax.annotation.PreDestroy;
-
-/**
- * Wraps an RPC connection to a Corda node.
- *
- * The RPC connection is configured using command line arguments.
- */
-@Component
-public class NodeRPCConnection implements AutoCloseable {
- // The host of the node we are connecting to.
- @Value("${config.rpc.host}")
- private String host;
- // The RPC port of the node we are connecting to.
- @Value("${config.rpc.username}")
- private String username;
- // The username for logging into the RPC client.
- @Value("${config.rpc.password}")
- private String password;
- // The password for logging into the RPC client.
- @Value("${config.rpc.port}")
- private int rpcPort;
-
- private CordaRPCConnection rpcConnection;
- CordaRPCOps proxy;
-
- @PostConstruct
- public void initialiseNodeRPCConnection() {
- NetworkHostAndPort rpcAddress = new NetworkHostAndPort(host, rpcPort);
- CordaRPCClient rpcClient = new CordaRPCClient(rpcAddress);
- rpcConnection = rpcClient.start(username, password);
- proxy = rpcConnection.getProxy();
- }
-
- @PreDestroy
- public void close() {
- rpcConnection.notifyServerAndClose();
- }
-}
\ No newline at end of file
diff --git a/Accounts/tictacthor/clients/src/main/java/com/tictacthor/webserver/Starter.java b/Accounts/tictacthor/clients/src/main/java/com/tictacthor/webserver/Starter.java
deleted file mode 100644
index 826b5d06..00000000
--- a/Accounts/tictacthor/clients/src/main/java/com/tictacthor/webserver/Starter.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package com.tictacthor.webserver;
-
-import org.springframework.boot.Banner;
-import org.springframework.boot.SpringApplication;
-import org.springframework.boot.autoconfigure.SpringBootApplication;
-
-import static org.springframework.boot.WebApplicationType.SERVLET;
-
-/**
- * Our Spring Boot application.
- */
-@SpringBootApplication
-public class Starter {
- /**
- * Starts our Spring Boot application.
- */
- public static void main(String[] args) {
- SpringApplication app = new SpringApplication(Starter.class);
- app.setBannerMode(Banner.Mode.OFF);
- app.setWebApplicationType(SERVLET);
- app.run(args);
- }
-}
\ No newline at end of file
diff --git a/Accounts/tictacthor/clients/src/main/java/net/corda/samples/tictacthor/Client.java b/Accounts/tictacthor/clients/src/main/java/net/corda/samples/tictacthor/Client.java
new file mode 100644
index 00000000..5a74c8cd
--- /dev/null
+++ b/Accounts/tictacthor/clients/src/main/java/net/corda/samples/tictacthor/Client.java
@@ -0,0 +1,36 @@
+package net.corda.samples.tictacthor;
+
+import net.corda.client.rpc.CordaRPCClient;
+import net.corda.core.messaging.CordaRPCOps;
+import net.corda.core.node.NodeInfo;
+import net.corda.core.utilities.NetworkHostAndPort;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.List;
+
+import static net.corda.core.utilities.NetworkHostAndPort.parse;
+
+/**
+ * Connects to a Corda node via RPC and performs RPC operations on the node.
+ *
+ * The RPC connection is configured using command line arguments.
+ */
+public class Client {
+ private static final Logger logger = LoggerFactory.getLogger(Client.class);
+
+ public static void main(String[] args) {
+ // Create an RPC connection to the node.
+ if (args.length != 3) throw new IllegalArgumentException("Usage: Client ");
+ final NetworkHostAndPort nodeAddress = parse(args[0]);
+ final String rpcUsername = args[1];
+ final String rpcPassword = args[2];
+ final CordaRPCClient client = new CordaRPCClient(nodeAddress);
+ final CordaRPCOps proxy = client.start(rpcUsername, rpcPassword).getProxy();
+
+ // Interact with the node.
+ // For example, here we print the nodes on the network.
+ final List nodes = proxy.networkMapSnapshot();
+ logger.info("{}", nodes);
+ }
+}
\ No newline at end of file
diff --git a/Accounts/tictacthor/clients/src/main/java/net/corda/samples/tictacthor/webserver/Controller.java b/Accounts/tictacthor/clients/src/main/java/net/corda/samples/tictacthor/webserver/Controller.java
new file mode 100644
index 00000000..eaa2c30c
--- /dev/null
+++ b/Accounts/tictacthor/clients/src/main/java/net/corda/samples/tictacthor/webserver/Controller.java
@@ -0,0 +1,218 @@
+package net.corda.samples.tictacthor.webserver;
+
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import net.corda.samples.tictacthor.accountUtilities.CreateNewAccount;
+import net.corda.samples.tictacthor.accountUtilities.ShareAccountTo;
+import net.corda.samples.tictacthor.accountUtilities.myGame;
+import net.corda.samples.tictacthor.flows.EndGameFlow;
+import net.corda.samples.tictacthor.flows.StartGameFlow;
+import net.corda.samples.tictacthor.flows.SubmitTurnFlow;
+import net.corda.samples.tictacthor.states.BoardState;
+import net.corda.client.jackson.JacksonSupport;
+import net.corda.core.contracts.UniqueIdentifier;
+import net.corda.core.identity.CordaX500Name;
+import net.corda.core.identity.Party;
+import net.corda.core.messaging.CordaRPCOps;
+import net.corda.core.node.NodeInfo;
+import java.util.*;
+import org.bouncycastle.asn1.x500.X500Name;
+import org.bouncycastle.asn1.x500.style.BCStyle;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.stream.Collectors;
+import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
+
+/**
+ * Define your API endpoints here.
+ */
+@RestController
+@RequestMapping("/") // The paths for HTTP requests are relative to this base path.
+public class Controller {
+ private static final Logger logger = LoggerFactory.getLogger(RestController.class);
+ private final CordaRPCOps proxy;
+ private final CordaX500Name me;
+
+ public Controller(NodeRPCConnection rpc) {
+ this.proxy = rpc.proxy;
+ this.me = proxy.nodeInfo().getLegalIdentities().get(0).getName();
+
+ }
+
+ /** Helpers for filtering the network map cache. */
+ public String toDisplayString(X500Name name){
+ return BCStyle.INSTANCE.toString(name);
+ }
+
+ private boolean isNotary(NodeInfo nodeInfo) {
+ return !proxy.notaryIdentities()
+ .stream().filter(el -> nodeInfo.isLegalIdentity(el))
+ .collect(Collectors.toList()).isEmpty();
+ }
+
+ private boolean isMe(NodeInfo nodeInfo){
+ return nodeInfo.getLegalIdentities().get(0).getName().equals(me);
+ }
+
+ private boolean isNetworkMap(NodeInfo nodeInfo){
+ return nodeInfo.getLegalIdentities().get(0).getName().getOrganisation().equals("Network Map Service");
+ }
+
+ @Configuration
+ class Plugin {
+ @Bean
+ public ObjectMapper registerModule() {
+ return JacksonSupport.createNonRpcMapper();
+ }
+ }
+
+ @GetMapping(value = "/me",produces = APPLICATION_JSON_VALUE)
+ private HashMap whoami(){
+ HashMap myMap = new HashMap<>();
+ myMap.put("me", me.toString());
+ return myMap;
+ }
+
+ @PostMapping(value = "createAccount/{acctName}")
+ private ResponseEntity createAccount(@PathVariable String acctName){
+ try{
+ String result = proxy.startTrackedFlowDynamic(CreateNewAccount.class,acctName).getReturnValue().get();
+ return ResponseEntity.status(HttpStatus.CREATED).body("Account "+acctName+" Created");
+
+ }catch (Exception e) {
+ return ResponseEntity
+ .status(HttpStatus.BAD_REQUEST)
+ .body(e.getMessage());
+ }
+ }
+
+ @PostMapping(value = "requestGameWith/{whoAmI}/{team}/{competeWith}")
+ private ResponseEntity requestGameWith(@PathVariable String whoAmI,@PathVariable String team, @PathVariable String competeWith){
+ Set matchingPasties = proxy.partiesFromName(team,false);
+ try{
+
+ Iterator iter = matchingPasties.iterator();
+ String result = proxy.startTrackedFlowDynamic(ShareAccountTo.class,whoAmI,iter.next()).getReturnValue().get();
+ return ResponseEntity.status(HttpStatus.CREATED).body("Game Request has Sent. When "+competeWith+" accepts your challenge, the game will start!");
+
+ }catch (Exception e) {
+ return ResponseEntity
+ .status(HttpStatus.BAD_REQUEST)
+ .body(e.getMessage());
+ }
+ }
+
+ @PostMapping(value = "acceptGameInvite/{whoAmI}/{team}/{competeWith}")
+ private ResponseEntity acceptGameInvite(@PathVariable String whoAmI,@PathVariable String team, @PathVariable String competeWith){
+ Set matchingPasties = proxy.partiesFromName(team,false);
+ try{
+
+ Iterator iter = matchingPasties.iterator();
+ String result = proxy.startTrackedFlowDynamic(ShareAccountTo.class,whoAmI,iter.next()).getReturnValue().get();
+ return ResponseEntity.status(HttpStatus.CREATED).body("I, "+whoAmI+" accepts "+competeWith+"'s challenge. Let's play!");
+
+ }catch (Exception e) {
+ return ResponseEntity
+ .status(HttpStatus.BAD_REQUEST)
+ .body(e.getMessage());
+ }
+ }
+
+ @PostMapping(value = "startGameAndFirstMove/{whoAmI}/{competeWith}/{position}")
+ private ResponseEntity startGameAndFirstMove(@PathVariable String whoAmI,
+ @PathVariable String competeWith,
+ @PathVariable String position){
+ int x = -1;
+ int y = -1;
+ int pos = Integer.parseInt(position);
+ if(pos == 0) {
+ x=0;y=0;
+ }else if(pos == 1){
+ x=0;y=1;
+ }else if(pos == 2){
+ x=0;y=2;
+ }else if(pos == 3){
+ x=1;y=0;
+ }else if(pos == 4){
+ x=1;y=1;
+ }else if(pos == 5){
+ x=1;y=2;
+ }else if(pos == 6){
+ x=2;y=0;
+ }else if(pos == 7){
+ x=2;y=1;
+ }else if(pos == 8){
+ x=2;y=2;
+ }
+ try{
+ UniqueIdentifier gameId = proxy.startTrackedFlowDynamic(StartGameFlow.class,whoAmI,competeWith).getReturnValue().get();
+ String submitTurn = proxy.startTrackedFlowDynamic(SubmitTurnFlow.class, gameId, whoAmI,competeWith,x,y).getReturnValue().get();
+ return ResponseEntity.status(HttpStatus.CREATED).body("Game Id Created: "+gameId+", "+whoAmI+" made the first move on position ["+x+","+y+"].");
+
+ }catch (Exception e) {
+ return ResponseEntity
+ .status(HttpStatus.BAD_REQUEST)
+ .body(e.getMessage());
+ }
+ }
+
+ @PostMapping(value = "submitMove/{whoAmI}/{competeWith}/{position}")
+ private ResponseEntity submitMove(@PathVariable String whoAmI,
+ @PathVariable String competeWith,
+ @PathVariable String position) {
+ int x = -1;
+ int y = -1;
+ int pos = Integer.parseInt(position);
+ if(pos == 0) {
+ x=0;y=0;
+ }else if(pos == 1){
+ x=0;y=1;
+ }else if(pos == 2){
+ x=0;y=2;
+ }else if(pos == 3){
+ x=1;y=0;
+ }else if(pos == 4){
+ x=1;y=1;
+ }else if(pos == 5){
+ x=1;y=2;
+ }else if(pos == 6){
+ x=2;y=0;
+ }else if(pos == 7){
+ x=2;y=1;
+ }else if(pos == 8){
+ x=2;y=2;
+ }
+ try{
+ UniqueIdentifier gameId = proxy.startTrackedFlowDynamic(myGame.class,whoAmI).getReturnValue().get().getLinearId();
+ String submitTurn = proxy.startTrackedFlowDynamic(SubmitTurnFlow.class, gameId, whoAmI,competeWith,x,y).getReturnValue().get();
+
+ if(isGameOver(whoAmI)){
+ proxy.startTrackedFlowDynamic(EndGameFlow.class, gameId, whoAmI,competeWith).getReturnValue().get();
+ return ResponseEntity.status(HttpStatus.CREATED).body(""+whoAmI+" made the move on position ["+x+","+y+"], and Game Over");
+ }else{
+ return ResponseEntity.status(HttpStatus.CREATED).body(""+whoAmI+"+ made the move on position ["+x+","+y+"]");
+ }
+ }catch (Exception e) {
+ return ResponseEntity
+ .status(HttpStatus.BAD_REQUEST)
+ .body(e.getMessage());
+ }
+ }
+
+ private Boolean isGameOver(String whoAmI){
+ //If the game is over, the Status should be a null variable
+ //So if the status returned is GAME_IN_PROGRESS, it means the game is not over.
+ try{
+ BoardState.Status gameStatus = proxy.startTrackedFlowDynamic(myGame.class,whoAmI).getReturnValue().get().getStatus();
+ return gameStatus != BoardState.Status.GAME_IN_PROGRESS;
+ }catch (Exception e) {
+ throw new IllegalArgumentException("No board");
+ }
+ }
+}
\ No newline at end of file
diff --git a/Accounts/tictacthor/clients/src/main/java/net/corda/samples/tictacthor/webserver/NodeRPCConnection.java b/Accounts/tictacthor/clients/src/main/java/net/corda/samples/tictacthor/webserver/NodeRPCConnection.java
new file mode 100644
index 00000000..b1c1362e
--- /dev/null
+++ b/Accounts/tictacthor/clients/src/main/java/net/corda/samples/tictacthor/webserver/NodeRPCConnection.java
@@ -0,0 +1,48 @@
+package net.corda.samples.tictacthor.webserver;
+
+import net.corda.client.rpc.CordaRPCClient;
+import net.corda.client.rpc.CordaRPCConnection;
+import net.corda.core.messaging.CordaRPCOps;
+import net.corda.core.utilities.NetworkHostAndPort;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+
+/**
+ * Wraps an RPC connection to a Corda node.
+ *
+ * The RPC connection is configured using command line arguments.
+ */
+@Component
+public class NodeRPCConnection implements AutoCloseable {
+ // The host of the node we are connecting to.
+ @Value("${config.rpc.host}")
+ private String host;
+ // The RPC port of the node we are connecting to.
+ @Value("${config.rpc.username}")
+ private String username;
+ // The username for logging into the RPC client.
+ @Value("${config.rpc.password}")
+ private String password;
+ // The password for logging into the RPC client.
+ @Value("${config.rpc.port}")
+ private int rpcPort;
+
+ private CordaRPCConnection rpcConnection;
+ CordaRPCOps proxy;
+
+ @PostConstruct
+ public void initialiseNodeRPCConnection() {
+ NetworkHostAndPort rpcAddress = new NetworkHostAndPort(host, rpcPort);
+ CordaRPCClient rpcClient = new CordaRPCClient(rpcAddress);
+ rpcConnection = rpcClient.start(username, password);
+ proxy = rpcConnection.getProxy();
+ }
+
+ @PreDestroy
+ public void close() {
+ rpcConnection.notifyServerAndClose();
+ }
+}
\ No newline at end of file
diff --git a/Accounts/tictacthor/clients/src/main/java/net/corda/samples/tictacthor/webserver/Starter.java b/Accounts/tictacthor/clients/src/main/java/net/corda/samples/tictacthor/webserver/Starter.java
new file mode 100644
index 00000000..7b1e329c
--- /dev/null
+++ b/Accounts/tictacthor/clients/src/main/java/net/corda/samples/tictacthor/webserver/Starter.java
@@ -0,0 +1,23 @@
+package net.corda.samples.tictacthor.webserver;
+
+import org.springframework.boot.Banner;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+import static org.springframework.boot.WebApplicationType.SERVLET;
+
+/**
+ * Our Spring Boot application.
+ */
+@SpringBootApplication
+public class Starter {
+ /**
+ * Starts our Spring Boot application.
+ */
+ public static void main(String[] args) {
+ SpringApplication app = new SpringApplication(Starter.class);
+ app.setBannerMode(Banner.Mode.OFF);
+ app.setWebApplicationType(SERVLET);
+ app.run(args);
+ }
+}
\ No newline at end of file
diff --git a/Accounts/tictacthor/contracts/build.gradle b/Accounts/tictacthor/contracts/build.gradle
index 818da95d..1ce77e8d 100644
--- a/Accounts/tictacthor/contracts/build.gradle
+++ b/Accounts/tictacthor/contracts/build.gradle
@@ -32,6 +32,6 @@ dependencies {
cordaCompile "$corda_core_release_group:corda-core:$corda_core_release_version"
cordaRuntime "$corda_release_group:corda:$corda_release_version"
testCompile "$corda_release_group:corda-node-driver:$corda_release_version"
- // Token Account dependencies.
+ // Account dependencies.
cordaCompile "$accounts_release_group:accounts-contracts:$accounts_release_version"
}
\ No newline at end of file
diff --git a/Accounts/tictacthor/contracts/src/main/java/com/tictacthor/contracts/BoardContract.java b/Accounts/tictacthor/contracts/src/main/java/com/tictacthor/contracts/BoardContract.java
deleted file mode 100644
index a39c46c7..00000000
--- a/Accounts/tictacthor/contracts/src/main/java/com/tictacthor/contracts/BoardContract.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package com.tictacthor.contracts;
-
-import com.tictacthor.states.BoardState;
-import kotlin.Pair;
-import net.corda.core.contracts.CommandData;
-import net.corda.core.contracts.CommandWithParties;
-import net.corda.core.contracts.Contract;
-import net.corda.core.transactions.LedgerTransaction;
-import static net.corda.core.contracts.ContractsDSL.requireSingleCommand;
-
-// ************
-// * Contract *
-// ************
-public class BoardContract implements Contract {
- // This is used to identify our contract when building a transaction.
- public static final String ID = "com.tictacthor.contracts.BoardContract";
-
- // A transaction is valid if the verify() function of the contract of all the transaction's input and output states
- // does not throw an exception.
- @Override
- public void verify(LedgerTransaction tx) {
-
- /* We can use the requireSingleCommand function to extract command data from transaction.
- * However, it is possible to have multiple commands in a signle transaction.*/
- final CommandWithParties command = requireSingleCommand(tx.getCommands(), Commands.class);
- final Commands commandData = command.getValue();
-
- }
-
- // Used to indicate the transaction's intent.
- public interface Commands extends CommandData {
- //In our hello-world app, We will only have one command.
- class StartGame implements Commands {}
- class SubmitTurn implements Commands {}
- class EndGame implements Commands {}
-
- }
-
-
- public static class BoardUtils{
- public static Boolean isGameOver(char[][] board){
- return (board[0][0] == board [0][1] && board[0][0] == board [0][2] && (board[0][0] == 'X' || board[0][0] == 'O')) ||
- (board[0][0] == board [1][1] && board[0][0] == board [2][2]&& (board[0][0] == 'X' || board[0][0] == 'O')) ||
- (board[0][0] == board [1][0] && board[0][0] == board [2][0]&& (board[0][0] == 'X' || board[0][0] == 'O')) ||
- (board[2][0] == board [2][1] && board[2][0] == board [2][2]&& (board[2][0] == 'X' || board[2][0] == 'O')) ||
- (board[2][0] == board [1][1] && board[0][0] == board [0][2]&& (board[2][0] == 'X' || board[2][0] == 'O')) ||
- (board[0][2] == board [1][2] && board[0][2] == board [2][2]&& (board[0][2] == 'X' || board[0][2] == 'O')) ||
- (board[0][1] == board [1][1] && board[0][1] == board [2][1]&& (board[0][1] == 'X' || board[0][1] == 'O')) ||
- (board[1][0] == board [1][1] && board[1][0] == board [1][2]&& (board[1][0] == 'X' || board[1][0] == 'O'));
- }
-
- }
-}
diff --git a/Accounts/tictacthor/contracts/src/main/java/net/corda/samples/tictacthor/contracts/BoardContract.java b/Accounts/tictacthor/contracts/src/main/java/net/corda/samples/tictacthor/contracts/BoardContract.java
new file mode 100644
index 00000000..31afd2d9
--- /dev/null
+++ b/Accounts/tictacthor/contracts/src/main/java/net/corda/samples/tictacthor/contracts/BoardContract.java
@@ -0,0 +1,74 @@
+package net.corda.samples.tictacthor.contracts;
+
+import net.corda.core.contracts.CommandData;
+import net.corda.core.contracts.CommandWithParties;
+import net.corda.core.contracts.Contract;
+import net.corda.core.contracts.ContractState;
+import net.corda.core.transactions.LedgerTransaction;
+import net.corda.samples.tictacthor.states.BoardState;
+
+import java.util.List;
+
+import static net.corda.core.contracts.ContractsDSL.requireSingleCommand;
+import static net.corda.core.contracts.ContractsDSL.requireThat;
+
+// ************
+// * Contract *
+// ************
+public class BoardContract implements Contract {
+ // This is used to identify our contract when building a transaction.
+ public static final String ID = "net.corda.samples.tictacthor.contracts.BoardContract";
+
+ // A transaction is valid if the verify() function of the contract of all the transaction's input and output states
+ // does not throw an exception.
+ @Override
+ public void verify(LedgerTransaction tx) {
+ final CommandWithParties command = requireSingleCommand(tx.getCommands(), BoardContract.Commands.class);
+
+ List inputs = tx.getInputStates();
+ List outputs = tx.getOutputStates();
+
+ if (command.getValue() instanceof BoardContract.Commands.StartGame) {
+
+ // Using Corda DSL function requireThat to replicate conditions-checks
+ requireThat(require -> {
+ require.using("No inputs should be consumed when creating a new Invoice State.", inputs.isEmpty());
+ require.using("Transaction must have exactly one output.", outputs.size() == 1);
+ BoardState output = (BoardState) outputs.get(0);
+ require.using("Output board must have status GAME_IN_PROGRESS", output.getStatus() == BoardState.Status.GAME_IN_PROGRESS);
+ require.using("You cannot play a game with yourself.", output.getPlayerO() != output.getPlayerX());
+ return null;
+ });
+
+ } else if (command.getValue() instanceof BoardContract.Commands.SubmitTurn){
+
+ }else if (command.getValue() instanceof BoardContract.Commands.EndGame){
+
+ }else{
+ throw new IllegalArgumentException("Command not found!");
+ }
+
+ }
+
+ // Used to indicate the transaction's intent.
+ public interface Commands extends CommandData {
+ //In our hello-world app, We will only have one command.
+ class StartGame implements Commands {}
+ class SubmitTurn implements Commands {}
+ class EndGame implements Commands {}
+ }
+
+ public static class BoardUtils{
+ public static Boolean isGameOver(char[][] board){
+ return (board[0][0] == board [0][1] && board[0][0] == board [0][2] && (board[0][0] == 'X' || board[0][0] == 'O')) ||
+ (board[0][0] == board [1][1] && board[0][0] == board [2][2]&& (board[0][0] == 'X' || board[0][0] == 'O')) ||
+ (board[0][0] == board [1][0] && board[0][0] == board [2][0]&& (board[0][0] == 'X' || board[0][0] == 'O')) ||
+ (board[2][0] == board [2][1] && board[2][0] == board [2][2]&& (board[2][0] == 'X' || board[2][0] == 'O')) ||
+ (board[2][0] == board [1][1] && board[0][0] == board [0][2]&& (board[2][0] == 'X' || board[2][0] == 'O')) ||
+ (board[0][2] == board [1][2] && board[0][2] == board [2][2]&& (board[0][2] == 'X' || board[0][2] == 'O')) ||
+ (board[0][1] == board [1][1] && board[0][1] == board [2][1]&& (board[0][1] == 'X' || board[0][1] == 'O')) ||
+ (board[1][0] == board [1][1] && board[1][0] == board [1][2]&& (board[1][0] == 'X' || board[1][0] == 'O'));
+ }
+
+ }
+}
diff --git a/Accounts/tictacthor/contracts/src/main/java/com/tictacthor/states/BoardState.java b/Accounts/tictacthor/contracts/src/main/java/net/corda/samples/tictacthor/states/BoardState.java
similarity index 97%
rename from Accounts/tictacthor/contracts/src/main/java/com/tictacthor/states/BoardState.java
rename to Accounts/tictacthor/contracts/src/main/java/net/corda/samples/tictacthor/states/BoardState.java
index 405aeb7a..51dce4ec 100644
--- a/Accounts/tictacthor/contracts/src/main/java/com/tictacthor/states/BoardState.java
+++ b/Accounts/tictacthor/contracts/src/main/java/net/corda/samples/tictacthor/states/BoardState.java
@@ -1,6 +1,6 @@
-package com.tictacthor.states;
+package net.corda.samples.tictacthor.states;
-import com.tictacthor.contracts.BoardContract;
+import net.corda.samples.tictacthor.contracts.BoardContract;
//import javafx.util.Pair;
import kotlin.Pair;
@@ -113,7 +113,6 @@ public BoardState returnNewBoardAfterMove(Pair pos, AnonymousPa
//getter setter
-
public UniqueIdentifier getPlayerO() {
return playerO;
}
diff --git a/Accounts/tictacthor/contracts/src/test/java/com/tictacthor/contracts/ContractTests.java b/Accounts/tictacthor/contracts/src/test/java/com/tictacthor/contracts/ContractTests.java
deleted file mode 100644
index f05ab9c3..00000000
--- a/Accounts/tictacthor/contracts/src/test/java/com/tictacthor/contracts/ContractTests.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package com.tictacthor.contracts;
-
-import net.corda.testing.node.MockServices;
-import org.junit.Test;
-
-public class ContractTests {
- private final MockServices ledgerServices = new MockServices();
-
- @Test
- public void dummyTest() {
-
- }
-}
\ No newline at end of file
diff --git a/Accounts/tictacthor/contracts/src/test/java/net/corda/samples/tictacthor/contracts/ContractTests.java b/Accounts/tictacthor/contracts/src/test/java/net/corda/samples/tictacthor/contracts/ContractTests.java
new file mode 100644
index 00000000..94f0d1ae
--- /dev/null
+++ b/Accounts/tictacthor/contracts/src/test/java/net/corda/samples/tictacthor/contracts/ContractTests.java
@@ -0,0 +1,41 @@
+package net.corda.samples.tictacthor.contracts;
+
+import net.corda.core.contracts.UniqueIdentifier;
+import net.corda.core.identity.AnonymousParty;
+import net.corda.core.identity.CordaX500Name;
+import net.corda.samples.tictacthor.states.BoardState;
+import net.corda.testing.core.TestIdentity;
+import net.corda.testing.node.MockServices;
+import org.junit.Test;
+
+import java.util.UUID;
+
+import static net.corda.testing.node.NodeTestUtils.ledger;
+
+public class ContractTests {
+ private final MockServices ledgerServices = new MockServices();
+ TestIdentity Operator = new TestIdentity(new CordaX500Name("Alice", "TestLand", "US"));
+ TestIdentity Operator2 = new TestIdentity(new CordaX500Name("Bob", "TestLand", "US"));
+
+ @Test
+ public void GameCanOnlyCreatedWhenTwoDifferentPlayerPresented() {
+ UniqueIdentifier playerX = new UniqueIdentifier();
+ BoardState tokenPass = new BoardState(new UniqueIdentifier(),new UniqueIdentifier(),
+ new AnonymousParty(Operator.getPublicKey()),new AnonymousParty(Operator2.getPublicKey()));
+ BoardState tokenfail = new BoardState(playerX,playerX,
+ new AnonymousParty(Operator.getPublicKey()),new AnonymousParty(Operator2.getPublicKey()));
+ ledger(ledgerServices, l -> {
+ l.transaction(tx -> {
+ tx.output(BoardContract.ID, tokenfail);
+ tx.command(Operator.getPublicKey(), new BoardContract.Commands.StartGame()); // Wrong type.
+ return tx.fails();
+ });
+ l.transaction(tx -> {
+ tx.output(BoardContract.ID, tokenPass);
+ tx.command(Operator.getPublicKey(), new BoardContract.Commands.StartGame()); // Wrong type.
+ return tx.verifies();
+ });
+ return null;
+ });
+ }
+}
\ No newline at end of file
diff --git a/Accounts/tictacthor/contracts/src/test/java/net/corda/samples/tictacthor/contracts/StateTests.java b/Accounts/tictacthor/contracts/src/test/java/net/corda/samples/tictacthor/contracts/StateTests.java
new file mode 100644
index 00000000..00602130
--- /dev/null
+++ b/Accounts/tictacthor/contracts/src/test/java/net/corda/samples/tictacthor/contracts/StateTests.java
@@ -0,0 +1,18 @@
+package net.corda.samples.tictacthor.contracts;
+
+import net.corda.core.contracts.UniqueIdentifier;
+import net.corda.samples.tictacthor.states.BoardState;
+import net.corda.testing.node.MockServices;
+import org.junit.Test;
+
+public class StateTests {
+ private final MockServices ledgerServices = new MockServices();
+
+ @Test
+ public void hasFieldOfCorrectType() throws NoSuchFieldException {
+ // Does the message field exist?
+ BoardState.class.getDeclaredField("playerO");
+ // Is the message field of the correct type?
+ assert(BoardState.class.getDeclaredField("playerO").getType().equals(UniqueIdentifier.class));
+ }
+}
\ No newline at end of file
diff --git a/Accounts/tictacthor/gradle.properties b/Accounts/tictacthor/gradle.properties
index ec9fcb16..47e31d39 100644
--- a/Accounts/tictacthor/gradle.properties
+++ b/Accounts/tictacthor/gradle.properties
@@ -1,3 +1,3 @@
-name=Test
+name=Tictacthor Cordapp
group=com.tictacthor
-version=0.1
\ No newline at end of file
+version=1.0
\ No newline at end of file
diff --git a/Accounts/tictacthor/gradle/wrapper/gradle-wrapper.properties b/Accounts/tictacthor/gradle/wrapper/gradle-wrapper.properties
index 2a2a3a8e..ae01072d 100644
--- a/Accounts/tictacthor/gradle/wrapper/gradle-wrapper.properties
+++ b/Accounts/tictacthor/gradle/wrapper/gradle-wrapper.properties
@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip
diff --git a/Accounts/tictacthor/repositories.gradle b/Accounts/tictacthor/repositories.gradle
index 2874c2ab..8be7b630 100644
--- a/Accounts/tictacthor/repositories.gradle
+++ b/Accounts/tictacthor/repositories.gradle
@@ -1,8 +1,8 @@
repositories {
mavenLocal()
mavenCentral()
- jcenter()
+
maven { url 'https://jitpack.io' }
- maven { url 'https://ci-artifactory.corda.r3cev.com/artifactory/corda' }
+ maven { url 'https://download.corda.net/maven/corda-dependencies' }
maven { url 'https://repo.gradle.org/gradle/libs-releases' }
}
diff --git a/Accounts/tictacthor/runServers.sh b/Accounts/tictacthor/runServers.sh
new file mode 100644
index 00000000..0807fb1f
--- /dev/null
+++ b/Accounts/tictacthor/runServers.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+./gradlew bootRunDevRel &
+./gradlew bootRunSOE
diff --git a/Accounts/tictacthor/workflows/build.gradle b/Accounts/tictacthor/workflows/build.gradle
index 5d34b3e5..e6adce24 100644
--- a/Accounts/tictacthor/workflows/build.gradle
+++ b/Accounts/tictacthor/workflows/build.gradle
@@ -57,6 +57,7 @@ dependencies {
// CorDapp dependencies.
cordapp project(":contracts")
+
//Account dependencies
cordaCompile "$confidential_id_release_group:ci-workflows:$confidential_id_release_version"
cordaCompile "$accounts_release_group:accounts-workflows:$accounts_release_version"
diff --git a/Accounts/tictacthor/workflows/src/integrationTest/java/com/tictacthor/DriverBasedTest.java b/Accounts/tictacthor/workflows/src/integrationTest/java/com/tictacthor/DriverBasedTest.java
deleted file mode 100644
index b27be9da..00000000
--- a/Accounts/tictacthor/workflows/src/integrationTest/java/com/tictacthor/DriverBasedTest.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package com.tictacthor;
-
-import com.google.common.collect.ImmutableList;
-import net.corda.core.concurrent.CordaFuture;
-import net.corda.core.identity.CordaX500Name;
-import net.corda.testing.core.TestIdentity;
-import net.corda.testing.driver.DriverParameters;
-import net.corda.testing.driver.NodeHandle;
-import net.corda.testing.driver.NodeParameters;
-import org.junit.Test;
-
-import java.util.List;
-
-import static net.corda.testing.driver.Driver.driver;
-import static org.junit.Assert.assertEquals;
-
-public class DriverBasedTest {
- private final TestIdentity bankA = new TestIdentity(new CordaX500Name("BankA", "", "GB"));
- private final TestIdentity bankB = new TestIdentity(new CordaX500Name("BankB", "", "US"));
-
- @Test
- public void nodeTest() {
- driver(new DriverParameters().withIsDebug(true).withStartNodesInProcess(true), dsl -> {
- // Start a pair of nodes and wait for them both to be ready.
- List> handleFutures = ImmutableList.of(
- dsl.startNode(new NodeParameters().withProvidedName(bankA.getName())),
- dsl.startNode(new NodeParameters().withProvidedName(bankB.getName()))
- );
-
- try {
- NodeHandle partyAHandle = handleFutures.get(0).get();
- NodeHandle partyBHandle = handleFutures.get(1).get();
-
- // From each node, make an RPC call to retrieve another node's name from the network map, to verify that the
- // nodes have started and can communicate.
-
- // This is a very basic test: in practice tests would be starting flows, and verifying the states in the vault
- // and other important metrics to ensure that your CorDapp is working as intended.
- assertEquals(partyAHandle.getRpc().wellKnownPartyFromX500Name(bankB.getName()).getName(), bankB.getName());
- assertEquals(partyBHandle.getRpc().wellKnownPartyFromX500Name(bankA.getName()).getName(), bankA.getName());
- } catch (Exception e) {
- throw new RuntimeException("Caught exception during test: ", e);
- }
-
- return null;
- });
- }
-}
\ No newline at end of file
diff --git a/Accounts/tictacthor/workflows/src/integrationTest/java/net/corda/samples/tictacthor/DriverBasedTest.java b/Accounts/tictacthor/workflows/src/integrationTest/java/net/corda/samples/tictacthor/DriverBasedTest.java
new file mode 100644
index 00000000..ac0c2c26
--- /dev/null
+++ b/Accounts/tictacthor/workflows/src/integrationTest/java/net/corda/samples/tictacthor/DriverBasedTest.java
@@ -0,0 +1,48 @@
+package net.corda.samples.tictacthor;
+
+import com.google.common.collect.ImmutableList;
+import net.corda.core.concurrent.CordaFuture;
+import net.corda.core.identity.CordaX500Name;
+import net.corda.testing.core.TestIdentity;
+import net.corda.testing.driver.DriverParameters;
+import net.corda.testing.driver.NodeHandle;
+import net.corda.testing.driver.NodeParameters;
+import org.junit.Test;
+
+import java.util.List;
+
+import static net.corda.testing.driver.Driver.driver;
+import static org.junit.Assert.assertEquals;
+
+public class DriverBasedTest {
+ private final TestIdentity bankA = new TestIdentity(new CordaX500Name("BankA", "", "GB"));
+ private final TestIdentity bankB = new TestIdentity(new CordaX500Name("BankB", "", "US"));
+
+ @Test
+ public void nodeTest() {
+ driver(new DriverParameters().withIsDebug(true).withStartNodesInProcess(true), dsl -> {
+ // Start a pair of nodes and wait for them both to be ready.
+ List> handleFutures = ImmutableList.of(
+ dsl.startNode(new NodeParameters().withProvidedName(bankA.getName())),
+ dsl.startNode(new NodeParameters().withProvidedName(bankB.getName()))
+ );
+
+ try {
+ NodeHandle partyAHandle = handleFutures.get(0).get();
+ NodeHandle partyBHandle = handleFutures.get(1).get();
+
+ // From each node, make an RPC call to retrieve another node's name from the network map, to verify that the
+ // nodes have started and can communicate.
+
+ // This is a very basic test: in practice tests would be starting flows, and verifying the states in the vault
+ // and other important metrics to ensure that your CorDapp is working as intended.
+ assertEquals(partyAHandle.getRpc().wellKnownPartyFromX500Name(bankB.getName()).getName(), bankB.getName());
+ assertEquals(partyBHandle.getRpc().wellKnownPartyFromX500Name(bankA.getName()).getName(), bankA.getName());
+ } catch (Exception e) {
+ throw new RuntimeException("Caught exception during test: ", e);
+ }
+
+ return null;
+ });
+ }
+}
\ No newline at end of file
diff --git a/Accounts/tictacthor/workflows/src/main/java/com/tictacthor/accountUtilities/CreateNewAccount.java b/Accounts/tictacthor/workflows/src/main/java/com/tictacthor/accountUtilities/CreateNewAccount.java
deleted file mode 100644
index 3ea3e355..00000000
--- a/Accounts/tictacthor/workflows/src/main/java/com/tictacthor/accountUtilities/CreateNewAccount.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package com.tictacthor.accountUtilities;
-
-import com.r3.corda.lib.accounts.contracts.states.AccountInfo;
-import com.r3.corda.lib.accounts.workflows.*;
-import com.r3.corda.lib.accounts.workflows.services.KeyManagementBackedAccountService;
-import net.corda.core.contracts.StateAndRef;
-import net.corda.core.flows.*;
-import co.paralleluniverse.fibers.Suspendable;
-import com.r3.corda.lib.accounts.workflows.services.AccountService;
-import net.corda.core.flows.FlowLogic;;
-import net.corda.core.flows.StartableByRPC;
-
-import java.util.UUID;
-
-@StartableByRPC
-@StartableByService
-@InitiatingFlow
-public class CreateNewAccount extends FlowLogic{
-
- private String acctName;
-
- public CreateNewAccount(String acctName) {
- this.acctName = acctName;
- }
-
-
- @Override
- public String call() throws FlowException {
- StateAndRef newAccount = null;
- try {
- newAccount = getServiceHub().cordaService(KeyManagementBackedAccountService.class).createAccount(acctName).get();
- } catch (Exception e) {
- e.printStackTrace();
- }
- AccountInfo acct = newAccount.getState().getData();
- return "" + acct.getName() + " team's account was created. UUID is : " + acct.getIdentifier();
- }
-}
diff --git a/Accounts/tictacthor/workflows/src/main/java/com/tictacthor/accountUtilities/NewKeyForAccount.java b/Accounts/tictacthor/workflows/src/main/java/com/tictacthor/accountUtilities/NewKeyForAccount.java
deleted file mode 100644
index 8e5f24b2..00000000
--- a/Accounts/tictacthor/workflows/src/main/java/com/tictacthor/accountUtilities/NewKeyForAccount.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package com.tictacthor.accountUtilities;
-
-import co.paralleluniverse.fibers.Suspendable;
-import net.corda.core.flows.FlowException;
-import net.corda.core.flows.FlowLogic;
-import net.corda.core.flows.StartableByRPC;
-import net.corda.core.flows.StartableByService;
-import net.corda.core.identity.PartyAndCertificate;
-import java.util.*;
-
-@StartableByRPC
-@StartableByService
-public class NewKeyForAccount extends FlowLogic{
-
- private final UUID accountID;
-
- public NewKeyForAccount(UUID accountID) {
- this.accountID = accountID;
- }
-
- @Override
- @Suspendable
- public PartyAndCertificate call() throws FlowException {
- return getServiceHub().getKeyManagementService().freshKeyAndCert(getOurIdentityAndCert(), false, accountID);
- }
-}
\ No newline at end of file
diff --git a/Accounts/tictacthor/workflows/src/main/java/com/tictacthor/accountUtilities/ShareAccountTo.java b/Accounts/tictacthor/workflows/src/main/java/com/tictacthor/accountUtilities/ShareAccountTo.java
deleted file mode 100644
index 401bef21..00000000
--- a/Accounts/tictacthor/workflows/src/main/java/com/tictacthor/accountUtilities/ShareAccountTo.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package com.tictacthor.accountUtilities;
-
-import co.paralleluniverse.fibers.Suspendable;
-import com.r3.corda.lib.accounts.contracts.states.AccountInfo;
-import com.r3.corda.lib.accounts.workflows.flows.AccountInfoByName;
-import com.r3.corda.lib.accounts.workflows.services.KeyManagementBackedAccountService;
-import net.corda.core.contracts.StateAndRef;
-import net.corda.core.flows.FlowException;
-import net.corda.core.flows.FlowLogic;
-import net.corda.core.flows.StartableByRPC;
-import net.corda.core.flows.StartableByService;
-import net.corda.core.identity.Party;
-import com.r3.corda.lib.accounts.workflows.flows.ShareAccountInfo;
-import java.util.*;
-
-@StartableByRPC
-@StartableByService
-public class ShareAccountTo extends FlowLogic{
-
- private final Party shareTo;
- private final String acctNameShared;
-
- public ShareAccountTo(String acctNameShared, Party shareTo) {
- this.acctNameShared = acctNameShared;
- this.shareTo = shareTo;
- }
-
- @Override
- @Suspendable
- public String call() throws FlowException {
- List> allmyAccounts = getServiceHub().cordaService(KeyManagementBackedAccountService.class).ourAccounts();
- StateAndRef SharedAccount = allmyAccounts.stream()
- .filter(it -> it.getState().getData().getName().equals(acctNameShared))
- .findAny().get();
-
- subFlow(new ShareAccountInfo(SharedAccount, Arrays.asList(shareTo)));
- return "Shared " + acctNameShared + " with " + shareTo.getName().getOrganisation();
- }
-}
\ No newline at end of file
diff --git a/Accounts/tictacthor/workflows/src/main/java/com/tictacthor/flows/StartGameFlow.java b/Accounts/tictacthor/workflows/src/main/java/com/tictacthor/flows/StartGameFlow.java
deleted file mode 100644
index dae028b4..00000000
--- a/Accounts/tictacthor/workflows/src/main/java/com/tictacthor/flows/StartGameFlow.java
+++ /dev/null
@@ -1,150 +0,0 @@
-package com.tictacthor.flows;
-
-import co.paralleluniverse.fibers.Suspendable;
-import com.r3.corda.lib.accounts.contracts.states.AccountInfo;
-import com.r3.corda.lib.accounts.workflows.services.AccountService;
-import com.r3.corda.lib.accounts.workflows.flows.RequestKeyForAccount;
-import com.r3.corda.lib.accounts.workflows.services.KeyManagementBackedAccountService;
-import com.sun.istack.NotNull;
-import com.tictacthor.accountUtilities.NewKeyForAccount;
-import com.tictacthor.contracts.BoardContract;
-import com.tictacthor.states.BoardState;
-import net.corda.core.contracts.StateAndRef;
-import net.corda.core.contracts.UniqueIdentifier;
-import net.corda.core.crypto.TransactionSignature;
-import net.corda.core.flows.*;
-import net.corda.core.identity.AnonymousParty;
-import net.corda.core.identity.Party;
-import net.corda.core.node.services.vault.QueryCriteria;
-import net.corda.core.transactions.SignedTransaction;
-import net.corda.core.transactions.TransactionBuilder;
-import net.corda.core.utilities.ProgressTracker;
-import java.security.PublicKey;
-import java.util.Arrays;
-import java.util.List;
-import java.util.stream.Collectors;
-
-// ******************
-// * Initiator flow *
-// ******************
-@InitiatingFlow
-@StartableByRPC
-public class StartGameFlow extends FlowLogic {
-
- private final ProgressTracker progressTracker = tracker();
-
- private static final ProgressTracker.Step GENERATING_TRANSACTION = new ProgressTracker.Step("Generating a HeartState transaction");
- private static final ProgressTracker.Step SIGNING_TRANSACTION = new ProgressTracker.Step("Signing transaction with our private key.");
- private static final ProgressTracker.Step FINALISING_TRANSACTION = new ProgressTracker.Step("Recording transaction") {
- @Override
- public ProgressTracker childProgressTracker() {
- return FinalityFlow.tracker();
- }
- };
-
- private static ProgressTracker tracker() {
- return new ProgressTracker(
- GENERATING_TRANSACTION,
- SIGNING_TRANSACTION,
- FINALISING_TRANSACTION
- );
- }
-
- @Override
- public ProgressTracker getProgressTracker() {
- return progressTracker;
- }
-
- //private variables
- private String whoAmI ;
- private String whereTo;
-
- //public constructor
- public StartGameFlow(String whoAmI, String whereTo){
- this.whoAmI = whoAmI;
- this.whereTo = whereTo;
- }
-
- @Suspendable
- @Override
- public UniqueIdentifier call() throws FlowException {
- //grab account service
- AccountService accountService = getServiceHub().cordaService(KeyManagementBackedAccountService.class);
- //grab the account information
- AccountInfo myAccount = accountService.accountInfo(whoAmI).get(0).getState().getData();
- PublicKey myKey = subFlow(new NewKeyForAccount(myAccount.getIdentifier().getId())).getOwningKey();
-
- AccountInfo targetAccount = accountService.accountInfo(whereTo).get(0).getState().getData();
- AnonymousParty targetAcctAnonymousParty = subFlow(new RequestKeyForAccount(targetAccount));
-
- //check if this account is in another game
- QueryCriteria.VaultQueryCriteria criteria = new QueryCriteria.VaultQueryCriteria().withExternalIds(Arrays.asList(myAccount.getIdentifier().getId()));
- List> results = getServiceHub().getVaultService().queryBy(BoardState.class,criteria).getStates();
- if(results.size() != 0){
- throw new IllegalArgumentException("You are in another game");
- }
-
- progressTracker.setCurrentStep(GENERATING_TRANSACTION);
- //generating State for transfer
- BoardState initialBoardState = new BoardState(myAccount.getIdentifier(),
- targetAccount.getIdentifier(),
- new AnonymousParty(myKey),
- targetAcctAnonymousParty);
-
- // Obtain a reference to a notary we wish to use.
- /** METHOD 1: Take first notary on network, WARNING: use for test, non-prod environments, and single-notary networks only!*
- * METHOD 2: Explicit selection of notary by CordaX500Name - argument can by coded in flow or parsed from config (Preferred)
- *
- * * - For production you always want to use Method 2 as it guarantees the expected notary is returned.
- */
- final Party notary = getServiceHub().getNetworkMapCache().getNotaryIdentities().get(0); // METHOD 1
- // final Party notary = getServiceHub().getNetworkMapCache().getNotary(CordaX500Name.parse("O=Notary,L=London,C=GB")); // METHOD 2
-
- TransactionBuilder txbuilder = new TransactionBuilder(notary)
- .addOutputState(initialBoardState)
- .addCommand(new BoardContract.Commands.StartGame(),Arrays.asList(myKey,targetAcctAnonymousParty.getOwningKey()));
-
-
- progressTracker.setCurrentStep(SIGNING_TRANSACTION);
- //self verify and sign Transaction
- txbuilder.verify(getServiceHub());
- SignedTransaction locallySignedTx = getServiceHub().signInitialTransaction(txbuilder,Arrays.asList(getOurIdentity().getOwningKey(),myKey));
-
- //Collect sigs
- FlowSession sessionForAccountToSendTo = initiateFlow(targetAccount.getHost());
- List accountToMoveToSignature = (List) subFlow(new CollectSignatureFlow(locallySignedTx,
- sessionForAccountToSendTo,targetAcctAnonymousParty.getOwningKey()));
- SignedTransaction signedByCounterParty = locallySignedTx.withAdditionalSignatures(accountToMoveToSignature);
- progressTracker.setCurrentStep(FINALISING_TRANSACTION);
- //Finalize
- subFlow(new FinalityFlow(signedByCounterParty,
- Arrays.asList(sessionForAccountToSendTo).stream().filter(it -> it.getCounterparty() != getOurIdentity()).collect(Collectors.toList())));
- return initialBoardState.getLinearId();
- }
-}
-
-
-@InitiatedBy(StartGameFlow.class)
-class StartGameFlowResponder extends FlowLogic {
- //private variable
- private FlowSession counterpartySession;
-
- //Constructor
- public StartGameFlowResponder(FlowSession counterpartySession) {
- this.counterpartySession = counterpartySession;
- }
-
- @Override
- @Suspendable
- public Void call() throws FlowException {
- subFlow(new SignTransactionFlow(counterpartySession) {
- @Override
- protected void checkTransaction(@NotNull SignedTransaction stx) throws FlowException {
- // Custom Logic to validate transaction.
- }
- });
- subFlow(new ReceiveFinalityFlow(counterpartySession));
- return null;
- }
-}
-
diff --git a/Accounts/tictacthor/workflows/src/main/java/com/tictacthor/flows/SyncGame.java b/Accounts/tictacthor/workflows/src/main/java/com/tictacthor/flows/SyncGame.java
deleted file mode 100644
index cd0c7f7a..00000000
--- a/Accounts/tictacthor/workflows/src/main/java/com/tictacthor/flows/SyncGame.java
+++ /dev/null
@@ -1,51 +0,0 @@
-package com.tictacthor.flows;
-
-import co.paralleluniverse.fibers.Suspendable;
-import com.r3.corda.lib.accounts.contracts.states.AccountInfo;
-import com.r3.corda.lib.accounts.workflows.flows.AccountInfoByName;
-import com.r3.corda.lib.accounts.workflows.services.AccountService;
-import com.r3.corda.lib.accounts.workflows.services.KeyManagementBackedAccountService;
-import com.tictacthor.states.BoardState;
-import net.corda.core.contracts.StateAndRef;
-import net.corda.core.contracts.UniqueIdentifier;
-import net.corda.core.flows.FlowException;
-import net.corda.core.flows.FlowLogic;
-import net.corda.core.flows.StartableByRPC;
-import net.corda.core.flows.StartableByService;
-import net.corda.core.identity.Party;
-import com.r3.corda.lib.accounts.workflows.flows.ShareAccountInfo;
-import net.corda.core.node.services.Vault;
-import net.corda.core.node.services.vault.QueryCriteria;
-import com.r3.corda.lib.accounts.workflows.flows.ShareStateAndSyncAccounts;
-
-import java.util.*;
-import java.util.stream.Collectors;
-
-@StartableByRPC
-@StartableByService
-public class SyncGame extends FlowLogic{
- private String gameId;
- private Party party;
-
- public SyncGame(String gameId, Party party) {
- this.gameId = gameId;
- this.party = party;
- }
-
- @Override
- @Suspendable
- public String call() throws FlowException {
-
- UUID id = UUID.fromString(gameId);
- QueryCriteria.LinearStateQueryCriteria queryCriteria = new QueryCriteria.LinearStateQueryCriteria()
- .withUuid(Arrays.asList(id)).withStatus(Vault.StateStatus.UNCONSUMED);
- try {
- StateAndRef inputBoardStateAndRef = getServiceHub().getVaultService().queryBy(BoardState.class,queryCriteria).getStates().get(0);
- subFlow(new ShareStateAndSyncAccounts(inputBoardStateAndRef,party));
-
- }catch (Exception e){
- throw new FlowException("GameState with id "+gameId+" not found.");
- }
- return "Game synced";
- }
-}
\ No newline at end of file
diff --git a/Accounts/tictacthor/workflows/src/main/java/net/corda/samples/tictacthor/accountUtilities/CreateNewAccount.java b/Accounts/tictacthor/workflows/src/main/java/net/corda/samples/tictacthor/accountUtilities/CreateNewAccount.java
new file mode 100644
index 00000000..e4a2c7c2
--- /dev/null
+++ b/Accounts/tictacthor/workflows/src/main/java/net/corda/samples/tictacthor/accountUtilities/CreateNewAccount.java
@@ -0,0 +1,38 @@
+package net.corda.samples.tictacthor.accountUtilities;
+
+import com.r3.corda.lib.accounts.contracts.states.AccountInfo;
+import com.r3.corda.lib.accounts.workflows.*;
+import com.r3.corda.lib.accounts.workflows.services.KeyManagementBackedAccountService;
+import net.corda.core.contracts.StateAndRef;
+import net.corda.core.flows.*;
+import co.paralleluniverse.fibers.Suspendable;
+import com.r3.corda.lib.accounts.workflows.services.AccountService;
+import net.corda.core.flows.FlowLogic;;
+import net.corda.core.flows.StartableByRPC;
+
+import java.util.UUID;
+
+@StartableByRPC
+@StartableByService
+@InitiatingFlow
+public class CreateNewAccount extends FlowLogic{
+
+ private String acctName;
+
+ public CreateNewAccount(String acctName) {
+ this.acctName = acctName;
+ }
+
+
+ @Override
+ public String call() throws FlowException {
+ StateAndRef newAccount = null;
+ try {
+ newAccount = getServiceHub().cordaService(KeyManagementBackedAccountService.class).createAccount(acctName).get();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ AccountInfo acct = newAccount.getState().getData();
+ return "" + acct.getName() + " team's account was created. UUID is : " + acct.getIdentifier();
+ }
+}
diff --git a/Accounts/tictacthor/workflows/src/main/java/net/corda/samples/tictacthor/accountUtilities/NewKeyForAccount.java b/Accounts/tictacthor/workflows/src/main/java/net/corda/samples/tictacthor/accountUtilities/NewKeyForAccount.java
new file mode 100644
index 00000000..d94f3bf2
--- /dev/null
+++ b/Accounts/tictacthor/workflows/src/main/java/net/corda/samples/tictacthor/accountUtilities/NewKeyForAccount.java
@@ -0,0 +1,26 @@
+package net.corda.samples.tictacthor.accountUtilities;
+
+import co.paralleluniverse.fibers.Suspendable;
+import net.corda.core.flows.FlowException;
+import net.corda.core.flows.FlowLogic;
+import net.corda.core.flows.StartableByRPC;
+import net.corda.core.flows.StartableByService;
+import net.corda.core.identity.PartyAndCertificate;
+import java.util.*;
+
+@StartableByRPC
+@StartableByService
+public class NewKeyForAccount extends FlowLogic{
+
+ private final UUID accountID;
+
+ public NewKeyForAccount(UUID accountID) {
+ this.accountID = accountID;
+ }
+
+ @Override
+ @Suspendable
+ public PartyAndCertificate call() throws FlowException {
+ return getServiceHub().getKeyManagementService().freshKeyAndCert(getOurIdentityAndCert(), false, accountID);
+ }
+}
\ No newline at end of file
diff --git a/Accounts/tictacthor/workflows/src/main/java/net/corda/samples/tictacthor/accountUtilities/ShareAccountTo.java b/Accounts/tictacthor/workflows/src/main/java/net/corda/samples/tictacthor/accountUtilities/ShareAccountTo.java
new file mode 100644
index 00000000..0132589b
--- /dev/null
+++ b/Accounts/tictacthor/workflows/src/main/java/net/corda/samples/tictacthor/accountUtilities/ShareAccountTo.java
@@ -0,0 +1,39 @@
+package net.corda.samples.tictacthor.accountUtilities;
+
+import co.paralleluniverse.fibers.Suspendable;
+import com.r3.corda.lib.accounts.contracts.states.AccountInfo;
+import com.r3.corda.lib.accounts.workflows.flows.AccountInfoByName;
+import com.r3.corda.lib.accounts.workflows.services.KeyManagementBackedAccountService;
+import net.corda.core.contracts.StateAndRef;
+import net.corda.core.flows.FlowException;
+import net.corda.core.flows.FlowLogic;
+import net.corda.core.flows.StartableByRPC;
+import net.corda.core.flows.StartableByService;
+import net.corda.core.identity.Party;
+import com.r3.corda.lib.accounts.workflows.flows.ShareAccountInfo;
+import java.util.*;
+
+@StartableByRPC
+@StartableByService
+public class ShareAccountTo extends FlowLogic{
+
+ private final Party shareTo;
+ private final String acctNameShared;
+
+ public ShareAccountTo(String acctNameShared, Party shareTo) {
+ this.acctNameShared = acctNameShared;
+ this.shareTo = shareTo;
+ }
+
+ @Override
+ @Suspendable
+ public String call() throws FlowException {
+ List> allmyAccounts = getServiceHub().cordaService(KeyManagementBackedAccountService.class).ourAccounts();
+ StateAndRef SharedAccount = allmyAccounts.stream()
+ .filter(it -> it.getState().getData().getName().equals(acctNameShared))
+ .findAny().get();
+
+ subFlow(new ShareAccountInfo(SharedAccount, Arrays.asList(shareTo)));
+ return "Shared " + acctNameShared + " with " + shareTo.getName().getOrganisation();
+ }
+}
\ No newline at end of file
diff --git a/Accounts/tictacthor/workflows/src/main/java/com/tictacthor/accountUtilities/ViewMyAccounts.java b/Accounts/tictacthor/workflows/src/main/java/net/corda/samples/tictacthor/accountUtilities/ViewMyAccounts.java
similarity index 95%
rename from Accounts/tictacthor/workflows/src/main/java/com/tictacthor/accountUtilities/ViewMyAccounts.java
rename to Accounts/tictacthor/workflows/src/main/java/net/corda/samples/tictacthor/accountUtilities/ViewMyAccounts.java
index aba3cfe4..fc48ac7d 100644
--- a/Accounts/tictacthor/workflows/src/main/java/com/tictacthor/accountUtilities/ViewMyAccounts.java
+++ b/Accounts/tictacthor/workflows/src/main/java/net/corda/samples/tictacthor/accountUtilities/ViewMyAccounts.java
@@ -1,4 +1,4 @@
-package com.tictacthor.accountUtilities;
+package net.corda.samples.tictacthor.accountUtilities;
import co.paralleluniverse.fibers.Suspendable;
import com.r3.corda.lib.accounts.contracts.states.AccountInfo;
diff --git a/Accounts/tictacthor/workflows/src/main/java/com/tictacthor/accountUtilities/myGame.java b/Accounts/tictacthor/workflows/src/main/java/net/corda/samples/tictacthor/accountUtilities/myGame.java
similarity index 79%
rename from Accounts/tictacthor/workflows/src/main/java/com/tictacthor/accountUtilities/myGame.java
rename to Accounts/tictacthor/workflows/src/main/java/net/corda/samples/tictacthor/accountUtilities/myGame.java
index b8f6cc6e..046751c5 100644
--- a/Accounts/tictacthor/workflows/src/main/java/com/tictacthor/accountUtilities/myGame.java
+++ b/Accounts/tictacthor/workflows/src/main/java/net/corda/samples/tictacthor/accountUtilities/myGame.java
@@ -1,22 +1,17 @@
-package com.tictacthor.accountUtilities;
+package net.corda.samples.tictacthor.accountUtilities;
import co.paralleluniverse.fibers.Suspendable;
import com.r3.corda.lib.accounts.contracts.states.AccountInfo;
-import com.r3.corda.lib.accounts.workflows.flows.AccountInfoByName;
import com.r3.corda.lib.accounts.workflows.services.AccountService;
import com.r3.corda.lib.accounts.workflows.services.KeyManagementBackedAccountService;
-import com.tictacthor.states.BoardState;
-import net.corda.core.contracts.StateAndRef;
+import net.corda.samples.tictacthor.states.BoardState;
import net.corda.core.flows.FlowException;
import net.corda.core.flows.FlowLogic;
import net.corda.core.flows.StartableByRPC;
import net.corda.core.flows.StartableByService;
-import net.corda.core.identity.Party;
-import com.r3.corda.lib.accounts.workflows.flows.ShareAccountInfo;
import net.corda.core.node.services.vault.QueryCriteria;
import java.util.*;
-import java.util.stream.Collectors;
@StartableByRPC
@StartableByService
diff --git a/Accounts/tictacthor/workflows/src/main/java/com/tictacthor/flows/EndGameFlow.java b/Accounts/tictacthor/workflows/src/main/java/net/corda/samples/tictacthor/flows/EndGameFlow.java
similarity index 87%
rename from Accounts/tictacthor/workflows/src/main/java/com/tictacthor/flows/EndGameFlow.java
rename to Accounts/tictacthor/workflows/src/main/java/net/corda/samples/tictacthor/flows/EndGameFlow.java
index 2c28353e..3f9d6ab6 100644
--- a/Accounts/tictacthor/workflows/src/main/java/com/tictacthor/flows/EndGameFlow.java
+++ b/Accounts/tictacthor/workflows/src/main/java/net/corda/samples/tictacthor/flows/EndGameFlow.java
@@ -1,4 +1,4 @@
-package com.tictacthor.flows;
+package net.corda.samples.tictacthor.flows;
import co.paralleluniverse.fibers.Suspendable;
import com.r3.corda.lib.accounts.contracts.states.AccountInfo;
@@ -6,9 +6,10 @@
import com.r3.corda.lib.accounts.workflows.flows.RequestKeyForAccount;
import com.r3.corda.lib.accounts.workflows.services.KeyManagementBackedAccountService;
import com.sun.istack.NotNull;
-import com.tictacthor.accountUtilities.NewKeyForAccount;
-import com.tictacthor.contracts.BoardContract;
-import com.tictacthor.states.BoardState;
+import net.corda.core.identity.CordaX500Name;
+import net.corda.samples.tictacthor.accountUtilities.NewKeyForAccount;
+import net.corda.samples.tictacthor.contracts.BoardContract;
+import net.corda.samples.tictacthor.states.BoardState;
import net.corda.core.contracts.StateAndRef;
import net.corda.core.contracts.UniqueIdentifier;
import net.corda.core.crypto.TransactionSignature;
@@ -20,6 +21,7 @@
import net.corda.core.transactions.SignedTransaction;
import net.corda.core.transactions.TransactionBuilder;
import net.corda.core.utilities.ProgressTracker;
+
import java.security.PublicKey;
import java.util.Arrays;
import java.util.List;
@@ -93,13 +95,8 @@ public String call() throws FlowException {
//generating State for transfer
// Obtain a reference to a notary we wish to use.
- /** METHOD 1: Take first notary on network, WARNING: use for test, non-prod environments, and single-notary networks only!*
- * METHOD 2: Explicit selection of notary by CordaX500Name - argument can by coded in flow or parsed from config (Preferred)
- *
- * * - For production you always want to use Method 2 as it guarantees the expected notary is returned.
- */
- final Party notary = getServiceHub().getNetworkMapCache().getNotaryIdentities().get(0); // METHOD 1
- // final Party notary = getServiceHub().getNetworkMapCache().getNotary(CordaX500Name.parse("O=Notary,L=London,C=GB")); // METHOD 2
+ /** Explicit selection of notary by CordaX500Name - argument can by coded in flows or parsed from config (Preferred)*/
+ Party notary = inputBoardStateAndRef.getState().getNotary();
TransactionBuilder txbuilder = new TransactionBuilder(notary)
.addInputState(inputBoardStateAndRef)
diff --git a/Accounts/tictacthor/workflows/src/main/java/net/corda/samples/tictacthor/flows/StartGameFlow.java b/Accounts/tictacthor/workflows/src/main/java/net/corda/samples/tictacthor/flows/StartGameFlow.java
new file mode 100644
index 00000000..76ba4367
--- /dev/null
+++ b/Accounts/tictacthor/workflows/src/main/java/net/corda/samples/tictacthor/flows/StartGameFlow.java
@@ -0,0 +1,147 @@
+package net.corda.samples.tictacthor.flows;
+
+import co.paralleluniverse.fibers.Suspendable;
+import com.r3.corda.lib.accounts.contracts.states.AccountInfo;
+import com.r3.corda.lib.accounts.workflows.services.AccountService;
+import com.r3.corda.lib.accounts.workflows.flows.RequestKeyForAccount;
+import com.r3.corda.lib.accounts.workflows.services.KeyManagementBackedAccountService;
+import com.sun.istack.NotNull;
+import net.corda.core.identity.CordaX500Name;
+import net.corda.samples.tictacthor.accountUtilities.NewKeyForAccount;
+import net.corda.samples.tictacthor.contracts.BoardContract;
+import net.corda.samples.tictacthor.states.BoardState;
+import net.corda.core.contracts.StateAndRef;
+import net.corda.core.contracts.UniqueIdentifier;
+import net.corda.core.crypto.TransactionSignature;
+import net.corda.core.flows.*;
+import net.corda.core.identity.AnonymousParty;
+import net.corda.core.identity.Party;
+import net.corda.core.node.services.vault.QueryCriteria;
+import net.corda.core.transactions.SignedTransaction;
+import net.corda.core.transactions.TransactionBuilder;
+import net.corda.core.utilities.ProgressTracker;
+
+import java.security.PublicKey;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
+// ******************
+// * Initiator flow *
+// ******************
+@InitiatingFlow
+@StartableByRPC
+public class StartGameFlow extends FlowLogic {
+
+ private final ProgressTracker progressTracker = tracker();
+
+ private static final ProgressTracker.Step GENERATING_TRANSACTION = new ProgressTracker.Step("Generating a HeartState transaction");
+ private static final ProgressTracker.Step SIGNING_TRANSACTION = new ProgressTracker.Step("Signing transaction with our private key.");
+ private static final ProgressTracker.Step FINALISING_TRANSACTION = new ProgressTracker.Step("Recording transaction") {
+ @Override
+ public ProgressTracker childProgressTracker() {
+ return FinalityFlow.tracker();
+ }
+ };
+
+ private static ProgressTracker tracker() {
+ return new ProgressTracker(
+ GENERATING_TRANSACTION,
+ SIGNING_TRANSACTION,
+ FINALISING_TRANSACTION
+ );
+ }
+
+ @Override
+ public ProgressTracker getProgressTracker() {
+ return progressTracker;
+ }
+
+ //private variables
+ private String whoAmI ;
+ private String whereTo;
+
+ //public constructor
+ public StartGameFlow(String whoAmI, String whereTo){
+ this.whoAmI = whoAmI;
+ this.whereTo = whereTo;
+ }
+
+ @Suspendable
+ @Override
+ public UniqueIdentifier call() throws FlowException {
+ //grab account service
+ AccountService accountService = getServiceHub().cordaService(KeyManagementBackedAccountService.class);
+ //grab the account information
+ AccountInfo myAccount = accountService.accountInfo(whoAmI).get(0).getState().getData();
+ PublicKey myKey = subFlow(new NewKeyForAccount(myAccount.getIdentifier().getId())).getOwningKey();
+
+ AccountInfo targetAccount = accountService.accountInfo(whereTo).get(0).getState().getData();
+ AnonymousParty targetAcctAnonymousParty = subFlow(new RequestKeyForAccount(targetAccount));
+
+ //check if this account is in another game
+ QueryCriteria.VaultQueryCriteria criteria = new QueryCriteria.VaultQueryCriteria().withExternalIds(Arrays.asList(myAccount.getIdentifier().getId()));
+ List> results = getServiceHub().getVaultService().queryBy(BoardState.class,criteria).getStates();
+ if(results.size() != 0){
+ throw new IllegalArgumentException("You are in another game");
+ }
+
+ progressTracker.setCurrentStep(GENERATING_TRANSACTION);
+ //generating State for transfer
+ BoardState initialBoardState = new BoardState(myAccount.getIdentifier(),
+ targetAccount.getIdentifier(),
+ new AnonymousParty(myKey),
+ targetAcctAnonymousParty);
+
+ // Obtain a reference to a notary we wish to use.
+ /** Explicit selection of notary by CordaX500Name - argument can by coded in flows or parsed from config (Preferred)*/
+ final Party notary = getServiceHub().getNetworkMapCache().getNotary(CordaX500Name.parse("O=Notary,L=London,C=GB"));
+
+ TransactionBuilder txbuilder = new TransactionBuilder(notary)
+ .addOutputState(initialBoardState)
+ .addCommand(new BoardContract.Commands.StartGame(),Arrays.asList(myKey,targetAcctAnonymousParty.getOwningKey()));
+
+
+ progressTracker.setCurrentStep(SIGNING_TRANSACTION);
+ //self verify and sign Transaction
+ txbuilder.verify(getServiceHub());
+ SignedTransaction locallySignedTx = getServiceHub().signInitialTransaction(txbuilder,Arrays.asList(getOurIdentity().getOwningKey(),myKey));
+
+ //Collect sigs
+ FlowSession sessionForAccountToSendTo = initiateFlow(targetAccount.getHost());
+ List accountToMoveToSignature = (List) subFlow(new CollectSignatureFlow(locallySignedTx,
+ sessionForAccountToSendTo,targetAcctAnonymousParty.getOwningKey()));
+ SignedTransaction signedByCounterParty = locallySignedTx.withAdditionalSignatures(accountToMoveToSignature);
+ progressTracker.setCurrentStep(FINALISING_TRANSACTION);
+ //Finalize
+ subFlow(new FinalityFlow(signedByCounterParty,
+ Arrays.asList(sessionForAccountToSendTo).stream().filter(it -> it.getCounterparty() != getOurIdentity()).collect(Collectors.toList())));
+ return initialBoardState.getLinearId();
+ }
+}
+
+
+@InitiatedBy(StartGameFlow.class)
+class StartGameFlowResponder extends FlowLogic {
+ //private variable
+ private FlowSession counterpartySession;
+
+ //Constructor
+ public StartGameFlowResponder(FlowSession counterpartySession) {
+ this.counterpartySession = counterpartySession;
+ }
+
+ @Override
+ @Suspendable
+ public Void call() throws FlowException {
+ subFlow(new SignTransactionFlow(counterpartySession) {
+ @Override
+ protected void checkTransaction(@NotNull SignedTransaction stx) throws FlowException {
+ // Custom Logic to validate transaction.
+ }
+ });
+ subFlow(new ReceiveFinalityFlow(counterpartySession));
+ return null;
+ }
+}
+
diff --git a/Accounts/tictacthor/workflows/src/main/java/com/tictacthor/flows/SubmitTurnFlow.java b/Accounts/tictacthor/workflows/src/main/java/net/corda/samples/tictacthor/flows/SubmitTurnFlow.java
similarity index 88%
rename from Accounts/tictacthor/workflows/src/main/java/com/tictacthor/flows/SubmitTurnFlow.java
rename to Accounts/tictacthor/workflows/src/main/java/net/corda/samples/tictacthor/flows/SubmitTurnFlow.java
index f607f01e..477f3a6a 100644
--- a/Accounts/tictacthor/workflows/src/main/java/com/tictacthor/flows/SubmitTurnFlow.java
+++ b/Accounts/tictacthor/workflows/src/main/java/net/corda/samples/tictacthor/flows/SubmitTurnFlow.java
@@ -1,4 +1,4 @@
-package com.tictacthor.flows;
+package net.corda.samples.tictacthor.flows;
import co.paralleluniverse.fibers.Suspendable;
import com.r3.corda.lib.accounts.contracts.states.AccountInfo;
@@ -6,9 +6,9 @@
import com.r3.corda.lib.accounts.workflows.flows.RequestKeyForAccount;
import com.r3.corda.lib.accounts.workflows.services.KeyManagementBackedAccountService;
import com.sun.istack.NotNull;
-import com.tictacthor.accountUtilities.NewKeyForAccount;
-import com.tictacthor.contracts.BoardContract;
-import com.tictacthor.states.BoardState;
+import net.corda.samples.tictacthor.accountUtilities.NewKeyForAccount;
+import net.corda.samples.tictacthor.contracts.BoardContract;
+import net.corda.samples.tictacthor.states.BoardState;
//import javafx.util.Pair;
import kotlin.Pair;
import net.corda.core.contracts.StateAndRef;
@@ -22,10 +22,10 @@
import net.corda.core.transactions.SignedTransaction;
import net.corda.core.transactions.TransactionBuilder;
import net.corda.core.utilities.ProgressTracker;
+
import java.security.PublicKey;
import java.util.Arrays;
import java.util.List;
-import java.util.UUID;
import java.util.stream.Collectors;
// ******************
@@ -106,13 +106,7 @@ public String call() throws FlowException {
BoardState outputBoardState = inputBoardState.returnNewBoardAfterMove(new Pair<>(x,y),new AnonymousParty(myKey), targetAcctAnonymousParty);
// Obtain a reference to a notary we wish to use.
- /** METHOD 1: Take first notary on network, WARNING: use for test, non-prod environments, and single-notary networks only!*
- * METHOD 2: Explicit selection of notary by CordaX500Name - argument can by coded in flow or parsed from config (Preferred)
- *
- * * - For production you always want to use Method 2 as it guarantees the expected notary is returned.
- */
- final Party notary = getServiceHub().getNetworkMapCache().getNotaryIdentities().get(0); // METHOD 1
- // final Party notary = getServiceHub().getNetworkMapCache().getNotary(CordaX500Name.parse("O=Notary,L=London,C=GB")); // METHOD 2
+ Party notary = inputBoardStateAndRef.getState().getNotary();
TransactionBuilder txbuilder = new TransactionBuilder(notary)
.addInputState(inputBoardStateAndRef)
diff --git a/Accounts/tictacthor/workflows/src/main/java/net/corda/samples/tictacthor/flows/SyncGame.java b/Accounts/tictacthor/workflows/src/main/java/net/corda/samples/tictacthor/flows/SyncGame.java
new file mode 100644
index 00000000..2703fc3a
--- /dev/null
+++ b/Accounts/tictacthor/workflows/src/main/java/net/corda/samples/tictacthor/flows/SyncGame.java
@@ -0,0 +1,44 @@
+package net.corda.samples.tictacthor.flows;
+
+import co.paralleluniverse.fibers.Suspendable;
+import net.corda.samples.tictacthor.states.BoardState;
+import net.corda.core.contracts.StateAndRef;
+import net.corda.core.flows.FlowException;
+import net.corda.core.flows.FlowLogic;
+import net.corda.core.flows.StartableByRPC;
+import net.corda.core.flows.StartableByService;
+import net.corda.core.identity.Party;
+import net.corda.core.node.services.Vault;
+import net.corda.core.node.services.vault.QueryCriteria;
+import com.r3.corda.lib.accounts.workflows.flows.ShareStateAndSyncAccounts;
+
+import java.util.*;
+
+@StartableByRPC
+@StartableByService
+public class SyncGame extends FlowLogic{
+ private String gameId;
+ private Party party;
+
+ public SyncGame(String gameId, Party party) {
+ this.gameId = gameId;
+ this.party = party;
+ }
+
+ @Override
+ @Suspendable
+ public String call() throws FlowException {
+
+ UUID id = UUID.fromString(gameId);
+ QueryCriteria.LinearStateQueryCriteria queryCriteria = new QueryCriteria.LinearStateQueryCriteria()
+ .withUuid(Arrays.asList(id)).withStatus(Vault.StateStatus.UNCONSUMED);
+ try {
+ StateAndRef inputBoardStateAndRef = getServiceHub().getVaultService().queryBy(BoardState.class,queryCriteria).getStates().get(0);
+ subFlow(new ShareStateAndSyncAccounts(inputBoardStateAndRef,party));
+
+ }catch (Exception e){
+ throw new FlowException("GameState with id "+gameId+" not found.");
+ }
+ return "Game synced";
+ }
+}
\ No newline at end of file
diff --git a/Accounts/tictacthor/workflows/src/test/java/com/tictacthor/ContractTests.java b/Accounts/tictacthor/workflows/src/test/java/com/tictacthor/ContractTests.java
deleted file mode 100644
index 8f97c2d1..00000000
--- a/Accounts/tictacthor/workflows/src/test/java/com/tictacthor/ContractTests.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package com.tictacthor;
-
-import net.corda.testing.node.MockServices;
-import org.junit.Test;
-
-public class ContractTests {
- private final MockServices ledgerServices = new MockServices();
-
- @Test
- public void dummyTest() {
-
- }
-}
\ No newline at end of file
diff --git a/Accounts/tictacthor/workflows/src/test/java/com/tictacthor/FlowTests.java b/Accounts/tictacthor/workflows/src/test/java/com/tictacthor/FlowTests.java
deleted file mode 100644
index 4590d2db..00000000
--- a/Accounts/tictacthor/workflows/src/test/java/com/tictacthor/FlowTests.java
+++ /dev/null
@@ -1,37 +0,0 @@
-package com.tictacthor;
-
-import com.google.common.collect.ImmutableList;
-import net.corda.testing.node.MockNetwork;
-import net.corda.testing.node.MockNetworkParameters;
-import net.corda.testing.node.StartedMockNode;
-import net.corda.testing.node.TestCordapp;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-public class FlowTests {
- private final MockNetwork network = new MockNetwork(new MockNetworkParameters(ImmutableList.of(
- TestCordapp.findCordapp("com.tictacthor.contracts"),
- TestCordapp.findCordapp("com.tictacthor.flows")
- )));
- private final StartedMockNode a = network.createNode();
- private final StartedMockNode b = network.createNode();
-
- public FlowTests() {
- }
-
- @Before
- public void setup() {
- network.runNetwork();
- }
-
- @After
- public void tearDown() {
- network.stopNodes();
- }
-
- @Test
- public void dummyTest() {
-
- }
-}
diff --git a/Accounts/tictacthor/workflows/src/test/java/com/tictacthor/NodeDriver.java b/Accounts/tictacthor/workflows/src/test/java/com/tictacthor/NodeDriver.java
deleted file mode 100644
index 3a4a2613..00000000
--- a/Accounts/tictacthor/workflows/src/test/java/com/tictacthor/NodeDriver.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package com.tictacthor;
-
-import com.google.common.collect.ImmutableList;
-import net.corda.core.identity.CordaX500Name;
-import net.corda.testing.driver.DriverParameters;
-import net.corda.testing.driver.NodeParameters;
-import net.corda.testing.node.User;
-import com.google.common.collect.ImmutableSet;
-
-import java.util.List;
-import static net.corda.testing.driver.Driver.driver;
-
-/**
- * Allows you to run your nodes through an IDE (as opposed to using deployNodes). Do not use in a production
- * environment.
- */
-public class NodeDriver {
- public static void main(String[] args) {
- final List rpcUsers =
- ImmutableList.of(new User("user1", "test", ImmutableSet.of("ALL")));
-
- driver(new DriverParameters().withStartNodesInProcess(true).withWaitForAllNodesToFinish(true), dsl -> {
- try {
- dsl.startNode(new NodeParameters()
- .withProvidedName(new CordaX500Name("PartyA", "London", "GB"))
- .withRpcUsers(rpcUsers)).get();
- dsl.startNode(new NodeParameters()
- .withProvidedName(new CordaX500Name("PartyB", "New York", "US"))
- .withRpcUsers(rpcUsers)).get();
- } catch (Throwable e) {
- System.err.println("Encountered exception in node startup: " + e.getMessage());
- e.printStackTrace();
- }
-
- return null;
- }
- );
- }
-}
diff --git a/Accounts/tictacthor/workflows/src/test/java/net/corda/samples/tictacthor/FlowTests.java b/Accounts/tictacthor/workflows/src/test/java/net/corda/samples/tictacthor/FlowTests.java
new file mode 100644
index 00000000..71f10d38
--- /dev/null
+++ b/Accounts/tictacthor/workflows/src/test/java/net/corda/samples/tictacthor/FlowTests.java
@@ -0,0 +1,95 @@
+package net.corda.samples.tictacthor;
+
+import com.google.common.collect.ImmutableList;
+import com.r3.corda.lib.accounts.contracts.states.AccountInfo;
+import com.r3.corda.lib.accounts.workflows.services.AccountService;
+import com.r3.corda.lib.accounts.workflows.services.KeyManagementBackedAccountService;
+import net.corda.core.contracts.StateAndRef;
+import net.corda.core.contracts.UniqueIdentifier;
+import net.corda.core.identity.CordaX500Name;
+import net.corda.core.node.NetworkParameters;
+import net.corda.core.node.services.vault.QueryCriteria;
+import net.corda.samples.tictacthor.accountUtilities.CreateNewAccount;
+import net.corda.samples.tictacthor.accountUtilities.ShareAccountTo;
+import net.corda.samples.tictacthor.flows.StartGameFlow;
+import net.corda.samples.tictacthor.states.BoardState;
+import net.corda.testing.node.*;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.*;
+import java.time.Instant;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+public class FlowTests {
+ private MockNetwork network;
+ private StartedMockNode a;
+ private StartedMockNode b;
+
+
+ private NetworkParameters testNetworkParameters =
+ new NetworkParameters(4, Arrays.asList(), 10485760, (10485760 * 5), Instant.now(),1, new LinkedHashMap<>());
+
+ @Before
+ public void setup() {
+
+ network = new MockNetwork(new MockNetworkParameters().withCordappsForAllNodes(ImmutableList.of(
+ TestCordapp.findCordapp("net.corda.samples.tictacthor.contracts"),
+ TestCordapp.findCordapp("net.corda.samples.tictacthor.flows"),
+ TestCordapp.findCordapp("com.r3.corda.lib.accounts.contracts"),
+ TestCordapp.findCordapp("com.r3.corda.lib.accounts.workflows"))).withNetworkParameters(testNetworkParameters)
+ .withNotarySpecs(ImmutableList.of(new MockNetworkNotarySpec(CordaX500Name.parse("O=Notary,L=London,C=GB"))))
+ );
+ a = network.createPartyNode(null);
+ b = network.createPartyNode(null);
+ network.runNetwork();
+ }
+
+ @After
+ public void tearDown() {
+ network.stopNodes();
+ }
+
+ @Test
+ public void AccountCreation() throws ExecutionException, InterruptedException {
+ CreateNewAccount createAcct = new CreateNewAccount("TestAccountA");
+ Future future = a.startFlow(createAcct);
+ network.runNetwork();
+ AccountService accountService = a.getServices().cordaService(KeyManagementBackedAccountService.class);
+ List> myAccount = accountService.accountInfo("TestAccountA");
+ assert (myAccount.size() != 0);
+ }
+
+ @Test
+ public void CreateGameTest() throws ExecutionException, InterruptedException {
+ CreateNewAccount createAcct = new CreateNewAccount("TestAccountA");
+ Future future = a.startFlow(createAcct);
+ network.runNetwork();
+ ShareAccountTo shareAToB = new ShareAccountTo("TestAccountA",b.getInfo().getLegalIdentities().get(0));
+ Future future2 = a.startFlow(shareAToB);
+ network.runNetwork();
+
+ CreateNewAccount createAcct2 = new CreateNewAccount("TestAccountB");
+ Future future3 = b.startFlow(createAcct2);
+ network.runNetwork();
+
+ ShareAccountTo shareBToA = new ShareAccountTo("TestAccountB",a.getInfo().getLegalIdentities().get(0));
+ Future future4 = b.startFlow(shareBToA);
+ network.runNetwork();
+
+ StartGameFlow startGame = new StartGameFlow("TestAccountA","TestAccountB");
+ Future future5 = a.startFlow(startGame);
+ network.runNetwork();
+
+ AccountService accountService = b.getServices().cordaService(KeyManagementBackedAccountService.class);
+ AccountInfo myAccount = accountService.accountInfo("TestAccountB").get(0).getState().getData();
+ QueryCriteria.VaultQueryCriteria criteria = new QueryCriteria.VaultQueryCriteria().withExternalIds(Arrays.asList(myAccount.getIdentifier().getId()));
+ List> storedGame = b.getServices().getVaultService().queryBy(BoardState.class,criteria).getStates();
+ assert (storedGame.size() != 0);
+
+ }
+
+
+}
diff --git a/Accounts/worldcupticketbooking/README.md b/Accounts/worldcupticketbooking/README.md
index 43a276e2..324533db 100644
--- a/Accounts/worldcupticketbooking/README.md
+++ b/Accounts/worldcupticketbooking/README.md
@@ -1,4 +1,4 @@
-# T20 Cricket World Cup Ticket Booking Cordapp [
](https://ide.corda.net/?folder=/home/coder/samples-java/Accounts/worldcupticketbooking)
+# T20 Cricket World Cup Ticket Booking CorDapp
## Introduction
@@ -11,10 +11,10 @@ of the tickets on Corda Platform.
Nodes:
* BCCI node: source of ticket creation. All the tickets in the market are created by this node.
-* Bank Node: souce of money. All the money that is transacted between each individual is issued by this node.
+* Bank Node: source of money. All the money that is transacted between each individual is issued by this node.
* Dealer1 Node: Dealer Agency 1 and it includes
- * agent1 account: who will get ticket from the BCCI and sell to others. (To demostrate same node account token transaction.)
- * buyer1 account: who will get the ticket from agent1 and later sell to buyer3 (To demostrate cross node account token transaction)
+ * agent1 account: who will get ticket from the BCCI and sell to others. (To demonstrate same node account token transaction.)
+ * buyer1 account: who will get the ticket from agent1 and later sell to buyer3 (To demonstrate cross node account token transaction)
* buyer2 account: who will buy the ticket from buyer3.
* Dealer2 Node: Dealer Agency 2 and it includes
* buyer3 account: who will get the ticket from buyer1 and sell to buyer2
@@ -23,41 +23,49 @@ Nodes:
+## Pre-Requisites
+
+For development environment setup, please refer to: [Setup Guide](https://docs.r3.com/en/platform/corda/4.9/community/getting-set-up.html).
+
+## Running the sample
+Deploy and run the nodes by:
+```
+./gradlew clean build deployNodes
+./build/nodes/runnodes
+```
### Step 1
+Run the below flow in Dealer1's interactive node shell. This will create the agent1, buyer1 and buyer2 accounts on the Dealer1 node and share this account info with BCCI, Bank, and Dealer2 node respectively.
```
flow start CreateAndShareAccountFlow accountName: agent1, partyToShareAccountInfoToList: [BCCI, Dealer2]
flow start CreateAndShareAccountFlow accountName: buyer1, partyToShareAccountInfoToList: [Bank, Dealer2]
flow start CreateAndShareAccountFlow accountName: buyer2, partyToShareAccountInfoToList: [Bank, Dealer2]
```
-Run the above flow on the Dealer1 node. This will create the agent1, buyer1 and buyer2 accounts on the Dealer1 node and share this account info with BCCI, Bank, and Dealer2 node respecticely.
-Then let's go to the Dealer2 node and create buyer3 account:
+Then let's go to the Dealer2 interactive node shell and create buyer3 account:
```
flow start CreateAndShareAccountFlow accountName: buyer3, partyToShareAccountInfoToList: [Bank, Dealer1]
```
-Run the below query to confirm if accounts are created on Dealer1 node. Also run the above query on Bank and BCCI node to confirm if account info is shared with these nodes.
+Run the below query to confirm if accounts are created on Dealer1 node. Also run the below query on Bank and BCCI's interactive node shell to confirm if account info is shared with these nodes.
run vaultQuery contractStateType : com.r3.corda.lib.accounts.contracts.states.AccountInfo
-
-
### Step 2
+Run the below command on the Bank's interactive node shell, which will issue 20 USD to buyer1 account.
```
start IssueCashFlow accountName : buyer1 , currency : USD , amount : 10
start IssueCashFlow accountName : buyer3 , currency : USD , amount : 20
start IssueCashFlow accountName : buyer2 , currency : USD , amount : 50
```
-Run the above command on the Bank node, which will issue 20 USD to buyer1 account.
### Step 3
```
flow start QuerybyAccount whoAmI: buyer1
```
-You can check balance of buyer1 account at Dealer1's node
-[Option] You can also run the below command to confirm if 20 USD fungible tokens are stored at Dealer1's node. The current holder field in the output will be an [AnonymousParty](https://docs.corda.net/docs/corda-os/4.4/api-identity.html#party) which specifies an account.
+You can check balance of buyer1 account at Dealer1's interactive node shell.
+[Option] You can also run the below command to confirm if 20 USD fungible tokens are stored at Dealer1's node. The current holder field in the output will be an [AnonymousParty](https://docs.r3.com/en/platform/corda/4.9/community/api-identity.html) which specifies an account.
```
run vaultQuery contractStateType : com.r3.corda.lib.tokens.contracts.states.FungibleToken
```
@@ -65,25 +73,27 @@ run vaultQuery contractStateType : com.r3.corda.lib.tokens.contracts.states.Fung
### Step 4
+Run the below flow on BCCI's node. BCCI node will create base token type for the T20 Ticket for the match MumbaiIndians Vs RajasthanRoyals. The ticket ID returned from this flow will be needed in the next steps.
+
start CreateT20CricketTicketTokenFlow ticketTeam : MumbaiIndiansVsRajasthanRoyals
-Run the above flow on BCCI's node. BCCI node will create base token type for the T20 Ticket for the match MumbaiIndians Vs RajasthanRoyals. The ticket ID returned from this flow will be needed in the next steps.
-You can see your ticket state generated via vault query at the BCCI'd node:
+You can see your ticket state generated via vault query at the BCCI's node:
run vaultQuery contractStateType : com.t20worldcup.states.T20CricketTicket
### Step 5
+Run the below flow on BCCI's node to issue a non-fungible token based off the token type which we created in Step5. You will need to replace the `` with the uuid returned from step 6. This token will be issued by the BCCI node to agent1 account on Dealer1 node.
+
start IssueNonFungibleTicketFlow tokenId : , dealerAccountName : agent1
-Run the above flow on BCCI's node to issue a non fungible token based off the token type which we created in Step5. You will need to replace the `` with the uuid returned from step 6. This token will be issued by the BCCI node to dealer1 account on Dealer1 node.
Switching to the Dealer1's node, you can run the following code to confirm if the token has been issued to the dealer1 account.
```
flow start QuerybyAccount whoAmI: agent1
```
-You can also look for the acutal state that is recoreded by:
+You can also look for the actual state that is recorded by:
run vaultQuery contractStateType : com.r3.corda.lib.tokens.contracts.states.NonFungibleToken
Note that, the current holder it will be a key representing the account.
@@ -97,7 +107,7 @@ flow start DVPAccountsOnSameNode tokenId: , buyerAccountName
This is the DVP flow where the buyer(buyer1 account on Dealer1 node) account will pay cash to seller account(agent1 account on Dealer1 node), and the seller account will transfer the ticket token to the buyer. Again, replace the `` with the uuid generated in step 6.
### Step 7
-Now lets continue the flow logic to intiate an ticket sale between buyer1 and buyer3. Go to Dealer2 node and run the following code:
+Now let's continue the flow logic to initiate a ticket sale between buyer1 and buyer3. Go to Dealer2 node and run the following code:
```
flow start DVPAccountsHostedOnDifferentNodes tokenId: , buyerAccountName: buyer3, sellerAccountName: buyer1, costOfTicket: 10, currency: USD
@@ -130,30 +140,32 @@ For someone who is looking into how to only transfer tokens from one account to
### Step 1
+Run the below flow on the Dealer1 node. This will create the agent1, buyer1 and buyer2 accounts on the Dealer1 node and share this account info with BCCI, Bank, and Dealer2 node respectively.
+
```
flow start CreateAndShareAccountFlow accountName: agent1, partyToShareAccountInfoToList: [BCCI, Dealer2]
flow start CreateAndShareAccountFlow accountName: buyer1, partyToShareAccountInfoToList: [Bank, Dealer2]
flow start CreateAndShareAccountFlow accountName: buyer2, partyToShareAccountInfoToList: [Bank, Dealer2]
```
-Run the above flow on the Dealer1 node. This will create the agent1, buyer1 and buyer2 accounts on the Dealer1 node and share this account info with BCCI, Bank, and Dealer2 node respecticely.
Then let's go to the Dealer2 node and create buyer3 account:
```
flow start CreateAndShareAccountFlow accountName: buyer3, partyToShareAccountInfoToList: [Bank, Dealer1]
```
-Run the below query to confirm if accounts are created on Dealer1 node. Also run the above query on Bank and BCCI node to confirm if account info is shared with these nodes.
+Run the below query to confirm if accounts are created on Dealer1 node. Also run the below query on Bank and BCCI node to confirm if account info is shared with these nodes.
run vaultQuery contractStateType : com.r3.corda.lib.accounts.contracts.states.AccountInfo
### Step 2
+Run the below command on the Bank node, which will issue 77 USD to buyer1 account.
+
```
start IssueCashFlow accountName : buyer1 , currency : USD , amount : 77
```
-Run the above command on the Bank node, which will issue 77 USD to buyer1 account.
### Step 3
```
diff --git a/Accounts/worldcupticketbooking/build.gradle b/Accounts/worldcupticketbooking/build.gradle
index 450b1cf5..e567053f 100644
--- a/Accounts/worldcupticketbooking/build.gradle
+++ b/Accounts/worldcupticketbooking/build.gradle
@@ -36,10 +36,10 @@ buildscript {
repositories {
mavenLocal()
mavenCentral()
- jcenter()
- maven { url 'https://ci-artifactory.corda.r3cev.com/artifactory/corda-releases' }
- // maven { url 'http://ci-artifactory.corda.r3cev.com/artifactory/corda-lib-dev' }
- maven { url 'http://ci-artifactory.corda.r3cev.com/artifactory/corda-lib' }
+
+ maven { url 'https://download.corda.net/maven/corda-releases' }
+ // maven { url 'http://software.r3.com/artifactory/corda-lib-dev' }
+ maven { url 'http://software.r3.com/artifactory/corda-lib' }
}
dependencies {
@@ -57,12 +57,12 @@ allprojects {
repositories {
mavenLocal()
- jcenter()
+
mavenCentral()
- maven { url 'https://ci-artifactory.corda.r3cev.com/artifactory/corda' }
+ maven { url 'https://download.corda.net/maven/corda-dependencies' }
// Can be removed post-release - used to get nightly snapshot build.
- maven { url 'https://ci-artifactory.corda.r3cev.com/artifactory/corda-lib' }
- maven { url 'https://ci-artifactory.corda.r3cev.com/artifactory/corda-lib-dev' }
+ maven { url 'https://download.corda.net/maven/corda-lib' }
+ maven { url 'https://download.corda.net/maven/corda-lib-dev' }
// maven { url 'https://jitpack.io' }
maven { url "https://repo.gradle.org/gradle/libs-releases-local" }
}
@@ -107,6 +107,7 @@ dependencies {
cordaCompile "org.apache.logging.log4j:log4j-slf4j-impl:${log4j_version}"
cordaCompile "org.apache.logging.log4j:log4j-web:${log4j_version}"
cordaCompile "org.slf4j:jul-to-slf4j:$slf4j_version"
+ cordaDriver "net.corda:corda-shell:4.10"
//accounts
cordapp "$accounts_release_group:accounts-contracts:$accounts_release_version"
diff --git a/Accounts/worldcupticketbooking/clients/build.gradle b/Accounts/worldcupticketbooking/clients/build.gradle
index bfed0e1f..c6be5398 100644
--- a/Accounts/worldcupticketbooking/clients/build.gradle
+++ b/Accounts/worldcupticketbooking/clients/build.gradle
@@ -8,6 +8,12 @@ sourceSets {
}
}
+configurations {
+ all {
+ exclude group: 'ch.qos.logback', module: 'logback-classic'
+ }
+}
+
dependencies {
// Corda dependencies.
compile "$corda_release_group:corda-rpc:$corda_release_version"
diff --git a/Accounts/worldcupticketbooking/repositories.gradle b/Accounts/worldcupticketbooking/repositories.gradle
index 64f5d567..072b616b 100644
--- a/Accounts/worldcupticketbooking/repositories.gradle
+++ b/Accounts/worldcupticketbooking/repositories.gradle
@@ -1,10 +1,10 @@
repositories {
mavenLocal()
mavenCentral()
- jcenter()
+
maven { url 'https://jitpack.io' }
- maven { url 'https://ci-artifactory.corda.r3cev.com/artifactory/corda' }
+ maven { url 'https://download.corda.net/maven/corda-dependencies' }
maven { url 'https://repo.gradle.org/gradle/libs-releases' }
- maven { url 'http://ci-artifactory.corda.r3cev.com/artifactory/corda-lib-dev' }
- maven { url 'http://ci-artifactory.corda.r3cev.com/artifactory/corda-lib' }
+ maven { url 'http://software.r3.com/artifactory/corda-lib-dev' }
+ maven { url 'http://software.r3.com/artifactory/corda-lib' }
}
diff --git a/Accounts/worldcupticketbooking/workflows/src/main/java/com/t20worldcup/flows/CreateT20CricketTicketTokenFlow.java b/Accounts/worldcupticketbooking/workflows/src/main/java/com/t20worldcup/flows/CreateT20CricketTicketTokenFlow.java
index fd119752..f75f0d25 100644
--- a/Accounts/worldcupticketbooking/workflows/src/main/java/com/t20worldcup/flows/CreateT20CricketTicketTokenFlow.java
+++ b/Accounts/worldcupticketbooking/workflows/src/main/java/com/t20worldcup/flows/CreateT20CricketTicketTokenFlow.java
@@ -11,6 +11,7 @@
import net.corda.core.flows.StartableByRPC;
import net.corda.core.identity.Party;
import net.corda.core.transactions.SignedTransaction;
+import net.corda.core.identity.CordaX500Name;
/**
* This flow should be run by BCCI node. BCCI node will take care of issuing the base token type for the Ipl ticket. The token type will be craeted on the BCCI node
@@ -31,13 +32,8 @@ public CreateT20CricketTicketTokenFlow(String ticketTeam) {
@Suspendable
public String call() throws FlowException {
// Obtain a reference to a notary we wish to use.
- /** METHOD 1: Take first notary on network, WARNING: use for test, non-prod environments, and single-notary networks only!*
- * METHOD 2: Explicit selection of notary by CordaX500Name - argument can by coded in flow or parsed from config (Preferred)
- *
- * * - For production you always want to use Method 2 as it guarantees the expected notary is returned.
- */
- final Party notary = getServiceHub().getNetworkMapCache().getNotaryIdentities().get(0); // METHOD 1
- // final Party notary = getServiceHub().getNetworkMapCache().getNotary(CordaX500Name.parse("O=Notary,L=London,C=GB")); // METHOD 2
+ /** Explicit selection of notary by CordaX500Name - argument can by coded in flows or parsed from config (Preferred)*/
+ final Party notary = getServiceHub().getNetworkMapCache().getNotary(CordaX500Name.parse("O=Notary,L=London,C=GB"));
//create token type by passing in the name of the ipl match. specify the maintainer as BCCI
UniqueIdentifier id = new UniqueIdentifier();
diff --git a/Accounts/worldcupticketbooking/workflows/src/main/java/com/t20worldcup/flows/DVPAccountsHostedOnDifferentNodes.java b/Accounts/worldcupticketbooking/workflows/src/main/java/com/t20worldcup/flows/DVPAccountsHostedOnDifferentNodes.java
index cb862e8d..39243ab4 100644
--- a/Accounts/worldcupticketbooking/workflows/src/main/java/com/t20worldcup/flows/DVPAccountsHostedOnDifferentNodes.java
+++ b/Accounts/worldcupticketbooking/workflows/src/main/java/com/t20worldcup/flows/DVPAccountsHostedOnDifferentNodes.java
@@ -229,13 +229,7 @@ public Void call() throws FlowException {
TokenPointer tokenPointer = evolvableTokenType.toPointer(evolvableTokenType.getClass());
// Obtain a reference to a notary we wish to use.
- /** METHOD 1: Take first notary on network, WARNING: use for test, non-prod environments, and single-notary networks only!*
- * METHOD 2: Explicit selection of notary by CordaX500Name - argument can by coded in flow or parsed from config (Preferred)
- *
- * * - For production you always want to use Method 2 as it guarantees the expected notary is returned.
- */
- final Party notary = getServiceHub().getNetworkMapCache().getNotaryIdentities().get(0); // METHOD 1
- // final Party notary = getServiceHub().getNetworkMapCache().getNotary(CordaX500Name.parse("O=Notary,L=London,C=GB")); // METHOD 2
+ Party notary = stateAndRef.getState().getNotary();
TransactionBuilder transactionBuilder = new TransactionBuilder(notary);
diff --git a/Accounts/worldcupticketbooking/workflows/src/main/java/com/t20worldcup/flows/DVPAccountsOnSameNode.java b/Accounts/worldcupticketbooking/workflows/src/main/java/com/t20worldcup/flows/DVPAccountsOnSameNode.java
index 977cb472..e71721e7 100644
--- a/Accounts/worldcupticketbooking/workflows/src/main/java/com/t20worldcup/flows/DVPAccountsOnSameNode.java
+++ b/Accounts/worldcupticketbooking/workflows/src/main/java/com/t20worldcup/flows/DVPAccountsOnSameNode.java
@@ -105,13 +105,7 @@ public String call() throws FlowException {
TokenPointer tokenPointer = evolvableTokenType.toPointer(evolvableTokenType.getClass());
// Obtain a reference to a notary we wish to use.
- /** METHOD 1: Take first notary on network, WARNING: use for test, non-prod environments, and single-notary networks only!*
- * METHOD 2: Explicit selection of notary by CordaX500Name - argument can by coded in flow or parsed from config (Preferred)
- *
- * * - For production you always want to use Method 2 as it guarantees the expected notary is returned.
- */
- final Party notary = getServiceHub().getNetworkMapCache().getNotaryIdentities().get(0); // METHOD 1
- // final Party notary = getServiceHub().getNetworkMapCache().getNotary(CordaX500Name.parse("O=Notary,L=London,C=GB")); // METHOD 2
+ Party notary = stateAndRef.getState().getNotary();
//create a transactionBuilder
TransactionBuilder transactionBuilder = new TransactionBuilder(notary);
diff --git a/Accounts/worldcupticketbooking/workflows/src/main/java/com/t20worldcup/flows/MoveTokensBetweenAccounts.java b/Accounts/worldcupticketbooking/workflows/src/main/java/com/t20worldcup/flows/MoveTokensBetweenAccounts.java
index b2daf738..c2f0ffb2 100644
--- a/Accounts/worldcupticketbooking/workflows/src/main/java/com/t20worldcup/flows/MoveTokensBetweenAccounts.java
+++ b/Accounts/worldcupticketbooking/workflows/src/main/java/com/t20worldcup/flows/MoveTokensBetweenAccounts.java
@@ -19,6 +19,7 @@
import net.corda.core.flows.*;
import net.corda.core.identity.AbstractParty;
import net.corda.core.identity.AnonymousParty;
+import net.corda.core.identity.CordaX500Name;
import net.corda.core.identity.Party;
import net.corda.core.node.services.vault.QueryCriteria;
import net.corda.core.transactions.SignedTransaction;
@@ -88,8 +89,9 @@ public String call() throws FlowException {
Pair>, List> inputsAndOutputs =
tokenSelection.generateMove(Arrays.asList(partyAndAmount), buyerAccount, new TokenQueryBy(), getRunId().getUuid());
- Party notary = getServiceHub().getNetworkMapCache().getNotaryIdentities().get(0);
-
+ // Obtain a reference to a notary we wish to use.
+ /** Explicit selection of notary by CordaX500Name - argument can by coded in flows or parsed from config (Preferred)*/
+ final Party notary = getServiceHub().getNetworkMapCache().getNotary(CordaX500Name.parse("O=Notary,L=London,C=GB"));
TransactionBuilder transactionBuilder = new TransactionBuilder(notary);
MoveTokensUtilitiesKt.addMoveTokens(transactionBuilder, inputsAndOutputs.getFirst(), inputsAndOutputs.getSecond());
diff --git a/Advanced/README.md b/Advanced/README.md
index 25637455..f5e9271c 100644
--- a/Advanced/README.md
+++ b/Advanced/README.md
@@ -1,19 +1,34 @@
-## samples-java/advanced-cordapps
+## Advanced Cordapp Samples
This folder features Advanced sample projects, each of them demonstrates a complex cordapp that uses multiple features of Corda.
-### [auction cordapp](./auction-cordapp):
+### [Auction Cordapp](./auction-cordapp):
An blockchain application that leverages different features of Corda like [SchedulableState](https://docs.corda.net/docs/corda-os/event-scheduling.html#how-to-implement-scheduled-events), [StatePointer](https://docs.corda.net/docs/corda-os/api-states.html#state-pointers)
and [OwnableState](https://docs.corda.net/docs/corda-os/api-states.html#ownablestate). It also demonstrates how to perform a DvP (Delivery vs Payment) transaction on Corda.
-[
](https://ide.corda.net/?folder=/home/coder/samples-java/Advanced/auction-cordapp)
+
+
+
-### [negotiation cordapp](./negotiation-cordapp):
+### [Due Diligence Cordapp](./duediligence-cordapp):
+An capital market themed app that depicts an ideal shareable due diligence process between banks. It uses advance feature attachment functionality to whitelist the trusted auditors.
+
+### [Negotiation Cordapp](./negotiation-cordapp):
An application that depicts the businsess negotiation and communication process over a distributed ledger system.
It consists of the proposing, negotiating, and settling a corda transaction.
-[
](https://ide.corda.net/?folder=/home/coder/samples-java/Advanced/negotiation-cordapp)
-### [obligation cordapp](./obligation-cordapp):
+### [Obligation Cordapp](./obligation-cordapp):
A simple i-owe-you application illustrates all of the steps of creating an obligation for a resource to change owners.
-[
](https://ide.corda.net/?folder=/home/coder/samples-java/Advanced/obligation-cordapp)
+### [Secret Santa Cordapp](./secretsanta-cordapp):
+This is an imlementation of Secret Santa using Corda as a tool to store multiple game states.It has a material-ui frontend that lets users create and self-service their own secret santa games. The frontend is implemented in ReactJS and the backend is implemented with a Spring Boot server and some corda flows. It is also equipped with an external emailing package(sendgrid), which you can utilze and turn the app into a live app and send the secret santa assignments to your friends'
+emails.
+
+
+
+
+### [Snake and Ladder Game Cordapp](./snakesandladders-cordapp):
+This sample implements a simple Snakes And Ladder Game on Corda. This cordapp demonstrate the use of multiple features, including Corda Account Library and Oracle service.
+
+
+
diff --git a/Advanced/auction-cordapp/README.md b/Advanced/auction-cordapp/README.md
index e9e7b8b5..fc3582a1 100644
--- a/Advanced/auction-cordapp/README.md
+++ b/Advanced/auction-cordapp/README.md
@@ -1,4 +1,4 @@
-# auction cordapp [
](https://ide.corda.net/?folder=/home/coder/samples-java/Advanced/auction-cordapp)
+# Auction Cordapp
This CorDapp serves as a demo of building an auction application on Corda. It leverages
different features of Corda like [SchedulableState](https://docs.corda.net/docs/corda-os/event-scheduling.html#how-to-implement-scheduled-events), [StatePointer](https://docs.corda.net/docs/corda-os/api-states.html#state-pointers) and [OwnableState](https://docs.corda.net/docs/corda-os/api-states.html#ownablestate). It also demonstrate
@@ -37,19 +37,19 @@ ownership. Left black for simplicity. Has two commands, `CreateAsset` and `Trans
### Flows:
-- `CreateAssetFlow`: This flow is used create an asset. Implemented in [CreateAssetFlow.java](./workflows/src/main/java/net/corda/samples/flows/CreateAssetFlow.java#L44-L66)
+- `CreateAssetFlow`: This flow is used create an asset. Implemented in `CreateAssetFlow.java`
-- `CreateAuctionFlow`: This flow is used to create an auction ([CreateAuctionFlow.java can be found here](./workflows/src/main/java/net/corda/samples/flows/CreateAuctionFlow.java#L58-L96)). Once an asset has been created using
+- `CreateAuctionFlow`: This flow is used to create an auction. Once an asset has been created using
the`CreateAssetFlow`, this flow can be used to put the asset on auction. The `AuctionState`
references to the `Asset` using a `StatePointer`.
Refer here to learn more about StatePointer: https://medium.com/corda/linking-corda-states-using-statepointer-16e24e5e602
- `BidFlow`: It is used to place a bid on an auction. Bids can be placed only till a predetermined
-deadline defined in the `AuctionState`. Implemented in [BidFlow.java](./workflows/src/main/java/net/corda/samples/flows/BidFlow.java#L42-L86).
+deadline defined in the `AuctionState`. Implemented in `BidFlow.java`.
- `EndAuctionFlow`: This is a scheduled flow, which run automatically on auction deadline to mark
-the corresponding auction as inactive, so that it stop receiving bids.The auction flow can be found [here](./workflows/src/main/java/net/corda/samples/flows/EndAuctionFlow.java#L39-L83)
+the corresponding auction as inactive, so that it stop receiving bids.
- `AuctionSettlementFlow`: It is used to settle an auction once the bidding deadline has passed. It internally triggers two flows:
@@ -63,10 +63,9 @@ the corresponding auction as inactive, so that it stop receiving bids.The auctio
## Usage
+## Pre-Requisites
+For development environment setup, please refer to: [Setup Guide](https://docs.corda.net/getting-set-up.html).
-### Pre-requisites:
-
-See https://docs.corda.net/getting-set-up.html.
### Running the nodes:
Open a terminal and go to the project root directory and type: (to deploy the nodes using bootstrapper)
diff --git a/Advanced/auction-cordapp/build.gradle b/Advanced/auction-cordapp/build.gradle
index 9ba06679..4d87e6dc 100644
--- a/Advanced/auction-cordapp/build.gradle
+++ b/Advanced/auction-cordapp/build.gradle
@@ -20,8 +20,9 @@ buildscript {
repositories {
mavenLocal()
mavenCentral()
- jcenter()
- maven { url 'https://ci-artifactory.corda.r3cev.com/artifactory/corda' }
+
+ maven { url 'https://download.corda.net/maven/corda-dependencies' }
+ maven { url 'https://download.corda.net/maven/corda-releases' }
}
dependencies {
@@ -37,9 +38,10 @@ allprojects {
repositories {
mavenLocal()
- jcenter()
+
mavenCentral()
- maven { url 'https://ci-artifactory.corda.r3cev.com/artifactory/corda' }
+ maven { url 'https://download.corda.net/maven/corda-dependencies' }
+ maven { url 'https://download.corda.net/maven/corda-releases' }
maven { url 'https://jitpack.io' }
maven { url 'https://repo.gradle.org/gradle/libs-releases' }
}
@@ -60,15 +62,6 @@ apply plugin: 'net.corda.plugins.cordapp'
apply plugin: 'net.corda.plugins.cordformation'
apply plugin: 'net.corda.plugins.quasar-utils'
-cordapp {
- info {
- name "CorDapp Template"
- vendor "Corda Open Source"
- targetPlatformVersion corda_platform_version.toInteger()
- minimumPlatformVersion corda_platform_version.toInteger()
- }
-}
-
sourceSets {
main {
resources {
@@ -96,6 +89,9 @@ dependencies {
cordaCompile "org.apache.logging.log4j:log4j-slf4j-impl:${log4j_version}"
cordaCompile "org.apache.logging.log4j:log4j-web:${log4j_version}"
cordaCompile "org.slf4j:jul-to-slf4j:$slf4j_version"
+
+ cordaDriver "net.corda:corda-shell:4.10"
+
}
task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar']) {
diff --git a/Advanced/auction-cordapp/client/build.gradle b/Advanced/auction-cordapp/client/build.gradle
index 5cc0879a..e94a0e39 100644
--- a/Advanced/auction-cordapp/client/build.gradle
+++ b/Advanced/auction-cordapp/client/build.gradle
@@ -1,12 +1,10 @@
apply plugin: 'org.springframework.boot'
-//sourceSets {
-// main {
-// resources {
-// srcDir rootProject.file("config/dev")
-// }
-// }
-//}
+configurations {
+ all {
+ exclude group: 'ch.qos.logback', module: 'logback-classic'
+ }
+}
dependencies {
// Corda dependencies.
@@ -33,10 +31,10 @@ dependencies {
}
springBoot {
- mainClassName = "net.corda.samples.client.Starter"
+ mainClassName = "net.corda.samples.auction.client.Starter"
}
task runAuctionClient(type: JavaExec, dependsOn: assemble) {
classpath = sourceSets.main.runtimeClasspath
- main = 'net.corda.samples.client.Starter'
+ main = 'net.corda.samples.auction.client.Starter'
}
\ No newline at end of file
diff --git a/Advanced/auction-cordapp/client/src/main/java/net/corda/samples/auction/client/APIResponse.java b/Advanced/auction-cordapp/client/src/main/java/net/corda/samples/auction/client/APIResponse.java
new file mode 100644
index 00000000..e6cfe3e5
--- /dev/null
+++ b/Advanced/auction-cordapp/client/src/main/java/net/corda/samples/auction/client/APIResponse.java
@@ -0,0 +1,41 @@
+package net.corda.samples.auction.client;
+
+/**
+ * A wrapper to send response from the rest calls.
+ * @param
+ */
+public class APIResponse {
+ private String message;
+ private T data;
+ private boolean status;
+
+ public APIResponse(String message, T data, boolean status) {
+ this.message = message;
+ this.data = data;
+ this.status = status;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public T getData() {
+ return data;
+ }
+
+ public boolean isStatus() {
+ return status;
+ }
+
+ public static APIResponse success(){
+ return new APIResponse<>("SUCCESS", null, true);
+ }
+
+ public static APIResponse success(T data){
+ return new APIResponse<>("SUCCESS", data, true);
+ }
+
+ public static APIResponse error(String message){
+ return new APIResponse<>(message, null, false);
+ }
+}
diff --git a/Advanced/auction-cordapp/client/src/main/java/net/corda/samples/auction/client/AppConfig.java b/Advanced/auction-cordapp/client/src/main/java/net/corda/samples/auction/client/AppConfig.java
new file mode 100644
index 00000000..a5a51420
--- /dev/null
+++ b/Advanced/auction-cordapp/client/src/main/java/net/corda/samples/auction/client/AppConfig.java
@@ -0,0 +1,54 @@
+package net.corda.samples.auction.client;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import net.corda.client.jackson.JacksonSupport;
+import net.corda.client.rpc.CordaRPCClient;
+import net.corda.core.messaging.CordaRPCOps;
+import net.corda.core.utilities.NetworkHostAndPort;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+@Configuration
+public class AppConfig implements WebMvcConfigurer {
+
+ @Value("${partyA.host}")
+ private String partyAHostAndPort;
+
+ @Value("${partyB.host}")
+ private String partyBHostAndPort;
+
+ @Value("${partyC.host}")
+ private String partyCHostAndPort;
+
+ @Bean(destroyMethod = "") // Avoids node shutdown on rpc disconnect
+ public CordaRPCOps partyAProxy(){
+ CordaRPCClient partyAClient = new CordaRPCClient(NetworkHostAndPort.parse(partyAHostAndPort));
+ return partyAClient.start("user1", "test").getProxy();
+ }
+
+ @Bean(destroyMethod = "")
+ public CordaRPCOps partyBProxy(){
+ CordaRPCClient partyBClient = new CordaRPCClient(NetworkHostAndPort.parse(partyBHostAndPort));
+ return partyBClient.start("user1", "test").getProxy();
+ }
+
+ @Bean(destroyMethod = "")
+ public CordaRPCOps partyCProxy(){
+ CordaRPCClient partyCClient = new CordaRPCClient(NetworkHostAndPort.parse(partyCHostAndPort));
+ return partyCClient.start("user1", "test").getProxy();
+ }
+
+ /**
+ * Corda Jackson Support, to convert corda objects to json
+ */
+ @Bean
+ public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter(){
+ ObjectMapper mapper = JacksonSupport.createDefaultMapper(partyAProxy());
+ MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
+ converter.setObjectMapper(mapper);
+ return converter;
+ }
+}
diff --git a/Advanced/auction-cordapp/client/src/main/java/net/corda/samples/auction/client/Controller.java b/Advanced/auction-cordapp/client/src/main/java/net/corda/samples/auction/client/Controller.java
new file mode 100644
index 00000000..71fd77dc
--- /dev/null
+++ b/Advanced/auction-cordapp/client/src/main/java/net/corda/samples/auction/client/Controller.java
@@ -0,0 +1,246 @@
+package net.corda.samples.auction.client;
+
+import net.corda.core.contracts.Amount;
+import net.corda.core.contracts.StateAndRef;
+import net.corda.core.contracts.TransactionVerificationException;
+import net.corda.core.messaging.CordaRPCOps;
+import net.corda.core.utilities.OpaqueBytes;
+import net.corda.finance.contracts.asset.Cash;
+import net.corda.finance.flows.CashIssueAndPaymentFlow;
+import net.corda.samples.auction.flows.*;
+import net.corda.samples.auction.states.Asset;
+import net.corda.samples.auction.states.AuctionState;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.web.bind.annotation.*;
+
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.List;
+import java.util.UUID;
+import java.util.concurrent.ExecutionException;
+
+@RestController
+@RequestMapping("/api/auction/")
+public class Controller {
+
+ @Autowired
+ private CordaRPCOps partyAProxy;
+
+ @Autowired
+ private CordaRPCOps partyBProxy;
+
+ @Autowired
+ private CordaRPCOps partyCProxy;
+
+ @Autowired
+ @Qualifier("partyAProxy")
+ private CordaRPCOps activeParty;
+
+ @GetMapping("list")
+ public APIResponse>> getAuctionList() {
+ try{
+ List> auctionList = activeParty.vaultQuery(AuctionState.class).getStates();
+ return APIResponse.success(auctionList);
+ }catch(Exception e){
+ return APIResponse.error(e.getMessage());
+ }
+ }
+
+ @GetMapping("asset/list")
+ public APIResponse>> getAssetList(){
+ try{
+ List> assetList = activeParty.vaultQuery(Asset.class).getStates();
+ return APIResponse.success(assetList);
+ }catch(Exception e){
+ return APIResponse.error(e.getMessage());
+ }
+ }
+
+ @PostMapping("asset/create")
+ public APIResponse createAsset(@RequestBody Forms.AssetForm assetForm){
+ try{
+ activeParty.startFlowDynamic(CreateAssetFlow.class, assetForm.getTitle(), assetForm.getDescription(),
+ assetForm.getImageUrl()).getReturnValue().get();
+ return APIResponse.success();
+ }catch(Exception e){
+ return APIResponse.error(e.getMessage());
+ }
+ }
+
+ @PostMapping("create")
+ public APIResponse createAuction(@RequestBody Forms.CreateAuctionForm auctionForm){
+ try {
+ activeParty.startFlowDynamic(CreateAuctionFlow.CreateAuctionInitiator.class,
+ Amount.parseCurrency(auctionForm.getBasePrice() + " USD"),
+ UUID.fromString(auctionForm.getAssetId()),
+ LocalDateTime.parse(auctionForm.getDeadline(),
+ DateTimeFormatter.ofPattern("dd-MM-yyyy hh:mm:ss a"))).getReturnValue().get();
+ return APIResponse.success();
+ }catch (ExecutionException e){
+ if(e.getCause() != null && e.getCause().getClass().equals(TransactionVerificationException.ContractRejection.class)){
+ return APIResponse.error(e.getCause().getMessage());
+ }else{
+ return APIResponse.error(e.getMessage());
+ }
+ }catch (Exception e){
+ return APIResponse.error(e.getMessage());
+ }
+ }
+
+ @PostMapping("delete/{auctionId}")
+ public APIResponse deleteAuction(@PathVariable String auctionId){
+ try {
+ activeParty.startFlowDynamic(AuctionExitFlow.AuctionExitInitiator.class, UUID.fromString(auctionId)).getReturnValue().get();
+ return APIResponse.success();
+ }catch (ExecutionException e){
+ if(e.getCause() != null && e.getCause().getClass().equals(TransactionVerificationException.ContractRejection.class)){
+ return APIResponse.error(e.getCause().getMessage());
+ }else{
+ return APIResponse.error(e.getMessage());
+ }
+ }catch (Exception e){
+ return APIResponse.error(e.getMessage());
+ }
+ }
+
+ @PostMapping("placeBid")
+ public APIResponse placeBid(@RequestBody Forms.BidForm bidForm){
+ try{
+ activeParty.startFlowDynamic(BidFlow.BidInitiator.class,
+ Amount.parseCurrency(bidForm.getAmount() + " USD"),
+ UUID.fromString(bidForm.getAuctionId()))
+ .getReturnValue().get();
+ return APIResponse.success();
+ }catch (ExecutionException e){
+ if(e.getCause() != null && e.getCause().getClass().equals(TransactionVerificationException.ContractRejection.class)){
+ return APIResponse.error(e.getCause().getMessage());
+ }else{
+ return APIResponse.error(e.getMessage());
+ }
+ }catch (Exception e){
+ return APIResponse.error(e.getMessage());
+ }
+ }
+
+ @PostMapping("payAndSettle")
+ public APIResponse payAndSettle(@RequestBody Forms.SettlementForm settlementForm){
+ try {
+ activeParty.startFlowDynamic(AuctionSettlementFlow.class,
+ UUID.fromString(settlementForm.getAuctionId()),
+ Amount.parseCurrency(settlementForm.getAmount()))
+ .getReturnValue().get();
+ return APIResponse.success();
+ }
+ catch (ExecutionException e){
+ if(e.getCause() != null && e.getCause().getClass().equals(TransactionVerificationException.ContractRejection.class)){
+ return APIResponse.error(e.getCause().getMessage());
+ }else{
+ return APIResponse.error(e.getMessage());
+ }
+ }catch (Exception e){
+ return APIResponse.error(e.getMessage());
+ }
+ }
+
+ @PostMapping("issueCash")
+ public APIResponse issueCash(@RequestBody Forms.IssueCashForm issueCashForm){
+ try{
+ activeParty.startFlowDynamic(CashIssueAndPaymentFlow.class,
+ Amount.parseCurrency(issueCashForm.getAmount() + " USD"),
+ OpaqueBytes.of("PartyA".getBytes()),
+ activeParty.partiesFromName(issueCashForm.getParty(), false).iterator().next(),
+ false,
+ activeParty.notaryIdentities().get(0))
+ .getReturnValue().get();
+ return APIResponse.success();
+ }catch (ExecutionException e){
+ if(e.getCause() != null && e.getCause().getClass().equals(TransactionVerificationException.ContractRejection.class)){
+ return APIResponse.error(e.getCause().getMessage());
+ }else{
+ return APIResponse.error(e.getMessage());
+ }
+ }catch (Exception e){
+ return APIResponse.error(e.getMessage());
+ }
+ }
+
+ @GetMapping("getCashBalance")
+ public APIResponse getCashBalance(){
+ try {
+ List> cashStateList = activeParty.vaultQuery(Cash.State.class).getStates();
+ Long amount = 0L;
+ if(cashStateList.size()>0) {
+ amount = cashStateList.stream().map(stateStateAndRef ->
+ stateStateAndRef.getState().getData().getAmount().getQuantity()).reduce(Long::sum).get();
+ if (amount >= 100) {
+ amount = amount / 100;
+ } else {
+ amount = 0L;
+ }
+ }
+ return APIResponse.success(amount);
+ }catch (Exception e){
+ return APIResponse.error(e.getMessage());
+ }
+ }
+
+ @PostMapping(value = "switch-party/{party}")
+ public APIResponse switchParty(@PathVariable String party){
+ if(party.equals("PartyA")){
+ activeParty = partyAProxy;
+ }else if(party.equals("PartyB")){
+ activeParty = partyBProxy;
+ }else if(party.equals("PartyC")){
+ activeParty = partyCProxy;
+ }else{
+ return APIResponse.error("Unrecognised Party");
+ }
+ return getCashBalance();
+ }
+
+ /**
+ * Create some initial data to play with.
+ * @return
+ */
+ @PostMapping("setup")
+ public APIResponse setupDemoData(){
+ try {
+ partyAProxy.startFlowDynamic(CreateAssetFlow.class,
+ "Mona Lisa",
+ "The most famous painting in the world, a masterpiece by Leonardo da Vinci, the mysterious woman with " +
+ "the enigmatic smile. The sitter in the painting is thought to be Lisa Gherardini, the wife of " +
+ "Florence merchant Francesco del Giocondo. It did represent an innovation in art -- the painting" +
+ " is the earliest known Italian portrait to focus so closely on the sitter in a half-length " +
+ "portrait.",
+ "img/Mona_Lisa.jpg");
+
+ partyAProxy.startFlowDynamic(CreateAssetFlow.class,
+ "The Last Supper",
+ "Yet another masterpiece by Leonardo da Vinci, painted in an era when religious imagery was still " +
+ "a dominant artistic theme, \"The Last Supper\" depicts the last time Jesus broke bread with " +
+ "his disciples before his crucifixion.",
+ "img/The_Last_Supper.jpg");
+
+
+ partyBProxy.startFlowDynamic(CreateAssetFlow.class,
+ "The Starry Night",
+ "Painted by Vincent van Gogh, this comparatively abstract painting is the signature example of " +
+ "van Gogh's innovative and bold use of thick brushstrokes. The painting's striking blues and " +
+ "yellows and the dreamy, swirling atmosphere have intrigued art lovers for decades.",
+ "img/The_Scary_Night.jpg");
+
+ partyCProxy.startFlowDynamic(CreateAssetFlow.class,
+ "The Scream",
+ "First things first -- \"The Scream\" is not a single work of art. According to a British Museum's blog," +
+ " there are two paintings, two pastels and then an unspecified number of prints. Date back to " +
+ "the the year 1893, this masterpiece is a work of Edvard Munch",
+ "img/The_Scream.jpg");
+
+ activeParty = partyAProxy;
+ }catch (Exception e){
+ return APIResponse.error(e.getMessage());
+ }
+ return APIResponse.success();
+ }
+}
diff --git a/Advanced/auction-cordapp/client/src/main/java/net/corda/samples/auction/client/Forms.java b/Advanced/auction-cordapp/client/src/main/java/net/corda/samples/auction/client/Forms.java
new file mode 100644
index 00000000..3786d69d
--- /dev/null
+++ b/Advanced/auction-cordapp/client/src/main/java/net/corda/samples/auction/client/Forms.java
@@ -0,0 +1,128 @@
+package net.corda.samples.auction.client;
+
+public class Forms {
+
+ public static class BidForm {
+ private String auctionId;
+ private int amount;
+
+ public String getAuctionId() {
+ return auctionId;
+ }
+
+ public void setAuctionId(String auctionId) {
+ this.auctionId = auctionId;
+ }
+
+ public int getAmount() {
+ return amount;
+ }
+
+ public void setAmount(int amount) {
+ this.amount = amount;
+ }
+ }
+
+ public static class SettlementForm {
+ private String auctionId;
+ private String amount;
+
+ public String getAuctionId() {
+ return auctionId;
+ }
+
+ public void setAuctionId(String auctionId) {
+ this.auctionId = auctionId;
+ }
+
+ public String getAmount() {
+ return amount;
+ }
+
+ public void setAmount(String amount) {
+ this.amount = amount;
+ }
+ }
+
+ public static class CreateAuctionForm {
+ private int basePrice;
+ private String assetId;
+ private String deadline;
+
+ public int getBasePrice() {
+ return basePrice;
+ }
+
+ public void setBasePrice(int basePrice) {
+ this.basePrice = basePrice;
+ }
+
+ public String getAssetId() {
+ return assetId;
+ }
+
+ public void setAssetId(String assetId) {
+ this.assetId = assetId;
+ }
+
+ public String getDeadline() {
+ return deadline;
+ }
+
+ public void setDeadline(String deadline) {
+ this.deadline = deadline;
+ }
+ }
+
+ public static class IssueCashForm {
+ private String party;
+ private int amount;
+
+ public String getParty() {
+ return party;
+ }
+
+ public void setParty(String party) {
+ this.party = party;
+ }
+
+ public int getAmount() {
+ return amount;
+ }
+
+ public void setAmount(int amount) {
+ this.amount = amount;
+ }
+ }
+
+ public static class AssetForm {
+ private String imageUrl;
+ private String title;
+ private String description;
+
+ public String getImageUrl() {
+ return imageUrl;
+ }
+
+ public void setImageUrl(String imageUrl) {
+ this.imageUrl = imageUrl;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+ }
+
+}
diff --git a/Advanced/auction-cordapp/client/src/main/java/net/corda/samples/auction/client/Starter.java b/Advanced/auction-cordapp/client/src/main/java/net/corda/samples/auction/client/Starter.java
new file mode 100644
index 00000000..26c69069
--- /dev/null
+++ b/Advanced/auction-cordapp/client/src/main/java/net/corda/samples/auction/client/Starter.java
@@ -0,0 +1,18 @@
+package net.corda.samples.auction.client;
+
+import org.springframework.boot.Banner;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.WebApplicationType;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class Starter {
+
+ public static void main(String[] args) {
+ SpringApplication app = new SpringApplication(Starter.class);
+ app.setBannerMode(Banner.Mode.OFF);
+ app.setWebApplicationType(WebApplicationType.SERVLET);
+ app.run(args);
+ }
+
+}
diff --git a/Advanced/auction-cordapp/client/src/main/java/net/corda/samples/client/APIResponse.java b/Advanced/auction-cordapp/client/src/main/java/net/corda/samples/client/APIResponse.java
deleted file mode 100644
index 4c541e1c..00000000
--- a/Advanced/auction-cordapp/client/src/main/java/net/corda/samples/client/APIResponse.java
+++ /dev/null
@@ -1,41 +0,0 @@
-package net.corda.samples.client;
-
-/**
- * A wrapper to send response from the rest calls.
- * @param
- */
-public class APIResponse {
- private String message;
- private T data;
- private boolean status;
-
- public APIResponse(String message, T data, boolean status) {
- this.message = message;
- this.data = data;
- this.status = status;
- }
-
- public String getMessage() {
- return message;
- }
-
- public T getData() {
- return data;
- }
-
- public boolean isStatus() {
- return status;
- }
-
- public static APIResponse success(){
- return new APIResponse<>("SUCCESS", null, true);
- }
-
- public static APIResponse success(T data){
- return new APIResponse<>("SUCCESS", data, true);
- }
-
- public static APIResponse error(String message){
- return new APIResponse<>(message, null, false);
- }
-}
diff --git a/Advanced/auction-cordapp/client/src/main/java/net/corda/samples/client/AppConfig.java b/Advanced/auction-cordapp/client/src/main/java/net/corda/samples/client/AppConfig.java
deleted file mode 100644
index 25680c2b..00000000
--- a/Advanced/auction-cordapp/client/src/main/java/net/corda/samples/client/AppConfig.java
+++ /dev/null
@@ -1,54 +0,0 @@
-package net.corda.samples.client;
-
-import com.fasterxml.jackson.databind.ObjectMapper;
-import net.corda.client.jackson.JacksonSupport;
-import net.corda.client.rpc.CordaRPCClient;
-import net.corda.core.messaging.CordaRPCOps;
-import net.corda.core.utilities.NetworkHostAndPort;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
-import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
-
-@Configuration
-public class AppConfig implements WebMvcConfigurer {
-
- @Value("${partyA.host}")
- private String partyAHostAndPort;
-
- @Value("${partyB.host}")
- private String partyBHostAndPort;
-
- @Value("${partyC.host}")
- private String partyCHostAndPort;
-
- @Bean(destroyMethod = "") // Avoids node shutdown on rpc disconnect
- public CordaRPCOps partyAProxy(){
- CordaRPCClient partyAClient = new CordaRPCClient(NetworkHostAndPort.parse(partyAHostAndPort));
- return partyAClient.start("user1", "test").getProxy();
- }
-
- @Bean(destroyMethod = "")
- public CordaRPCOps partyBProxy(){
- CordaRPCClient partyBClient = new CordaRPCClient(NetworkHostAndPort.parse(partyBHostAndPort));
- return partyBClient.start("user1", "test").getProxy();
- }
-
- @Bean(destroyMethod = "")
- public CordaRPCOps partyCProxy(){
- CordaRPCClient partyCClient = new CordaRPCClient(NetworkHostAndPort.parse(partyCHostAndPort));
- return partyCClient.start("user1", "test").getProxy();
- }
-
- /**
- * Corda Jackson Support, to convert corda objects to json
- */
- @Bean
- public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter(){
- ObjectMapper mapper = JacksonSupport.createDefaultMapper(partyAProxy());
- MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
- converter.setObjectMapper(mapper);
- return converter;
- }
-}
diff --git a/Advanced/auction-cordapp/client/src/main/java/net/corda/samples/client/Controller.java b/Advanced/auction-cordapp/client/src/main/java/net/corda/samples/client/Controller.java
deleted file mode 100644
index 5dc31c4a..00000000
--- a/Advanced/auction-cordapp/client/src/main/java/net/corda/samples/client/Controller.java
+++ /dev/null
@@ -1,246 +0,0 @@
-package net.corda.samples.client;
-
-import net.corda.core.contracts.Amount;
-import net.corda.core.contracts.StateAndRef;
-import net.corda.core.contracts.TransactionVerificationException;
-import net.corda.core.messaging.CordaRPCOps;
-import net.corda.core.utilities.OpaqueBytes;
-import net.corda.finance.contracts.asset.Cash;
-import net.corda.finance.flows.CashIssueAndPaymentFlow;
-import net.corda.samples.flows.*;
-import net.corda.samples.states.Asset;
-import net.corda.samples.states.AuctionState;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Qualifier;
-import org.springframework.web.bind.annotation.*;
-
-import java.time.LocalDateTime;
-import java.time.format.DateTimeFormatter;
-import java.util.List;
-import java.util.UUID;
-import java.util.concurrent.ExecutionException;
-
-@RestController
-@RequestMapping("/api/auction/")
-public class Controller {
-
- @Autowired
- private CordaRPCOps partyAProxy;
-
- @Autowired
- private CordaRPCOps partyBProxy;
-
- @Autowired
- private CordaRPCOps partyCProxy;
-
- @Autowired
- @Qualifier("partyAProxy")
- private CordaRPCOps activeParty;
-
- @GetMapping("list")
- public APIResponse>> getAuctionList() {
- try{
- List> auctionList = activeParty.vaultQuery(AuctionState.class).getStates();
- return APIResponse.success(auctionList);
- }catch(Exception e){
- return APIResponse.error(e.getMessage());
- }
- }
-
- @GetMapping("asset/list")
- public APIResponse>> getAssetList(){
- try{
- List> assetList = activeParty.vaultQuery(Asset.class).getStates();
- return APIResponse.success(assetList);
- }catch(Exception e){
- return APIResponse.error(e.getMessage());
- }
- }
-
- @PostMapping("asset/create")
- public APIResponse createAsset(@RequestBody Forms.AssetForm assetForm){
- try{
- activeParty.startFlowDynamic(CreateAssetFlow.class, assetForm.getTitle(), assetForm.getDescription(),
- assetForm.getImageUrl()).getReturnValue().get();
- return APIResponse.success();
- }catch(Exception e){
- return APIResponse.error(e.getMessage());
- }
- }
-
- @PostMapping("create")
- public APIResponse createAuction(@RequestBody Forms.CreateAuctionForm auctionForm){
- try {
- activeParty.startFlowDynamic(CreateAuctionFlow.Initiator.class,
- Amount.parseCurrency(auctionForm.getBasePrice() + " USD"),
- UUID.fromString(auctionForm.getAssetId()),
- LocalDateTime.parse(auctionForm.getDeadline(),
- DateTimeFormatter.ofPattern("dd-MM-yyyy hh:mm:ss a"))).getReturnValue().get();
- return APIResponse.success();
- }catch (ExecutionException e){
- if(e.getCause() != null && e.getCause().getClass().equals(TransactionVerificationException.ContractRejection.class)){
- return APIResponse.error(e.getCause().getMessage());
- }else{
- return APIResponse.error(e.getMessage());
- }
- }catch (Exception e){
- return APIResponse.error(e.getMessage());
- }
- }
-
- @PostMapping("delete/{auctionId}")
- public APIResponse deleteAuction(@PathVariable String auctionId){
- try {
- activeParty.startFlowDynamic(AuctionExitFlow.Initiator.class, UUID.fromString(auctionId)).getReturnValue().get();
- return APIResponse.success();
- }catch (ExecutionException e){
- if(e.getCause() != null && e.getCause().getClass().equals(TransactionVerificationException.ContractRejection.class)){
- return APIResponse.error(e.getCause().getMessage());
- }else{
- return APIResponse.error(e.getMessage());
- }
- }catch (Exception e){
- return APIResponse.error(e.getMessage());
- }
- }
-
- @PostMapping("placeBid")
- public APIResponse placeBid(@RequestBody Forms.BidForm bidForm){
- try{
- activeParty.startFlowDynamic(BidFlow.Initiator.class,
- Amount.parseCurrency(bidForm.getAmount() + " USD"),
- UUID.fromString(bidForm.getAuctionId()))
- .getReturnValue().get();
- return APIResponse.success();
- }catch (ExecutionException e){
- if(e.getCause() != null && e.getCause().getClass().equals(TransactionVerificationException.ContractRejection.class)){
- return APIResponse.error(e.getCause().getMessage());
- }else{
- return APIResponse.error(e.getMessage());
- }
- }catch (Exception e){
- return APIResponse.error(e.getMessage());
- }
- }
-
- @PostMapping("payAndSettle")
- public APIResponse payAndSettle(@RequestBody Forms.SettlementForm settlementForm){
- try {
- activeParty.startFlowDynamic(AuctionSettlementFlow.class,
- UUID.fromString(settlementForm.getAuctionId()),
- Amount.parseCurrency(settlementForm.getAmount()))
- .getReturnValue().get();
- return APIResponse.success();
- }
- catch (ExecutionException e){
- if(e.getCause() != null && e.getCause().getClass().equals(TransactionVerificationException.ContractRejection.class)){
- return APIResponse.error(e.getCause().getMessage());
- }else{
- return APIResponse.error(e.getMessage());
- }
- }catch (Exception e){
- return APIResponse.error(e.getMessage());
- }
- }
-
- @PostMapping("issueCash")
- public APIResponse issueCash(@RequestBody Forms.IssueCashForm issueCashForm){
- try{
- activeParty.startFlowDynamic(CashIssueAndPaymentFlow.class,
- Amount.parseCurrency(issueCashForm.getAmount() + " USD"),
- OpaqueBytes.of("PartyA".getBytes()),
- activeParty.partiesFromName(issueCashForm.getParty(), false).iterator().next(),
- false,
- activeParty.notaryIdentities().get(0))
- .getReturnValue().get();
- return APIResponse.success();
- }catch (ExecutionException e){
- if(e.getCause() != null && e.getCause().getClass().equals(TransactionVerificationException.ContractRejection.class)){
- return APIResponse.error(e.getCause().getMessage());
- }else{
- return APIResponse.error(e.getMessage());
- }
- }catch (Exception e){
- return APIResponse.error(e.getMessage());
- }
- }
-
- @GetMapping("getCashBalance")
- public APIResponse getCashBalance(){
- try {
- List> cashStateList = activeParty.vaultQuery(Cash.State.class).getStates();
- Long amount = 0L;
- if(cashStateList.size()>0) {
- amount = cashStateList.stream().map(stateStateAndRef ->
- stateStateAndRef.getState().getData().getAmount().getQuantity()).reduce(Long::sum).get();
- if (amount >= 100) {
- amount = amount / 100;
- } else {
- amount = 0L;
- }
- }
- return APIResponse.success(amount);
- }catch (Exception e){
- return APIResponse.error(e.getMessage());
- }
- }
-
- @PostMapping(value = "switch-party/{party}")
- public APIResponse switchParty(@PathVariable String party){
- if(party.equals("PartyA")){
- activeParty = partyAProxy;
- }else if(party.equals("PartyB")){
- activeParty = partyBProxy;
- }else if(party.equals("PartyC")){
- activeParty = partyCProxy;
- }else{
- return APIResponse.error("Unrecognised Party");
- }
- return getCashBalance();
- }
-
- /**
- * Create some initial data to play with.
- * @return
- */
- @PostMapping("setup")
- public APIResponse setupDemoData(){
- try {
- partyAProxy.startFlowDynamic(CreateAssetFlow.class,
- "Mona Lisa",
- "The most famous painting in the world, a masterpiece by Leonardo da Vinci, the mysterious woman with " +
- "the enigmatic smile. The sitter in the painting is thought to be Lisa Gherardini, the wife of " +
- "Florence merchant Francesco del Giocondo. It did represent an innovation in art -- the painting" +
- " is the earliest known Italian portrait to focus so closely on the sitter in a half-length " +
- "portrait.",
- "img/Mona_Lisa.jpg");
-
- partyAProxy.startFlowDynamic(CreateAssetFlow.class,
- "The Last Supper",
- "Yet another masterpiece by Leonardo da Vinci, painted in an era when religious imagery was still " +
- "a dominant artistic theme, \"The Last Supper\" depicts the last time Jesus broke bread with " +
- "his disciples before his crucifixion.",
- "img/The_Last_Supper.jpg");
-
-
- partyBProxy.startFlowDynamic(CreateAssetFlow.class,
- "The Starry Night",
- "Painted by Vincent van Gogh, this comparatively abstract painting is the signature example of " +
- "van Gogh's innovative and bold use of thick brushstrokes. The painting's striking blues and " +
- "yellows and the dreamy, swirling atmosphere have intrigued art lovers for decades.",
- "img/The_Scary_Night.jpg");
-
- partyCProxy.startFlowDynamic(CreateAssetFlow.class,
- "The Scream",
- "First things first -- \"The Scream\" is not a single work of art. According to a British Museum's blog," +
- " there are two paintings, two pastels and then an unspecified number of prints. Date back to " +
- "the the year 1893, this masterpiece is a work of Edvard Munch",
- "img/The_Scream.jpg");
-
- activeParty = partyAProxy;
- }catch (Exception e){
- return APIResponse.error(e.getMessage());
- }
- return APIResponse.success();
- }
-}
diff --git a/Advanced/auction-cordapp/client/src/main/java/net/corda/samples/client/Forms.java b/Advanced/auction-cordapp/client/src/main/java/net/corda/samples/client/Forms.java
deleted file mode 100644
index 1b490132..00000000
--- a/Advanced/auction-cordapp/client/src/main/java/net/corda/samples/client/Forms.java
+++ /dev/null
@@ -1,128 +0,0 @@
-package net.corda.samples.client;
-
-public class Forms {
-
- public static class BidForm {
- private String auctionId;
- private int amount;
-
- public String getAuctionId() {
- return auctionId;
- }
-
- public void setAuctionId(String auctionId) {
- this.auctionId = auctionId;
- }
-
- public int getAmount() {
- return amount;
- }
-
- public void setAmount(int amount) {
- this.amount = amount;
- }
- }
-
- public static class SettlementForm {
- private String auctionId;
- private String amount;
-
- public String getAuctionId() {
- return auctionId;
- }
-
- public void setAuctionId(String auctionId) {
- this.auctionId = auctionId;
- }
-
- public String getAmount() {
- return amount;
- }
-
- public void setAmount(String amount) {
- this.amount = amount;
- }
- }
-
- public static class CreateAuctionForm {
- private int basePrice;
- private String assetId;
- private String deadline;
-
- public int getBasePrice() {
- return basePrice;
- }
-
- public void setBasePrice(int basePrice) {
- this.basePrice = basePrice;
- }
-
- public String getAssetId() {
- return assetId;
- }
-
- public void setAssetId(String assetId) {
- this.assetId = assetId;
- }
-
- public String getDeadline() {
- return deadline;
- }
-
- public void setDeadline(String deadline) {
- this.deadline = deadline;
- }
- }
-
- public static class IssueCashForm {
- private String party;
- private int amount;
-
- public String getParty() {
- return party;
- }
-
- public void setParty(String party) {
- this.party = party;
- }
-
- public int getAmount() {
- return amount;
- }
-
- public void setAmount(int amount) {
- this.amount = amount;
- }
- }
-
- public static class AssetForm {
- private String imageUrl;
- private String title;
- private String description;
-
- public String getImageUrl() {
- return imageUrl;
- }
-
- public void setImageUrl(String imageUrl) {
- this.imageUrl = imageUrl;
- }
-
- public String getTitle() {
- return title;
- }
-
- public void setTitle(String title) {
- this.title = title;
- }
-
- public String getDescription() {
- return description;
- }
-
- public void setDescription(String description) {
- this.description = description;
- }
- }
-
-}
diff --git a/Advanced/auction-cordapp/client/src/main/java/net/corda/samples/client/Starter.java b/Advanced/auction-cordapp/client/src/main/java/net/corda/samples/client/Starter.java
deleted file mode 100644
index 7c991ba8..00000000
--- a/Advanced/auction-cordapp/client/src/main/java/net/corda/samples/client/Starter.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package net.corda.samples.client;
-
-import org.springframework.boot.Banner;
-import org.springframework.boot.SpringApplication;
-import org.springframework.boot.WebApplicationType;
-import org.springframework.boot.autoconfigure.SpringBootApplication;
-
-@SpringBootApplication
-public class Starter {
-
- public static void main(String[] args) {
- SpringApplication app = new SpringApplication(Starter.class);
- app.setBannerMode(Banner.Mode.OFF);
- app.setWebApplicationType(WebApplicationType.SERVLET);
- app.run(args);
- }
-
-}
\ No newline at end of file
diff --git a/Advanced/auction-cordapp/contracts/build.gradle b/Advanced/auction-cordapp/contracts/build.gradle
index 6d9813f8..d35b4df3 100644
--- a/Advanced/auction-cordapp/contracts/build.gradle
+++ b/Advanced/auction-cordapp/contracts/build.gradle
@@ -23,7 +23,7 @@ dependencies {
// Corda dependencies.
cordaCompile "$corda_core_release_group:corda-core:$corda_core_release_version"
- compileOnly "$corda_release_group:corda-testserver-impl:$corda_release_version"
+
cordaRuntime "$corda_release_group:corda:$corda_release_version"
cordaRuntime "$corda_release_group:corda-testserver:$corda_release_version"
diff --git a/Advanced/auction-cordapp/contracts/src/main/java/net/corda/samples/auction/contracts/AssetContract.java b/Advanced/auction-cordapp/contracts/src/main/java/net/corda/samples/auction/contracts/AssetContract.java
new file mode 100644
index 00000000..014596e7
--- /dev/null
+++ b/Advanced/auction-cordapp/contracts/src/main/java/net/corda/samples/auction/contracts/AssetContract.java
@@ -0,0 +1,22 @@
+package net.corda.samples.auction.contracts;
+
+import net.corda.core.contracts.CommandData;
+import net.corda.core.contracts.Contract;
+import net.corda.core.transactions.LedgerTransaction;
+import org.jetbrains.annotations.NotNull;
+
+//TODO
+public class AssetContract implements Contract {
+ // This is used to identify our contracts when building a transaction.
+ public static final String ID = "net.corda.samples.auction.contracts.AssetContract";
+
+ @Override
+ public void verify(@NotNull LedgerTransaction tx) throws IllegalArgumentException {
+ // Contract Verification code goes here. Left blank for simplicity
+ }
+
+ public interface Commands extends CommandData {
+ class CreateAsset implements Commands {}
+ class TransferAsset implements Commands {}
+ }
+}
diff --git a/Advanced/auction-cordapp/contracts/src/main/java/net/corda/samples/contracts/AuctionContract.java b/Advanced/auction-cordapp/contracts/src/main/java/net/corda/samples/auction/contracts/AuctionContract.java
similarity index 92%
rename from Advanced/auction-cordapp/contracts/src/main/java/net/corda/samples/contracts/AuctionContract.java
rename to Advanced/auction-cordapp/contracts/src/main/java/net/corda/samples/auction/contracts/AuctionContract.java
index 8703bfec..abd174ac 100644
--- a/Advanced/auction-cordapp/contracts/src/main/java/net/corda/samples/contracts/AuctionContract.java
+++ b/Advanced/auction-cordapp/contracts/src/main/java/net/corda/samples/auction/contracts/AuctionContract.java
@@ -1,20 +1,20 @@
-package net.corda.samples.contracts;
+package net.corda.samples.auction.contracts;
import net.corda.core.contracts.Command;
import net.corda.core.contracts.CommandData;
import net.corda.core.contracts.Contract;
import net.corda.core.transactions.LedgerTransaction;
-import net.corda.samples.states.Asset;
-import net.corda.samples.states.AuctionState;
+import net.corda.samples.auction.states.Asset;
+import net.corda.samples.auction.states.AuctionState;
// ************
// * Contract *
// ************
public class AuctionContract implements Contract {
- // This is used to identify our contract when building a transaction.
- public static final String ID = "net.corda.samples.contracts.AuctionContract";
+ // This is used to identify our contracts when building a transaction.
+ public static final String ID = "net.corda.samples.auction.contracts.AuctionContract";
- // A transaction is valid if the verify() function of the contract of all the transaction's input and output states
+ // A transaction is valid if the verify() function of the contracts of all the transaction's input and output states
// does not throw an exception.
@Override
public void verify(LedgerTransaction tx) {
@@ -118,4 +118,4 @@ class Settlement implements Commands {}
class Exit implements Commands {}
}
-}
\ No newline at end of file
+}
diff --git a/Advanced/auction-cordapp/contracts/src/main/java/net/corda/samples/states/Asset.java b/Advanced/auction-cordapp/contracts/src/main/java/net/corda/samples/auction/states/Asset.java
similarity index 83%
rename from Advanced/auction-cordapp/contracts/src/main/java/net/corda/samples/states/Asset.java
rename to Advanced/auction-cordapp/contracts/src/main/java/net/corda/samples/auction/states/Asset.java
index 83ac221f..d40d3222 100644
--- a/Advanced/auction-cordapp/contracts/src/main/java/net/corda/samples/states/Asset.java
+++ b/Advanced/auction-cordapp/contracts/src/main/java/net/corda/samples/auction/states/Asset.java
@@ -1,17 +1,15 @@
-package net.corda.samples.states;
+package net.corda.samples.auction.states;
-import com.google.common.collect.ImmutableList;
import net.corda.core.contracts.*;
import net.corda.core.identity.AbstractParty;
-import net.corda.samples.contracts.AssetContract;
-import net.corda.samples.contracts.AuctionContract;
+import net.corda.samples.auction.contracts.AssetContract;
import org.jetbrains.annotations.NotNull;
import java.util.Arrays;
import java.util.List;
/**
- * An ownable state to represent an asset that could be put on auction.
+ * An ownable states to represent an asset that could be put on auction.
*/
@BelongsToContract(AssetContract.class)
public class Asset implements OwnableState, LinearState {
@@ -44,11 +42,11 @@ public AbstractParty getOwner() {
}
/**
- * This method should be called to retrieve an ownership transfer command and the updated state with the new owner
+ * This method should be called to retrieve an ownership transfer command and the updated states with the new owner
* passed as a parameter to the method.
*
* @param newOwner of the asset
- * @return A CommandAndState object encapsulating the command and the new state with the changed owner, to be used
+ * @return A CommandAndState object encapsulating the command and the new states with the changed owner, to be used
* in the ownership transfer transaction.
*/
@NotNull
diff --git a/Advanced/auction-cordapp/contracts/src/main/java/net/corda/samples/states/AuctionState.java b/Advanced/auction-cordapp/contracts/src/main/java/net/corda/samples/auction/states/AuctionState.java
similarity index 94%
rename from Advanced/auction-cordapp/contracts/src/main/java/net/corda/samples/states/AuctionState.java
rename to Advanced/auction-cordapp/contracts/src/main/java/net/corda/samples/auction/states/AuctionState.java
index 85bb717c..b87f9deb 100644
--- a/Advanced/auction-cordapp/contracts/src/main/java/net/corda/samples/states/AuctionState.java
+++ b/Advanced/auction-cordapp/contracts/src/main/java/net/corda/samples/auction/states/AuctionState.java
@@ -1,11 +1,11 @@
-package net.corda.samples.states;
+package net.corda.samples.auction.states;
import net.corda.core.contracts.*;
import net.corda.core.flows.FlowLogicRef;
import net.corda.core.flows.FlowLogicRefFactory;
import net.corda.core.identity.AbstractParty;
import net.corda.core.identity.Party;
-import net.corda.samples.contracts.AuctionContract;
+import net.corda.samples.auction.contracts.AuctionContract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -63,7 +63,7 @@ public AuctionState(LinearPointer auctionItem, UUID auctionId, Amou
}
/**
- * This method returns a ScheduledActivity. The ScheduledActivity encapsulates a flow ref and a trigger time
+ * This method returns a ScheduledActivity. The ScheduledActivity encapsulates a flows ref and a trigger time
* to start the ScheduledFlow.
*
* @param thisStateRef
@@ -78,7 +78,7 @@ public ScheduledActivity nextScheduledActivity(@NotNull StateRef thisStateRef,
return null;
FlowLogicRef flowLogicRef = flowLogicRefFactory.create(
- "net.corda.samples.flows.EndAuctionFlow$Initiator", auctionId);
+ "net.corda.samples.auction.flows.EndAuctionFlow$EndAuctionInitiator", auctionId);
return new ScheduledActivity(flowLogicRef, bidEndTime);
}
diff --git a/Advanced/auction-cordapp/contracts/src/main/java/net/corda/samples/contracts/AssetContract.java b/Advanced/auction-cordapp/contracts/src/main/java/net/corda/samples/contracts/AssetContract.java
deleted file mode 100644
index 60d9c61a..00000000
--- a/Advanced/auction-cordapp/contracts/src/main/java/net/corda/samples/contracts/AssetContract.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package net.corda.samples.contracts;
-
-import net.corda.core.contracts.CommandData;
-import net.corda.core.contracts.Contract;
-import net.corda.core.transactions.LedgerTransaction;
-import org.jetbrains.annotations.NotNull;
-
-public class AssetContract implements Contract {
- @Override
- public void verify(@NotNull LedgerTransaction tx) throws IllegalArgumentException {
- // Contract Verification code goes here. Left blank for simplicity
- }
-
- public interface Commands extends CommandData {
- class CreateAsset implements Commands {}
- class TransferAsset implements Commands {}
- }
-}
diff --git a/Advanced/auction-cordapp/contracts/src/test/java/net/corda/samples/auction/contracts/ContractTests.java b/Advanced/auction-cordapp/contracts/src/test/java/net/corda/samples/auction/contracts/ContractTests.java
new file mode 100644
index 00000000..096aa6fd
--- /dev/null
+++ b/Advanced/auction-cordapp/contracts/src/test/java/net/corda/samples/auction/contracts/ContractTests.java
@@ -0,0 +1,94 @@
+package net.corda.samples.auction.contracts;
+
+import net.corda.core.contracts.Amount;
+import net.corda.core.identity.CordaX500Name;
+import net.corda.samples.auction.states.AuctionState;
+import net.corda.testing.core.TestIdentity;
+import net.corda.testing.node.MockServices;
+import org.junit.Test;
+
+import java.util.Arrays;
+
+import static net.corda.testing.node.NodeTestUtils.transaction;
+
+public class ContractTests {
+ private final TestIdentity alice = new TestIdentity(new CordaX500Name("Alice", "", "GB"));
+ private final TestIdentity bob = new TestIdentity(new CordaX500Name("Bob", "", "GB"));
+ private MockServices ledgerServices = new MockServices(new TestIdentity(new CordaX500Name("TestId", "", "GB")));
+
+
+ @Test
+ public void testVerifyBid() {
+ AuctionState input = new AuctionState(null, null, Amount.parseCurrency("100 USD"),
+ Amount.parseCurrency("200 USD"), null, null, null, true, null,
+ null, null);
+
+
+ AuctionState input_inactive = new AuctionState(null, null, Amount.parseCurrency("100 USD"),
+ Amount.parseCurrency("200 USD"), null, null, null, false, null,
+ null, null);
+
+ AuctionState output = new AuctionState(null, null, Amount.parseCurrency("100 USD"),
+ Amount.parseCurrency("220 USD"), null, null, null, true, null,
+ null, null);
+
+ AuctionState output_lt_basePrice = new AuctionState(null, null, Amount.parseCurrency("100 USD"),
+ Amount.parseCurrency("80 USD"), null, null, null, true, null,
+ null, null);
+
+
+ // Should fail auction is inactive
+ transaction(ledgerServices, tx -> {
+ tx.input(AuctionContract.ID, input_inactive);
+ tx.output(AuctionContract.ID, output);
+ tx.command(Arrays.asList(alice.getPublicKey(), bob.getPublicKey()), new AuctionContract.Commands.Bid());
+ tx.fails();
+ return null;
+ });
+
+
+ // Should fail bid price is less than base price
+ transaction(ledgerServices, tx -> {
+ tx.input(AuctionContract.ID, input);
+ tx.output(AuctionContract.ID, output_lt_basePrice);
+ tx.command(Arrays.asList(alice.getPublicKey(), bob.getPublicKey()), new AuctionContract.Commands.Bid());
+ tx.fails();
+ return null;
+ });
+
+ AuctionState output_lt_highestBid = new AuctionState(null, null, Amount.parseCurrency("100 USD"),
+ Amount.parseCurrency("180 USD"), null, null, null, true, null,
+ null, null);
+
+ // Should fail bid price is less than previous highest bid
+ transaction(ledgerServices, tx -> {
+ tx.input(AuctionContract.ID, input);
+ tx.output(AuctionContract.ID, output_lt_highestBid);
+ tx.command(Arrays.asList(alice.getPublicKey(), bob.getPublicKey()), new AuctionContract.Commands.Bid());
+ tx.fails();
+ return null;
+ });
+
+ AuctionState output_eq_highestBid = new AuctionState(null, null, Amount.parseCurrency("100 USD"),
+ Amount.parseCurrency("200 USD"), null, null, null, true, null,
+ null, null);
+
+ // Should fail bid price is equal to previous highest bid
+ transaction(ledgerServices, tx -> {
+ tx.input(AuctionContract.ID, input);
+ tx.output(AuctionContract.ID, output_eq_highestBid);
+ tx.command(Arrays.asList(alice.getPublicKey(), bob.getPublicKey()), new AuctionContract.Commands.Bid());
+ tx.fails();
+ return null;
+ });
+
+ //Should verify
+ transaction(ledgerServices, tx -> {
+ tx.input(AuctionContract.ID, input);
+ tx.output(AuctionContract.ID, output);
+ tx.command(Arrays.asList(alice.getPublicKey(), bob.getPublicKey()), new AuctionContract.Commands.Bid());
+ tx.verifies();
+ return null;
+ });
+ }
+}
\ No newline at end of file
diff --git a/Advanced/auction-cordapp/contracts/src/test/java/net/corda/samples/auction/contracts/StateTests.java b/Advanced/auction-cordapp/contracts/src/test/java/net/corda/samples/auction/contracts/StateTests.java
new file mode 100644
index 00000000..e83bbc21
--- /dev/null
+++ b/Advanced/auction-cordapp/contracts/src/test/java/net/corda/samples/auction/contracts/StateTests.java
@@ -0,0 +1,20 @@
+package net.corda.samples.auction.contracts;
+
+import net.corda.core.contracts.UniqueIdentifier;
+import net.corda.samples.auction.states.AuctionState;
+import net.corda.testing.node.MockServices;
+import org.junit.Test;
+
+import java.util.UUID;
+
+public class StateTests {
+ private final MockServices ledgerServices = new MockServices();
+
+ @Test
+ public void hasFieldOfCorrectType() throws NoSuchFieldException {
+ // Does the message field exist?
+ AuctionState.class.getDeclaredField("auctionId");
+ // Is the message field of the correct type?
+ assert(AuctionState.class.getDeclaredField("auctionId").getType().equals(UUID.class));
+ }
+}
\ No newline at end of file
diff --git a/Advanced/auction-cordapp/contracts/src/test/java/net/corda/samples/contracts/ContractTests.java b/Advanced/auction-cordapp/contracts/src/test/java/net/corda/samples/contracts/ContractTests.java
deleted file mode 100644
index 733be464..00000000
--- a/Advanced/auction-cordapp/contracts/src/test/java/net/corda/samples/contracts/ContractTests.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package net.corda.samples.contracts;
-
-import net.corda.testing.node.MockServices;
-import org.junit.Test;
-
-public class ContractTests {
- private final MockServices ledgerServices = new MockServices();
-
- @Test
- public void dummyTest() {
-
- }
-}
\ No newline at end of file
diff --git a/Advanced/auction-cordapp/gradle.properties b/Advanced/auction-cordapp/gradle.properties
index 10468f74..edd7041f 100644
--- a/Advanced/auction-cordapp/gradle.properties
+++ b/Advanced/auction-cordapp/gradle.properties
@@ -1,3 +1,3 @@
name=Auction CorDapp
-group=net.corda.samples
-version=1.0
\ No newline at end of file
+group=com.auction
+version=1.0
diff --git a/Advanced/auction-cordapp/gradle/wrapper/gradle-wrapper.properties b/Advanced/auction-cordapp/gradle/wrapper/gradle-wrapper.properties
index 857061e8..504900f7 100644
--- a/Advanced/auction-cordapp/gradle/wrapper/gradle-wrapper.properties
+++ b/Advanced/auction-cordapp/gradle/wrapper/gradle-wrapper.properties
@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https://services.gradle.org/distributions/gradle-5.4.1-all.zip
+distributionUrl=https://services.gradle.org/distributions/gradle-5.6.4-all.zip
diff --git a/Advanced/auction-cordapp/workflows/src/integrationTest/java/net/corda/samples/DriverBasedTest.java b/Advanced/auction-cordapp/workflows/src/integrationTest/java/net/corda/samples/DriverBasedTest.java
deleted file mode 100644
index 4f66f387..00000000
--- a/Advanced/auction-cordapp/workflows/src/integrationTest/java/net/corda/samples/DriverBasedTest.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package net.corda.samples;
-
-import com.google.common.collect.ImmutableList;
-import net.corda.core.concurrent.CordaFuture;
-import net.corda.core.identity.CordaX500Name;
-import net.corda.testing.core.TestIdentity;
-import net.corda.testing.driver.DriverParameters;
-import net.corda.testing.driver.NodeHandle;
-import net.corda.testing.driver.NodeParameters;
-import org.junit.Test;
-
-import java.util.List;
-
-import static net.corda.testing.driver.Driver.driver;
-import static org.junit.Assert.assertEquals;
-
-public class DriverBasedTest {
- private final TestIdentity bankA = new TestIdentity(new CordaX500Name("BankA", "", "GB"));
- private final TestIdentity bankB = new TestIdentity(new CordaX500Name("BankB", "", "US"));
-
- @Test
- public void nodeTest() {
- driver(new DriverParameters().withIsDebug(true).withStartNodesInProcess(true), dsl -> {
- // Start a pair of nodes and wait for them both to be ready.
- List> handleFutures = ImmutableList.of(
- dsl.startNode(new NodeParameters().withProvidedName(bankA.getName())),
- dsl.startNode(new NodeParameters().withProvidedName(bankB.getName()))
- );
-
- try {
- NodeHandle partyAHandle = handleFutures.get(0).get();
- NodeHandle partyBHandle = handleFutures.get(1).get();
-
- // From each node, make an RPC call to retrieve another node's name from the network map, to verify that the
- // nodes have started and can communicate.
-
- // This is a very basic test: in practice tests would be starting flows, and verifying the states in the vault
- // and other important metrics to ensure that your CorDapp is working as intended.
- assertEquals(partyAHandle.getRpc().wellKnownPartyFromX500Name(bankB.getName()).getName(), bankB.getName());
- assertEquals(partyBHandle.getRpc().wellKnownPartyFromX500Name(bankA.getName()).getName(), bankA.getName());
- } catch (Exception e) {
- throw new RuntimeException("Caught exception during test: ", e);
- }
-
- return null;
- });
- }
-}
\ No newline at end of file
diff --git a/Advanced/auction-cordapp/workflows/src/integrationTest/java/net/corda/samples/auction/DriverBasedTest.java b/Advanced/auction-cordapp/workflows/src/integrationTest/java/net/corda/samples/auction/DriverBasedTest.java
new file mode 100644
index 00000000..4fe5bf2a
--- /dev/null
+++ b/Advanced/auction-cordapp/workflows/src/integrationTest/java/net/corda/samples/auction/DriverBasedTest.java
@@ -0,0 +1,48 @@
+package net.corda.samples.auction;
+
+import com.google.common.collect.ImmutableList;
+import net.corda.core.concurrent.CordaFuture;
+import net.corda.core.identity.CordaX500Name;
+import net.corda.testing.core.TestIdentity;
+import net.corda.testing.driver.DriverParameters;
+import net.corda.testing.driver.NodeHandle;
+import net.corda.testing.driver.NodeParameters;
+import org.junit.Test;
+
+import java.util.List;
+
+import static net.corda.testing.driver.Driver.driver;
+import static org.junit.Assert.assertEquals;
+
+public class DriverBasedTest {
+ private final TestIdentity bankA = new TestIdentity(new CordaX500Name("BankA", "", "GB"));
+ private final TestIdentity bankB = new TestIdentity(new CordaX500Name("BankB", "", "US"));
+
+ @Test
+ public void nodeTest() {
+ driver(new DriverParameters().withIsDebug(true).withStartNodesInProcess(true), dsl -> {
+ // Start a pair of nodes and wait for them both to be ready.
+ List> handleFutures = ImmutableList.of(
+ dsl.startNode(new NodeParameters().withProvidedName(bankA.getName())),
+ dsl.startNode(new NodeParameters().withProvidedName(bankB.getName()))
+ );
+
+ try {
+ NodeHandle partyAHandle = handleFutures.get(0).get();
+ NodeHandle partyBHandle = handleFutures.get(1).get();
+
+ // From each node, make an RPC call to retrieve another node's name from the network map, to verify that the
+ // nodes have started and can communicate.
+
+ // This is a very basic test: in practice tests would be starting flows, and verifying the states in the vault
+ // and other important metrics to ensure that your CorDapp is working as intended.
+ assertEquals(partyAHandle.getRpc().wellKnownPartyFromX500Name(bankB.getName()).getName(), bankB.getName());
+ assertEquals(partyBHandle.getRpc().wellKnownPartyFromX500Name(bankA.getName()).getName(), bankA.getName());
+ } catch (Exception e) {
+ throw new RuntimeException("Caught exception during test: ", e);
+ }
+
+ return null;
+ });
+ }
+}
diff --git a/Advanced/auction-cordapp/workflows/src/main/java/net/corda/samples/flows/AuctionDvPFlow.java b/Advanced/auction-cordapp/workflows/src/main/java/net/corda/samples/auction/flows/AuctionDvPFlow.java
similarity index 78%
rename from Advanced/auction-cordapp/workflows/src/main/java/net/corda/samples/flows/AuctionDvPFlow.java
rename to Advanced/auction-cordapp/workflows/src/main/java/net/corda/samples/auction/flows/AuctionDvPFlow.java
index 64ea23c7..e4321c63 100644
--- a/Advanced/auction-cordapp/workflows/src/main/java/net/corda/samples/flows/AuctionDvPFlow.java
+++ b/Advanced/auction-cordapp/workflows/src/main/java/net/corda/samples/auction/flows/AuctionDvPFlow.java
@@ -1,4 +1,4 @@
-package net.corda.samples.flows;
+package net.corda.samples.auction.flows;
import co.paralleluniverse.fibers.Suspendable;
import kotlin.Pair;
@@ -11,11 +11,9 @@
import net.corda.core.node.services.vault.QueryCriteria;
import net.corda.core.transactions.SignedTransaction;
import net.corda.core.transactions.TransactionBuilder;
-import net.corda.finance.contracts.asset.OnLedgerAsset;
-import net.corda.finance.contracts.asset.PartyAndAmount;
import net.corda.finance.workflows.asset.CashUtils;
-import net.corda.samples.states.Asset;
-import net.corda.samples.states.AuctionState;
+import net.corda.samples.auction.states.Asset;
+import net.corda.samples.auction.states.AuctionState;
import org.jetbrains.annotations.NotNull;
@@ -23,7 +21,7 @@
import java.util.*;
/**
- * This flow takes care of the delivery-vs-payment for settlement of the auction. The auctioned asset's ownership is
+ * This flows takes care of the delivery-vs-payment for settlement of the auction. The auctioned asset's ownership is
* transferred from the auctioneer to the highest bidder and the bid amount is transferred from the highest bidder to
* the auctioneer in a single atomic transaction.
*/
@@ -31,19 +29,19 @@ public class AuctionDvPFlow {
@StartableByRPC
@InitiatingFlow
- public static class Initiator extends FlowLogic{
+ public static class AuctionDvPInitiator extends FlowLogic{
private final UUID auctionId;
private final Amount payment;
/**
- * Constructor to initialise flow parameters.
+ * Constructor to initialise flows parameters.
*
* @param auctionId is the unique id of the auction to be settled
* @param payment is the bid amount which is required to be transferred from the highest bidded to auctioneer to
* settle the auction.
*/
- public Initiator(UUID auctionId, Amount payment) {
+ public AuctionDvPInitiator(UUID auctionId, Amount payment) {
this.auctionId = auctionId;
this.payment = payment;
}
@@ -52,8 +50,8 @@ public Initiator(UUID auctionId, Amount payment) {
@Suspendable
public SignedTransaction call() throws FlowException {
- // Query the vault to fetch a list of all AuctionState state, and filter the results based on the auctionId
- // to fetch the desired AuctionState state from the vault.
+ // Query the vault to fetch a list of all AuctionState states, and filter the results based on the auctionId
+ // to fetch the desired AuctionState states from the vault.
List> auntionStateAndRefs = getServiceHub().getVaultService()
.queryBy(AuctionState.class).getStates();
StateAndRef auctionStateAndRef = auntionStateAndRefs.stream().filter(stateAndRef -> {
@@ -75,19 +73,14 @@ public SignedTransaction call() throws FlowException {
StateAndRef assetStateAndRef = getServiceHub().getVaultService().
queryBy(Asset.class, queryCriteria).getStates().get(0);
- // Use the withNewOwner() of the Ownable state get the command and the output state to be used in the
+ // Use the withNewOwner() of the Ownable states get the command and the output states to be used in the
// transaction from ownership transfer of the asset.
CommandAndState commandAndState = assetStateAndRef.getState().getData()
.withNewOwner(auctionState.getWinner());
// Obtain a reference to a notary we wish to use.
- /** METHOD 1: Take first notary on network, WARNING: use for test, non-prod environments, and single-notary networks only!*
- * METHOD 2: Explicit selection of notary by CordaX500Name - argument can by coded in flow or parsed from config (Preferred)
- *
- * * - For production you always want to use Method 2 as it guarantees the expected notary is returned.
- */
- final Party notary = getServiceHub().getNetworkMapCache().getNotaryIdentities().get(0); // METHOD 1
- // final Party notary = getServiceHub().getNetworkMapCache().getNotary(CordaX500Name.parse("O=Notary,L=London,C=GB")); // METHOD 2
+ /** Explicit selection of notary by CordaX500Name - argument can by coded in flows or parsed from config (Preferred)*/
+ final Party notary = auctionStateAndRef.getState().getNotary();
// Create the transaction builder.
TransactionBuilder transactionBuilder = new TransactionBuilder(notary);
@@ -126,12 +119,12 @@ public SignedTransaction call() throws FlowException {
}
}
- @InitiatedBy(Initiator.class)
- public static class Responder extends FlowLogic{
+ @InitiatedBy(AuctionDvPInitiator.class)
+ public static class AuctionDvPResponder extends FlowLogic{
private FlowSession otherPartySession;
- public Responder(FlowSession otherPartySession) {
+ public AuctionDvPResponder(FlowSession otherPartySession) {
this.otherPartySession = otherPartySession;
}
diff --git a/Advanced/auction-cordapp/workflows/src/main/java/net/corda/samples/flows/AuctionExitFlow.java b/Advanced/auction-cordapp/workflows/src/main/java/net/corda/samples/auction/flows/AuctionExitFlow.java
similarity index 85%
rename from Advanced/auction-cordapp/workflows/src/main/java/net/corda/samples/flows/AuctionExitFlow.java
rename to Advanced/auction-cordapp/workflows/src/main/java/net/corda/samples/auction/flows/AuctionExitFlow.java
index 1eeec8ad..7a4a3b54 100644
--- a/Advanced/auction-cordapp/workflows/src/main/java/net/corda/samples/flows/AuctionExitFlow.java
+++ b/Advanced/auction-cordapp/workflows/src/main/java/net/corda/samples/auction/flows/AuctionExitFlow.java
@@ -1,4 +1,4 @@
-package net.corda.samples.flows;
+package net.corda.samples.auction.flows;
import co.paralleluniverse.fibers.Suspendable;
import net.corda.core.contracts.StateAndRef;
@@ -6,8 +6,8 @@
import net.corda.core.identity.Party;
import net.corda.core.transactions.SignedTransaction;
import net.corda.core.transactions.TransactionBuilder;
-import net.corda.samples.contracts.AuctionContract;
-import net.corda.samples.states.AuctionState;
+import net.corda.samples.auction.contracts.AuctionContract;
+import net.corda.samples.auction.states.AuctionState;
import org.jetbrains.annotations.NotNull;
import java.security.PublicKey;
@@ -17,26 +17,24 @@
import java.util.UUID;
/**
- * This flow is used to exit an auction state once it has been settled or auction did not received bids till the
+ * This flows is used to exit an auction states once it has been settled or auction did not received bids till the
* deadline.
*
- * The flow is initiated by the highest bidder in case as part of auction settlement flow.
+ * The flows is initiated by the highest bidder in case as part of auction settlement flows.
* In case of no bids received, it can be initiated by the auctioneer to exit the auction.
*/
public class AuctionExitFlow {
- private AuctionExitFlow(){}
-
@StartableByRPC
@InitiatingFlow
- public static class Initiator extends FlowLogic{
+ public static class AuctionExitInitiator extends FlowLogic{
private UUID auctionId;
/**
*
* @param auctionId is the unique id of the auction to be consumed.
*/
- public Initiator(UUID auctionId) {
+ public AuctionExitInitiator(UUID auctionId) {
this.auctionId = auctionId;
}
@@ -44,8 +42,8 @@ public Initiator(UUID auctionId) {
@Suspendable
public SignedTransaction call() throws FlowException {
- // Query the vault to fetch a list of all AuctionState state, and filter the results based on the auctionId
- // to fetch the desired AuctionState state from the vault. This filtered state would be used as input to the
+ // Query the vault to fetch a list of all AuctionState states, and filter the results based on the auctionId
+ // to fetch the desired AuctionState states from the vault. This filtered states would be used as input to the
// transaction.
List> auntionStateAndRefs = getServiceHub().getVaultService()
.queryBy(AuctionState.class).getStates();
@@ -106,11 +104,11 @@ public SignedTransaction call() throws FlowException {
}
}
- @InitiatedBy(Initiator.class)
- public static class Responder extends FlowLogic {
+ @InitiatedBy(AuctionExitInitiator.class)
+ public static class AuctionExitResponder extends FlowLogic {
private FlowSession otherPartySession;
- public Responder(FlowSession otherPartySession) {
+ public AuctionExitResponder(FlowSession otherPartySession) {
this.otherPartySession = otherPartySession;
}
diff --git a/Advanced/auction-cordapp/workflows/src/main/java/net/corda/samples/auction/flows/AuctionSettlementFlow.java b/Advanced/auction-cordapp/workflows/src/main/java/net/corda/samples/auction/flows/AuctionSettlementFlow.java
new file mode 100644
index 00000000..3218d4e5
--- /dev/null
+++ b/Advanced/auction-cordapp/workflows/src/main/java/net/corda/samples/auction/flows/AuctionSettlementFlow.java
@@ -0,0 +1,48 @@
+package net.corda.samples.auction.flows;
+
+import co.paralleluniverse.fibers.Suspendable;
+import net.corda.core.contracts.Amount;
+import net.corda.core.flows.FlowException;
+import net.corda.core.flows.FlowLogic;
+import net.corda.core.flows.StartableByRPC;
+import net.corda.samples.auction.flows.AuctionDvPFlow;
+import net.corda.samples.auction.flows.AuctionExitFlow;
+
+import java.util.Currency;
+import java.util.UUID;
+
+/**
+ * This purpose of this flows is the settle the auction which includes:
+ * - Transferring the highest bid amount to the auctioneer.
+ * - Transferring the auctioned asset's ownership to the highest bidder
+ * - Consuming the auction states.
+ *
+ * The AuctionDvPFlow does the delivery-vs-payment of the auctioned asset and the bid amount.
+ * The AuctionExitFlow consumes the auction states.
+ */
+@StartableByRPC
+public class AuctionSettlementFlow extends FlowLogic {
+
+ private final UUID auctionId;
+ private final Amount amount;
+
+ /**
+ * Constructor to initialise flows parameters received from rpc.
+ *
+ * @param auctionId is the unique id of the auction to be settled
+ * @param amount is the bid amount which is required to be transferred from the highest bidded to auctioneer to
+ * settle the auction.
+ */
+ public AuctionSettlementFlow(UUID auctionId, Amount amount) {
+ this.auctionId = auctionId;
+ this.amount = amount;
+ }
+
+ @Override
+ @Suspendable
+ public Void call() throws FlowException {
+ subFlow(new AuctionDvPFlow.AuctionDvPInitiator(auctionId, amount));
+ subFlow(new AuctionExitFlow.AuctionExitInitiator(auctionId));
+ return null;
+ }
+}
diff --git a/Advanced/auction-cordapp/workflows/src/main/java/net/corda/samples/flows/BidFlow.java b/Advanced/auction-cordapp/workflows/src/main/java/net/corda/samples/auction/flows/BidFlow.java
similarity index 77%
rename from Advanced/auction-cordapp/workflows/src/main/java/net/corda/samples/flows/BidFlow.java
rename to Advanced/auction-cordapp/workflows/src/main/java/net/corda/samples/auction/flows/BidFlow.java
index 60399463..d91976fa 100644
--- a/Advanced/auction-cordapp/workflows/src/main/java/net/corda/samples/flows/BidFlow.java
+++ b/Advanced/auction-cordapp/workflows/src/main/java/net/corda/samples/auction/flows/BidFlow.java
@@ -1,4 +1,4 @@
-package net.corda.samples.flows;
+package net.corda.samples.auction.flows;
import co.paralleluniverse.fibers.Suspendable;
import net.corda.core.contracts.Amount;
@@ -7,32 +7,30 @@
import net.corda.core.identity.Party;
import net.corda.core.transactions.SignedTransaction;
import net.corda.core.transactions.TransactionBuilder;
-import net.corda.samples.contracts.AuctionContract;
-import net.corda.samples.states.AuctionState;
+import net.corda.samples.auction.contracts.AuctionContract;
+import net.corda.samples.auction.states.AuctionState;
import java.util.*;
/**
- * This flow is used to put a bid on an asset put on auction.
+ * This flows is used to put a bid on an asset put on auction.
*/
public class BidFlow {
- private BidFlow(){}
-
@InitiatingFlow
@StartableByRPC
- public static class Initiator extends FlowLogic{
+ public static class BidInitiator extends FlowLogic{
private final Amount bidAmount;
private final UUID auctionId;
/**
- * Constructor to initialise flow parameters received from rpc.
+ * Constructor to initialise flows parameters received from rpc.
*
* @param bidAmount is the amount the bidder is bidding for for the asset on auction.
* @param auctionId is the unique identifier of the auction on which this bid it put.
*/
- public Initiator(Amount bidAmount, UUID auctionId) {
+ public BidInitiator(Amount bidAmount, UUID auctionId) {
this.bidAmount = bidAmount;
this.auctionId = auctionId;
}
@@ -41,8 +39,8 @@ public Initiator(Amount bidAmount, UUID auctionId) {
@Suspendable
public SignedTransaction call() throws FlowException {
- // Query the vault to fetch a list of all AuctionState state, and filter the results based on the auctionId
- // to fetch the desired AuctionState state from the vault. This filtered state would be used as input to the
+ // Query the vault to fetch a list of all AuctionState states, and filter the results based on the auctionId
+ // to fetch the desired AuctionState states from the vault. This filtered states would be used as input to the
// transaction.
List> auntionStateAndRefs = getServiceHub().getVaultService()
.queryBy(AuctionState.class).getStates();
@@ -56,13 +54,13 @@ public SignedTransaction call() throws FlowException {
AuctionState input = inputStateAndRef.getState().getData();
- //Create the output state
+ //Create the output states
AuctionState output = new AuctionState(input.getAuctionItem(), input.getAuctionId(), input.getBasePrice(),
bidAmount, getOurIdentity(), input.getBidEndTime(), null, true,
input.getAuctioneer(), input.getBidders(), null);
- // Build the transaction. On successful completion of the transaction the current auction state is consumed
- // and a new auction state is create as an output containg tge bid details.
+ // Build the transaction. On successful completion of the transaction the current auction states is consumed
+ // and a new auction states is create as an output containg tge bid details.
TransactionBuilder builder = new TransactionBuilder(inputStateAndRef.getState().getNotary())
.addInputState(inputStateAndRef)
.addOutputState(output)
@@ -86,12 +84,12 @@ bidAmount, getOurIdentity(), input.getBidEndTime(), null, true,
}
}
- @InitiatedBy(Initiator.class)
- public static class Responder extends FlowLogic {
+ @InitiatedBy(BidInitiator.class)
+ public static class BidResponder extends FlowLogic {
private FlowSession counterpartySession;
- public Responder(FlowSession counterpartySession) {
+ public BidResponder(FlowSession counterpartySession) {
this.counterpartySession = counterpartySession;
}
@@ -101,4 +99,4 @@ public SignedTransaction call() throws FlowException {
return subFlow(new ReceiveFinalityFlow(counterpartySession));
}
}
-}
\ No newline at end of file
+}
diff --git a/Advanced/auction-cordapp/workflows/src/main/java/net/corda/samples/auction/flows/CreateAssetFlow.java b/Advanced/auction-cordapp/workflows/src/main/java/net/corda/samples/auction/flows/CreateAssetFlow.java
new file mode 100644
index 00000000..dc95df45
--- /dev/null
+++ b/Advanced/auction-cordapp/workflows/src/main/java/net/corda/samples/auction/flows/CreateAssetFlow.java
@@ -0,0 +1,68 @@
+package net.corda.samples.auction.flows;
+
+import co.paralleluniverse.fibers.Suspendable;
+import net.corda.core.contracts.UniqueIdentifier;
+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.samples.auction.contracts.AssetContract;
+import net.corda.samples.auction.states.Asset;
+import net.corda.core.identity.CordaX500Name;
+
+import java.util.Arrays;
+import java.util.Collections;
+
+
+/**
+ * This flows is used to build a transaction to issue an asset on the Corda Ledger, which can later be put on auction.
+ * It creates a self issues transaction, the states is only issued on the ledger of the party who executes the flows.
+ */
+@StartableByRPC
+public class CreateAssetFlow extends FlowLogic {
+
+ private final String title;
+ private final String description;
+ private final String imageURL;
+
+ /**
+ * Constructor to initialise flows parameters received from rpc.
+ *
+ * @param title of the asset to be issued on ledger
+ * @param description of the asset to be issued in ledger
+ * @param imageURL is a url of an image of the asset
+ */
+ public CreateAssetFlow(String title, String description, String imageURL) {
+ this.title = title;
+ this.description = description;
+ this.imageURL = imageURL;
+ }
+
+
+ @Override
+ @Suspendable
+ public SignedTransaction call() throws FlowException {
+ // Obtain a reference to a notary we wish to use.
+ /** Explicit selection of notary by CordaX500Name - argument can by coded in flows or parsed from config (Preferred)*/
+ final Party notary = getServiceHub().getNetworkMapCache().getNotary(CordaX500Name.parse("O=Notary,L=London,C=GB"));
+
+ // Create the output states
+ Asset output = new Asset(new UniqueIdentifier(), title, description, imageURL,
+ getOurIdentity());
+
+ // Build the transaction, add the output states and the command to the transaction.
+ TransactionBuilder transactionBuilder = new TransactionBuilder(notary)
+ .addOutputState(output)
+ .addCommand(new AssetContract.Commands.CreateAsset(),
+ Arrays.asList(getOurIdentity().getOwningKey())); // Required Signers
+
+ // Verify the transaction
+ transactionBuilder.verify(getServiceHub());
+
+ // Sign the transaction
+ SignedTransaction signedTransaction = getServiceHub().signInitialTransaction(transactionBuilder);
+
+ // Notarise the transaction and record the states in the ledger.
+ return subFlow(new FinalityFlow(signedTransaction, Collections.emptyList()));
+ }
+}
diff --git a/Advanced/auction-cordapp/workflows/src/main/java/net/corda/samples/flows/CreateAuctionFlow.java b/Advanced/auction-cordapp/workflows/src/main/java/net/corda/samples/auction/flows/CreateAuctionFlow.java
similarity index 75%
rename from Advanced/auction-cordapp/workflows/src/main/java/net/corda/samples/flows/CreateAuctionFlow.java
rename to Advanced/auction-cordapp/workflows/src/main/java/net/corda/samples/auction/flows/CreateAuctionFlow.java
index 6cb204ea..b9b1ccd8 100644
--- a/Advanced/auction-cordapp/workflows/src/main/java/net/corda/samples/flows/CreateAuctionFlow.java
+++ b/Advanced/auction-cordapp/workflows/src/main/java/net/corda/samples/auction/flows/CreateAuctionFlow.java
@@ -1,4 +1,5 @@
-package net.corda.samples.flows;
+package net.corda.samples.auction.flows;
+
import co.paralleluniverse.fibers.Suspendable;
import net.corda.core.contracts.Amount;
@@ -6,12 +7,14 @@
import net.corda.core.contracts.LinearState;
import net.corda.core.contracts.UniqueIdentifier;
import net.corda.core.flows.*;
+import net.corda.core.identity.CordaX500Name;
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.samples.contracts.AuctionContract;
-import net.corda.samples.states.AuctionState;
+import net.corda.samples.auction.contracts.AuctionContract;
+import net.corda.samples.auction.states.AuctionState;
+import net.corda.core.identity.CordaX500Name;
import java.time.LocalDateTime;
import java.time.ZoneId;
@@ -23,11 +26,9 @@
*/
public class CreateAuctionFlow {
- private CreateAuctionFlow(){}
-
@InitiatingFlow
@StartableByRPC
- public static class Initiator extends FlowLogic {
+ public static class CreateAuctionInitiator extends FlowLogic {
private final ProgressTracker progressTracker = new ProgressTracker();
@@ -42,7 +43,7 @@ public static class Initiator extends FlowLogic {
* @param auctionItem is the uuid of the asset to be put on auction
* @param bidDeadLine is the time till when the auction will be active
*/
- public Initiator(Amount basePrice, UUID auctionItem, LocalDateTime bidDeadLine) {
+ public CreateAuctionInitiator(Amount basePrice, UUID auctionItem, LocalDateTime bidDeadLine) {
this.basePrice = basePrice;
this.auctionItem = auctionItem;
this.bidDeadLine = bidDeadLine;
@@ -57,13 +58,8 @@ public ProgressTracker getProgressTracker() {
@Override
public SignedTransaction call() throws FlowException {
// Obtain a reference to a notary we wish to use.
- /** METHOD 1: Take first notary on network, WARNING: use for test, non-prod environments, and single-notary networks only!*
- * METHOD 2: Explicit selection of notary by CordaX500Name - argument can by coded in flow or parsed from config (Preferred)
- *
- * * - For production you always want to use Method 2 as it guarantees the expected notary is returned.
- */
- final Party notary = getServiceHub().getNetworkMapCache().getNotaryIdentities().get(0); // METHOD 1
- // final Party notary = getServiceHub().getNetworkMapCache().getNotary(CordaX500Name.parse("O=Notary,L=London,C=GB")); // METHOD 2
+ /** Explicit selection of notary by CordaX500Name - argument can by coded in flows or parsed from config (Preferred)*/
+ final Party notary = getServiceHub().getNetworkMapCache().getNotary(CordaX500Name.parse("O=Notary,L=London,C=GB"));
Party auctioneer = getOurIdentity();
@@ -85,8 +81,8 @@ public SignedTransaction call() throws FlowException {
// Build the transaction
TransactionBuilder builder = new TransactionBuilder(notary)
- .addOutputState(auctionState)
- .addCommand(new AuctionContract.Commands.CreateAuction(), Arrays.asList(auctioneer.getOwningKey()));
+ .addOutputState(auctionState)
+ .addCommand(new AuctionContract.Commands.CreateAuction(), Arrays.asList(auctioneer.getOwningKey()));
// Verify the transaction
builder.verify(getServiceHub());
@@ -103,12 +99,12 @@ public SignedTransaction call() throws FlowException {
}
}
- @InitiatedBy(Initiator.class)
- public static class Responder extends FlowLogic {
+ @InitiatedBy(CreateAuctionInitiator.class)
+ public static class CreateAuctionResponder extends FlowLogic {
private FlowSession counterpartySession;
- public Responder(FlowSession counterpartySession) {
+ public CreateAuctionResponder(FlowSession counterpartySession) {
this.counterpartySession = counterpartySession;
}
diff --git a/Advanced/auction-cordapp/workflows/src/main/java/net/corda/samples/flows/EndAuctionFlow.java b/Advanced/auction-cordapp/workflows/src/main/java/net/corda/samples/auction/flows/EndAuctionFlow.java
similarity index 89%
rename from Advanced/auction-cordapp/workflows/src/main/java/net/corda/samples/flows/EndAuctionFlow.java
rename to Advanced/auction-cordapp/workflows/src/main/java/net/corda/samples/auction/flows/EndAuctionFlow.java
index f07c2737..720dc8ce 100644
--- a/Advanced/auction-cordapp/workflows/src/main/java/net/corda/samples/flows/EndAuctionFlow.java
+++ b/Advanced/auction-cordapp/workflows/src/main/java/net/corda/samples/auction/flows/EndAuctionFlow.java
@@ -1,4 +1,4 @@
-package net.corda.samples.flows;
+package net.corda.samples.auction.flows;
import co.paralleluniverse.fibers.Suspendable;
import net.corda.core.contracts.StateAndRef;
@@ -6,8 +6,8 @@
import net.corda.core.identity.Party;
import net.corda.core.transactions.SignedTransaction;
import net.corda.core.transactions.TransactionBuilder;
-import net.corda.samples.contracts.AuctionContract;
-import net.corda.samples.states.AuctionState;
+import net.corda.samples.auction.contracts.AuctionContract;
+import net.corda.samples.auction.states.AuctionState;
import java.util.ArrayList;
import java.util.List;
@@ -19,18 +19,16 @@
*/
public class EndAuctionFlow {
- private EndAuctionFlow() {}
-
//Scheduled Flows must be annotated with @SchedulableFlow.
@SchedulableFlow
@InitiatingFlow
- public static class Initiator extends FlowLogic{
+ public static class EndAuctionInitiator extends FlowLogic{
private final UUID auctionId;
/**
* @param auctionId is the unique identifier of the auction to be closed.
*/
- public Initiator(UUID auctionId) {
+ public EndAuctionInitiator(UUID auctionId) {
this.auctionId = auctionId;
}
@@ -84,12 +82,12 @@ public SignedTransaction call() throws FlowException {
}
- @InitiatedBy(Initiator.class)
- public static class Responder extends FlowLogic {
+ @InitiatedBy(EndAuctionInitiator.class)
+ public static class EndAuctionResponder extends FlowLogic {
private FlowSession counterpartySession;
- public Responder(FlowSession counterpartySession) {
+ public EndAuctionResponder(FlowSession counterpartySession) {
this.counterpartySession = counterpartySession;
}
diff --git a/Advanced/auction-cordapp/workflows/src/main/java/net/corda/samples/flows/AuctionSettlementFlow.java b/Advanced/auction-cordapp/workflows/src/main/java/net/corda/samples/flows/AuctionSettlementFlow.java
deleted file mode 100644
index 9522076f..00000000
--- a/Advanced/auction-cordapp/workflows/src/main/java/net/corda/samples/flows/AuctionSettlementFlow.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package net.corda.samples.flows;
-
-import co.paralleluniverse.fibers.Suspendable;
-import net.corda.core.contracts.Amount;
-import net.corda.core.flows.FlowException;
-import net.corda.core.flows.FlowLogic;
-import net.corda.core.flows.StartableByRPC;
-
-import java.util.Currency;
-import java.util.UUID;
-
-/**
- * This purpose of this flow is the settle the auction which includes:
- * - Transferring the highest bid amount to the auctioneer.
- * - Transferring the auctioned asset's ownership to the highest bidder
- * - Consuming the auction state.
- *
- * The AuctionDvPFlow does the delivery-vs-payment of the auctioned asset and the bid amount.
- * The AuctionExitFlow consumes the auction state.
- */
-@StartableByRPC
-public class AuctionSettlementFlow extends FlowLogic {
-
- private final UUID auctionId;
- private final Amount amount;
-
- /**
- * Constructor to initialise flow parameters received from rpc.
- *
- * @param auctionId is the unique id of the auction to be settled
- * @param amount is the bid amount which is required to be transferred from the highest bidded to auctioneer to
- * settle the auction.
- */
- public AuctionSettlementFlow(UUID auctionId, Amount amount) {
- this.auctionId = auctionId;
- this.amount = amount;
- }
-
- @Override
- @Suspendable
- public Void call() throws FlowException {
- subFlow(new AuctionDvPFlow.Initiator(auctionId, amount));
- subFlow(new AuctionExitFlow.Initiator(auctionId));
- return null;
- }
-}
\ No newline at end of file
diff --git a/Advanced/auction-cordapp/workflows/src/main/java/net/corda/samples/flows/CreateAssetFlow.java b/Advanced/auction-cordapp/workflows/src/main/java/net/corda/samples/flows/CreateAssetFlow.java
deleted file mode 100644
index 58934d97..00000000
--- a/Advanced/auction-cordapp/workflows/src/main/java/net/corda/samples/flows/CreateAssetFlow.java
+++ /dev/null
@@ -1,73 +0,0 @@
-package net.corda.samples.flows;
-
-import co.paralleluniverse.fibers.Suspendable;
-import net.corda.core.contracts.UniqueIdentifier;
-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.samples.contracts.AssetContract;
-import net.corda.samples.states.Asset;
-
-import java.util.Arrays;
-import java.util.Collections;
-
-
-/**
- * This flow is used to build a transaction to issue an asset on the Corda Ledger, which can later be put on auction.
- * It creates a self issues transaction, the state is only issued on the ledger of the party who executes the flow.
- */
-@InitiatingFlow
-@StartableByRPC
-public class CreateAssetFlow extends FlowLogic {
-
- private final String title;
- private final String description;
- private final String imageURL;
-
- /**
- * Constructor to initialise flow parameters received from rpc.
- *
- * @param title of the asset to be issued on ledger
- * @param description of the asset to be issued in ledger
- * @param imageURL is a url of an image of the asset
- */
- public CreateAssetFlow(String title, String description, String imageURL) {
- this.title = title;
- this.description = description;
- this.imageURL = imageURL;
- }
-
-
- @Override
- @Suspendable
- public SignedTransaction call() throws FlowException {
- // Obtain a reference to a notary we wish to use.
- /** METHOD 1: Take first notary on network, WARNING: use for test, non-prod environments, and single-notary networks only!*
- * METHOD 2: Explicit selection of notary by CordaX500Name - argument can by coded in flow or parsed from config (Preferred)
- *
- * * - For production you always want to use Method 2 as it guarantees the expected notary is returned.
- */
- final Party notary = getServiceHub().getNetworkMapCache().getNotaryIdentities().get(0); // METHOD 1
- // final Party notary = getServiceHub().getNetworkMapCache().getNotary(CordaX500Name.parse("O=Notary,L=London,C=GB")); // METHOD 2
-
- // Create the output state
- Asset output = new Asset(new UniqueIdentifier(), title, description, imageURL,
- getOurIdentity());
-
- // Build the transaction, add the output state and the command to the transaction.
- TransactionBuilder transactionBuilder = new TransactionBuilder(notary)
- .addOutputState(output)
- .addCommand(new AssetContract.Commands.CreateAsset(),
- Arrays.asList(getOurIdentity().getOwningKey())); // Required Signers
-
- // Verify the transaction
- transactionBuilder.verify(getServiceHub());
-
- // Sign the transaction
- SignedTransaction signedTransaction = getServiceHub().signInitialTransaction(transactionBuilder);
-
- // Notarise the transaction and record the state in the ledger.
- return subFlow(new FinalityFlow(signedTransaction, Collections.emptyList()));
- }
-}
\ No newline at end of file
diff --git a/Advanced/auction-cordapp/workflows/src/test/java/net/corda/samples/FlowTests.java b/Advanced/auction-cordapp/workflows/src/test/java/net/corda/samples/FlowTests.java
deleted file mode 100644
index 5b32e7d7..00000000
--- a/Advanced/auction-cordapp/workflows/src/test/java/net/corda/samples/FlowTests.java
+++ /dev/null
@@ -1,82 +0,0 @@
-package net.corda.samples;
-
-import com.google.common.collect.ImmutableList;
-import net.corda.core.concurrent.CordaFuture;
-import net.corda.core.contracts.Amount;
-import net.corda.core.node.NetworkParameters;
-import net.corda.core.transactions.SignedTransaction;
-import net.corda.samples.flows.BidFlow;
-import net.corda.samples.flows.CreateAssetFlow;
-import net.corda.samples.flows.CreateAuctionFlow;
-import net.corda.samples.states.Asset;
-import net.corda.samples.states.AuctionState;
-import net.corda.testing.node.MockNetwork;
-import net.corda.testing.node.MockNetworkParameters;
-import net.corda.testing.node.StartedMockNode;
-import net.corda.testing.node.TestCordapp;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-import java.time.Duration;
-import java.time.Instant;
-import java.time.LocalDateTime;
-import java.time.ZoneId;
-import java.util.Collections;
-import java.util.UUID;
-
-import static org.junit.Assert.*;
-
-public class FlowTests {
- private MockNetwork network;
- private StartedMockNode a;
- private StartedMockNode b;
-
- @Before
- public void setup() {
- network = new MockNetwork(
- new MockNetworkParameters(
- ImmutableList.of(
- TestCordapp.findCordapp("net.corda.samples.flows"),
- TestCordapp.findCordapp("net.corda.samples.contracts")
- )
- ).withNetworkParameters(new NetworkParameters(4, Collections.emptyList(),
- 10485760, 10485760 * 50, Instant.now(), 1,
- Collections.emptyMap()))
- );
- a = network.createPartyNode(null);
- b = network.createPartyNode(null);
- network.runNetwork();
- }
-
- @After
- public void tearDown() {
- network.stopNodes();
- }
-
- @Test
- public void testCreateAssetFlow() throws Exception {
- CreateAssetFlow flow = new CreateAssetFlow("Test Asset", "Dummy Asset", "http://abc.com/dummy.png");
- CordaFuture future = a.startFlow(flow);
- network.runNetwork();
- SignedTransaction signedTransaction = future.get();
- Asset asset = (Asset) signedTransaction.getTx().getOutput(0);
- assertNotNull(asset);
- }
-
- @Test
- public void testCreateAuctionFlow() throws Exception {
- CreateAssetFlow assetflow = new CreateAssetFlow("Test Asset", "Dummy Asset", "http://abc.com/dummy.png");
- CordaFuture future = a.startFlow(assetflow);
- network.runNetwork();
- SignedTransaction signedTransaction = future.get();
- Asset asset = (Asset) signedTransaction.getTx().getOutput(0);
- CreateAuctionFlow.Initiator auctionFlow = new CreateAuctionFlow.Initiator(Amount.parseCurrency("1000 USD"),
- asset.getLinearId().getId(), LocalDateTime.ofInstant(Instant.now().plusMillis(30000), ZoneId.systemDefault()));
- CordaFuture future1 = a.startFlow(auctionFlow);
- network.runNetwork();
- SignedTransaction transaction = future1.get();
- AuctionState auctionState = (AuctionState) transaction.getTx().getOutput(0);
- assertNotNull(auctionState);
- }
-}
\ No newline at end of file
diff --git a/Advanced/auction-cordapp/workflows/src/test/java/net/corda/samples/NodeDriver.java b/Advanced/auction-cordapp/workflows/src/test/java/net/corda/samples/NodeDriver.java
deleted file mode 100644
index 591f99a0..00000000
--- a/Advanced/auction-cordapp/workflows/src/test/java/net/corda/samples/NodeDriver.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package net.corda.samples;
-
-import com.google.common.collect.ImmutableList;
-import net.corda.core.identity.CordaX500Name;
-import net.corda.testing.driver.DriverParameters;
-import net.corda.testing.driver.NodeParameters;
-import net.corda.testing.node.User;
-import com.google.common.collect.ImmutableSet;
-
-import java.util.List;
-import static net.corda.testing.driver.Driver.driver;
-
-/**
- * Allows you to run your nodes through an IDE (as opposed to using deployNodes). Do not use in a production
- * environment.
- */
-public class NodeDriver {
- public static void main(String[] args) {
- final List rpcUsers =
- ImmutableList.of(new User("user1", "test", ImmutableSet.of("ALL")));
-
- driver(new DriverParameters().withStartNodesInProcess(true).withWaitForAllNodesToFinish(true), dsl -> {
- try {
- dsl.startNode(new NodeParameters()
- .withProvidedName(new CordaX500Name("PartyA", "London", "GB"))
- .withRpcUsers(rpcUsers)).get();
- dsl.startNode(new NodeParameters()
- .withProvidedName(new CordaX500Name("PartyB", "New York", "US"))
- .withRpcUsers(rpcUsers)).get();
- } catch (Throwable e) {
- System.err.println("Encountered exception in node startup: " + e.getMessage());
- e.printStackTrace();
- }
-
- return null;
- }
- );
- }
-}
diff --git a/Advanced/auction-cordapp/workflows/src/test/java/net/corda/samples/auction/FlowTests.java b/Advanced/auction-cordapp/workflows/src/test/java/net/corda/samples/auction/FlowTests.java
new file mode 100644
index 00000000..58b2a115
--- /dev/null
+++ b/Advanced/auction-cordapp/workflows/src/test/java/net/corda/samples/auction/FlowTests.java
@@ -0,0 +1,78 @@
+package net.corda.samples.auction;
+
+import com.google.common.collect.ImmutableList;
+import net.corda.core.concurrent.CordaFuture;
+import net.corda.core.contracts.Amount;
+import net.corda.core.identity.CordaX500Name;
+import net.corda.core.node.NetworkParameters;
+import net.corda.core.transactions.SignedTransaction;
+import net.corda.samples.auction.flows.CreateAssetFlow;
+import net.corda.samples.auction.flows.CreateAuctionFlow;
+import net.corda.samples.auction.states.Asset;
+import net.corda.samples.auction.states.AuctionState;
+import net.corda.testing.node.*;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.time.Instant;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.util.Collections;
+
+import static org.junit.Assert.*;
+
+public class FlowTests {
+ private MockNetwork network;
+ private StartedMockNode a;
+ private StartedMockNode b;
+
+ @Before
+ public void setup() {
+ network = new MockNetwork(
+ new MockNetworkParameters(
+ ImmutableList.of(
+ TestCordapp.findCordapp("net.corda.samples.auction.flows"),
+ TestCordapp.findCordapp("net.corda.samples.auction.contracts")
+ )
+ ).withNetworkParameters(new NetworkParameters(4, Collections.emptyList(),
+ 10485760, 10485760 * 50, Instant.now(), 1,
+ Collections.emptyMap())
+ ).withNotarySpecs(ImmutableList.of(new MockNetworkNotarySpec(CordaX500Name.parse("O=Notary,L=London,C=GB"))))
+ );
+ a = network.createPartyNode(null);
+ b = network.createPartyNode(null);
+ network.runNetwork();
+ }
+
+ @After
+ public void tearDown() {
+ network.stopNodes();
+ }
+
+ @Test
+ public void testCreateAssetFlow() throws Exception {
+ CreateAssetFlow flow = new CreateAssetFlow("Test Asset", "Dummy Asset", "http://abc.com/dummy.png");
+ CordaFuture future = a.startFlow(flow);
+ network.runNetwork();
+ SignedTransaction signedTransaction = future.get();
+ Asset asset = (Asset) signedTransaction.getTx().getOutput(0);
+ assertNotNull(asset);
+ }
+
+ @Test
+ public void testCreateAuctionFlow() throws Exception {
+ CreateAssetFlow assetflow = new CreateAssetFlow("Test Asset", "Dummy Asset", "http://abc.com/dummy.png");
+ CordaFuture future = a.startFlow(assetflow);
+ network.runNetwork();
+ SignedTransaction signedTransaction = future.get();
+ Asset asset = (Asset) signedTransaction.getTx().getOutput(0);
+ CreateAuctionFlow.CreateAuctionInitiator auctionFlow = new CreateAuctionFlow.CreateAuctionInitiator(Amount.parseCurrency("1000 USD"),
+ asset.getLinearId().getId(), LocalDateTime.ofInstant(Instant.now().plusMillis(30000), ZoneId.systemDefault()));
+ CordaFuture future1 = a.startFlow(auctionFlow);
+ network.runNetwork();
+ SignedTransaction transaction = future1.get();
+ AuctionState auctionState = (AuctionState) transaction.getTx().getOutput(0);
+ assertNotNull(auctionState);
+ }
+}
\ No newline at end of file
diff --git a/Advanced/constants.properties b/Advanced/constants.properties
index 2cd5a28c..adcdb361 100644
--- a/Advanced/constants.properties
+++ b/Advanced/constants.properties
@@ -1,12 +1,12 @@
cordaReleaseGroup=net.corda
cordaCoreReleaseGroup=net.corda
-cordaVersion=4.6
-cordaCoreVersion=4.6
+cordaVersion=4.10
+cordaCoreVersion=4.10
gradlePluginsVersion=5.0.12
kotlinVersion=1.2.71
junitVersion=4.12
quasarVersion=0.7.10
-log4jVersion =2.11.2
-platformVersion=8
+log4jVersion =2.17.1
+platformVersion=12
slf4jVersion=1.7.25
nettyVersion=4.1.22.Final
diff --git a/Basic/rpc-nodeinfo/LICENCE b/Advanced/duediligence-cordapp/LICENCE
similarity index 100%
rename from Basic/rpc-nodeinfo/LICENCE
rename to Advanced/duediligence-cordapp/LICENCE
diff --git a/Advanced/duediligence-cordapp/README.md b/Advanced/duediligence-cordapp/README.md
new file mode 100644
index 00000000..7dbbf0cb
--- /dev/null
+++ b/Advanced/duediligence-cordapp/README.md
@@ -0,0 +1,66 @@
+# Due Diligence Cordapp
+
+This cordapp is an example of how blockchain can work in the capital market industry. Due diligence is commonly the first step of any action in the capital market. In many of the industry, it is also required by the regulators to prevent fraudulent and risky transactions. Each firm will have its own due-diligence process and standards, but at the same time, the cost of executing due diligence is also bared by them individually.
+
+## App Design
+
+
+The above picture is a high level mock overview of a shareable due diligence DLT app. BankA will initiate the original Corporate Records auditing with an autitor. Then it will share the auditiing report with BankB to save BankB's cost on getting the same report. Wise versa, BankB can work with a different auditor and produce a different report and share with BankA. In the implmentation of this sample cordapp, we will only cover one type of the file auditing.
+
+Notes: another key feature of this app is whitlisting trusted auditors. It is done by utilizing attachment function in Corda. More samples on how to use attachment can be found in the [Features samples folder](../../Features)
+
+
+## Pre-running the app
+
+Deploying nodes: `./gradlew clean deployNodes`
+
+Starting the nodes: `./build/nodes/runnodes`
+
+Uploading whitelisted Auditors: `./gradlew uploadWhitelists`
+
+
+
+## Running the Cordapp
+Step #1: At PartyA, file the original Corporate Records auditing process with Auditor(Trusted Auditor)
+```
+flow start RequestToValidateCorporateRecordsInitiator validater: Trusted Auditor, numberOfFiles: 10
+```
+
+Step #2: Go to the Trusted Auditor Node, validate the auditing request(This step symbolize the auditing process by this third party auditor). Put in the linearId which was returned in Step #1.
+```
+flow start ValidateCorporateRecordsInitiator linearId:
+```
+
+Step #3: Go to PartyA, Do a query to confirm that the request has been validated. You should see the variable `qualification=true`.
+
+```
+run vaultQuery contractStateType: net.corda.samples.duediligence.states.CorporateRecordsAuditRequest
+```
+Then, we will instruct PartyA to share a copy of the auditing result with PartyB: (Again, You would need put in the linearId returned from Step #1). The parameter `trustedAuditorAttachment` is a jar file which records the trusted auditors. If PartyA used an untrusted auditor to accquire the corporate records auditing report. He will be prohibited to share with anyone because it is valueless effort(in this business use case, Of course you can modify the business use cases).
+```
+flow start ShareAuditingResultInitiator AuditingResultID: , sendTo: BankB, trustedAuditorAttachment: "8DF3275D80B26B9A45AB022F2FDA4A2ED996449B425F8F2245FA5BCF7D1AC587"
+```
+This flow will return the LinearId of the copy of auditing report, you would need this in Step #6.
+
+Step #4: Go to PartyB, do a query to confirm the delievery of copy of the Auditing Report.
+```
+run vaultQuery contractStateType: net.corda.samples.duediligence.states.CopyOfCoporateRecordsAuditRequest
+```
+As of now, the sharing of the trusted auditing report is done. What left now for both PartyA and PartyB in this use case is to upload the Corporate Records auditing report into a due-diligence list, which they can share with a regulator.(You can again alter this step to suit any other use cases).
+
+
+Step #5: Go to PartyA, Attach the Corporate Records auditing report into a due-diligence checklist and report to the Regulator. Again, the approvalId is the linearId returned in Step #1.
+```
+flow start CreateCheckListAndAddApprovalInitiator reportTo: Regulator, approvalId:
+
+```
+Step #6: Go to PartyB, Attach the copy of the Corporate Records auditing report into a due-diligence checklist and report to the Regulator. You would need the linearId that is return from Step #5
+```
+flow start CreateCheckListAndAddApprovalInitiator reportTo: Regulator, approvalId:
+```
+Step #7: Go to Regulator, do a query on reported due-diligence checklists. You will be able to see both PartyA and PartyB had filed a due-diligence checklist.
+```
+run vaultQuery contractStateType: net.corda.samples.duediligence.states.DueDChecklist
+
+```
+This use of Distributed technology Corda helped PartyB saved the cost of go through corporate records due-diligence process while still reaching a trusted auditing report.
diff --git a/Advanced/duediligence-cordapp/TRADEMARK b/Advanced/duediligence-cordapp/TRADEMARK
new file mode 100644
index 00000000..d2e056b5
--- /dev/null
+++ b/Advanced/duediligence-cordapp/TRADEMARK
@@ -0,0 +1,4 @@
+Corda and the Corda logo are trademarks of R3CEV LLC and its affiliates. All rights reserved.
+
+For R3CEV LLC's trademark and logo usage information, please consult our Trademark Usage Policy at
+https://www.r3.com/trademark-policy/.
\ No newline at end of file
diff --git a/Advanced/duediligence-cordapp/build.gradle b/Advanced/duediligence-cordapp/build.gradle
new file mode 100644
index 00000000..ef682822
--- /dev/null
+++ b/Advanced/duediligence-cordapp/build.gradle
@@ -0,0 +1,154 @@
+buildscript {//properties that you need to build the project
+ Properties constants = new Properties()
+ file("$projectDir/../constants.properties").withInputStream { constants.load(it) }
+
+ ext {
+ corda_release_group = constants.getProperty("cordaReleaseGroup")
+ corda_core_release_group = constants.getProperty("cordaCoreReleaseGroup")
+ corda_release_version = constants.getProperty("cordaVersion")
+ corda_core_release_version = constants.getProperty("cordaCoreVersion")
+ corda_gradle_plugins_version = constants.getProperty("gradlePluginsVersion")
+ kotlin_version = constants.getProperty("kotlinVersion")
+ junit_version = constants.getProperty("junitVersion")
+ quasar_version = constants.getProperty("quasarVersion")
+ log4j_version = constants.getProperty("log4jVersion")
+ slf4j_version = constants.getProperty("slf4jVersion")
+ corda_platform_version = constants.getProperty("platformVersion").toInteger()
+ //springboot
+ spring_boot_version = '2.0.2.RELEASE'
+ spring_boot_gradle_plugin_version = '2.0.2.RELEASE'
+ }
+
+ repositories {
+ mavenLocal()
+ mavenCentral()
+
+ maven { url 'https://download.corda.net/maven/corda-releases' }
+ }
+
+ dependencies {
+ classpath "net.corda.plugins:cordapp:$corda_gradle_plugins_version"
+ classpath "net.corda.plugins:cordformation:$corda_gradle_plugins_version"
+ classpath "net.corda.plugins:quasar-utils:$corda_gradle_plugins_version"
+ classpath "org.springframework.boot:spring-boot-gradle-plugin:$spring_boot_gradle_plugin_version"
+ }
+}
+
+allprojects {//Properties that you need to compile your project (The application)
+ apply from: "${rootProject.projectDir}/repositories.gradle"
+ apply plugin: 'java'
+
+ repositories {
+ mavenLocal()
+
+ mavenCentral()
+ maven { url 'https://download.corda.net/maven/corda-dependencies' }
+ maven { url 'https://jitpack.io' }
+ }
+
+ tasks.withType(JavaCompile) {
+ options.compilerArgs << "-parameters" // Required by Corda's serialisation framework.
+ }
+
+ jar {
+ // This makes the JAR's SHA-256 hash repeatable.
+ preserveFileTimestamps = false
+ reproducibleFileOrder = true
+ duplicatesStrategy = DuplicatesStrategy.EXCLUDE
+ }
+}
+
+apply plugin: 'net.corda.plugins.cordapp'
+apply plugin: 'net.corda.plugins.cordformation'
+apply plugin: 'net.corda.plugins.quasar-utils'
+
+sourceSets {
+ main {
+ resources {
+ srcDir rootProject.file("config/dev")
+ }
+ }
+}
+//Module dependencis
+dependencies {
+ // Corda dependencies.
+ cordaCompile "$corda_core_release_group:corda-core:$corda_core_release_version"
+ cordaCompile "$corda_release_group:corda-node-api:$corda_release_version"
+ cordaRuntime "$corda_release_group:corda:$corda_release_version"
+
+ // CorDapp dependencies.
+ cordapp project(":workflows")
+ cordapp project(":contracts")
+
+ cordaCompile "org.apache.logging.log4j:log4j-slf4j-impl:${log4j_version}"
+ cordaCompile "org.apache.logging.log4j:log4j-web:${log4j_version}"
+ cordaCompile "org.slf4j:jul-to-slf4j:$slf4j_version"
+ cordaDriver "net.corda:corda-shell:4.10"
+
+}
+
+
+//Task to deploy the nodes in order to bootstrap a network
+task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar']) {
+
+ /* This property will load the CorDapps to each of the node by default, including the Notary. You can find them
+ * in the cordapps folder of the node at build/nodes/Notary/cordapps. However, the notary doesn't really understand
+ * the notion of cordapps. In production, Notary does not need cordapps as well. This is just a short cut to load
+ * the Corda network bootstrapper.
+ */
+ nodeDefaults {
+ projectCordapp {
+ deploy = false
+ }
+ cordapp project(':contracts')
+ cordapp project(':workflows')
+ runSchemaMigration = true //This configuration is for any CorDapps with custom schema, We will leave this as true to avoid
+ //problems for developers who are not familiar with Corda. If you are not using custom schemas, you can change
+ //it to false for quicker project compiling time.
+ }
+ node {
+ name "O=Notary,L=London,C=GB"
+ notary = [validating : false]
+ p2pPort 10002
+ rpcSettings {
+ address("localhost:10003")
+ adminAddress("localhost:10043")
+ }
+ }
+ node {
+ name "O=BankA,L=London,C=GB"
+ p2pPort 10005
+ rpcSettings {
+ address("localhost:10006")
+ adminAddress("localhost:10046")
+ }
+ rpcUsers = [[ user: "user1", "password": "test", "permissions": ["ALL"]]]
+ }
+ node {
+ name "O=BankB,L=New York,C=US"
+ p2pPort 10008
+ rpcSettings {
+ address("localhost:10009")
+ adminAddress("localhost:10049")
+ }
+ rpcUsers = [[ user: "user1", "password": "test", "permissions": ["ALL"]]]
+ }
+ node {
+ name "O=Trusted Auditor,L=New York,C=US"
+ p2pPort 10011
+ rpcSettings {
+ address("localhost:10012")
+ adminAddress("localhost:10052")
+ }
+ rpcUsers = [[ user: "user1", "password": "test", "permissions": ["ALL"]]]
+ }
+ node {
+ name "O=Regulator,L=New York,C=US"
+ p2pPort 10014
+ rpcSettings {
+ address("localhost:10015")
+ adminAddress("localhost:10055")
+ }
+ rpcUsers = [[ user: "user1", "password": "test", "permissions": ["ALL"]]]
+ }
+}
diff --git a/Advanced/duediligence-cordapp/clients/build.gradle b/Advanced/duediligence-cordapp/clients/build.gradle
new file mode 100644
index 00000000..0585ba30
--- /dev/null
+++ b/Advanced/duediligence-cordapp/clients/build.gradle
@@ -0,0 +1,37 @@
+apply plugin: 'org.springframework.boot'
+
+sourceSets {
+ main {
+ resources {
+ srcDir rootProject.file("config/dev")
+ }
+ }
+}
+
+configurations {
+ all {
+ exclude group: 'ch.qos.logback', module: 'logback-classic'
+ }
+}
+
+dependencies {
+ // Corda dependencies.
+ compile "$corda_release_group:corda-rpc:$corda_release_version"
+
+ // CorDapp dependencies.
+ compile project(":contracts")
+ compile project(":workflows")
+ compile("org.springframework.boot:spring-boot-starter-websocket:$spring_boot_version") {
+ exclude group: "org.springframework.boot", module: "spring-boot-starter-logging"
+ }
+ compile "org.apache.logging.log4j:log4j-slf4j-impl:${log4j_version}"
+ compile "org.apache.logging.log4j:log4j-web:${log4j_version}"
+ compile "org.slf4j:jul-to-slf4j:$slf4j_version"
+}
+
+
+task uploadWhitelists(type: JavaExec, dependsOn: assemble) {
+ classpath = sourceSets.main.runtimeClasspath
+ main = 'net.corda.samples.duediligence.client.Client'
+ args 'localhost:10006', 'localhost:10009', 'localhost:10012'
+}
\ No newline at end of file
diff --git a/Advanced/duediligence-cordapp/clients/src/main/java/net/corda/samples/duediligence/client/Client.java b/Advanced/duediligence-cordapp/clients/src/main/java/net/corda/samples/duediligence/client/Client.java
new file mode 100644
index 00000000..0e5fad53
--- /dev/null
+++ b/Advanced/duediligence-cordapp/clients/src/main/java/net/corda/samples/duediligence/client/Client.java
@@ -0,0 +1,96 @@
+package net.corda.samples.duediligence.client;
+
+import com.google.common.base.Charsets;
+import net.corda.client.rpc.CordaRPCClient;
+import net.corda.client.rpc.CordaRPCConnection;
+import net.corda.core.crypto.SecureHash;
+import net.corda.core.messaging.CordaRPCOps;
+import net.corda.core.utilities.NetworkHostAndPort;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import net.corda.samples.duediligence.Constants;
+
+import java.io.*;
+import java.nio.file.FileAlreadyExistsException;
+import java.util.List;
+import java.util.jar.JarInputStream;
+import java.util.stream.Collectors;
+
+public class Client {
+
+ private static class Companion {
+ static Logger logger = LoggerFactory.getLogger(Client.class);
+ }
+
+ /**
+ * Uploads the jar of blacklisted counterparties with whom agreements cannot be struck to the node.
+ */
+ public static void main(String[] args) throws IOException {
+ if (args.length == 0) {
+ String message = "Usage: uploadBlacklist ...";
+ throw new IllegalArgumentException(message.toString());
+ }
+
+ for (String arg : args) {
+ NetworkHostAndPort nodeAddress = NetworkHostAndPort.parse(arg);
+ CordaRPCConnection rpcConnection = new CordaRPCClient(nodeAddress).start("user1", "test");
+ CordaRPCOps proxy = rpcConnection.getProxy();
+
+ SecureHash attachmentHash = Constants.CORPORATE_JAR_HASH;
+
+ // take relative path using substring of constant BLACKLIST_JAR_PATH, check if node contains blacklist already
+ if (!proxy.attachmentExists(attachmentHash)) {
+ System.out.println("Working Directory = " +
+ System.getProperty("user.dir"));
+ attachmentHash = uploadAttachment(proxy, Constants.CORPORATE_JAR_PATH);
+ Companion.logger.info("Corporate Auditor List uploaded to node at " + nodeAddress);
+ } else {
+ Companion.logger.info("Node already contains Corporate Auditor List, skipping upload at " + nodeAddress);
+ }
+
+ JarInputStream attachmentJar = downloadAttachment(proxy, attachmentHash);
+ Companion.logger.info("Corporate Auditor List downloaded from node at " + nodeAddress);
+
+ checkAttachment(attachmentJar, Constants.CORPORATE_ATTACTMENT_FILE_NAME, Constants.CORPORATE_ATTACHMENT_EXPECTED_CONTENTS);
+ Companion.logger.info("Attachment contents checked on node at " + nodeAddress);
+ }
+
+ }
+
+ /**
+ * Uploads the attachment at [attachmentPath] to the node.
+ */
+ private static SecureHash uploadAttachment(CordaRPCOps proxy, String attachmentPath) throws FileNotFoundException, FileAlreadyExistsException {
+ FileInputStream attachmentUploadInputStream = new FileInputStream(new File(attachmentPath));
+ return proxy.uploadAttachment(attachmentUploadInputStream);
+ }
+
+ /**
+ * Downloads the attachment with hash [attachmentHash] from the node.
+ */
+ private static JarInputStream downloadAttachment(CordaRPCOps proxy, SecureHash attachmentHash) throws IOException {
+ InputStream attachmentDownloadInputStream = proxy.openAttachment(attachmentHash);
+ return new JarInputStream(attachmentDownloadInputStream);
+ }
+
+ /**
+ * Checks the [expectedFileName] and [expectedContents] of the downloaded [attachmentJar].
+ */
+ private static void checkAttachment(JarInputStream attachmentJar, String expectedFileName, List expectedContents) throws IOException {
+ String name = attachmentJar.getNextEntry().getName();
+ while (!name.equals(expectedFileName)) {
+ name = attachmentJar.getNextEntry().getName();
+ }
+
+ BufferedInputStream bisAttachmentJar = new BufferedInputStream(attachmentJar, (8 * 1024));
+ InputStreamReader isrAttachmentJar = new InputStreamReader(bisAttachmentJar, Charsets.UTF_8);
+ BufferedReader brAttachmentJar = new BufferedReader(isrAttachmentJar);
+
+ List contents = brAttachmentJar.lines().collect(Collectors.toList());
+
+ if (!contents.equals(expectedContents)) {
+ throw new IllegalArgumentException("Downloaded JAR did not have the expected contents.");
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/Basic/ping-pong/client-java/src/main/resources/log4j2.xml b/Advanced/duediligence-cordapp/config/dev/log4j2.xml
similarity index 100%
rename from Basic/ping-pong/client-java/src/main/resources/log4j2.xml
rename to Advanced/duediligence-cordapp/config/dev/log4j2.xml
diff --git a/Basic/yo-cordapp/config/test/log4j2.xml b/Advanced/duediligence-cordapp/config/test/log4j2.xml
similarity index 100%
rename from Basic/yo-cordapp/config/test/log4j2.xml
rename to Advanced/duediligence-cordapp/config/test/log4j2.xml
diff --git a/Advanced/duediligence-cordapp/contracts/build.gradle b/Advanced/duediligence-cordapp/contracts/build.gradle
new file mode 100644
index 00000000..9d669fa4
--- /dev/null
+++ b/Advanced/duediligence-cordapp/contracts/build.gradle
@@ -0,0 +1,35 @@
+apply plugin: 'net.corda.plugins.cordapp'
+apply plugin: 'net.corda.plugins.cordformation'
+
+cordapp {
+ targetPlatformVersion corda_platform_version
+ minimumPlatformVersion corda_platform_version
+ contract {
+ name "Due Diligence Contracts"
+ vendor "Corda Open Source"
+ licence "Apache License, Version 2.0"
+ versionId 1
+ }
+}
+
+sourceSets {
+ main{
+ java {
+ srcDir 'src/main/java'
+ java.outputDir = file('bin/main')
+ }
+ }
+ test{
+ java{
+ srcDir 'src/test/java'
+ java.outputDir = file('bin/test')
+ }
+ }
+}
+
+dependencies {
+ // Corda dependencies.
+ cordaCompile "$corda_core_release_group:corda-core:$corda_core_release_version"
+ cordaRuntime "$corda_release_group:corda:$corda_release_version"
+ testCompile "$corda_release_group:corda-node-driver:$corda_release_version"
+}
\ No newline at end of file
diff --git a/Advanced/duediligence-cordapp/contracts/src/main/java/net/corda/samples/duediligence/Constants.java b/Advanced/duediligence-cordapp/contracts/src/main/java/net/corda/samples/duediligence/Constants.java
new file mode 100644
index 00000000..24d84b8c
--- /dev/null
+++ b/Advanced/duediligence-cordapp/contracts/src/main/java/net/corda/samples/duediligence/Constants.java
@@ -0,0 +1,26 @@
+package net.corda.samples.duediligence;
+
+import net.corda.core.crypto.SecureHash;
+
+import java.util.Arrays;
+import java.util.List;
+
+public interface Constants {
+ //Whitelisted Corporate Auditors
+ String CORPORATE_JAR_PATH = "../contracts/src/main/resources/corporateAuditors.jar";
+ SecureHash CORPORATE_JAR_HASH = SecureHash.parse("8DF3275D80B26B9A45AB022F2FDA4A2ED996449B425F8F2245FA5BCF7D1AC587");
+ String CORPORATE_ATTACTMENT_FILE_NAME = "whitelistedCorporateAuditors.txt";
+ List CORPORATE_ATTACHMENT_EXPECTED_CONTENTS = Arrays.asList(
+ "Crossland Savings",
+ "Trusted Auditor"
+ );
+
+ //Whitelisted Finance Auditors
+ String FINANCIAL_JAR_PATH = "../contracts/src/main/resources/financialAuditors.jar";
+ SecureHash FINANCIAL_JAR_HASH = SecureHash.parse("DE7635E2AD626BC57D811D065F7841FC35839FA2D0CF095857CACE1579756A1C");
+ String FINANCIAL_ATTACTMENT_FILE_NAME = "whitelistedFinancialAuditors.txt";
+ List FINANCIAL_ATTACHMENT_EXPECTED_CONTENTS = Arrays.asList(
+ "Detroit Partners Group",
+ "Tifton Banking Company"
+ );
+}
diff --git a/Advanced/duediligence-cordapp/contracts/src/main/java/net/corda/samples/duediligence/contracts/CorporateRecordsContract.java b/Advanced/duediligence-cordapp/contracts/src/main/java/net/corda/samples/duediligence/contracts/CorporateRecordsContract.java
new file mode 100644
index 00000000..c0f892b6
--- /dev/null
+++ b/Advanced/duediligence-cordapp/contracts/src/main/java/net/corda/samples/duediligence/contracts/CorporateRecordsContract.java
@@ -0,0 +1,125 @@
+package net.corda.samples.duediligence.contracts;
+
+import kotlin.text.Charsets;
+import net.corda.core.contracts.*;
+import net.corda.core.identity.AbstractParty;
+import net.corda.core.identity.Party;
+import net.corda.core.transactions.LedgerTransaction;
+import net.corda.samples.duediligence.states.CopyOfCoporateRecordsAuditRequest;
+import net.corda.samples.duediligence.states.CorporateRecordsAuditRequest;
+import org.jetbrains.annotations.NotNull;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.jar.JarInputStream;
+import java.util.stream.Collectors;
+
+import static net.corda.core.contracts.ContractsDSL.requireThat;
+import static net.corda.samples.duediligence.Constants.CORPORATE_JAR_HASH;
+
+public class CorporateRecordsContract implements Contract {
+
+ public static final String CorporateRecordsContract_ID = "net.corda.samples.duediligence.contracts.CorporateRecordsContract";
+
+ @Override
+ public void verify(@NotNull LedgerTransaction tx) throws IllegalArgumentException {
+ final CommandWithParties command = tx.getCommands().get(0);
+
+ //Propose request
+ if (command.getValue() instanceof Commands.Propose) {
+ requireThat(require -> {
+ require.using("There are no inputs", tx.getInputs().isEmpty());
+ require.using("Only one output state should be created.", tx.getOutputs().size() == 1);
+ require.using("The single output is of type CorporateRecords State", tx.outputsOfType(CorporateRecordsAuditRequest.class).size() == 1);
+ return null;
+ });
+ }else if (command.getValue() instanceof Commands.Validate) { //Validate Rules
+ requireThat(require -> {
+ require.using("Only one output state should be created.", tx.getOutputs().size() == 1);
+ require.using("The single output is of type CorporateRecords State", tx.outputsOfType(CorporateRecordsAuditRequest.class).size() == 1);
+ return null;
+ });
+ }else if (command.getValue() instanceof Commands.Reject) { //Rejection Rules
+ requireThat(require -> {
+ require.using("Only one output state should be created.", tx.getOutputs().size() == 1);
+ require.using("The single output is of type CorporateRecords State", tx.outputsOfType(CorporateRecordsAuditRequest.class).size() == 1);
+ return null;
+ });
+ }
+ else if (command.getValue() instanceof Commands.Share) { //Share Rules
+
+ // Check if the report has any value to share among other network participants.
+ List nonContractAttachments = tx.getAttachments()
+ .stream()
+ .filter(p -> !(p instanceof ContractAttachment))
+ .map(p -> (Attachment) p)
+ .collect(Collectors.toList());
+
+ Attachment attached = nonContractAttachments.get(0);
+
+ ContractsDSL.requireThat(req -> {
+ req.using("The transaction should have a single non-contract attachment",
+ nonContractAttachments.size() == 1);
+ req.using("The jar's hash should be correct", attached.getId().equals(CORPORATE_JAR_HASH));
+ return null;
+ });
+
+ // Extract the whitelisted company names from the JAR.
+ List whitelistedCompanies = new ArrayList<>();
+ JarInputStream attachmentJar = attached.openAsJAR();
+ try {
+ while (!attachmentJar.getNextEntry().getName().equals("whitelistedCorporateAuditors.txt")) {
+ // Calling 'getNextEntry()' causes us to scroll through the JAR.
+ }
+ InputStreamReader isrWhitelistlist = new InputStreamReader(attachmentJar, Charsets.UTF_8);
+ BufferedReader brWhitelist = new BufferedReader(isrWhitelistlist, (8 * 1024)); // Note - changed BIR to BR
+
+ String company = brWhitelist.readLine();
+
+ while (company != null) {
+ whitelistedCompanies.add(company);
+ company = brWhitelist.readLine();
+ }
+ } catch (IOException e) {
+ System.out.println("error reading whitelistedCorporateAuditors.txt");
+ }
+
+ // Constraints on the Whitelist parties
+ //CorporateRecordsAuditRequest corporateRecords = tx.outputsOfType(CorporateRecordsAuditRequest.class).get(0);
+ //CorporateRecordsAuditRequest corporateRecords = tx.inputsOfType(CorporateRecordsAuditRequest.class).get(0);
+ StateAndRef recordsStateAndRef = tx.referenceInputRefsOfType(CorporateRecordsAuditRequest.class).get(0);
+ CorporateRecordsAuditRequest corporateRecords = recordsStateAndRef.getState().getData();
+
+ List participants = new ArrayList<>();
+ List participantsOrgs = new ArrayList<>();
+ for (AbstractParty p : corporateRecords.getParticipants()) {
+ Party participant = (Party) p;
+ participantsOrgs.add(participant.getName().getOrganisation());
+ participants.add(participant);
+ }
+
+ // overlap is whether any participants in the transaction belong to a whitelisted org.
+ Set overlap = new HashSet<>(whitelistedCompanies); //Crossland Savings & TCF National Bank Wisconsin
+ overlap.retainAll(new HashSet<>(participantsOrgs)); // intersection | TCF & PartyA
+
+ ContractsDSL.requireThat(req -> {
+ req.using("The agreement did not use any whitelisted auditors" + overlap.toString(), (!overlap.isEmpty()));
+ return null;
+ });
+ }
+ }
+
+ public interface Commands extends CommandData {
+ class Propose implements Commands { }
+ class Validate implements Commands { }
+ class Reject implements Commands { }
+ class Share implements Commands { }
+ class Report implements Commands { }
+ }
+
+}
diff --git a/Advanced/duediligence-cordapp/contracts/src/main/java/net/corda/samples/duediligence/contracts/DueDChecklistContract.java b/Advanced/duediligence-cordapp/contracts/src/main/java/net/corda/samples/duediligence/contracts/DueDChecklistContract.java
new file mode 100644
index 00000000..0bc61562
--- /dev/null
+++ b/Advanced/duediligence-cordapp/contracts/src/main/java/net/corda/samples/duediligence/contracts/DueDChecklistContract.java
@@ -0,0 +1,37 @@
+package net.corda.samples.duediligence.contracts;
+
+import net.corda.core.contracts.*;
+import net.corda.core.transactions.LedgerTransaction;
+import net.corda.samples.duediligence.states.CopyOfCoporateRecordsAuditRequest;
+import net.corda.samples.duediligence.states.CorporateRecordsAuditRequest;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.List;
+
+import static net.corda.core.contracts.ContractsDSL.requireThat;
+
+public class DueDChecklistContract implements Contract {
+ @Override
+ public void verify(@NotNull LedgerTransaction tx) throws IllegalArgumentException {
+ final CommandWithParties command = tx.getCommands().get(0);
+
+ //Propose request
+ if (command.getValue() instanceof DueDChecklistContract.Commands.Add) {
+ requireThat(require -> {
+ StateAndRef input = tx.getInputs().get(0);
+ if (input.getState().getData().getClass() == CorporateRecordsAuditRequest.class){
+ CorporateRecordsAuditRequest request = (CorporateRecordsAuditRequest)input.getState().getData();
+ require.using("Qualification Must be True", request.getQualification());
+ }else{
+ CopyOfCoporateRecordsAuditRequest request = (CopyOfCoporateRecordsAuditRequest) input.getState().getData();
+ require.using("Qualification Must be True", request.getQualification());
+ }
+ return null;
+ });
+ }
+ }
+
+ public interface Commands extends CommandData {
+ class Add implements Commands { }
+ }
+}
diff --git a/Advanced/duediligence-cordapp/contracts/src/main/java/net/corda/samples/duediligence/states/CopyOfCoporateRecordsAuditRequest.java b/Advanced/duediligence-cordapp/contracts/src/main/java/net/corda/samples/duediligence/states/CopyOfCoporateRecordsAuditRequest.java
new file mode 100644
index 00000000..cb403c35
--- /dev/null
+++ b/Advanced/duediligence-cordapp/contracts/src/main/java/net/corda/samples/duediligence/states/CopyOfCoporateRecordsAuditRequest.java
@@ -0,0 +1,74 @@
+package net.corda.samples.duediligence.states;
+
+import net.corda.core.contracts.BelongsToContract;
+import net.corda.core.contracts.ContractState;
+import net.corda.core.contracts.LinearState;
+import net.corda.core.contracts.UniqueIdentifier;
+import net.corda.core.crypto.SecureHash;
+import net.corda.core.identity.AbstractParty;
+import net.corda.core.identity.Party;
+import net.corda.samples.duediligence.contracts.CorporateRecordsContract;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Arrays;
+import java.util.List;
+
+@BelongsToContract(CorporateRecordsContract.class)
+public class CopyOfCoporateRecordsAuditRequest implements LinearState {
+
+
+ //private variables
+ private Boolean qualification = false;
+ private Party originalOwner;
+ private Party copyReceiver;
+ private UniqueIdentifier originalRequestId;
+ private SecureHash originalReportTxId;
+ private UniqueIdentifier linearId;
+ private Party originalValidater;
+
+ public CopyOfCoporateRecordsAuditRequest(Party originalOwner, Party copyReceiver,
+ UniqueIdentifier originalRequestId, SecureHash originalReportTxId,
+ Party originalValidater,Boolean qualification, UniqueIdentifier linearId) {
+ this.originalOwner = originalOwner;
+ this.copyReceiver = copyReceiver;
+ this.originalRequestId = originalRequestId;
+ this.originalValidater = originalValidater;
+ this.originalReportTxId = originalReportTxId;
+ this.linearId = linearId;
+ this.qualification = qualification;
+ }
+
+ public Party getOriginalOwner() {
+ return originalOwner;
+ }
+
+ public Party getCopyReceiver() {
+ return copyReceiver;
+ }
+
+ public UniqueIdentifier getOriginalRequestId() {
+ return originalRequestId;
+ }
+
+ public UniqueIdentifier getLinearId() {
+ return linearId;
+ }
+
+ public Party getoriginalValidater() {
+ return originalValidater;
+ }
+
+ public Boolean getQualification() {
+ return qualification;
+ }
+
+ public SecureHash getOriginalReportTxId() {
+ return originalReportTxId;
+ }
+
+ @NotNull
+ @Override
+ public List getParticipants() {
+ return Arrays.asList(copyReceiver);
+ }
+}
diff --git a/Advanced/duediligence-cordapp/contracts/src/main/java/net/corda/samples/duediligence/states/CorporateRecordsAuditRequest.java b/Advanced/duediligence-cordapp/contracts/src/main/java/net/corda/samples/duediligence/states/CorporateRecordsAuditRequest.java
new file mode 100644
index 00000000..d6433574
--- /dev/null
+++ b/Advanced/duediligence-cordapp/contracts/src/main/java/net/corda/samples/duediligence/states/CorporateRecordsAuditRequest.java
@@ -0,0 +1,79 @@
+package net.corda.samples.duediligence.states;
+
+import net.corda.core.contracts.LinearState;
+import net.corda.core.contracts.UniqueIdentifier;
+import net.corda.core.serialization.ConstructorForDeserialization;
+import net.corda.samples.duediligence.contracts.CorporateRecordsContract;
+import net.corda.core.contracts.BelongsToContract;
+import net.corda.core.contracts.ContractState;
+import net.corda.core.identity.AbstractParty;
+import net.corda.core.identity.Party;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Arrays;
+import java.util.List;
+
+// *********
+// * State *
+// *********
+@BelongsToContract(CorporateRecordsContract.class)
+public class CorporateRecordsAuditRequest implements LinearState {
+ /*This can include reviewing incorporation documents, company constitutions,
+ organisational charts, a list of security holders, employee share plans and any
+ options granted to acquire securities.*/
+
+ //private variables
+ private Boolean qualification = false;
+ private Party applicant;
+ private Party validater;
+ private int numberOfFiles;
+ private UniqueIdentifier linearId;
+
+ /* Constructor of your Corda state */
+ @ConstructorForDeserialization
+ public CorporateRecordsAuditRequest(Party applicant, Party validater, int numberOfFiles, UniqueIdentifier linearId, Boolean qualification) {
+ this.applicant = applicant;
+ this.validater = validater;
+ this.numberOfFiles = numberOfFiles;
+ this.linearId = linearId;
+ this.qualification = qualification;
+ }
+
+ public CorporateRecordsAuditRequest(Party applicant, Party validater, int numberOfFiles, UniqueIdentifier linearId) {
+ this.applicant = applicant;
+ this.validater = validater;
+ this.numberOfFiles = numberOfFiles;
+ this.linearId = linearId;
+ }
+
+ public CorporateRecordsAuditRequest(Party applicant, Party validater, int numberOfFiles) {
+ this.qualification = qualification;
+ this.applicant = applicant;
+ this.validater = validater;
+ this.numberOfFiles = numberOfFiles;
+ this.linearId = new UniqueIdentifier();
+ }
+
+ //getters
+ public Boolean getQualification() { return qualification; }
+ public Party getApplicant() { return applicant; }
+ public Party getValidater() { return validater; }
+ public int getNumberOfFiles() { return numberOfFiles; }
+
+ /* This method will indicate who are the participants and required signers when
+ * this state is used in a transaction. */
+ @Override
+ public List getParticipants() {
+ return Arrays.asList(applicant,validater);
+ }
+
+ public void validatedAndApproved (){
+ this.qualification = true;
+ }
+
+ @NotNull
+ @Override
+ public UniqueIdentifier getLinearId() {
+ return this.linearId;
+ }
+}
\ No newline at end of file
diff --git a/Advanced/duediligence-cordapp/contracts/src/main/java/net/corda/samples/duediligence/states/DueDChecklist.java b/Advanced/duediligence-cordapp/contracts/src/main/java/net/corda/samples/duediligence/states/DueDChecklist.java
new file mode 100644
index 00000000..36cf1f54
--- /dev/null
+++ b/Advanced/duediligence-cordapp/contracts/src/main/java/net/corda/samples/duediligence/states/DueDChecklist.java
@@ -0,0 +1,84 @@
+package net.corda.samples.duediligence.states;
+
+import net.corda.core.contracts.LinearState;
+import net.corda.core.contracts.UniqueIdentifier;
+import net.corda.core.serialization.ConstructorForDeserialization;
+import net.corda.samples.duediligence.contracts.DueDChecklistContract;
+import net.corda.core.contracts.BelongsToContract;
+import net.corda.core.identity.AbstractParty;
+import net.corda.core.identity.Party;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+// *********
+// * State *
+// *********
+@BelongsToContract(DueDChecklistContract.class)
+public class DueDChecklist implements LinearState {
+
+ //private variables
+ private int numberOfapprovalsNeeded;
+ private String status = "INCOMPLETE";
+ private Party operationNode;
+ private Party reportTo;
+ private List attachedApprovals = new ArrayList();
+ private UniqueIdentifier linearID;
+
+ /* Constructor of your Corda state */
+ @ConstructorForDeserialization
+ public DueDChecklist(int numberOfapprovalsNeeded, String status, Party operationNode, Party reportTo, List attachedApprovals, UniqueIdentifier linearID) {
+ this.numberOfapprovalsNeeded = numberOfapprovalsNeeded;
+ this.status = status;
+ this.operationNode = operationNode;
+ this.reportTo = reportTo;
+ this.attachedApprovals = attachedApprovals;
+ this.linearID = linearID;
+ }
+
+ //Modification will
+ public DueDChecklist(int numberOfapprovalsNeeded, Party operationNode, Party reportTo, UniqueIdentifier linearID) {
+ this.numberOfapprovalsNeeded = numberOfapprovalsNeeded;
+ this.operationNode = operationNode;
+ this.reportTo = reportTo;
+ this.linearID = linearID;
+ }
+
+ //getters
+ public int getNumberOfapprovals() { return numberOfapprovalsNeeded; }
+ public String getStatus() { return status; }
+ public Party getOperationNode() { return operationNode; }
+
+ public int getNumberOfapprovalsNeeded() {
+ return numberOfapprovalsNeeded;
+ }
+
+ public List getAttachedApprovals() {
+ return attachedApprovals;
+ }
+
+ public void uploadApproval(UniqueIdentifier approvalId){
+ List copyOfExistingList = new ArrayList();
+ for (UniqueIdentifier id : attachedApprovals){
+ copyOfExistingList.add(id);
+ }
+ copyOfExistingList.add(approvalId);
+ this.attachedApprovals = copyOfExistingList;
+ }
+
+
+ /* This method will indicate who are the participants and required signers when
+ * this state is used in a transaction. */
+ @Override
+ public List getParticipants() {
+ return Arrays.asList(operationNode,reportTo);
+ }
+
+ @NotNull
+ @Override
+ public UniqueIdentifier getLinearId() {
+ return this.linearID;
+ }
+}
\ No newline at end of file
diff --git a/Advanced/duediligence-cordapp/contracts/src/main/resources/corporateAuditors.jar b/Advanced/duediligence-cordapp/contracts/src/main/resources/corporateAuditors.jar
new file mode 100644
index 00000000..b4b25be1
Binary files /dev/null and b/Advanced/duediligence-cordapp/contracts/src/main/resources/corporateAuditors.jar differ
diff --git a/Advanced/duediligence-cordapp/contracts/src/main/resources/financialAuditors.jar b/Advanced/duediligence-cordapp/contracts/src/main/resources/financialAuditors.jar
new file mode 100644
index 00000000..d50b1452
Binary files /dev/null and b/Advanced/duediligence-cordapp/contracts/src/main/resources/financialAuditors.jar differ
diff --git a/Advanced/duediligence-cordapp/contracts/src/main/resources/whitelistedCorporateAuditors.txt b/Advanced/duediligence-cordapp/contracts/src/main/resources/whitelistedCorporateAuditors.txt
new file mode 100644
index 00000000..fa5db9de
--- /dev/null
+++ b/Advanced/duediligence-cordapp/contracts/src/main/resources/whitelistedCorporateAuditors.txt
@@ -0,0 +1,2 @@
+Crossland Savings
+Trusted Auditor
\ No newline at end of file
diff --git a/Advanced/duediligence-cordapp/contracts/src/main/resources/whitelistedFinancialAuditors.txt b/Advanced/duediligence-cordapp/contracts/src/main/resources/whitelistedFinancialAuditors.txt
new file mode 100644
index 00000000..3a26bc0e
--- /dev/null
+++ b/Advanced/duediligence-cordapp/contracts/src/main/resources/whitelistedFinancialAuditors.txt
@@ -0,0 +1,2 @@
+Detroit Partners Group
+Tifton Banking Company
\ No newline at end of file
diff --git a/Advanced/duediligence-cordapp/contracts/src/test/java/net/corda/samples/duediligence/contracts/ContractTests.java b/Advanced/duediligence-cordapp/contracts/src/test/java/net/corda/samples/duediligence/contracts/ContractTests.java
new file mode 100644
index 00000000..e992d98e
--- /dev/null
+++ b/Advanced/duediligence-cordapp/contracts/src/test/java/net/corda/samples/duediligence/contracts/ContractTests.java
@@ -0,0 +1,40 @@
+package net.corda.samples.duediligence.contracts;
+
+import net.corda.core.identity.CordaX500Name;
+import net.corda.samples.duediligence.states.CorporateRecordsAuditRequest;
+import net.corda.testing.core.TestIdentity;
+import net.corda.testing.node.MockServices;
+import org.junit.Test;
+
+import java.util.Arrays;
+
+import static net.corda.samples.duediligence.contracts.CorporateRecordsContract.CorporateRecordsContract_ID;
+import static net.corda.testing.node.NodeTestUtils.ledger;
+
+public class ContractTests {
+ private final MockServices ledgerServices = new MockServices(
+ Arrays.asList("net.corda.samples.duediligence.contracts")
+ );
+ public static TestIdentity alice = new TestIdentity(new CordaX500Name("Alice", "TestLand", "US"));
+ public static TestIdentity bob = new TestIdentity(new CordaX500Name("Bob", "TestCity", "US"));
+
+ @Test
+ public void ProposeTransactionshouldhavezeroinput() {
+ CorporateRecordsAuditRequest cr = new CorporateRecordsAuditRequest(alice.getParty(),bob.getParty(),10);
+
+ ledger(ledgerServices, l -> {
+ l.transaction(tx -> {
+ tx.input(CorporateRecordsContract_ID, cr);
+ tx.command(Arrays.asList(alice.getPublicKey(), bob.getPublicKey()), new CorporateRecordsContract.Commands.Propose());
+ tx.output(CorporateRecordsContract_ID, cr);
+ return tx.fails();
+ });
+ l.transaction(tx -> {
+ tx.command(Arrays.asList(alice.getPublicKey(), bob.getPublicKey()), new CorporateRecordsContract.Commands.Propose());
+ tx.output(CorporateRecordsContract_ID, cr);
+ return tx.verifies(); // As there are no input sates
+ });
+ return null;
+ });
+ }
+}
\ No newline at end of file
diff --git a/Advanced/duediligence-cordapp/contracts/src/test/java/net/corda/samples/duediligence/contracts/StateTests.java b/Advanced/duediligence-cordapp/contracts/src/test/java/net/corda/samples/duediligence/contracts/StateTests.java
new file mode 100644
index 00000000..77320744
--- /dev/null
+++ b/Advanced/duediligence-cordapp/contracts/src/test/java/net/corda/samples/duediligence/contracts/StateTests.java
@@ -0,0 +1,18 @@
+package net.corda.samples.duediligence.contracts;
+
+import net.corda.core.identity.Party;
+import net.corda.samples.duediligence.states.CorporateRecordsAuditRequest;
+import net.corda.testing.node.MockServices;
+import org.junit.Test;
+
+public class StateTests {
+ private final MockServices ledgerServices = new MockServices();
+
+ @Test
+ public void hasFieldOfCorrectType() throws NoSuchFieldException {
+ // Does the message field exist?
+ CorporateRecordsAuditRequest.class.getDeclaredField("applicant");
+ // Is the message field of the correct type?
+ assert(CorporateRecordsAuditRequest.class.getDeclaredField("applicant").getType().equals(Party.class));
+ }
+}
\ No newline at end of file
diff --git a/Advanced/duediligence-cordapp/due-d diagram.png b/Advanced/duediligence-cordapp/due-d diagram.png
new file mode 100644
index 00000000..7dd6f0c8
Binary files /dev/null and b/Advanced/duediligence-cordapp/due-d diagram.png differ
diff --git a/Advanced/duediligence-cordapp/gradle.properties b/Advanced/duediligence-cordapp/gradle.properties
new file mode 100644
index 00000000..5a45466c
--- /dev/null
+++ b/Advanced/duediligence-cordapp/gradle.properties
@@ -0,0 +1,3 @@
+name=Due diligence Cordapp
+group=com.duediligence
+version=1.0
\ No newline at end of file
diff --git a/Basic/spring-webserver/gradle/wrapper/gradle-wrapper.jar b/Advanced/duediligence-cordapp/gradle/wrapper/gradle-wrapper.jar
similarity index 100%
rename from Basic/spring-webserver/gradle/wrapper/gradle-wrapper.jar
rename to Advanced/duediligence-cordapp/gradle/wrapper/gradle-wrapper.jar
diff --git a/Advanced/duediligence-cordapp/gradle/wrapper/gradle-wrapper.properties b/Advanced/duediligence-cordapp/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 00000000..0188225a
--- /dev/null
+++ b/Advanced/duediligence-cordapp/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,7 @@
+#Fri Aug 25 12:50:39 BST 2017
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip
+
diff --git a/Basic/rpc-nodeinfo/gradlew b/Advanced/duediligence-cordapp/gradlew
similarity index 100%
rename from Basic/rpc-nodeinfo/gradlew
rename to Advanced/duediligence-cordapp/gradlew
diff --git a/Basic/rpc-nodeinfo/gradlew.bat b/Advanced/duediligence-cordapp/gradlew.bat
similarity index 100%
rename from Basic/rpc-nodeinfo/gradlew.bat
rename to Advanced/duediligence-cordapp/gradlew.bat
diff --git a/Advanced/duediligence-cordapp/repositories.gradle b/Advanced/duediligence-cordapp/repositories.gradle
new file mode 100644
index 00000000..8be7b630
--- /dev/null
+++ b/Advanced/duediligence-cordapp/repositories.gradle
@@ -0,0 +1,8 @@
+repositories {
+ mavenLocal()
+ mavenCentral()
+
+ maven { url 'https://jitpack.io' }
+ maven { url 'https://download.corda.net/maven/corda-dependencies' }
+ maven { url 'https://repo.gradle.org/gradle/libs-releases' }
+}
diff --git a/Advanced/duediligence-cordapp/settings.gradle b/Advanced/duediligence-cordapp/settings.gradle
new file mode 100644
index 00000000..2514aca2
--- /dev/null
+++ b/Advanced/duediligence-cordapp/settings.gradle
@@ -0,0 +1,3 @@
+include 'workflows'
+include 'contracts'
+include 'clients'
\ No newline at end of file
diff --git a/Advanced/duediligence-cordapp/workflows/build.gradle b/Advanced/duediligence-cordapp/workflows/build.gradle
new file mode 100644
index 00000000..996f079c
--- /dev/null
+++ b/Advanced/duediligence-cordapp/workflows/build.gradle
@@ -0,0 +1,64 @@
+apply plugin: 'net.corda.plugins.cordapp'
+apply plugin: 'net.corda.plugins.cordformation'
+apply plugin: 'net.corda.plugins.quasar-utils'
+
+cordapp {
+ targetPlatformVersion corda_platform_version
+ minimumPlatformVersion corda_platform_version
+ workflow {
+ name "Due Diligence Flows"
+ vendor "Corda Open Source"
+ licence "Apache License, Version 2.0"
+ versionId 1
+ }
+}
+
+sourceSets {
+ main {
+ java {
+ srcDir 'src/main/java'
+ java.outputDir = file('bin/main')
+ }
+ resources {
+ srcDir rootProject.file("config/dev")
+ }
+ }
+ test {
+ java {
+ srcDir 'src/test/java'
+ java.outputDir = file('bin/main')
+ }
+ resources {
+ srcDir rootProject.file("config/test")
+ }
+ }
+ integrationTest {
+ java {
+ compileClasspath += main.output + test.output
+ runtimeClasspath += main.output + test.output
+ srcDir file('src/integrationTest/java')
+ }
+ }
+}
+
+configurations {
+ integrationTestCompile.extendsFrom testCompile
+ integrationTestRuntime.extendsFrom testRuntime
+}
+
+dependencies {
+ testCompile "junit:junit:$junit_version"
+
+ // Corda dependencies.
+ cordaCompile "$corda_core_release_group:corda-core:$corda_core_release_version"
+ cordaRuntime "$corda_release_group:corda:$corda_release_version"
+ testCompile "$corda_release_group:corda-node-driver:$corda_release_version"
+
+ // CorDapp dependencies.
+ cordapp project(":contracts")
+}
+
+task integrationTest(type: Test, dependsOn: []) {
+ testClassesDirs = sourceSets.integrationTest.output.classesDirs
+ classpath = sourceSets.integrationTest.runtimeClasspath
+}
\ No newline at end of file
diff --git a/Advanced/duediligence-cordapp/workflows/src/integrationTest/java/net/corda/samples/duediligence/DriverBasedTest.java b/Advanced/duediligence-cordapp/workflows/src/integrationTest/java/net/corda/samples/duediligence/DriverBasedTest.java
new file mode 100644
index 00000000..17a3d698
--- /dev/null
+++ b/Advanced/duediligence-cordapp/workflows/src/integrationTest/java/net/corda/samples/duediligence/DriverBasedTest.java
@@ -0,0 +1,48 @@
+package net.corda.samples.duediligence;
+
+import com.google.common.collect.ImmutableList;
+import net.corda.core.concurrent.CordaFuture;
+import net.corda.core.identity.CordaX500Name;
+import net.corda.testing.core.TestIdentity;
+import net.corda.testing.driver.DriverParameters;
+import net.corda.testing.driver.NodeHandle;
+import net.corda.testing.driver.NodeParameters;
+import org.junit.Test;
+
+import java.util.List;
+
+import static net.corda.testing.driver.Driver.driver;
+import static org.junit.Assert.assertEquals;
+
+public class DriverBasedTest {
+ private final TestIdentity bankA = new TestIdentity(new CordaX500Name("BankA", "", "GB"));
+ private final TestIdentity bankB = new TestIdentity(new CordaX500Name("BankB", "", "US"));
+
+ @Test
+ public void nodeTest() {
+ driver(new DriverParameters().withIsDebug(true).withStartNodesInProcess(true), dsl -> {
+ // Start a pair of nodes and wait for them both to be ready.
+ List> handleFutures = ImmutableList.of(
+ dsl.startNode(new NodeParameters().withProvidedName(bankA.getName())),
+ dsl.startNode(new NodeParameters().withProvidedName(bankB.getName()))
+ );
+
+ try {
+ NodeHandle partyAHandle = handleFutures.get(0).get();
+ NodeHandle partyBHandle = handleFutures.get(1).get();
+
+ // From each node, make an RPC call to retrieve another node's name from the network map, to verify that the
+ // nodes have started and can communicate.
+
+ // This is a very basic test: in practice tests would be starting flows, and verifying the states in the vault
+ // and other important metrics to ensure that your CorDapp is working as intended.
+ assertEquals(partyAHandle.getRpc().wellKnownPartyFromX500Name(bankB.getName()).getName(), bankB.getName());
+ assertEquals(partyBHandle.getRpc().wellKnownPartyFromX500Name(bankA.getName()).getName(), bankA.getName());
+ } catch (Exception e) {
+ throw new RuntimeException("Caught exception during test: ", e);
+ }
+
+ return null;
+ });
+ }
+}
\ No newline at end of file
diff --git a/Advanced/duediligence-cordapp/workflows/src/main/java/net/corda/samples/duediligence/flows/AddApprovalsToCheckList.java b/Advanced/duediligence-cordapp/workflows/src/main/java/net/corda/samples/duediligence/flows/AddApprovalsToCheckList.java
new file mode 100644
index 00000000..a97fdb1f
--- /dev/null
+++ b/Advanced/duediligence-cordapp/workflows/src/main/java/net/corda/samples/duediligence/flows/AddApprovalsToCheckList.java
@@ -0,0 +1,107 @@
+package net.corda.samples.duediligence.flows;
+
+import co.paralleluniverse.fibers.Suspendable;
+import net.corda.core.contracts.ContractState;
+import net.corda.core.contracts.StateAndRef;
+import net.corda.core.contracts.UniqueIdentifier;
+import net.corda.core.flows.*;
+import net.corda.core.identity.Party;
+import net.corda.core.node.services.Vault;
+import net.corda.core.node.services.vault.QueryCriteria;
+import net.corda.core.transactions.SignedTransaction;
+import net.corda.core.transactions.TransactionBuilder;
+import net.corda.samples.duediligence.contracts.DueDChecklistContract;
+import net.corda.samples.duediligence.states.CopyOfCoporateRecordsAuditRequest;
+import net.corda.samples.duediligence.states.CorporateRecordsAuditRequest;
+import net.corda.samples.duediligence.states.DueDChecklist;
+
+import javax.naming.ldap.UnsolicitedNotification;
+import java.util.Arrays;
+import java.util.UUID;
+
+public class AddApprovalsToCheckList {
+
+ @InitiatingFlow
+ @StartableByRPC
+ public static class CreateCheckListAndAddApprovalInitiator extends FlowLogic {
+
+ private Party reportTo;
+ private UniqueIdentifier approvalId;
+
+ public CreateCheckListAndAddApprovalInitiator(Party reportTo, UniqueIdentifier approvalId) {
+ this.reportTo = reportTo;
+ this.approvalId = approvalId;
+ }
+
+ @Override
+ @Suspendable
+ public SignedTransaction call() throws FlowException {
+
+ //Query the input
+ QueryCriteria.LinearStateQueryCriteria inputCriteria = new QueryCriteria.LinearStateQueryCriteria()
+ .withUuid(Arrays.asList(UUID.fromString(approvalId.toString())))
+ .withStatus(Vault.StateStatus.UNCONSUMED)
+ .withRelevancyStatus(Vault.RelevancyStatus.RELEVANT);
+ StateAndRef inputStateAndRef = getServiceHub().getVaultService().queryBy(ContractState.class, inputCriteria).getStates().get(0);
+
+ //extract the notary
+ Party notary = inputStateAndRef.getState().getNotary();
+
+
+ //create due-diligence Checklist
+ DueDChecklist checklist = new DueDChecklist(3,getOurIdentity(),reportTo,new UniqueIdentifier());
+ checklist.uploadApproval(this.approvalId);
+
+ TransactionBuilder txBuilder = new TransactionBuilder(notary)
+ .addInputState(inputStateAndRef)
+ .addOutputState(checklist)
+ .addCommand(new DueDChecklistContract.Commands.Add(),Arrays.asList(getOurIdentity().getOwningKey(),reportTo.getOwningKey()));
+
+ // Verify that the transaction is valid.
+ txBuilder.verify(getServiceHub());
+
+ // Sign the transaction.
+ final SignedTransaction partSignedTx = getServiceHub().signInitialTransaction(txBuilder);
+
+ // Send the state to the counterparty, and receive it back with their signature.
+ FlowSession otherPartySession = initiateFlow(reportTo);
+ final SignedTransaction fullySignedTx = subFlow(
+ new CollectSignaturesFlow(partSignedTx, Arrays.asList(otherPartySession), CollectSignaturesFlow.Companion.tracker()));
+
+ // Notarise and record the transaction in both parties' vaults.
+ if (inputStateAndRef.getState().getData().getClass() == CorporateRecordsAuditRequest.class){
+ CorporateRecordsAuditRequest request = (CorporateRecordsAuditRequest) inputStateAndRef.getState().getData();
+ return subFlow(new FinalityFlow(fullySignedTx, Arrays.asList(otherPartySession,initiateFlow(request.getValidater()))));
+ }else{
+ CopyOfCoporateRecordsAuditRequest request = (CopyOfCoporateRecordsAuditRequest) inputStateAndRef.getState().getData();
+ return subFlow(new FinalityFlow(fullySignedTx, Arrays.asList(otherPartySession,initiateFlow(request.getoriginalValidater()),initiateFlow(request.getOriginalOwner()))));
+ }
+ }
+ }
+
+ @InitiatedBy(CreateCheckListAndAddApprovalInitiator.class)
+ public static class CreateCheckListAndAddApprovalResponder extends FlowLogic {
+ //private variable
+ private FlowSession counterpartySession;
+
+ //Constructor
+ public CreateCheckListAndAddApprovalResponder(FlowSession counterpartySession) {
+ this.counterpartySession = counterpartySession;
+ }
+
+ @Suspendable
+ @Override
+ public Void call() throws FlowException {
+ SignedTransaction signedTransaction = subFlow(new SignTransactionFlow(counterpartySession) {
+ @Suspendable
+ @Override
+ protected void checkTransaction(SignedTransaction stx) throws FlowException {
+ }
+ });
+ //Stored the transaction into data base.
+ subFlow(new ReceiveFinalityFlow(counterpartySession, signedTransaction.getId()));
+ return null;
+ }
+ }
+
+}
diff --git a/Advanced/duediligence-cordapp/workflows/src/main/java/net/corda/samples/duediligence/flows/RequestToValidateCorporateRecords.java b/Advanced/duediligence-cordapp/workflows/src/main/java/net/corda/samples/duediligence/flows/RequestToValidateCorporateRecords.java
new file mode 100644
index 00000000..c8b20d09
--- /dev/null
+++ b/Advanced/duediligence-cordapp/workflows/src/main/java/net/corda/samples/duediligence/flows/RequestToValidateCorporateRecords.java
@@ -0,0 +1,91 @@
+package net.corda.samples.duediligence.flows;
+
+import co.paralleluniverse.fibers.Suspendable;
+import net.corda.core.crypto.SecureHash;
+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.samples.duediligence.contracts.CorporateRecordsContract;
+import net.corda.samples.duediligence.states.CorporateRecordsAuditRequest;
+import net.corda.core.identity.CordaX500Name;
+
+import java.util.Arrays;
+import java.util.List;
+
+public class RequestToValidateCorporateRecords {
+
+ @InitiatingFlow
+ @StartableByRPC
+ public static class RequestToValidateCorporateRecordsInitiator extends FlowLogic {
+
+ //private variables
+ private Party validater;
+ private int numberOfFiles;
+
+
+ public RequestToValidateCorporateRecordsInitiator(Party validater, int numberOfFiles) {
+ this.validater = validater;
+ this.numberOfFiles = numberOfFiles;
+
+ }
+
+ @Suspendable
+ @Override
+ public String call() throws FlowException {
+ //notary
+ /** Explicit selection of notary by CordaX500Name - argument can by coded in flows or parsed from config (Preferred)*/
+ final Party notary = getServiceHub().getNetworkMapCache().getNotary(CordaX500Name.parse("O=Notary,L=London,C=GB"));
+
+ //Initiate Corporate Records validation
+ CorporateRecordsAuditRequest cr = new CorporateRecordsAuditRequest(getOurIdentity(),this.validater,this.numberOfFiles);
+
+ //Build transaction
+ final TransactionBuilder txBuilder = new TransactionBuilder(notary)
+ .addOutputState(cr)
+ .addCommand(new CorporateRecordsContract.Commands.Propose(),
+ Arrays.asList(getOurIdentity().getOwningKey(),validater.getOwningKey()));
+
+ // Verify that the transaction is valid.
+ txBuilder.verify(getServiceHub());
+
+ // Sign the transaction.
+ final SignedTransaction partSignedTx = getServiceHub().signInitialTransaction(txBuilder);
+
+ // Send the state to the counterparty, and receive it back with their signature.
+ FlowSession otherPartySession = initiateFlow(validater);
+ final SignedTransaction fullySignedTx = subFlow(
+ new CollectSignaturesFlow(partSignedTx, Arrays.asList(otherPartySession), CollectSignaturesFlow.Companion.tracker()));
+
+ // Notarise and record the transaction in both parties' vaults.
+ subFlow(new FinalityFlow(fullySignedTx, Arrays.asList(otherPartySession)));
+ return "Corporate Records Auditing Request has sent to: " + cr.getValidater().getName().getOrganisation()
+ +"\nCase Id: "+ cr.getLinearId();
+ }
+ }
+
+ @InitiatedBy(RequestToValidateCorporateRecordsInitiator.class)
+ public static class RequestToValidateCorporateRecordsResponder extends FlowLogic {
+ //private variable
+ private FlowSession counterpartySession;
+
+ //Constructor
+ public RequestToValidateCorporateRecordsResponder(FlowSession counterpartySession) {
+ this.counterpartySession = counterpartySession;
+ }
+
+ @Suspendable
+ @Override
+ public Void call() throws FlowException {
+ SignedTransaction signedTransaction = subFlow(new SignTransactionFlow(counterpartySession) {
+ @Suspendable
+ @Override
+ protected void checkTransaction(SignedTransaction stx) throws FlowException {
+ }
+ });
+ //Stored the transaction into data base.
+ subFlow(new ReceiveFinalityFlow(counterpartySession, signedTransaction.getId()));
+ return null;
+ }
+ }
+}
diff --git a/Advanced/duediligence-cordapp/workflows/src/main/java/net/corda/samples/duediligence/flows/ShareAuditingResult.java b/Advanced/duediligence-cordapp/workflows/src/main/java/net/corda/samples/duediligence/flows/ShareAuditingResult.java
new file mode 100644
index 00000000..5389ad64
--- /dev/null
+++ b/Advanced/duediligence-cordapp/workflows/src/main/java/net/corda/samples/duediligence/flows/ShareAuditingResult.java
@@ -0,0 +1,112 @@
+package net.corda.samples.duediligence.flows;
+
+import co.paralleluniverse.fibers.Suspendable;
+import net.corda.core.contracts.CommandAndState;
+import net.corda.core.contracts.StateAndRef;
+import net.corda.core.contracts.UniqueIdentifier;
+import net.corda.core.crypto.SecureHash;
+import net.corda.core.flows.*;
+import net.corda.core.identity.Party;
+import net.corda.core.node.services.Vault;
+import net.corda.core.node.services.vault.QueryCriteria;
+import net.corda.core.transactions.SignedTransaction;
+import net.corda.core.transactions.TransactionBuilder;
+import net.corda.samples.duediligence.contracts.CorporateRecordsContract;
+import net.corda.samples.duediligence.states.CopyOfCoporateRecordsAuditRequest;
+import net.corda.samples.duediligence.states.CorporateRecordsAuditRequest;
+
+import java.util.Arrays;
+import java.util.UUID;
+
+public class ShareAuditingResult {
+
+ @InitiatingFlow
+ @StartableByRPC
+ public static class ShareAuditingResultInitiator extends FlowLogic {
+
+ private UniqueIdentifier AuditingResultID;
+ private Party sendTo;
+ private static SecureHash trustedAuditorAttachment;
+
+
+ public ShareAuditingResultInitiator(UniqueIdentifier AuditingResultID, Party sendTo, SecureHash trustedAuditorAttachment) {
+ this.AuditingResultID = AuditingResultID;
+ this.sendTo = sendTo;
+ this.trustedAuditorAttachment = trustedAuditorAttachment;
+
+ }
+
+ @Override
+ @Suspendable
+ public String call() throws FlowException {
+
+ //Query the input
+ QueryCriteria.LinearStateQueryCriteria inputCriteria = new QueryCriteria.LinearStateQueryCriteria()
+ .withUuid(Arrays.asList(UUID.fromString(AuditingResultID.toString())))
+ .withStatus(Vault.StateStatus.UNCONSUMED)
+ .withRelevancyStatus(Vault.RelevancyStatus.RELEVANT);
+ StateAndRef inputStateAndRef = getServiceHub().getVaultService().queryBy(CorporateRecordsAuditRequest.class, inputCriteria).getStates().get(0);
+ CorporateRecordsAuditRequest input = (CorporateRecordsAuditRequest) inputStateAndRef.getState().getData();
+
+ //Send the copy to PartyB.
+ SignedTransaction originalTx = getServiceHub().getValidatedTransactions().getTransaction(inputStateAndRef.getRef().getTxhash());
+ //subFlow(new SendTransactionFlow(initiateFlow(sendTo), originalTx));
+
+ //extract the notary
+ Party notary = inputStateAndRef.getState().getNotary();
+ //CorporateRecordsAuditRequest imageState = new CorporateRecordsAuditRequest(input.getApplicant(),input.getValidater(),input.getNumberOfFiles(),input.getLinearId(),input.getQualification());
+ UniqueIdentifier copyId = new UniqueIdentifier();
+ CopyOfCoporateRecordsAuditRequest copyOfResult = new CopyOfCoporateRecordsAuditRequest(input.getApplicant(),sendTo,input.getLinearId(),
+ originalTx.getId(), input.getValidater(), input.getQualification(), copyId);
+
+ TransactionBuilder txBuilder = new TransactionBuilder(notary)
+ .addReferenceState(inputStateAndRef.referenced())
+ .addOutputState(copyOfResult)
+ .addCommand(new CorporateRecordsContract.Commands.Share(), Arrays.asList(input.getApplicant().getOwningKey(),sendTo.getOwningKey()))
+ .addAttachment(trustedAuditorAttachment);
+ ;
+
+ // Verify that the transaction is valid.
+ txBuilder.verify(getServiceHub());
+
+ // Sign the transaction.
+ final SignedTransaction partSignedTx = getServiceHub().signInitialTransaction(txBuilder);
+
+ // Send the state to the counterparty, and receive it back with their signature.
+ FlowSession otherPartySession = initiateFlow(sendTo);
+ final SignedTransaction fullySignedTx = subFlow(
+ new CollectSignaturesFlow(partSignedTx, Arrays.asList(otherPartySession), CollectSignaturesFlow.Companion.tracker()));
+
+ // Notarise and record the transaction in both parties' vaults.
+ subFlow(new FinalityFlow(fullySignedTx, Arrays.asList(otherPartySession)));
+ return "A Copy of Corporate Auditing Report has sent to" + sendTo.getName().getOrganisation() +
+ "\nID of the Copy: "+ copyId;
+ }
+ }
+
+ @InitiatedBy(ShareAuditingResultInitiator.class)
+ public static class ShareAuditingResultResponder extends FlowLogic {
+ //private variable
+ private FlowSession counterpartySession;
+
+ //Constructor
+ public ShareAuditingResultResponder(FlowSession counterpartySession) {
+ this.counterpartySession = counterpartySession;
+ }
+
+ @Suspendable
+ @Override
+ public Void call() throws FlowException {
+ SignedTransaction signedTransaction = subFlow(new SignTransactionFlow(counterpartySession) {
+ @Suspendable
+ @Override
+ protected void checkTransaction(SignedTransaction stx) throws FlowException {
+ }
+ });
+ //Stored the transaction into data base.
+ subFlow(new ReceiveFinalityFlow(counterpartySession, signedTransaction.getId()));
+ return null;
+ }
+ }
+
+}
diff --git a/Advanced/duediligence-cordapp/workflows/src/main/java/net/corda/samples/duediligence/flows/ValidateCorporateRecords.java b/Advanced/duediligence-cordapp/workflows/src/main/java/net/corda/samples/duediligence/flows/ValidateCorporateRecords.java
new file mode 100644
index 00000000..ee553798
--- /dev/null
+++ b/Advanced/duediligence-cordapp/workflows/src/main/java/net/corda/samples/duediligence/flows/ValidateCorporateRecords.java
@@ -0,0 +1,99 @@
+package net.corda.samples.duediligence.flows;
+
+import co.paralleluniverse.fibers.Suspendable;
+import net.corda.core.contracts.StateAndRef;
+import net.corda.core.contracts.UniqueIdentifier;
+import net.corda.core.flows.*;
+import net.corda.core.identity.Party;
+import net.corda.core.node.services.Vault;
+import net.corda.core.node.services.vault.QueryCriteria;
+import net.corda.core.transactions.SignedTransaction;
+import net.corda.core.transactions.TransactionBuilder;
+import net.corda.samples.duediligence.contracts.CorporateRecordsContract;
+import net.corda.samples.duediligence.states.CorporateRecordsAuditRequest;
+
+import java.util.Arrays;
+import java.util.UUID;
+
+public class ValidateCorporateRecords {
+
+ @InitiatingFlow
+ @StartableByRPC
+ public static class ValidateCorporateRecordsInitiator extends FlowLogic {
+
+ private UniqueIdentifier linearId;
+
+
+ public ValidateCorporateRecordsInitiator(UniqueIdentifier linearId) {
+ this.linearId = linearId;
+ }
+
+ @Suspendable
+ @Override
+ public SignedTransaction call() throws FlowException {
+
+ //Query the input
+ QueryCriteria.LinearStateQueryCriteria inputCriteria = new QueryCriteria.LinearStateQueryCriteria()
+ .withUuid(Arrays.asList(UUID.fromString(linearId.toString())))
+ .withStatus(Vault.StateStatus.UNCONSUMED)
+ .withRelevancyStatus(Vault.RelevancyStatus.RELEVANT);
+ StateAndRef inputStateAndRef = getServiceHub().getVaultService().queryBy(CorporateRecordsAuditRequest.class, inputCriteria).getStates().get(0);
+ CorporateRecordsAuditRequest input = (CorporateRecordsAuditRequest) inputStateAndRef.getState().getData();
+
+ //extract the notary
+ Party notary = inputStateAndRef.getState().getNotary();
+
+ //Creating the output
+ CorporateRecordsAuditRequest output = new CorporateRecordsAuditRequest(input.getApplicant(),getOurIdentity(),input.getNumberOfFiles(),input.getLinearId());
+
+ //set validation status to true
+ output.validatedAndApproved();
+
+ //Build transaction
+ final TransactionBuilder txBuilder = new TransactionBuilder(notary)
+ .addInputState(inputStateAndRef)
+ .addOutputState(output)
+ .addCommand(new CorporateRecordsContract.Commands.Validate(),
+ Arrays.asList(getOurIdentity().getOwningKey(),input.getApplicant().getOwningKey()));
+
+ // Verify that the transaction is valid.
+ txBuilder.verify(getServiceHub());
+
+ // Sign the transaction.
+ final SignedTransaction partSignedTx = getServiceHub().signInitialTransaction(txBuilder);
+
+ // Send the state to the counterparty, and receive it back with their signature.
+ FlowSession otherPartySession = initiateFlow(input.getApplicant());
+ final SignedTransaction fullySignedTx = subFlow(
+ new CollectSignaturesFlow(partSignedTx, Arrays.asList(otherPartySession), CollectSignaturesFlow.Companion.tracker()));
+
+ // Notarise and record the transaction in both parties' vaults.
+ return subFlow(new FinalityFlow(fullySignedTx, Arrays.asList(otherPartySession)));
+ }
+ }
+
+ @InitiatedBy(ValidateCorporateRecordsInitiator.class)
+ public static class ValidateCorporateRecordsResponder extends FlowLogic {
+ //private variable
+ private FlowSession counterpartySession;
+
+ //Constructor
+ public ValidateCorporateRecordsResponder(FlowSession counterpartySession) {
+ this.counterpartySession = counterpartySession;
+ }
+
+ @Suspendable
+ @Override
+ public Void call() throws FlowException {
+ SignedTransaction signedTransaction = subFlow(new SignTransactionFlow(counterpartySession) {
+ @Suspendable
+ @Override
+ protected void checkTransaction(SignedTransaction stx) throws FlowException {
+ }
+ });
+ //Stored the transaction into data base.
+ subFlow(new ReceiveFinalityFlow(counterpartySession, signedTransaction.getId()));
+ return null;
+ }
+ }
+}
diff --git a/Advanced/duediligence-cordapp/workflows/src/test/java/net/corda/samples/duediligence/FlowTests.java b/Advanced/duediligence-cordapp/workflows/src/test/java/net/corda/samples/duediligence/FlowTests.java
new file mode 100644
index 00000000..ae0438d4
--- /dev/null
+++ b/Advanced/duediligence-cordapp/workflows/src/test/java/net/corda/samples/duediligence/FlowTests.java
@@ -0,0 +1,66 @@
+package net.corda.samples.duediligence;
+
+import com.google.common.collect.ImmutableList;
+import net.corda.core.contracts.ContractState;
+import net.corda.core.contracts.StateAndRef;
+import net.corda.core.contracts.UniqueIdentifier;
+import net.corda.core.identity.CordaX500Name;
+import net.corda.core.node.services.Vault;
+import net.corda.core.node.services.vault.QueryCriteria;
+import net.corda.samples.duediligence.flows.RequestToValidateCorporateRecords;
+import net.corda.samples.duediligence.states.CorporateRecordsAuditRequest;
+import net.corda.testing.node.*;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.Arrays;
+import java.util.UUID;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import static org.junit.Assert.assertEquals;
+
+public class FlowTests {
+ private MockNetwork network;
+ private StartedMockNode a;
+ private StartedMockNode b;
+
+ @Before
+ public void setup() {
+ network = new MockNetwork(new MockNetworkParameters().withCordappsForAllNodes(ImmutableList.of(
+ TestCordapp.findCordapp("net.corda.samples.duediligence.contracts"),
+ TestCordapp.findCordapp("net.corda.samples.duediligence.flows")))
+ .withNotarySpecs(ImmutableList.of(new MockNetworkNotarySpec(CordaX500Name.parse("O=Notary,L=London,C=GB")))));
+ a = network.createPartyNode(null);
+ b = network.createPartyNode(null);
+ network.runNetwork();
+ }
+
+ @After
+ public void tearDown() {
+ network.stopNodes();
+ }
+
+ @Test
+ public void CreationAndSigningTheAuditingRequest() throws ExecutionException, InterruptedException {
+ RequestToValidateCorporateRecords.RequestToValidateCorporateRecordsInitiator flow1 =
+ new RequestToValidateCorporateRecords.RequestToValidateCorporateRecordsInitiator(b.getInfo().getLegalIdentities().get(0),10);
+ Future future = a.startFlow(flow1);
+ network.runNetwork();
+ String result1 = future.get();
+ System.out.println(result1);
+ int subString = result1.indexOf("Case Id: ");
+ String ApproalID = result1.substring(subString+9);
+ System.out.println("-"+ ApproalID+"-");
+
+ UniqueIdentifier id = UniqueIdentifier.Companion.fromString(ApproalID);
+ //Query the input
+ QueryCriteria.LinearStateQueryCriteria inputCriteria = new QueryCriteria.LinearStateQueryCriteria()
+ .withUuid(Arrays.asList(UUID.fromString(id.toString())))
+ .withStatus(Vault.StateStatus.UNCONSUMED)
+ .withRelevancyStatus(Vault.RelevancyStatus.RELEVANT);
+ StateAndRef inputStateAndRef = a.getServices().getVaultService().queryBy(ContractState.class, inputCriteria).getStates().get(0);
+ CorporateRecordsAuditRequest result = (CorporateRecordsAuditRequest)inputStateAndRef.getState().getData();
+ assertEquals(result.getLinearId(),id);
+ }
+}
diff --git a/Advanced/negotiation-cordapp/README.md b/Advanced/negotiation-cordapp/README.md
index 68d1c2a5..582340f6 100644
--- a/Advanced/negotiation-cordapp/README.md
+++ b/Advanced/negotiation-cordapp/README.md
@@ -1,4 +1,4 @@
-# negotiation cordapp [
](https://ide.corda.net/?folder=/home/coder/samples-java/Advanced/negotiation-cordapp)
+# Negotiation Cordapp
This CorDapp shows how multi-party negotiation is handled on the Corda ledger, in the absence of an API for user
interaction.
@@ -16,21 +16,21 @@ accept or modify the proposal, this attempt will be rejected automatically at th
### Flows
-We start with the proposal flow implemented in [ProposalFlow.java](./workflows/src/main/java/negotiation/flows/ProposalFlow.java)
+We start with the proposal flow implemented in `ProposalFlow.java`.
-The modification of the proposal is implemented in [ModificationFlow.java](./workflows/src/main/java/negotiation/flows/ModificationFlow.java#L42-L49).
+The modification of the proposal is implemented in `ModificationFlow.java`.
-In the [AcceptanceFlow.java](./workflows/src/main/java/negotiation/flows/AcceptanceFlow.java#L42-L75), we receive the modified ProposalState and it's converted into a TradeState.
+In the `AcceptanceFlow.java`, we receive the modified ProposalState and it's converted into a TradeState.
## Usage
-### Pre-requisites:
+### Pre-Requisites
+For development environment setup, please refer to: [Setup Guide](https://docs.corda.net/getting-set-up.html).
-See https://docs.corda.net/getting-set-up.html.
### Running the nodes:
@@ -52,7 +52,7 @@ First, go the the shell of PartyA, and propose a deal with yourself as buyer and
We can now look at the proposals in the PartyA's vault:
- run vaultQuery contractStateType: negotiation.states.ProposalState
+ run vaultQuery contractStateType: ProposalState
If we note down the state's `linearId.id`, we can now modify the proposal from the shell of PartyB by running:
@@ -65,4 +65,4 @@ Finally, let's have PartyA accept the proposal:
We can now see the accepted trade in our vault with the new value by running the command (note we are now querying for
`TradeState`s, not `ProposalState`s):
- run vaultQuery contractStateType: negotiation.states.TradeState
+ run vaultQuery contractStateType: TradeState
diff --git a/Advanced/negotiation-cordapp/build.gradle b/Advanced/negotiation-cordapp/build.gradle
index ee6c57e8..d98cff3d 100644
--- a/Advanced/negotiation-cordapp/build.gradle
+++ b/Advanced/negotiation-cordapp/build.gradle
@@ -3,9 +3,8 @@ buildscript {
file("$projectDir/../constants.properties").withInputStream { constants.load(it) }
ext {
-
corda_release_group = constants.getProperty("cordaReleaseGroup")
- corda_core_release_group = constants.getProperty("cordaCoreReleaseGroup")
+ corda_core_release_group = constants.getProperty("cordaCoreReleaseGroup")
corda_release_version = constants.getProperty("cordaVersion")
corda_core_release_version = constants.getProperty("cordaCoreVersion")
corda_gradle_plugins_version = constants.getProperty("gradlePluginsVersion")
@@ -21,14 +20,17 @@ buildscript {
}
repositories {
+
mavenLocal()
mavenCentral()
- jcenter()
- maven { url 'http://ci-artifactory.corda.r3cev.com/artifactory/corda-lib-dev' }
- maven { url 'http://ci-artifactory.corda.r3cev.com/artifactory/corda-lib' }
- maven { url 'https://ci-artifactory.corda.r3cev.com/artifactory/corda' }
+
+ maven { url 'https://download.corda.net/maven/corda-dependencies' }
+ maven { url 'http://software.r3.com/artifactory/corda-lib' }
+ maven { url 'http://software.r3.com/artifactory/corda-lib-dev' }
+ maven { url 'https://download.corda.net/maven/corda-releases' }
+
// Corda dependencies for the patched Quasar version
- maven { url "https://software.r3.com/artifactory/corda-dependencies" } // access to the patched Quasar version
+ maven { url "https://download.corda.net/maven/corda-dependencies" } // access to the patched Quasar version
}
dependencies {
@@ -36,7 +38,6 @@ buildscript {
classpath "net.corda.plugins:cordformation:$corda_gradle_plugins_version"
classpath "net.corda.plugins:quasar-utils:$corda_gradle_plugins_version"
classpath "org.springframework.boot:spring-boot-gradle-plugin:$spring_boot_gradle_plugin_version"
-
}
}
@@ -46,12 +47,12 @@ allprojects {
repositories {
mavenLocal()
- jcenter()
+
mavenCentral()
- maven { url 'https://ci-artifactory.corda.r3cev.com/artifactory/corda' }
+ maven { url 'https://download.corda.net/maven/corda-dependencies' }
// Can be removed post-release - used to get nightly snapshot build.
- maven { url 'https://ci-artifactory.corda.r3cev.com/artifactory/corda-lib' }
- maven { url 'https://ci-artifactory.corda.r3cev.com/artifactory/corda-lib-dev' }
+ maven { url 'https://download.corda.net/maven/corda-lib' }
+ maven { url 'https://download.corda.net/maven/corda-lib-dev' }
maven { url 'https://jitpack.io' }
maven { url "https://repo.gradle.org/gradle/libs-releases-local" }
}
@@ -93,6 +94,8 @@ dependencies {
cordaCompile "org.apache.logging.log4j:log4j-slf4j-impl:${log4j_version}"
cordaCompile "org.apache.logging.log4j:log4j-web:${log4j_version}"
cordaCompile "org.slf4j:jul-to-slf4j:$slf4j_version"
+ cordaDriver "net.corda:corda-shell:4.10"
+
}
cordapp {
@@ -106,29 +109,17 @@ cordapp {
}
}
-task ganache {
- subprojects {
- if (it.project.name != "clients") {
- dependsOn jar
- doLast {
- copy {
- from "${buildDir}/libs"
- into "${rootDir}/build/libs"
- }
- }
- }
- }
-}
-
task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar']) {
- nodeDefaults {
+ nodeDefaults {
cordapp project(':contracts')
- runSchemaMigration = true
+ cordapp project(':workflows')
+ runSchemaMigration = true
}
+
node {
name "O=Notary,L=London,C=GB"
- notary = [validating : false]
+ notary = [validating: false]
p2pPort 10002
rpcSettings {
address("localhost:10003")
@@ -142,7 +133,7 @@ task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar']) {
address("localhost:10006")
adminAddress("localhost:10046")
}
- rpcUsers = [[ user: "user1", "password": "test", "permissions": ["ALL"]]]
+ rpcUsers = [[user: "user1", "password": "test", "permissions": ["ALL"]]]
}
node {
name "O=PartyB,L=New York,C=US"
@@ -151,7 +142,13 @@ task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar']) {
address("localhost:10009")
adminAddress("localhost:10049")
}
- rpcUsers = [[ user: "user1", "password": "test", "permissions": ["ALL"]]]
+ rpcUsers = [[user: "user1", "password": "test", "permissions": ["ALL"]]]
}
}
+task installQuasar(type: Copy) {
+ destinationDir rootProject.file("lib")
+ from(configurations.quasar) {
+ rename 'quasar-core(.*).jar', 'quasar.jar'
+ }
+}
diff --git a/Advanced/negotiation-cordapp/contracts/build.gradle b/Advanced/negotiation-cordapp/contracts/build.gradle
index 78e414df..589d8ab7 100644
--- a/Advanced/negotiation-cordapp/contracts/build.gradle
+++ b/Advanced/negotiation-cordapp/contracts/build.gradle
@@ -1,7 +1,7 @@
apply plugin: 'java'
apply plugin: 'net.corda.plugins.cordapp'
-jar.baseName = "timesheet-timesheet-contracts"
+//jar.baseName = "timesheet-timesheet-contracts" TODO remove this
cordapp {
targetPlatformVersion corda_platform_version.toInteger()
@@ -29,4 +29,4 @@ dependencies {
tasks.withType(JavaCompile) {
options.compilerArgs << "-parameters" // Required for shell commands.
-}
\ No newline at end of file
+}
diff --git a/Advanced/negotiation-cordapp/contracts/src/main/java/negotiation/contracts/ProposalAndTradeContract.java b/Advanced/negotiation-cordapp/contracts/src/main/java/net/corda/samples/negotiation/contracts/ProposalAndTradeContract.java
similarity index 87%
rename from Advanced/negotiation-cordapp/contracts/src/main/java/negotiation/contracts/ProposalAndTradeContract.java
rename to Advanced/negotiation-cordapp/contracts/src/main/java/net/corda/samples/negotiation/contracts/ProposalAndTradeContract.java
index afa50151..d72648d4 100644
--- a/Advanced/negotiation-cordapp/contracts/src/main/java/negotiation/contracts/ProposalAndTradeContract.java
+++ b/Advanced/negotiation-cordapp/contracts/src/main/java/net/corda/samples/negotiation/contracts/ProposalAndTradeContract.java
@@ -1,21 +1,23 @@
-package negotiation.contracts;
+package net.corda.samples.negotiation.contracts;
import com.google.common.collect.ImmutableSet;
-import negotiation.states.ProposalState;
-import negotiation.states.TradeState;
+import net.corda.samples.negotiation.states.ProposalState;
+import net.corda.samples.negotiation.states.TradeState;
import net.corda.core.contracts.CommandData;
import net.corda.core.contracts.CommandWithParties;
import net.corda.core.contracts.Contract;
import net.corda.core.transactions.LedgerTransaction;
+
import static net.corda.core.contracts.ContractsDSL.requireThat;
public class ProposalAndTradeContract implements Contract {
- public static String ID = "negotiation.contracts.ProposalAndTradeContract";
+ public static String ID = "net.corda.samples.negotiation.contracts.ProposalAndTradeContract";
+
@Override
public void verify(LedgerTransaction tx) throws IllegalArgumentException {
final CommandWithParties command = tx.getCommands().get(0);
- if( command.getValue() instanceof Commands.Propose) {
+ if (command.getValue() instanceof Commands.Propose) {
requireThat(require -> {
require.using("There are no inputs", tx.getInputs().isEmpty());
require.using("Only one output state should be created.", tx.getOutputs().size() == 1);
@@ -28,7 +30,7 @@ public void verify(LedgerTransaction tx) throws IllegalArgumentException {
require.using("The proposee is a required signer", command.getSigners().contains(output.getProposee().getOwningKey()));
return null;
});
- }else if(command.getValue() instanceof Commands.Accept){
+ } else if (command.getValue() instanceof Commands.Accept) {
requireThat(require -> {
require.using("There is exactly one input", tx.getInputStates().size() == 1);
require.using("The single input is of type ProposalState", tx.inputsOfType(ProposalState.class).size() == 1);
@@ -48,8 +50,8 @@ public void verify(LedgerTransaction tx) throws IllegalArgumentException {
require.using("The proposee is a required signer", command.getSigners().contains(input.getProposee().getOwningKey()));
return null;
});
- }else if(command.getValue() instanceof Commands.Modify){
- requireThat(require ->{
+ } else if (command.getValue() instanceof Commands.Modify) {
+ requireThat(require -> {
require.using("There is exactly one input", tx.getInputStates().size() == 1);
require.using("The single input is of type ProposalState", tx.inputsOfType(ProposalState.class).size() == 1);
require.using("There is exactly one output", tx.getOutputs().size() == 1);
@@ -69,7 +71,7 @@ public void verify(LedgerTransaction tx) throws IllegalArgumentException {
return null;
});
- }else{
+ } else {
throw new IllegalArgumentException("Command of incorrect type");
}
@@ -77,8 +79,19 @@ public void verify(LedgerTransaction tx) throws IllegalArgumentException {
public interface Commands extends CommandData {
- class Propose implements Commands{};
- class Accept implements Commands{};
- class Modify implements Commands{};
+ class Propose implements Commands {
+ }
+
+ ;
+
+ class Accept implements Commands {
+ }
+
+ ;
+
+ class Modify implements Commands {
+ }
+
+ ;
}
}
diff --git a/Advanced/negotiation-cordapp/contracts/src/main/java/negotiation/states/ProposalState.java b/Advanced/negotiation-cordapp/contracts/src/main/java/net/corda/samples/negotiation/states/ProposalState.java
similarity index 91%
rename from Advanced/negotiation-cordapp/contracts/src/main/java/negotiation/states/ProposalState.java
rename to Advanced/negotiation-cordapp/contracts/src/main/java/net/corda/samples/negotiation/states/ProposalState.java
index 51301105..d3c2ed05 100644
--- a/Advanced/negotiation-cordapp/contracts/src/main/java/negotiation/states/ProposalState.java
+++ b/Advanced/negotiation-cordapp/contracts/src/main/java/net/corda/samples/negotiation/states/ProposalState.java
@@ -1,14 +1,14 @@
-package negotiation.states;
+package net.corda.samples.negotiation.states;
import com.google.common.collect.ImmutableList;
-import negotiation.contracts.ProposalAndTradeContract;
+
import net.corda.core.contracts.BelongsToContract;
-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.serialization.ConstructorForDeserialization;
+import net.corda.samples.negotiation.contracts.ProposalAndTradeContract;
import org.jetbrains.annotations.NotNull;
import java.util.List;
@@ -67,8 +67,7 @@ public UniqueIdentifier getLinearId() {
@NotNull
@Override
- public List getParticipants(){
+ public List getParticipants() {
return ImmutableList.of(proposer, proposee);
-
}
}
diff --git a/Advanced/negotiation-cordapp/contracts/src/main/java/negotiation/states/TradeState.java b/Advanced/negotiation-cordapp/contracts/src/main/java/net/corda/samples/negotiation/states/TradeState.java
similarity index 89%
rename from Advanced/negotiation-cordapp/contracts/src/main/java/negotiation/states/TradeState.java
rename to Advanced/negotiation-cordapp/contracts/src/main/java/net/corda/samples/negotiation/states/TradeState.java
index 8ed5d9dc..597bf922 100644
--- a/Advanced/negotiation-cordapp/contracts/src/main/java/negotiation/states/TradeState.java
+++ b/Advanced/negotiation-cordapp/contracts/src/main/java/net/corda/samples/negotiation/states/TradeState.java
@@ -1,7 +1,7 @@
-package negotiation.states;
+package net.corda.samples.negotiation.states;
import com.google.common.collect.ImmutableList;
-import negotiation.contracts.ProposalAndTradeContract;
+import net.corda.samples.negotiation.contracts.ProposalAndTradeContract;
import net.corda.core.contracts.BelongsToContract;
import net.corda.core.contracts.LinearState;
import net.corda.core.contracts.UniqueIdentifier;
@@ -51,6 +51,6 @@ public UniqueIdentifier getLinearId() {
@Override
public List getParticipants() {
- return ImmutableList.of(buyer,seller);
+ return ImmutableList.of(buyer, seller);
}
}
diff --git a/Advanced/negotiation-cordapp/contracts/src/test/java/negotiation/contracts/AcceptanceContractTests.java b/Advanced/negotiation-cordapp/contracts/src/test/java/net/corda/samples/negotiation/contracts/AcceptanceContractTests.java
similarity index 97%
rename from Advanced/negotiation-cordapp/contracts/src/test/java/negotiation/contracts/AcceptanceContractTests.java
rename to Advanced/negotiation-cordapp/contracts/src/test/java/net/corda/samples/negotiation/contracts/AcceptanceContractTests.java
index 233d6354..9897dfc3 100644
--- a/Advanced/negotiation-cordapp/contracts/src/test/java/negotiation/contracts/AcceptanceContractTests.java
+++ b/Advanced/negotiation-cordapp/contracts/src/test/java/net/corda/samples/negotiation/contracts/AcceptanceContractTests.java
@@ -1,8 +1,8 @@
-package negotiation.contracts;
+package net.corda.samples.negotiation.contracts;
import com.google.common.collect.ImmutableList;
-import negotiation.states.ProposalState;
-import negotiation.states.TradeState;
+import net.corda.samples.negotiation.states.ProposalState;
+import net.corda.samples.negotiation.states.TradeState;
import net.corda.testing.core.DummyCommandData;
import net.corda.testing.core.TestIdentity;
import net.corda.testing.node.MockServices;
@@ -14,7 +14,7 @@
public class AcceptanceContractTests {
- private MockServices ledgerServices = new MockServices(ImmutableList.of("negotiation.contracts"));
+ private MockServices ledgerServices = new MockServices(ImmutableList.of("net.corda.samples.negotiation.contracts"));
private TestIdentity alice = new TestIdentity(new net.corda.core.identity.CordaX500Name("alice","New York", "US"));
private TestIdentity bob = new TestIdentity(new net.corda.core.identity.CordaX500Name("bob","Tokyo", "JP"));
private TestIdentity charlie = new TestIdentity(new net.corda.core.identity.CordaX500Name("charlie","London", "GB"));
diff --git a/Advanced/negotiation-cordapp/contracts/src/test/java/negotiation/contracts/ModificationContractTests.java b/Advanced/negotiation-cordapp/contracts/src/test/java/net/corda/samples/negotiation/contracts/ModificationContractTests.java
similarity index 97%
rename from Advanced/negotiation-cordapp/contracts/src/test/java/negotiation/contracts/ModificationContractTests.java
rename to Advanced/negotiation-cordapp/contracts/src/test/java/net/corda/samples/negotiation/contracts/ModificationContractTests.java
index ee6b8ef9..089b77e9 100644
--- a/Advanced/negotiation-cordapp/contracts/src/test/java/negotiation/contracts/ModificationContractTests.java
+++ b/Advanced/negotiation-cordapp/contracts/src/test/java/net/corda/samples/negotiation/contracts/ModificationContractTests.java
@@ -1,8 +1,8 @@
-package negotiation.contracts;
+package net.corda.samples.negotiation.contracts;
import com.google.common.collect.ImmutableList;
-import negotiation.states.ProposalState;
-import negotiation.states.TradeState;
+import net.corda.samples.negotiation.states.ProposalState;
+import net.corda.samples.negotiation.states.TradeState;
import net.corda.testing.core.DummyCommandData;
import net.corda.testing.core.TestIdentity;
import net.corda.testing.node.MockServices;
@@ -13,7 +13,8 @@
import static net.corda.testing.node.NodeTestUtils.ledger;
public class ModificationContractTests {
- private MockServices ledgerServices = new MockServices(ImmutableList.of("negotiation.contracts"));
+
+ private MockServices ledgerServices = new MockServices(ImmutableList.of("net.corda.samples.negotiation.contracts"));
private TestIdentity alice = new TestIdentity(new net.corda.core.identity.CordaX500Name("alice","New York", "US"));
private TestIdentity bob = new TestIdentity(new net.corda.core.identity.CordaX500Name("bob","Tokyo", "JP"));
private TestIdentity charlie = new TestIdentity(new net.corda.core.identity.CordaX500Name("charlie","London", "GB"));
diff --git a/Advanced/negotiation-cordapp/contracts/src/test/java/negotiation/contracts/ProposalContractTests.java b/Advanced/negotiation-cordapp/contracts/src/test/java/net/corda/samples/negotiation/contracts/ProposalContractTests.java
similarity index 97%
rename from Advanced/negotiation-cordapp/contracts/src/test/java/negotiation/contracts/ProposalContractTests.java
rename to Advanced/negotiation-cordapp/contracts/src/test/java/net/corda/samples/negotiation/contracts/ProposalContractTests.java
index 29905a8c..74df7938 100644
--- a/Advanced/negotiation-cordapp/contracts/src/test/java/negotiation/contracts/ProposalContractTests.java
+++ b/Advanced/negotiation-cordapp/contracts/src/test/java/net/corda/samples/negotiation/contracts/ProposalContractTests.java
@@ -1,7 +1,7 @@
-package negotiation.contracts;
+package net.corda.samples.negotiation.contracts;
import com.google.common.collect.ImmutableList;
-import negotiation.states.ProposalState;
+import net.corda.samples.negotiation.states.ProposalState;
import net.corda.testing.contracts.DummyState;
import net.corda.testing.core.DummyCommandData;
import net.corda.testing.core.TestIdentity;
@@ -15,7 +15,7 @@
public class ProposalContractTests {
- private MockServices ledgerServices = new MockServices(ImmutableList.of("negotiation.contracts"));
+ private MockServices ledgerServices = new MockServices(ImmutableList.of("net.corda.samples.negotiation.contracts"));
private TestIdentity alice = new TestIdentity(new net.corda.core.identity.CordaX500Name("alice","New York", "US"));
private TestIdentity bob = new TestIdentity(new net.corda.core.identity.CordaX500Name("bob","Tokyo", "JP"));
private TestIdentity charlie = new TestIdentity(new net.corda.core.identity.CordaX500Name("charlie","London", "GB"));
diff --git a/Advanced/negotiation-cordapp/contracts/src/test/java/net/corda/samples/negotiation/states/ProposalStateTests.java b/Advanced/negotiation-cordapp/contracts/src/test/java/net/corda/samples/negotiation/states/ProposalStateTests.java
new file mode 100644
index 00000000..c4550d67
--- /dev/null
+++ b/Advanced/negotiation-cordapp/contracts/src/test/java/net/corda/samples/negotiation/states/ProposalStateTests.java
@@ -0,0 +1,57 @@
+package net.corda.samples.negotiation.states;
+
+import net.corda.core.contracts.UniqueIdentifier;
+import net.corda.core.identity.CordaX500Name;
+import net.corda.core.identity.Party;
+import net.corda.testing.core.TestIdentity;
+import org.junit.Test;
+
+import static junit.framework.TestCase.assertEquals;
+import static org.junit.Assert.*;
+
+
+public class ProposalStateTests {
+
+ private int amount = 10;
+ private final Party proposer = new TestIdentity(new CordaX500Name("Alice", "", "GB")).getParty();
+ private final Party buyer = new TestIdentity(new CordaX500Name("Bob", "", "GB")).getParty();
+ private final Party seller = new TestIdentity(new CordaX500Name("Charlie", "", "GB")).getParty();
+ private final Party proposee = new TestIdentity(new CordaX500Name("Dan", "", "GB")).getParty();
+
+ @Test
+ public void constructorTest() {
+
+ UniqueIdentifier tempId = new UniqueIdentifier();
+ ProposalState ps = new ProposalState(amount, buyer, seller, proposer, proposee, tempId);
+
+ assertEquals(ps.getAmount(), amount);
+ assertEquals(ps.getBuyer(), buyer);
+ assertEquals(ps.getSeller(), seller);
+ assertEquals(ps.getProposer(), proposer);
+ assertEquals(ps.getProposee(), proposee);
+ assertEquals(ps.getLinearId(), tempId);
+
+ assertNotEquals(ps.getAmount(), 0);
+ assertNotEquals(ps.getAmount(), -5);
+ assertNotEquals(ps.getAmount(), null);
+ }
+
+ @Test
+ public void linearIdTest() {
+ ProposalState ps = new ProposalState(amount, buyer, seller, proposer, proposee);
+
+ // ensure ID is generated with shorter constructor stub
+ assertTrue(ps.getLinearId() instanceof UniqueIdentifier);
+ }
+
+ @Test
+ public void participantTest() {
+ ProposalState ps = new ProposalState(amount, buyer, seller, proposer, proposee);
+
+ // ensure participants are generated correctly
+ assertTrue(ps.getParticipants().contains(proposer));
+ assertTrue(ps.getParticipants().contains(proposee));
+ assertFalse(ps.getParticipants().contains(buyer));
+ assertFalse(ps.getParticipants().contains(seller));
+ }
+}
diff --git a/Advanced/negotiation-cordapp/contracts/src/test/java/net/corda/samples/negotiation/states/TradeStateTests.java b/Advanced/negotiation-cordapp/contracts/src/test/java/net/corda/samples/negotiation/states/TradeStateTests.java
new file mode 100644
index 00000000..3828ef69
--- /dev/null
+++ b/Advanced/negotiation-cordapp/contracts/src/test/java/net/corda/samples/negotiation/states/TradeStateTests.java
@@ -0,0 +1,52 @@
+package net.corda.samples.negotiation.states;
+
+import net.corda.core.contracts.UniqueIdentifier;
+import net.corda.core.identity.CordaX500Name;
+import net.corda.core.identity.Party;
+import net.corda.testing.core.TestIdentity;
+import org.junit.Test;
+
+import static junit.framework.TestCase.assertEquals;
+import static org.junit.Assert.*;
+
+
+public class TradeStateTests {
+
+ private int amount = 10;
+ private final Party buyer = new TestIdentity(new CordaX500Name("Bob", "", "GB")).getParty();
+ private final Party seller = new TestIdentity(new CordaX500Name("Charlie", "", "GB")).getParty();
+
+ @Test
+ public void constructorTest() {
+
+ UniqueIdentifier tempId = new UniqueIdentifier();
+ TradeState ts = new TradeState(amount, buyer, seller, tempId);
+
+ assertEquals(ts.getAmount(), amount);
+ assertEquals(ts.getBuyer(), buyer);
+ assertEquals(ts.getSeller(), seller);
+ assertEquals(ts.getLinearId(), tempId);
+
+ assertNotEquals(ts.getAmount(), 0);
+ assertNotEquals(ts.getAmount(), -5);
+ assertNotEquals(ts.getAmount(), null);
+ }
+
+ @Test
+ public void linearIdTest() {
+ TradeState ts = new TradeState(amount, buyer, seller);
+
+ // ensure ID is generated with shorter constructor stub
+ assertTrue(ts.getLinearId() instanceof UniqueIdentifier);
+ }
+
+ @Test
+ public void participantTest() {
+ TradeState ts = new TradeState(amount, buyer, seller);
+
+ // ensure participants are generated correctly
+ assertTrue(ts.getParticipants().contains(buyer));
+ assertTrue(ts.getParticipants().contains(seller));
+ }
+
+}
diff --git a/Advanced/negotiation-cordapp/gradle.properties b/Advanced/negotiation-cordapp/gradle.properties
index 80ba07ea..03a6057a 100644
--- a/Advanced/negotiation-cordapp/gradle.properties
+++ b/Advanced/negotiation-cordapp/gradle.properties
@@ -1,3 +1,3 @@
-name=Test
-group=com.negotiation
+name=Negotiation Cordapp
+group=net.corda.samples.negotiation
version=0.2
diff --git a/Advanced/negotiation-cordapp/gradle/wrapper/gradle-wrapper.properties b/Advanced/negotiation-cordapp/gradle/wrapper/gradle-wrapper.properties
index d757f3d3..674bdda0 100644
--- a/Advanced/negotiation-cordapp/gradle/wrapper/gradle-wrapper.properties
+++ b/Advanced/negotiation-cordapp/gradle/wrapper/gradle-wrapper.properties
@@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip
diff --git a/Advanced/negotiation-cordapp/repositories.gradle b/Advanced/negotiation-cordapp/repositories.gradle
index 2874c2ab..9797c0ea 100644
--- a/Advanced/negotiation-cordapp/repositories.gradle
+++ b/Advanced/negotiation-cordapp/repositories.gradle
@@ -1,8 +1,7 @@
repositories {
mavenLocal()
mavenCentral()
- jcenter()
maven { url 'https://jitpack.io' }
- maven { url 'https://ci-artifactory.corda.r3cev.com/artifactory/corda' }
+ maven { url 'https://download.corda.net/maven/corda-dependencies' }
maven { url 'https://repo.gradle.org/gradle/libs-releases' }
}
diff --git a/Advanced/negotiation-cordapp/workflows/src/integrationTest/java/net/corda/samples/negotiation/flows/DriverBasedTest.java b/Advanced/negotiation-cordapp/workflows/src/integrationTest/java/net/corda/samples/negotiation/flows/DriverBasedTest.java
new file mode 100644
index 00000000..a68ffa86
--- /dev/null
+++ b/Advanced/negotiation-cordapp/workflows/src/integrationTest/java/net/corda/samples/negotiation/flows/DriverBasedTest.java
@@ -0,0 +1,48 @@
+package net.corda.samples.negotiation.flows;
+
+import com.google.common.collect.ImmutableList;
+import net.corda.core.concurrent.CordaFuture;
+import net.corda.core.identity.CordaX500Name;
+import net.corda.testing.core.TestIdentity;
+import net.corda.testing.driver.DriverParameters;
+import net.corda.testing.driver.NodeHandle;
+import net.corda.testing.driver.NodeParameters;
+import org.junit.Test;
+
+import java.util.List;
+
+import static net.corda.testing.driver.Driver.driver;
+import static org.junit.Assert.assertEquals;
+
+public class DriverBasedTest {
+ private final TestIdentity bankA = new TestIdentity(new CordaX500Name("BankA", "", "GB"));
+ private final TestIdentity bankB = new TestIdentity(new CordaX500Name("BankB", "", "US"));
+
+ @Test
+ public void nodeTest() {
+ driver(new DriverParameters().withIsDebug(true).withStartNodesInProcess(true), dsl -> {
+ // Start a pair of nodes and wait for them both to be ready.
+ List> handleFutures = ImmutableList.of(
+ dsl.startNode(new NodeParameters().withProvidedName(bankA.getName())),
+ dsl.startNode(new NodeParameters().withProvidedName(bankB.getName()))
+ );
+
+ try {
+ NodeHandle partyAHandle = handleFutures.get(0).get();
+ NodeHandle partyBHandle = handleFutures.get(1).get();
+
+ // From each node, make an RPC call to retrieve another node's name from the network map, to verify that the
+ // nodes have started and can communicate.
+
+ // This is a very basic test: in practice tests would be starting flows, and verifying the states in the vault
+ // and other important metrics to ensure that your CorDapp is working as intended.
+ assertEquals(partyAHandle.getRpc().wellKnownPartyFromX500Name(bankB.getName()).getName(), bankB.getName());
+ assertEquals(partyBHandle.getRpc().wellKnownPartyFromX500Name(bankA.getName()).getName(), bankA.getName());
+ } catch (Exception e) {
+ throw new RuntimeException("Caught exception during test: ", e);
+ }
+
+ return null;
+ });
+ }
+}
diff --git a/Advanced/negotiation-cordapp/workflows/src/main/java/negotiation/flows/AcceptanceFlow.java b/Advanced/negotiation-cordapp/workflows/src/main/java/net/corda/samples/negotiation/flows/AcceptanceFlow.java
similarity index 95%
rename from Advanced/negotiation-cordapp/workflows/src/main/java/negotiation/flows/AcceptanceFlow.java
rename to Advanced/negotiation-cordapp/workflows/src/main/java/net/corda/samples/negotiation/flows/AcceptanceFlow.java
index 28f83567..62426e2c 100644
--- a/Advanced/negotiation-cordapp/workflows/src/main/java/negotiation/flows/AcceptanceFlow.java
+++ b/Advanced/negotiation-cordapp/workflows/src/main/java/net/corda/samples/negotiation/flows/AcceptanceFlow.java
@@ -1,11 +1,11 @@
-package negotiation.flows;
+package net.corda.samples.negotiation.flows;
import co.paralleluniverse.fibers.Suspendable;
import com.google.common.collect.ImmutableList;
-import negotiation.contracts.ProposalAndTradeContract;
-import negotiation.states.ProposalState;
-import negotiation.states.TradeState;
+import net.corda.samples.negotiation.contracts.ProposalAndTradeContract;
+import net.corda.samples.negotiation.states.ProposalState;
+import net.corda.samples.negotiation.states.TradeState;
import net.corda.core.contracts.Command;
import net.corda.core.contracts.StateAndRef;
import net.corda.core.contracts.UniqueIdentifier;
diff --git a/Advanced/negotiation-cordapp/workflows/src/main/java/negotiation/flows/ModificationFlow.java b/Advanced/negotiation-cordapp/workflows/src/main/java/net/corda/samples/negotiation/flows/ModificationFlow.java
similarity index 96%
rename from Advanced/negotiation-cordapp/workflows/src/main/java/negotiation/flows/ModificationFlow.java
rename to Advanced/negotiation-cordapp/workflows/src/main/java/net/corda/samples/negotiation/flows/ModificationFlow.java
index 3ad1dd40..2d6e8d39 100644
--- a/Advanced/negotiation-cordapp/workflows/src/main/java/negotiation/flows/ModificationFlow.java
+++ b/Advanced/negotiation-cordapp/workflows/src/main/java/net/corda/samples/negotiation/flows/ModificationFlow.java
@@ -1,9 +1,9 @@
-package negotiation.flows;
+package net.corda.samples.negotiation.flows;
import co.paralleluniverse.fibers.Suspendable;
import com.google.common.collect.ImmutableList;
-import negotiation.contracts.ProposalAndTradeContract;
-import negotiation.states.ProposalState;
+import net.corda.samples.negotiation.contracts.ProposalAndTradeContract;
+import net.corda.samples.negotiation.states.ProposalState;
import net.corda.core.contracts.Command;
import net.corda.core.contracts.StateAndRef;
import net.corda.core.contracts.UniqueIdentifier;
@@ -18,7 +18,6 @@
import net.corda.core.utilities.ProgressTracker;
import org.jetbrains.annotations.NotNull;
-import javax.annotation.Signed;
import java.security.PublicKey;
import java.security.SignatureException;
import java.util.List;
diff --git a/Advanced/negotiation-cordapp/workflows/src/main/java/negotiation/flows/ProposalFlow.java b/Advanced/negotiation-cordapp/workflows/src/main/java/net/corda/samples/negotiation/flows/ProposalFlow.java
similarity index 83%
rename from Advanced/negotiation-cordapp/workflows/src/main/java/negotiation/flows/ProposalFlow.java
rename to Advanced/negotiation-cordapp/workflows/src/main/java/net/corda/samples/negotiation/flows/ProposalFlow.java
index be001d21..45def7ee 100644
--- a/Advanced/negotiation-cordapp/workflows/src/main/java/negotiation/flows/ProposalFlow.java
+++ b/Advanced/negotiation-cordapp/workflows/src/main/java/net/corda/samples/negotiation/flows/ProposalFlow.java
@@ -1,9 +1,9 @@
-package negotiation.flows;
+package net.corda.samples.negotiation.flows;
import co.paralleluniverse.fibers.Suspendable;
import com.google.common.collect.ImmutableList;
-import negotiation.contracts.ProposalAndTradeContract;
-import negotiation.states.ProposalState;
+import net.corda.samples.negotiation.contracts.ProposalAndTradeContract;
+import net.corda.samples.negotiation.states.ProposalState;
import net.corda.core.contracts.Command;
import net.corda.core.contracts.UniqueIdentifier;
import net.corda.core.crypto.SecureHash;
@@ -15,6 +15,7 @@
import java.security.PublicKey;
import java.util.List;
+import net.corda.core.identity.CordaX500Name;
public class ProposalFlow {
@InitiatingFlow
@@ -51,13 +52,8 @@ public UniqueIdentifier call() throws FlowException {
//Building the transaction
// Obtain a reference to a notary we wish to use.
- /** METHOD 1: Take first notary on network, WARNING: use for test, non-prod environments, and single-notary networks only!*
- * METHOD 2: Explicit selection of notary by CordaX500Name - argument can by coded in flow or parsed from config (Preferred)
- *
- * * - For production you always want to use Method 2 as it guarantees the expected notary is returned.
- */
- final Party notary = getServiceHub().getNetworkMapCache().getNotaryIdentities().get(0); // METHOD 1
- // final Party notary = getServiceHub().getNetworkMapCache().getNotary(CordaX500Name.parse("O=Notary,L=London,C=GB")); // METHOD 2
+ /** Explicit selection of notary by CordaX500Name - argument can by coded in flows or parsed from config (Preferred)*/
+ final Party notary = getServiceHub().getNetworkMapCache().getNotary(CordaX500Name.parse("O=Notary,L=London,C=GB"));
TransactionBuilder txBuilder = new TransactionBuilder(notary)
.addOutputState(output, ProposalAndTradeContract.ID)
diff --git a/Advanced/negotiation-cordapp/workflows/src/test/java/negotiation/flows/FlowTestsBase.java b/Advanced/negotiation-cordapp/workflows/src/test/java/negotiation/flows/FlowTestsBase.java
deleted file mode 100644
index 2753a862..00000000
--- a/Advanced/negotiation-cordapp/workflows/src/test/java/negotiation/flows/FlowTestsBase.java
+++ /dev/null
@@ -1,71 +0,0 @@
-package negotiation.flows;
-
-import com.google.common.collect.ImmutableList;
-import net.corda.core.contracts.UniqueIdentifier;
-import net.corda.core.identity.Party;
-import net.corda.testing.node.MockNetwork;
-import net.corda.testing.node.MockNetworkParameters;
-import net.corda.testing.node.StartedMockNode;
-import net.corda.testing.node.TestCordapp;
-import org.junit.After;
-import org.junit.Before;
-
-import java.util.List;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Future;
-
-abstract class FlowTestsBase {
- protected MockNetwork network;
- protected StartedMockNode a;
- protected StartedMockNode b;
-
- @Before
- public void setup(){
- network = new MockNetwork(new MockNetworkParameters(ImmutableList.of(
- TestCordapp.findCordapp("negotiation.flows"),
- TestCordapp.findCordapp("negotiation.contracts")
- )
- ));
- a = network.createPartyNode(null);
- b = network.createPartyNode(null);
-
- List responseflows = ImmutableList.of(ProposalFlow.Responder.class, AcceptanceFlow.Responder.class, ModificationFlow.Responder.class);
-
- ImmutableList.of(a,b).forEach(node -> {
- for (Class flow:responseflows
- ) {
- node.registerInitiatedFlow(flow);
-
- }
- });
- network.runNetwork();
-
- }
-
- @After
- public void tearDown(){
- network.stopNodes();
- }
-
- public UniqueIdentifier nodeACreatesProposal(Boolean isBuyer, int amount, Party counterparty) throws ExecutionException, InterruptedException {
- ProposalFlow.Initiator flow = new ProposalFlow.Initiator(isBuyer, amount, counterparty);
- Future future = a.startFlow(flow);
- network.runNetwork();
- return (UniqueIdentifier) future.get();
-
- }
-
- public void nodeBAcceptsProposal(UniqueIdentifier proposalId) throws ExecutionException, InterruptedException {
- AcceptanceFlow.Initiator flow = new AcceptanceFlow.Initiator(proposalId);
- Future future = b.startFlow(flow);
- network.runNetwork();
- future.get();
- }
-
- public void nodeBModifiesProposal(UniqueIdentifier proposalId, int newAmount) throws ExecutionException, InterruptedException {
- ModificationFlow.Initiator flow = new ModificationFlow.Initiator(proposalId, newAmount);
- Future future = b.startFlow(flow);
- network.runNetwork();
- future.get();
- }
-}
diff --git a/Advanced/negotiation-cordapp/workflows/src/test/java/negotiation/flows/AcceptanceFlowTests.java b/Advanced/negotiation-cordapp/workflows/src/test/java/net/corda/samples/negotiation/flows/AcceptanceFlowTests.java
similarity index 89%
rename from Advanced/negotiation-cordapp/workflows/src/test/java/negotiation/flows/AcceptanceFlowTests.java
rename to Advanced/negotiation-cordapp/workflows/src/test/java/net/corda/samples/negotiation/flows/AcceptanceFlowTests.java
index cbb4cdf9..6bf73176 100644
--- a/Advanced/negotiation-cordapp/workflows/src/test/java/negotiation/flows/AcceptanceFlowTests.java
+++ b/Advanced/negotiation-cordapp/workflows/src/test/java/net/corda/samples/negotiation/flows/AcceptanceFlowTests.java
@@ -1,8 +1,8 @@
-package negotiation.flows;
+package net.corda.samples.negotiation.flows;
import com.google.common.collect.ImmutableList;
-import negotiation.states.ProposalState;
-import negotiation.states.TradeState;
+import net.corda.samples.negotiation.states.ProposalState;
+import net.corda.samples.negotiation.states.TradeState;
import net.corda.core.contracts.StateAndRef;
import net.corda.core.contracts.UniqueIdentifier;
import net.corda.core.identity.Party;
@@ -13,7 +13,7 @@
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
-public class AcceptanceFlowTests extends FlowTestsBase{
+public class AcceptanceFlowTests extends FlowTestBase {
@Test
public void acceptanceFlowConsumesTheProposalsInBothNodesVaultsAndReplacesWithEquivAccTradesWhenInitiatorIsBuyer() throws ExecutionException, InterruptedException {
@@ -43,7 +43,7 @@ private void testAcceptance(Boolean isBuyer) throws ExecutionException, Interrup
Party counterparty = b.getInfo().getLegalIdentitiesAndCerts().get(0).getParty();
UniqueIdentifier proposalId = nodeACreatesProposal(isBuyer, amount, counterparty);
nodeBAcceptsProposal(proposalId);
- ImmutableList.of(a,b).forEach(node -> {
+ ImmutableList.of(a, b).forEach(node -> {
node.transaction(() -> {
List> proposals = node.getServices().getVaultService().queryBy(ProposalState.class).getStates();
Assert.assertEquals(0, proposals.size());
@@ -56,10 +56,10 @@ private void testAcceptance(Boolean isBuyer) throws ExecutionException, Interrup
Party buyer;
Party seller;
- if(isBuyer){
+ if (isBuyer) {
buyer = a.getInfo().getLegalIdentitiesAndCerts().get(0).getParty();
seller = b.getInfo().getLegalIdentitiesAndCerts().get(0).getParty();
- }else{
+ } else {
seller = a.getInfo().getLegalIdentitiesAndCerts().get(0).getParty();
buyer = b.getInfo().getLegalIdentitiesAndCerts().get(0).getParty();
}
diff --git a/Advanced/negotiation-cordapp/workflows/src/test/java/net/corda/samples/negotiation/flows/FlowTestBase.java b/Advanced/negotiation-cordapp/workflows/src/test/java/net/corda/samples/negotiation/flows/FlowTestBase.java
new file mode 100644
index 00000000..d6e2fd85
--- /dev/null
+++ b/Advanced/negotiation-cordapp/workflows/src/test/java/net/corda/samples/negotiation/flows/FlowTestBase.java
@@ -0,0 +1,71 @@
+package net.corda.samples.negotiation.flows;
+
+import com.google.common.collect.ImmutableList;
+import net.corda.core.contracts.UniqueIdentifier;
+import net.corda.core.identity.CordaX500Name;
+import net.corda.core.identity.Party;
+import net.corda.testing.driver.VerifierType;
+import net.corda.testing.node.*;
+import org.junit.After;
+import org.junit.Before;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+abstract class FlowTestBase {
+ protected MockNetwork network;
+ protected StartedMockNode a;
+ protected StartedMockNode b;
+
+ @Before
+ public void setup() {
+ network = new MockNetwork(new MockNetworkParameters(
+ ImmutableList.of(
+ TestCordapp.findCordapp("net.corda.samples.negotiation.flows"),
+ TestCordapp.findCordapp("net.corda.samples.negotiation.contracts"))
+ ).withNotarySpecs(ImmutableList.of(new MockNetworkNotarySpec(CordaX500Name.parse("O=Notary,L=London,C=GB")))));
+ a = network.createPartyNode(null);
+ b = network.createPartyNode(null);
+
+ List responseflows = ImmutableList.of(ProposalFlow.Responder.class, AcceptanceFlow.Responder.class, ModificationFlow.Responder.class);
+
+ ImmutableList.of(a,b).forEach(node -> {
+ for (Class flow:responseflows
+ ) {
+ node.registerInitiatedFlow(flow);
+
+ }
+ });
+ network.runNetwork();
+
+ }
+
+ @After
+ public void tearDown(){
+ network.stopNodes();
+ }
+
+ public UniqueIdentifier nodeACreatesProposal(Boolean isBuyer, int amount, Party counterparty) throws ExecutionException, InterruptedException {
+ ProposalFlow.Initiator flow = new ProposalFlow.Initiator(isBuyer, amount, counterparty);
+ Future future = a.startFlow(flow);
+ network.runNetwork();
+ return (UniqueIdentifier) future.get();
+
+ }
+
+ public void nodeBAcceptsProposal(UniqueIdentifier proposalId) throws ExecutionException, InterruptedException {
+ AcceptanceFlow.Initiator flow = new AcceptanceFlow.Initiator(proposalId);
+ Future future = b.startFlow(flow);
+ network.runNetwork();
+ future.get();
+ }
+
+ public void nodeBModifiesProposal(UniqueIdentifier proposalId, int newAmount) throws ExecutionException, InterruptedException {
+ ModificationFlow.Initiator flow = new ModificationFlow.Initiator(proposalId, newAmount);
+ Future future = b.startFlow(flow);
+ network.runNetwork();
+ future.get();
+ }
+}
diff --git a/Advanced/negotiation-cordapp/workflows/src/test/java/negotiation/flows/ModifyFlowTests.java b/Advanced/negotiation-cordapp/workflows/src/test/java/net/corda/samples/negotiation/flows/ModifyFlowTests.java
similarity index 95%
rename from Advanced/negotiation-cordapp/workflows/src/test/java/negotiation/flows/ModifyFlowTests.java
rename to Advanced/negotiation-cordapp/workflows/src/test/java/net/corda/samples/negotiation/flows/ModifyFlowTests.java
index d14a5417..424b6b8c 100644
--- a/Advanced/negotiation-cordapp/workflows/src/test/java/negotiation/flows/ModifyFlowTests.java
+++ b/Advanced/negotiation-cordapp/workflows/src/test/java/net/corda/samples/negotiation/flows/ModifyFlowTests.java
@@ -1,7 +1,7 @@
-package negotiation.flows;
+package net.corda.samples.negotiation.flows;
import com.google.common.collect.ImmutableList;
-import negotiation.states.ProposalState;
+import net.corda.samples.negotiation.states.ProposalState;
import net.corda.core.contracts.StateAndRef;
import net.corda.core.contracts.UniqueIdentifier;
import net.corda.core.identity.Party;
@@ -12,7 +12,7 @@
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
-public class ModifyFlowTests extends FlowTestsBase {
+public class ModifyFlowTests extends FlowTestBase {
@Test
public void modificationFlowConsumesTheProposalsInBothNodesVaultsAndReplacesWithEquivWithNEwAmountsWhenInitiatorISBuyer() throws ExecutionException, InterruptedException {
diff --git a/Advanced/negotiation-cordapp/workflows/src/test/java/negotiation/flows/ProposalFlowTests.java b/Advanced/negotiation-cordapp/workflows/src/test/java/net/corda/samples/negotiation/flows/ProposalFlowTests.java
similarity index 88%
rename from Advanced/negotiation-cordapp/workflows/src/test/java/negotiation/flows/ProposalFlowTests.java
rename to Advanced/negotiation-cordapp/workflows/src/test/java/net/corda/samples/negotiation/flows/ProposalFlowTests.java
index c810a557..04a4bdc5 100644
--- a/Advanced/negotiation-cordapp/workflows/src/test/java/negotiation/flows/ProposalFlowTests.java
+++ b/Advanced/negotiation-cordapp/workflows/src/test/java/net/corda/samples/negotiation/flows/ProposalFlowTests.java
@@ -1,7 +1,7 @@
-package negotiation.flows;
+package net.corda.samples.negotiation.flows;
import com.google.common.collect.ImmutableList;
-import negotiation.states.ProposalState;
+import net.corda.samples.negotiation.states.ProposalState;
import net.corda.core.contracts.StateAndRef;
import net.corda.core.identity.Party;
import org.junit.Assert;
@@ -10,7 +10,7 @@
import java.util.List;
import java.util.concurrent.ExecutionException;
-public class ProposalFlowTests extends FlowTestsBase {
+public class ProposalFlowTests extends FlowTestBase {
@Test
public void proposalFlowCreatesTheCorrectProposalsInBothNodesVaultsWhenInitiatorIsBuyer() throws ExecutionException, InterruptedException {
@@ -22,12 +22,11 @@ public void proposalFlowCreatesTheCorrectProposalsInBothNodesVaultsWhenInitiator
testProposal(false);
}
-
private void testProposal(Boolean isBuyer) throws ExecutionException, InterruptedException {
int amount = 1;
Party counterparty = b.getInfo().getLegalIdentitiesAndCerts().get(0).getParty();
nodeACreatesProposal(isBuyer, amount, counterparty);
- ImmutableList.of(a,b).forEach(node -> {
+ ImmutableList.of(a, b).forEach(node -> {
node.transaction(() -> {
List> proposals = node.getServices().getVaultService().queryBy(ProposalState.class).getStates();
Assert.assertEquals(1, proposals.size());
@@ -38,10 +37,10 @@ private void testProposal(Boolean isBuyer) throws ExecutionException, Interrupte
Party buyer;
Party seller;
- if(isBuyer){
+ if (isBuyer) {
buyer = a.getInfo().getLegalIdentitiesAndCerts().get(0).getParty();
seller = b.getInfo().getLegalIdentitiesAndCerts().get(0).getParty();
- }else{
+ } else {
seller = a.getInfo().getLegalIdentitiesAndCerts().get(0).getParty();
buyer = b.getInfo().getLegalIdentitiesAndCerts().get(0).getParty();
}
diff --git a/Advanced/obligation-cordapp/README.md b/Advanced/obligation-cordapp/README.md
index 01bbe1c7..952c7f9a 100644
--- a/Advanced/obligation-cordapp/README.md
+++ b/Advanced/obligation-cordapp/README.md
@@ -1,26 +1,20 @@
-# obligation-cordap [
](https://ide.corda.net/?folder=/home/coder/samples-java/Advanced/obligation-cordapp)
+# Obligation Cordap
-This Cordapp is the complete implementation of our signature IOU (I-owe-you) demonstration.
+This CorDapp is the complete implementation of our signature IOU (I-owe-you) demonstration.
## Concepts
-An IOU is someone who has cash that is paying it back to someone they owe it to.
-
-You have to have the original concept of the debt itself, (the IOU), and the cash.
-
-Then the ability to exchange assets like cash or assets, and then the ability to settle up.
-
-Given this is intended to implement an IOU, our cordapp consists of three flows `issue`, `transfer` and `settle` flows.
+An IOU is someone who has cash that is paying it back to someone they owe it to. You have to have the original concept of the debt itself, (the IOU), and the cash. Then the ability to exchange assets like cash or assets, and then the ability to settle up. Given this is intended to implement an IOU, our cordapp consists of three flows `issue`, `transfer` and `settle` flows.
### Flows
-The first flows are the ones that issue the original cash and assets. You can find that the cash flow [here](./workflows/src/main/java/net/corda/samples/flows/SelfIssueCashFlow.java#L24-L32) and the IOU issurance in [IOUIssueFlow.java](./workflows/src/main/java/net/corda/samples/flows/IOUIssueFlow.java#L40-L80).
+The first flows are the ones that issue the original cash and assets. You can find that the cash flow at `SelfIssueCashFlow.java` and the IOU issuance in `IOUIssueFlow.java`.
-The next flow is the one that transfers ownership of that asset over to another party. That can be found in [IOUTransferFlow.java](./workflows/src/main/java/net/corda/samples/flows/IOUTransferFlow.java#L132-L159).
+The next flow is the one that transfers ownership of that asset over to another party. That can be found in `IOUTransferFlow.java`.
-Finally, once we have the ability to transfer assets, we just need to settle up. That functiionality can be found here in [IOUSettleFlow.java](./workflows/src/main/java/net/corda/samples/flows/IOUSettleFlow.java#L54-L116)
+Finally, once we have the ability to transfer assets, we just need to settle up. That functionality can be found here in `IOUSettleFlow.java`
diff --git a/Advanced/obligation-cordapp/build.gradle b/Advanced/obligation-cordapp/build.gradle
index 0b88ba70..15bd2c09 100644
--- a/Advanced/obligation-cordapp/build.gradle
+++ b/Advanced/obligation-cordapp/build.gradle
@@ -22,8 +22,8 @@ buildscript {
repositories {
mavenLocal()
mavenCentral()
- jcenter()
- maven { url 'https://ci-artifactory.corda.r3cev.com/artifactory/corda-releases' }
+
+ maven { url 'https://download.corda.net/maven/corda-releases' }
}
dependencies {
@@ -41,9 +41,8 @@ allprojects {
repositories {
mavenLocal()
- jcenter()
mavenCentral()
- maven { url 'https://software.r3.com/artifactory/corda' }
+ maven { url 'https://download.corda.net/maven/corda-dependencies' }
maven { url 'https://jitpack.io' }
}
@@ -60,8 +59,6 @@ allprojects {
}
-
-
apply plugin: 'net.corda.plugins.cordapp'
apply plugin: 'net.corda.plugins.cordformation'
apply plugin: 'net.corda.plugins.quasar-utils'
@@ -75,15 +72,18 @@ sourceSets {
}
dependencies {
+
// Corda dependencies.
cordaCompile "$corda_core_release_group:corda-core:$corda_core_release_version"
cordaCompile "$corda_release_group:corda-finance-contracts:$corda_release_version"
cordaCompile "$corda_release_group:corda-finance-workflows:$corda_release_version"
cordaCompile "$corda_release_group:corda-node-api:$corda_release_version"
cordaRuntime "$corda_release_group:corda:$corda_release_version"
+
// CorDapp dependencies.
cordapp project(":workflows")
cordapp project(":contracts")
+
cordapp "$corda_release_group:corda-finance-contracts:$corda_release_version"
cordapp "$corda_release_group:corda-finance-workflows:$corda_release_version"
cordapp "$corda_release_group:corda-confidential-identities:$corda_release_version"
@@ -91,11 +91,13 @@ dependencies {
cordaCompile "org.apache.logging.log4j:log4j-slf4j-impl:${log4j_version}"
cordaCompile "org.apache.logging.log4j:log4j-web:${log4j_version}"
cordaCompile "org.slf4j:jul-to-slf4j:$slf4j_version"
+ cordaDriver "net.corda:corda-shell:4.10"
+
}
cordapp {
info {
- name "CorDapp Template"
+ name "Obligation CorDapp"
vendor "Corda Open Source"
targetPlatformVersion corda_platform_version
minimumPlatformVersion corda_platform_version
@@ -107,8 +109,10 @@ task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar']) {
projectCordapp {
deploy = false
}
- cordapp project(':contracts')
- cordapp project(':workflows')
+
+ cordapp project(":workflows")
+ cordapp project(":contracts")
+
runSchemaMigration = true
cordapp("$corda_release_group:corda-finance-contracts:$corda_release_version")
cordapp("$corda_release_group:corda-finance-workflows:$corda_release_version")
diff --git a/Advanced/obligation-cordapp/clients/build.gradle b/Advanced/obligation-cordapp/clients/build.gradle
index 2540c673..6bf3c08f 100644
--- a/Advanced/obligation-cordapp/clients/build.gradle
+++ b/Advanced/obligation-cordapp/clients/build.gradle
@@ -1,6 +1,6 @@
repositories {
mavenLocal()
- jcenter()
+
mavenCentral()
maven { url 'https://jitpack.io' }
maven { url 'https://ci-artifactory.corda.r3cev.com/artifactory/corda-releases' }
@@ -26,6 +26,12 @@ dependencyManagement {
}
}
+configurations {
+ all {
+ exclude group: 'ch.qos.logback', module: 'logback-classic'
+ }
+}
+
dependencies {
// CorDapp dependencies.
compile project(":contracts")
@@ -53,18 +59,18 @@ dependencies {
task runPartyAServer(type: JavaExec, dependsOn: jar) {
classpath = sourceSets.main.runtimeClasspath
- main = 'net.corda.samples.server.Server'
+ main = 'net.corda.samples.obligation.server.Server'
args '--server.port=10009', '--config.rpc.host=localhost', '--config.rpc.port=10008', '--config.rpc.username=user1', '--config.rpc.password=password'
}
task runPartyBServer(type: JavaExec, dependsOn: jar) {
classpath = sourceSets.main.runtimeClasspath
- main = 'net.corda.samples.server.Server'
+ main = 'net.corda.samples.obligation.server.Server'
args '--server.port=10012', '--config.rpc.host=localhost', '--config.rpc.port=10011', '--config.rpc.username=user1', '--config.rpc.password=password'
}
task runPartyCServer(type: JavaExec, dependsOn: jar) {
classpath = sourceSets.main.runtimeClasspath
- main = 'net.corda.samples.server.Server'
+ main = 'net.corda.samples.obligation.server.Server'
args '--server.port=10015', '--config.rpc.host=localhost', '--config.rpc.port=10014', '--config.rpc.username=user1', '--config.rpc.password=password'
}
diff --git a/Advanced/obligation-cordapp/clients/src/main/java/net/corda/samples/obligation/server/CONSTANTS.java b/Advanced/obligation-cordapp/clients/src/main/java/net/corda/samples/obligation/server/CONSTANTS.java
new file mode 100644
index 00000000..8c838881
--- /dev/null
+++ b/Advanced/obligation-cordapp/clients/src/main/java/net/corda/samples/obligation/server/CONSTANTS.java
@@ -0,0 +1,8 @@
+package net.corda.samples.obligation.server;
+
+public interface CONSTANTS {
+ String CORDA_USER_NAME = "config.rpc.username";
+ String CORDA_USER_PASSWORD = "config.rpc.password";
+ String CORDA_NODE_HOST = "config.rpc.host";
+ String CORDA_RPC_PORT = "config.rpc.port";
+}
diff --git a/Advanced/obligation-cordapp/clients/src/main/java/net/corda/samples/obligation/server/MainController.java b/Advanced/obligation-cordapp/clients/src/main/java/net/corda/samples/obligation/server/MainController.java
new file mode 100644
index 00000000..373213a4
--- /dev/null
+++ b/Advanced/obligation-cordapp/clients/src/main/java/net/corda/samples/obligation/server/MainController.java
@@ -0,0 +1,232 @@
+package net.corda.samples.obligation.server;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import net.corda.client.jackson.JacksonSupport;
+import net.corda.core.contracts.*;
+import net.corda.core.identity.CordaX500Name;
+import net.corda.core.identity.Party;
+import net.corda.core.messaging.CordaRPCOps;
+import net.corda.core.node.NodeInfo;
+import net.corda.core.transactions.SignedTransaction;
+import net.corda.finance.contracts.asset.Cash;
+import net.corda.samples.obligation.flows.IOUIssueFlow;
+import net.corda.samples.obligation.flows.IOUSettleFlow;
+import net.corda.samples.obligation.flows.IOUTransferFlow;
+import net.corda.samples.obligation.flows.SelfIssueCashFlow;
+import net.corda.samples.obligation.states.IOUState;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.util.*;
+import org.bouncycastle.asn1.x500.X500Name;
+import org.bouncycastle.asn1.x500.style.BCStyle;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import static net.corda.finance.workflows.GetBalances.getCashBalances;
+import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
+import static org.springframework.http.MediaType.TEXT_PLAIN_VALUE;
+
+/**
+ * Define your API endpoints here.
+ */
+@RestController
+@RequestMapping("/api/iou") // The paths for HTTP requests are relative to this base path.
+public class MainController {
+ private static final Logger logger = LoggerFactory.getLogger(RestController.class);
+ private final CordaRPCOps proxy;
+ private final CordaX500Name me;
+
+ public MainController(NodeRPCConnection rpc) {
+ this.proxy = rpc.getProxy();
+ this.me = proxy.nodeInfo().getLegalIdentities().get(0).getName();
+
+ }
+
+ /** Helpers for filtering the network map cache. */
+ public String toDisplayString(X500Name name){
+ return BCStyle.INSTANCE.toString(name);
+ }
+
+ private boolean isNotary(NodeInfo nodeInfo) {
+ return !proxy.notaryIdentities()
+ .stream().filter(el -> nodeInfo.isLegalIdentity(el))
+ .collect(Collectors.toList()).isEmpty();
+ }
+
+ private boolean isMe(NodeInfo nodeInfo){
+ return nodeInfo.getLegalIdentities().get(0).getName().equals(me);
+ }
+
+ private boolean isNetworkMap(NodeInfo nodeInfo){
+ return nodeInfo.getLegalIdentities().get(0).getName().getOrganisation().equals("Network Map Service");
+ }
+
+ @Configuration
+ class Plugin {
+ @Bean
+ public ObjectMapper registerModule() {
+ return JacksonSupport.createNonRpcMapper();
+ }
+ }
+
+ @GetMapping(value = "/status", produces = TEXT_PLAIN_VALUE)
+ private String status() {
+ return "200";
+ }
+
+ @GetMapping(value = "/servertime", produces = TEXT_PLAIN_VALUE)
+ private String serverTime() {
+ return (LocalDateTime.ofInstant(proxy.currentNodeTime(), ZoneId.of("UTC"))).toString();
+ }
+
+ @GetMapping(value = "/addresses", produces = TEXT_PLAIN_VALUE)
+ private String addresses() {
+ return proxy.nodeInfo().getAddresses().toString();
+ }
+
+ @GetMapping(value = "/identities", produces = TEXT_PLAIN_VALUE)
+ private String identities() {
+ return proxy.nodeInfo().getLegalIdentities().toString();
+ }
+
+ @GetMapping(value = "/platformversion", produces = TEXT_PLAIN_VALUE)
+ private String platformVersion() {
+ return Integer.toString(proxy.nodeInfo().getPlatformVersion());
+ }
+
+ @GetMapping(value = "/peers", produces = APPLICATION_JSON_VALUE)
+ public HashMap> getPeers() {
+ HashMap> myMap = new HashMap<>();
+
+ // Find all nodes that are not notaries, ourself, or the network map.
+ Stream filteredNodes = proxy.networkMapSnapshot().stream()
+ .filter(el -> !isNotary(el) && !isMe(el) && !isNetworkMap(el));
+ // Get their names as strings
+ List nodeNames = filteredNodes.map(el -> el.getLegalIdentities().get(0).getName().toString())
+ .collect(Collectors.toList());
+
+ myMap.put("peers", nodeNames);
+ return myMap;
+ }
+
+ @GetMapping(value = "/notaries", produces = TEXT_PLAIN_VALUE)
+ private String notaries() {
+ return proxy.notaryIdentities().toString();
+ }
+
+ @GetMapping(value = "/flows", produces = TEXT_PLAIN_VALUE)
+ private String flows() {
+ return proxy.registeredFlows().toString();
+ }
+
+ @GetMapping(value = "/states", produces = TEXT_PLAIN_VALUE)
+ private String states() {
+ return proxy.vaultQuery(ContractState.class).getStates().toString();
+ }
+
+ @GetMapping(value = "/me",produces = APPLICATION_JSON_VALUE)
+ private HashMap