diff --git a/Accounts/README.md b/Accounts/README.md
index 81a297d5..f304320a 100644
--- a/Accounts/README.md
+++ b/Accounts/README.md
@@ -6,7 +6,7 @@ This folder features Corda Accounts sample projects. Learn more about [Accounts]
This CorDapp mimics a supply chain transaction, where the deal is incorporated among different teams in the companies on both side of the trade.
-
+
### [Tic Tac Thor](./tictacthor):
@@ -15,3 +15,7 @@ This CorDapp recreates the game of Tic Tac Toe via Corda. It primarily demonstra
+
+### [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 cc8730a4..87168170 100644
--- a/Accounts/supplychain/README.md
+++ b/Accounts/supplychain/README.md
@@ -1,6 +1,6 @@
# 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: 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 67dde5d5..4d70ff49 100644
--- a/Accounts/supplychain/build.gradle
+++ b/Accounts/supplychain/build.gradle
@@ -26,8 +26,7 @@ buildscript {
repositories {
mavenLocal()
mavenCentral()
- jcenter()
- maven { url 'https://software.r3.com/artifactory/corda-releases' }
+ maven { url 'https://download.corda.net/maven/corda-releases' }
}
dependencies {
@@ -43,12 +42,12 @@ 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' }
//SDK lib
- maven { url 'https://software.r3.com/artifactory/corda-lib' }
+ maven { url 'https://download.corda.net/maven/corda-lib' }
//Gradle Plugins
maven { url 'https://repo.gradle.org/gradle/libs-releases' }
}
@@ -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"
diff --git a/Accounts/supplychain/repositories.gradle b/Accounts/supplychain/repositories.gradle
index 206b9c68..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://software.r3.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/main/java/net/corda/samples/supplychain/flows/InternalMessage.java b/Accounts/supplychain/workflows/src/main/java/net/corda/samples/supplychain/flows/InternalMessage.java
index 140fcf18..eadf9f59 100644
--- a/Accounts/supplychain/workflows/src/main/java/net/corda/samples/supplychain/flows/InternalMessage.java
+++ b/Accounts/supplychain/workflows/src/main/java/net/corda/samples/supplychain/flows/InternalMessage.java
@@ -6,6 +6,7 @@
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.supplychain.accountUtilities.NewKeyForAccount;
import net.corda.samples.supplychain.contracts.InternalMessageStateContract;
import net.corda.samples.supplychain.states.InternalMessageState;
@@ -81,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/net/corda/samples/supplychain/flows/SendCargo.java b/Accounts/supplychain/workflows/src/main/java/net/corda/samples/supplychain/flows/SendCargo.java
index d59c269c..d51f2527 100644
--- a/Accounts/supplychain/workflows/src/main/java/net/corda/samples/supplychain/flows/SendCargo.java
+++ b/Accounts/supplychain/workflows/src/main/java/net/corda/samples/supplychain/flows/SendCargo.java
@@ -6,6 +6,7 @@
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.supplychain.accountUtilities.NewKeyForAccount;
import net.corda.samples.supplychain.contracts.CargoStateContract;
import net.corda.samples.supplychain.states.CargoState;
@@ -58,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/net/corda/samples/supplychain/flows/SendInvoice.java b/Accounts/supplychain/workflows/src/main/java/net/corda/samples/supplychain/flows/SendInvoice.java
index 6162258a..5d17627c 100644
--- a/Accounts/supplychain/workflows/src/main/java/net/corda/samples/supplychain/flows/SendInvoice.java
+++ b/Accounts/supplychain/workflows/src/main/java/net/corda/samples/supplychain/flows/SendInvoice.java
@@ -6,6 +6,7 @@
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.supplychain.accountUtilities.NewKeyForAccount;
import net.corda.samples.supplychain.contracts.InvoiceStateContract;
import net.corda.samples.supplychain.states.InvoiceState;
@@ -58,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/net/corda/samples/supplychain/flows/SendPayment.java b/Accounts/supplychain/workflows/src/main/java/net/corda/samples/supplychain/flows/SendPayment.java
index dfca4452..9a65d6df 100644
--- a/Accounts/supplychain/workflows/src/main/java/net/corda/samples/supplychain/flows/SendPayment.java
+++ b/Accounts/supplychain/workflows/src/main/java/net/corda/samples/supplychain/flows/SendPayment.java
@@ -6,6 +6,7 @@
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.supplychain.accountUtilities.NewKeyForAccount;
import net.corda.samples.supplychain.contracts.PaymentStateContract;
import net.corda.samples.supplychain.states.PaymentState;
@@ -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/net/corda/samples/supplychain/flows/SendShippingRequest.java b/Accounts/supplychain/workflows/src/main/java/net/corda/samples/supplychain/flows/SendShippingRequest.java
index 9db64235..962770ee 100644
--- a/Accounts/supplychain/workflows/src/main/java/net/corda/samples/supplychain/flows/SendShippingRequest.java
+++ b/Accounts/supplychain/workflows/src/main/java/net/corda/samples/supplychain/flows/SendShippingRequest.java
@@ -5,6 +5,7 @@
import com.r3.corda.lib.accounts.workflows.services.AccountService;
import com.r3.corda.lib.accounts.workflows.services.KeyManagementBackedAccountService;
import com.sun.istack.NotNull;
+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;
@@ -84,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/net/corda/samples/supplychain/FlowTests.java b/Accounts/supplychain/workflows/src/test/java/net/corda/samples/supplychain/FlowTests.java
index 5dbb7cc6..5332c1fb 100644
--- 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
@@ -6,6 +6,7 @@
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;
@@ -13,13 +14,11 @@
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.MockNetwork;
-import net.corda.testing.node.MockNetworkParameters;
-import net.corda.testing.node.TestCordapp;
+import net.corda.testing.node.*;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
-import net.corda.testing.node.StartedMockNode;
+
import java.util.*;
import java.time.Instant;
import java.util.concurrent.ExecutionException;
@@ -42,7 +41,9 @@ public void setup() {
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));
+ 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();
diff --git a/Accounts/tictacthor/README.md b/Accounts/tictacthor/README.md
index b989e03f..5c388345 100644
--- a/Accounts/tictacthor/README.md
+++ b/Accounts/tictacthor/README.md
@@ -1,31 +1,36 @@
# Tic Tac Thor
-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.
+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 3c1b415c..b33c32b0 100644
--- a/Accounts/tictacthor/build.gradle
+++ b/Accounts/tictacthor/build.gradle
@@ -31,8 +31,8 @@ buildscript {
repositories {
mavenLocal()
mavenCentral()
- jcenter()
- maven { url 'https://software.r3.com/artifactory/corda-releases' }
+
+ maven { url 'https://download.corda.net/maven/corda-releases' }
}
dependencies {
@@ -50,12 +50,12 @@ 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' }
//SDK lib
- maven { url 'https://software.r3.com/artifactory/corda-lib' }
+ maven { url 'https://download.corda.net/maven/corda-lib' }
//Gradle Plugins
maven { url 'https://repo.gradle.org/gradle/libs-releases' }
}
@@ -100,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"
@@ -117,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"
diff --git a/Accounts/tictacthor/clients/build.gradle b/Accounts/tictacthor/clients/build.gradle
index 5bc011bd..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"
diff --git a/Accounts/tictacthor/repositories.gradle b/Accounts/tictacthor/repositories.gradle
index 206b9c68..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://software.r3.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/workflows/src/main/java/net/corda/samples/tictacthor/flows/EndGameFlow.java b/Accounts/tictacthor/workflows/src/main/java/net/corda/samples/tictacthor/flows/EndGameFlow.java
index bc6bb5f4..3f9d6ab6 100644
--- a/Accounts/tictacthor/workflows/src/main/java/net/corda/samples/tictacthor/flows/EndGameFlow.java
+++ b/Accounts/tictacthor/workflows/src/main/java/net/corda/samples/tictacthor/flows/EndGameFlow.java
@@ -6,6 +6,7 @@
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;
@@ -94,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
index 4a6f0e0b..76ba4367 100644
--- 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
@@ -6,6 +6,7 @@
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;
@@ -93,13 +94,8 @@ public UniqueIdentifier call() throws FlowException {
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(initialBoardState)
diff --git a/Accounts/tictacthor/workflows/src/main/java/net/corda/samples/tictacthor/flows/SubmitTurnFlow.java b/Accounts/tictacthor/workflows/src/main/java/net/corda/samples/tictacthor/flows/SubmitTurnFlow.java
index dbfed5a4..477f3a6a 100644
--- a/Accounts/tictacthor/workflows/src/main/java/net/corda/samples/tictacthor/flows/SubmitTurnFlow.java
+++ b/Accounts/tictacthor/workflows/src/main/java/net/corda/samples/tictacthor/flows/SubmitTurnFlow.java
@@ -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/test/java/net/corda/samples/tictacthor/FlowTests.java b/Accounts/tictacthor/workflows/src/test/java/net/corda/samples/tictacthor/FlowTests.java
index 841c3ca0..71f10d38 100644
--- 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
@@ -6,19 +6,18 @@
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.MockNetwork;
-import net.corda.testing.node.MockNetworkParameters;
-import net.corda.testing.node.TestCordapp;
+import net.corda.testing.node.*;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
-import net.corda.testing.node.StartedMockNode;
+
import java.util.*;
import java.time.Instant;
import java.util.concurrent.ExecutionException;
@@ -40,7 +39,9 @@ public void setup() {
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));
+ 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();
diff --git a/Accounts/worldcupticketbooking/LICENCE b/Accounts/worldcupticketbooking/LICENCE
new file mode 100644
index 00000000..3ff572d1
--- /dev/null
+++ b/Accounts/worldcupticketbooking/LICENCE
@@ -0,0 +1,13 @@
+ Copyright 2016, R3 Limited.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
\ No newline at end of file
diff --git a/Accounts/worldcupticketbooking/README.md b/Accounts/worldcupticketbooking/README.md
new file mode 100644
index 00000000..324533db
--- /dev/null
+++ b/Accounts/worldcupticketbooking/README.md
@@ -0,0 +1,209 @@
+# T20 Cricket World Cup Ticket Booking CorDapp
+
+
+## Introduction
+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.
+
+## Flow logic of the sample application
+
+Nodes:
+
+* BCCI node: source of ticket creation. All the tickets in the market are created 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 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
+
+
+
+
+
+## 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]
+```
+
+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 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
+```
+
+### Step 3
+```
+flow start QuerybyAccount whoAmI: buyer1
+```
+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
+```
+
+
+### 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
+
+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
+
+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 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.
+
+
+### Step 6
+```
+flow start DVPAccountsOnSameNode tokenId: , buyerAccountName: buyer1, sellerAccountName: agent1, costOfTicket: 5, currency: USD
+```
+
+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 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
+
+```
+Again, We can check for the current vault status by `flow start QuerybyAccount whoAmI: XXXXX`
+
+### Step 8
+Lastly, we will finish the flow logic by one last transaction between buyer3(from Dealer2 node) and buyer2(from dealer1 node). Go to the Dealer1 node and run:
+```
+flow start DVPAccountsHostedOnDifferentNodes tokenId: , buyerAccountName: buyer2, sellerAccountName: buyer3, costOfTicket: 25, currency: USD
+```
+We can finish the demo with the following query to see how much they each get after the full cycle of sales.
+At Dealer1 node
+```
+flow start QuerybyAccount whoAmI: agent1
+flow start QuerybyAccount whoAmI: buyer1
+flow start QuerybyAccount whoAmI: buyer2
+```
+At Dealer2 node
+```
+flow start QuerybyAccount whoAmI: buyer3
+
+```
+Confirm who owns the [FungibleToken](https://training.corda.net/libraries/tokens-sdk/#fungibletoken) (cash) and [NonFungibleToken](https://training.corda.net/libraries/tokens-sdk/#nonfungibletoken) (ticket) again by running this on Dealer1's node.
+
+
+## Transfer tokens from one account to other
+
+For someone who is looking into how to only transfer tokens from one account to other use below steps.
+
+
+### 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]
+```
+
+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 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
+
+```
+
+### 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 which specifies an account.
+```
+run vaultQuery contractStateType : com.r3.corda.lib.tokens.contracts.states.FungibleToken
+```
+
+### Step 4
+
+ start MoveTokensBetweenAccounts buyerAccountName : buyer1, sellerAccountName : buyer3 , currency : USD , costOfTicket : 10
+
+This will move tokens from account buyer1 to account buyer3
+
+
+
+### Step 5
+```
+flow start QuerybyAccount whoAmI: buyer1
+```
+You can check balance of buyer1 account at Dealer1's node
+```
+run vaultQuery contractStateType : com.r3.corda.lib.tokens.contracts.states.FungibleToken
+```
+
+### Step 6
+```
+flow start QuerybyAccount whoAmI: buyer3
+```
+You can check balance of buyer3 account at Dealer2's node
+```
+run vaultQuery contractStateType : com.r3.corda.lib.tokens.contracts.states.FungibleToken
+```
+## Further Reading
+
+For accounts visit https://github.com/corda/accounts.
+
+For tokens visit https://github.com/corda/token-sdk.
diff --git a/Accounts/worldcupticketbooking/TRADEMARK b/Accounts/worldcupticketbooking/TRADEMARK
new file mode 100644
index 00000000..d2e056b5
--- /dev/null
+++ b/Accounts/worldcupticketbooking/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/Accounts/worldcupticketbooking/build.gradle b/Accounts/worldcupticketbooking/build.gradle
new file mode 100644
index 00000000..e567053f
--- /dev/null
+++ b/Accounts/worldcupticketbooking/build.gradle
@@ -0,0 +1,228 @@
+buildscript {
+ 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()
+
+ //TODO
+ //move to constant.prop
+ //accounts
+ accounts_release_version = '1.0'
+ accounts_release_group = 'com.r3.corda.lib.accounts'
+ confidential_id_release_group = "com.r3.corda.lib.ci"
+ confidential_id_release_version = "1.0"
+
+ //tokens
+ tokens_release_version = '1.1'
+ tokens_release_group = 'com.r3.corda.lib.tokens'
+
+ //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' }
+ // maven { url 'http://software.r3.com/artifactory/corda-lib-dev' }
+ maven { url 'http://software.r3.com/artifactory/corda-lib' }
+ }
+
+ 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 {
+ apply from: "${rootProject.projectDir}/repositories.gradle"
+ apply plugin: 'java'
+
+ repositories {
+ mavenLocal()
+
+ mavenCentral()
+ maven { url 'https://download.corda.net/maven/corda-dependencies' }
+ // Can be removed post-release - used to get nightly snapshot build.
+ 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" }
+ }
+
+ 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")
+ }
+ }
+}
+
+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"
+
+ //accounts
+ cordapp "$accounts_release_group:accounts-contracts:$accounts_release_version"
+ cordapp "$confidential_id_release_group:ci-workflows:$confidential_id_release_version"
+ cordapp "$accounts_release_group:accounts-workflows:$accounts_release_version"
+
+ //tokens
+ cordapp "$tokens_release_group:tokens-contracts:$tokens_release_version"
+ cordapp "$tokens_release_group:tokens-workflows:$tokens_release_version"
+ cordapp "$tokens_release_group:tokens-money:$tokens_release_version"
+ cordapp "$tokens_release_group:tokens-selection:$tokens_release_version"
+
+
+}
+
+cordapp {
+ info {
+ name "CorDapp t20worldcup"
+ 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 {
+ deploy = false
+ }
+
+ //acounts
+ cordapp project(':contracts')
+ cordapp project(':workflows')
+ 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")
+
+ //tokens
+ cordapp("$tokens_release_group:tokens-contracts:$tokens_release_version")
+ cordapp("$tokens_release_group:tokens-workflows:$tokens_release_version")
+ cordapp("$tokens_release_group:tokens-money:$tokens_release_version")
+ cordapp("$tokens_release_group:tokens-selection:$tokens_release_version")
+ runSchemaMigration = true
+ }
+ node {
+ name "O=Notary,L=London,C=GB"
+ notary = [validating : false]
+ p2pPort 10002
+ rpcSettings {
+ address("localhost:10003")
+ adminAddress("localhost:10043")
+ }
+ extraConfig = ['h2Settings.address' : 'localhost:20040']
+ }
+ node {
+ name "O=Dealer1,L=London,C=GB"
+ p2pPort 10005
+ rpcSettings {
+ address("localhost:10006")
+ adminAddress("localhost:10046")
+ }
+ rpcUsers = [[ user: "user1", "password": "test", "permissions": ["ALL"]]]
+ extraConfig = ['h2Settings.address' : 'localhost:20041']
+ }
+ node {
+ name "O=BCCI,L=New York,C=US"
+ p2pPort 10008
+ rpcSettings {
+ address("localhost:10009")
+ adminAddress("localhost:10049")
+ }
+ rpcUsers = [[ user: "user1", "password": "test", "permissions": ["ALL"]]]
+ extraConfig = ['h2Settings.address' : 'localhost:20042']
+ }
+ node {
+ name "O=Bank,L=Delhi,C=IN"
+ p2pPort 10017
+ rpcSettings {
+ address("localhost:10018")
+ adminAddress("localhost:10058")
+ }
+ rpcUsers = [[ user: "user1", "password": "test", "permissions": ["ALL"]]]
+ extraConfig = ['h2Settings.address' : 'localhost:20043']
+ }
+
+ node {
+ name "O=Dealer2,L=Delhi,C=IN"
+ p2pPort 10090
+ rpcSettings {
+ address("localhost:10091")
+ adminAddress("localhost:10092")
+ }
+ rpcUsers = [[ user: "user1", "password": "test", "permissions": ["ALL"]]]
+ extraConfig = ['h2Settings.address' : 'localhost:20093']
+ }
+}
+
+task installQuasar(type: Copy) {
+ destinationDir rootProject.file("lib")
+ from(configurations.quasar) {
+ rename 'quasar-core(.*).jar', 'quasar.jar'
+ }
+}
+
diff --git a/Accounts/worldcupticketbooking/clients/build.gradle b/Accounts/worldcupticketbooking/clients/build.gradle
new file mode 100644
index 00000000..c6be5398
--- /dev/null
+++ b/Accounts/worldcupticketbooking/clients/build.gradle
@@ -0,0 +1,48 @@
+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"
+}
+
+springBoot {
+ mainClassName = "com.t20worldcup.webserver.Server"
+}
+
+task runClient(type: JavaExec, dependsOn: assemble) {
+ classpath = sourceSets.main.runtimeClasspath
+ main = 'com.t20worldcup.Client'
+ args 'localhost:10006', 'user1', 'test'
+}
+
+task runServer(type: JavaExec, dependsOn: assemble) {
+ classpath = sourceSets.main.runtimeClasspath
+ main = 'com.t20worldcup.webserver.Starter'
+ args '--server.port=10050', '--config.rpc.host=localhost', '--config.rpc.port=10006', '--config.rpc.username=user1', '--config.rpc.password=test'
+}
diff --git a/Accounts/worldcupticketbooking/clients/src/main/java/com/t20worldcup/Client.java b/Accounts/worldcupticketbooking/clients/src/main/java/com/t20worldcup/Client.java
new file mode 100644
index 00000000..910c7c67
--- /dev/null
+++ b/Accounts/worldcupticketbooking/clients/src/main/java/com/t20worldcup/Client.java
@@ -0,0 +1,36 @@
+package com.t20worldcup;
+
+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/worldcupticketbooking/clients/src/main/java/com/t20worldcup/webserver/Controller.java b/Accounts/worldcupticketbooking/clients/src/main/java/com/t20worldcup/webserver/Controller.java
new file mode 100644
index 00000000..a851c79f
--- /dev/null
+++ b/Accounts/worldcupticketbooking/clients/src/main/java/com/t20worldcup/webserver/Controller.java
@@ -0,0 +1,89 @@
+package com.t20worldcup.webserver;
+
+import com.r3.corda.lib.accounts.contracts.states.AccountInfo;
+import com.r3.corda.lib.tokens.contracts.states.FungibleToken;
+import com.r3.corda.lib.tokens.contracts.states.NonFungibleToken;
+import com.t20worldcup.flows.GetAllAccounts;
+import net.corda.core.contracts.StateAndRef;
+import net.corda.core.messaging.CordaRPCOps;
+import net.corda.core.node.services.Vault;
+import net.corda.core.node.services.vault.QueryCriteria;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.UUID;
+import java.util.concurrent.ExecutionException;
+
+@RestController
+@RequestMapping("/")
+public class Controller {
+ private final CordaRPCOps proxy;
+ private final static Logger logger = LoggerFactory.getLogger(Controller.class);
+
+ public Controller(NodeRPCConnection rpc) {
+ this.proxy = rpc.proxy;
+ }
+
+
+
+ @GetMapping(value = "/all-accounts")
+ private List getAllAccounts() {
+ List result = null;
+ try {
+ result = this.proxy.startTrackedFlowDynamic(GetAllAccounts.class).getReturnValue().get();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ } catch (ExecutionException e) {
+ e.printStackTrace();
+ }
+
+ List accountInfoNames = new ArrayList<>();
+
+ for(AccountInfo accountInfo : result) {
+ accountInfoNames.add(accountInfo.getName());
+ }
+
+ return accountInfoNames;
+ }
+
+ @PostMapping(value = "/cash-balance")
+ private Long getCashBalanceForAccount(String accountId) {
+
+ UUID uuid = UUID.fromString(accountId);
+
+ QueryCriteria criteria = new QueryCriteria.VaultQueryCriteria().withStatus(Vault.StateStatus.UNCONSUMED).
+ withExternalIds(Arrays.asList(uuid));
+
+ List> list = this.proxy.vaultQueryByCriteria(criteria, FungibleToken.class).getStates();
+
+ Long totalBalance = 0L;
+
+ for(StateAndRef stateAndRef : list) {
+ totalBalance += stateAndRef.getState().getData().getAmount().getQuantity();
+ }
+
+ return totalBalance;
+ }
+
+ @PostMapping(value = "/is-account-owner-of-ticket")
+ private String isAccountOwnerOfTicket(String accountId, String nonFungibleTokenId) {
+
+ UUID uuid = UUID.fromString(accountId);
+
+ QueryCriteria criteria = new QueryCriteria.VaultQueryCriteria().withStatus(Vault.StateStatus.UNCONSUMED).
+ withExternalIds(Arrays.asList(uuid));
+
+ List> list = this.proxy.vaultQueryByCriteria(criteria, NonFungibleToken.class).getStates();
+
+ for(StateAndRef nonFungibleTokenStateAndRef : list) {
+ if (nonFungibleTokenStateAndRef.getState().getData().getLinearId().getId().equals(UUID.fromString(nonFungibleTokenId))) {
+ return "This account does hold the ticket";
+ }
+ }
+ return "This account does not hold the ticket";
+ }
+}
\ No newline at end of file
diff --git a/Accounts/worldcupticketbooking/clients/src/main/java/com/t20worldcup/webserver/NodeRPCConnection.java b/Accounts/worldcupticketbooking/clients/src/main/java/com/t20worldcup/webserver/NodeRPCConnection.java
new file mode 100644
index 00000000..af714c22
--- /dev/null
+++ b/Accounts/worldcupticketbooking/clients/src/main/java/com/t20worldcup/webserver/NodeRPCConnection.java
@@ -0,0 +1,48 @@
+package com.t20worldcup.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/worldcupticketbooking/clients/src/main/java/com/t20worldcup/webserver/Starter.java b/Accounts/worldcupticketbooking/clients/src/main/java/com/t20worldcup/webserver/Starter.java
new file mode 100644
index 00000000..cb9e63ee
--- /dev/null
+++ b/Accounts/worldcupticketbooking/clients/src/main/java/com/t20worldcup/webserver/Starter.java
@@ -0,0 +1,23 @@
+package com.t20worldcup.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();
+ }
+}
\ No newline at end of file
diff --git a/Accounts/worldcupticketbooking/clients/src/main/resources/static/app.js b/Accounts/worldcupticketbooking/clients/src/main/resources/static/app.js
new file mode 100644
index 00000000..c58d2de8
--- /dev/null
+++ b/Accounts/worldcupticketbooking/clients/src/main/resources/static/app.js
@@ -0,0 +1,3 @@
+"use strict";
+
+// Define your client-side logic here.
\ No newline at end of file
diff --git a/Accounts/worldcupticketbooking/clients/src/main/resources/static/index.html b/Accounts/worldcupticketbooking/clients/src/main/resources/static/index.html
new file mode 100644
index 00000000..758501dd
--- /dev/null
+++ b/Accounts/worldcupticketbooking/clients/src/main/resources/static/index.html
@@ -0,0 +1,10 @@
+
+
+
+
+ Example front-end.
+
+
+
Define your front-end here.
+
+
\ No newline at end of file
diff --git a/Accounts/worldcupticketbooking/config/dev/log4j2.xml b/Accounts/worldcupticketbooking/config/dev/log4j2.xml
new file mode 100644
index 00000000..34ba4d45
--- /dev/null
+++ b/Accounts/worldcupticketbooking/config/dev/log4j2.xml
@@ -0,0 +1,59 @@
+
+
+
+
+ logs
+ node-${hostName}
+ ${log-path}/archive
+
+
+
+
+
+
+
+
+ %highlight{%level{length=1} %d{HH:mm:ss} %T %c{1}.%M - %msg%n}{INFO=white,WARN=red,FATAL=bright red blink}
+ >
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Accounts/worldcupticketbooking/config/test/log4j2.xml b/Accounts/worldcupticketbooking/config/test/log4j2.xml
new file mode 100644
index 00000000..cd9926ca
--- /dev/null
+++ b/Accounts/worldcupticketbooking/config/test/log4j2.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+ [%-5level] %d{HH:mm:ss.SSS} [%t] %c{1}.%M - %msg%n
+ >
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Accounts/worldcupticketbooking/contracts/build.gradle b/Accounts/worldcupticketbooking/contracts/build.gradle
new file mode 100644
index 00000000..a8f6b788
--- /dev/null
+++ b/Accounts/worldcupticketbooking/contracts/build.gradle
@@ -0,0 +1,37 @@
+apply plugin: 'net.corda.plugins.cordapp'
+apply plugin: 'net.corda.plugins.cordformation'
+
+cordapp {
+ targetPlatformVersion corda_platform_version
+ minimumPlatformVersion corda_platform_version
+ contract {
+ name "t20worldcup 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"
+
+ cordaCompile "$tokens_release_group:tokens-contracts:$tokens_release_version"
+}
\ No newline at end of file
diff --git a/Accounts/worldcupticketbooking/contracts/src/main/java/com/t20worldcup/contracts/T20CricketTicketContract.java b/Accounts/worldcupticketbooking/contracts/src/main/java/com/t20worldcup/contracts/T20CricketTicketContract.java
new file mode 100644
index 00000000..ebd02248
--- /dev/null
+++ b/Accounts/worldcupticketbooking/contracts/src/main/java/com/t20worldcup/contracts/T20CricketTicketContract.java
@@ -0,0 +1,26 @@
+package com.t20worldcup.contracts;
+
+import com.r3.corda.lib.tokens.contracts.EvolvableTokenContract;
+import net.corda.core.contracts.Contract;
+import net.corda.core.transactions.LedgerTransaction;
+import org.jetbrains.annotations.NotNull;
+
+public class T20CricketTicketContract extends EvolvableTokenContract implements Contract {
+
+ @Override
+ public void verify(@NotNull LedgerTransaction tx) throws IllegalArgumentException {
+
+ }
+
+ @Override
+ public void additionalCreateChecks(@NotNull LedgerTransaction tx) {
+ // Write contract validation logic to be performed while creation of token
+
+ }
+
+ @Override
+ public void additionalUpdateChecks(@NotNull LedgerTransaction tx) {
+ // Write contract validation logic to be performed while updation of token
+ }
+
+}
diff --git a/Accounts/worldcupticketbooking/contracts/src/main/java/com/t20worldcup/states/T20CricketTicket.java b/Accounts/worldcupticketbooking/contracts/src/main/java/com/t20worldcup/states/T20CricketTicket.java
new file mode 100644
index 00000000..76998c06
--- /dev/null
+++ b/Accounts/worldcupticketbooking/contracts/src/main/java/com/t20worldcup/states/T20CricketTicket.java
@@ -0,0 +1,63 @@
+package com.t20worldcup.states;
+
+import com.r3.corda.lib.tokens.contracts.states.EvolvableTokenType;
+import com.t20worldcup.contracts.T20CricketTicketContract;
+import net.corda.core.contracts.BelongsToContract;
+import net.corda.core.contracts.UniqueIdentifier;
+import net.corda.core.identity.Party;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Arrays;
+import java.util.List;
+
+@BelongsToContract(T20CricketTicketContract.class)
+public class T20CricketTicket extends EvolvableTokenType {
+
+ private UniqueIdentifier linearId;
+ private String ticketTeam;
+ private Party issuer;//dealer
+ //private AbstractParty owner;//for the first time dealer then customers
+
+ public T20CricketTicket(UniqueIdentifier linearId, String ticketTeam, Party issuer) {
+ this.linearId = linearId;
+ this.ticketTeam = ticketTeam;
+ this.issuer = issuer;
+ //this.owner = owner;
+ }
+
+ @Override
+ public int getFractionDigits() {
+ return 0;
+ }
+
+ @NotNull
+ @Override
+ public List getMaintainers() {
+ return Arrays.asList(this.getIssuer());
+ }
+
+// @NotNull
+// @Override
+// public List getParticipants() {
+// return Arrays.asList(this.getOwner());
+// }
+
+ @NotNull
+ @Override
+ public UniqueIdentifier getLinearId() {
+ return this.linearId;
+ }
+
+// public AbstractParty getOwner() {
+// return owner;
+// }
+
+ public String getTicketTeam() {
+ return ticketTeam;
+ }
+
+ public Party getIssuer() {
+ return issuer;
+ }
+
+}
diff --git a/Accounts/worldcupticketbooking/contracts/src/test/java/com/t20worldcup/contracts/ContractTests.java b/Accounts/worldcupticketbooking/contracts/src/test/java/com/t20worldcup/contracts/ContractTests.java
new file mode 100644
index 00000000..d5c7394d
--- /dev/null
+++ b/Accounts/worldcupticketbooking/contracts/src/test/java/com/t20worldcup/contracts/ContractTests.java
@@ -0,0 +1,13 @@
+package com.t20worldcup.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/worldcupticketbooking/gradle.properties b/Accounts/worldcupticketbooking/gradle.properties
new file mode 100644
index 00000000..9c8df25c
--- /dev/null
+++ b/Accounts/worldcupticketbooking/gradle.properties
@@ -0,0 +1,3 @@
+name=Test
+group=com.t20worldcup
+version=0.1
\ No newline at end of file
diff --git a/Accounts/worldcupticketbooking/gradle/wrapper/gradle-wrapper.jar b/Accounts/worldcupticketbooking/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 00000000..99340b4a
Binary files /dev/null and b/Accounts/worldcupticketbooking/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/Accounts/worldcupticketbooking/gradle/wrapper/gradle-wrapper.properties b/Accounts/worldcupticketbooking/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 00000000..2a2a3a8e
--- /dev/null
+++ b/Accounts/worldcupticketbooking/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#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.4.1-all.zip
diff --git a/Accounts/worldcupticketbooking/gradlew b/Accounts/worldcupticketbooking/gradlew
new file mode 100755
index 00000000..cccdd3d5
--- /dev/null
+++ b/Accounts/worldcupticketbooking/gradlew
@@ -0,0 +1,172 @@
+#!/usr/bin/env sh
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+ echo "$*"
+}
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+ NONSTOP* )
+ nonstop=true
+ ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Escape application args
+save () {
+ for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+ echo " "
+}
+APP_ARGS=$(save "$@")
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
+if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
+ cd "$(dirname "$0")"
+fi
+
+exec "$JAVACMD" "$@"
diff --git a/Accounts/worldcupticketbooking/gradlew.bat b/Accounts/worldcupticketbooking/gradlew.bat
new file mode 100644
index 00000000..f9553162
--- /dev/null
+++ b/Accounts/worldcupticketbooking/gradlew.bat
@@ -0,0 +1,84 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windows variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/Accounts/worldcupticketbooking/images/T20-World-Cup-e1578570579412.jpg b/Accounts/worldcupticketbooking/images/T20-World-Cup-e1578570579412.jpg
new file mode 100644
index 00000000..9c7e051a
Binary files /dev/null and b/Accounts/worldcupticketbooking/images/T20-World-Cup-e1578570579412.jpg differ
diff --git a/Accounts/worldcupticketbooking/images/graph.png b/Accounts/worldcupticketbooking/images/graph.png
new file mode 100644
index 00000000..f434fe1e
Binary files /dev/null and b/Accounts/worldcupticketbooking/images/graph.png differ
diff --git a/Accounts/worldcupticketbooking/images/workflow.png b/Accounts/worldcupticketbooking/images/workflow.png
new file mode 100644
index 00000000..bc401c35
Binary files /dev/null and b/Accounts/worldcupticketbooking/images/workflow.png differ
diff --git a/Accounts/worldcupticketbooking/repositories.gradle b/Accounts/worldcupticketbooking/repositories.gradle
new file mode 100644
index 00000000..072b616b
--- /dev/null
+++ b/Accounts/worldcupticketbooking/repositories.gradle
@@ -0,0 +1,10 @@
+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' }
+ maven { url 'http://software.r3.com/artifactory/corda-lib-dev' }
+ maven { url 'http://software.r3.com/artifactory/corda-lib' }
+}
diff --git a/Accounts/worldcupticketbooking/settings.gradle b/Accounts/worldcupticketbooking/settings.gradle
new file mode 100644
index 00000000..2514aca2
--- /dev/null
+++ b/Accounts/worldcupticketbooking/settings.gradle
@@ -0,0 +1,3 @@
+include 'workflows'
+include 'contracts'
+include 'clients'
\ No newline at end of file
diff --git a/Accounts/worldcupticketbooking/workflows/build.gradle b/Accounts/worldcupticketbooking/workflows/build.gradle
new file mode 100644
index 00000000..b2f724d5
--- /dev/null
+++ b/Accounts/worldcupticketbooking/workflows/build.gradle
@@ -0,0 +1,78 @@
+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 "t20worldcup 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")
+
+ //Account dependencies
+ cordaCompile "$confidential_id_release_group:ci-workflows:$confidential_id_release_version"
+ cordaCompile "$accounts_release_group:accounts-workflows:$accounts_release_version"
+ cordaCompile "$accounts_release_group:accounts-contracts:$accounts_release_version"
+
+
+ // Token SDK dependencies.
+ cordaCompile "$tokens_release_group:tokens-workflows:$tokens_release_version"
+ cordaCompile "$tokens_release_group:tokens-contracts:$tokens_release_version"
+ cordaCompile "$tokens_release_group:tokens-money:$tokens_release_version"
+ cordapp "$tokens_release_group:tokens-selection:$tokens_release_version"
+
+}
+
+task integrationTest(type: Test, dependsOn: []) {
+ testClassesDirs = sourceSets.integrationTest.output.classesDirs
+ classpath = sourceSets.integrationTest.runtimeClasspath
+}
\ No newline at end of file
diff --git a/Accounts/worldcupticketbooking/workflows/src/integrationTest/java/com/t20worldcup/DriverBasedTest.java b/Accounts/worldcupticketbooking/workflows/src/integrationTest/java/com/t20worldcup/DriverBasedTest.java
new file mode 100644
index 00000000..1ba4baba
--- /dev/null
+++ b/Accounts/worldcupticketbooking/workflows/src/integrationTest/java/com/t20worldcup/DriverBasedTest.java
@@ -0,0 +1,48 @@
+package com.t20worldcup;
+
+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/worldcupticketbooking/workflows/src/main/java/com/t20worldcup/flows/CreateAndShareAccountFlow.java b/Accounts/worldcupticketbooking/workflows/src/main/java/com/t20worldcup/flows/CreateAndShareAccountFlow.java
new file mode 100644
index 00000000..cb226518
--- /dev/null
+++ b/Accounts/worldcupticketbooking/workflows/src/main/java/com/t20worldcup/flows/CreateAndShareAccountFlow.java
@@ -0,0 +1,46 @@
+package com.t20worldcup.flows;
+
+import co.paralleluniverse.fibers.Suspendable;
+import com.r3.corda.lib.accounts.contracts.states.AccountInfo;
+import com.r3.corda.lib.accounts.workflows.flows.CreateAccount;
+import com.r3.corda.lib.accounts.workflows.flows.ShareAccountInfo;
+import net.corda.core.contracts.StateAndRef;
+import net.corda.core.flows.FlowException;
+import net.corda.core.flows.FlowLogic;
+import net.corda.core.flows.InitiatingFlow;
+import net.corda.core.flows.StartableByRPC;
+import net.corda.core.identity.Party;
+import net.corda.core.transactions.SignedTransaction;
+
+import java.util.List;
+
+/**
+ * This flow will create the account on the node on which you run this flow. This is done using inbuilt flow called CreateAccount.
+ * CreateAccount creates an AccountInfo object which has name, host and id as its fields. This is mapped to Account table in the db.
+ * For any other party to transact with this account, this AccountInfo will haveto be shared with that Party.
+ * Hence the Ipl Ticket Dealers create the ticket buyers accounts on their end and share this accountInfo with the Bank node and BCCI node.
+ */
+@StartableByRPC
+@InitiatingFlow
+public class CreateAndShareAccountFlow extends FlowLogic {
+
+ private final String accountName;
+ private final List partyToShareAccountInfoToList;
+
+ public CreateAndShareAccountFlow(String accountName, List partyToShareAccountInfoToList) {
+ this.accountName = accountName;
+ this.partyToShareAccountInfoToList = partyToShareAccountInfoToList;
+ }
+
+ @Override
+ @Suspendable
+ public String call() throws FlowException {
+
+ //Call inbuilt CreateAccount flow to create the AccountInfo object
+ StateAndRef accountInfoStateAndRef = (StateAndRef) subFlow(new CreateAccount(accountName));
+
+ //Share this AccountInfo object with the parties who want to transact with this account
+ subFlow(new ShareAccountInfo(accountInfoStateAndRef, partyToShareAccountInfoToList));
+ return "" + accountName +"has been created and shared to " +partyToShareAccountInfoToList+".";
+ }
+}
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
new file mode 100644
index 00000000..f75f0d25
--- /dev/null
+++ b/Accounts/worldcupticketbooking/workflows/src/main/java/com/t20worldcup/flows/CreateT20CricketTicketTokenFlow.java
@@ -0,0 +1,51 @@
+package com.t20worldcup.flows;
+
+import co.paralleluniverse.fibers.Suspendable;
+import com.t20worldcup.states.T20CricketTicket;
+import com.r3.corda.lib.tokens.workflows.flows.rpc.CreateEvolvableTokens;
+import net.corda.core.contracts.TransactionState;
+import net.corda.core.contracts.UniqueIdentifier;
+import net.corda.core.flows.FlowException;
+import net.corda.core.flows.FlowLogic;
+import net.corda.core.flows.InitiatingFlow;
+import net.corda.core.flows.StartableByRPC;
+import net.corda.core.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
+ * and need not be shared with anyone. Later BCCI will Issue NonFungible tokens on this base type.
+ * Ipl base type will be of type EvolvableToken. Keep in mind that the maintainer of the EvolvableTokenType is of type Party and not of type AnonymousParty
+ */
+@StartableByRPC
+@InitiatingFlow
+public class CreateT20CricketTicketTokenFlow extends FlowLogic {
+
+ private final String ticketTeam;
+
+ public CreateT20CricketTicketTokenFlow(String ticketTeam) {
+ this.ticketTeam = ticketTeam;
+ }
+
+ @Override
+ @Suspendable
+ public String 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 token type by passing in the name of the ipl match. specify the maintainer as BCCI
+ UniqueIdentifier id = new UniqueIdentifier();
+ T20CricketTicket t20CricketTicket = new T20CricketTicket(id, ticketTeam, getOurIdentity());
+
+ //warp it with transaction state specifying the notary
+ TransactionState transactionState = new TransactionState(t20CricketTicket, notary);
+
+ //call built in sub flow CreateEvolvableTokens to craete the base type on BCCI node
+ SignedTransaction stx = subFlow(new CreateEvolvableTokens(transactionState));
+
+ return "Ticket for "+ticketTeam+" has been created. With Ticket ID: "+ id.toString()+"" +
+ "\ntxId: "+stx.getId()+"";
+ }
+}
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
new file mode 100644
index 00000000..39243ab4
--- /dev/null
+++ b/Accounts/worldcupticketbooking/workflows/src/main/java/com/t20worldcup/flows/DVPAccountsHostedOnDifferentNodes.java
@@ -0,0 +1,281 @@
+package com.t20worldcup.flows;
+
+
+import co.paralleluniverse.fibers.Suspendable;
+import com.r3.corda.lib.tokens.contracts.states.NonFungibleToken;
+import com.r3.corda.lib.tokens.workflows.utilities.QueryUtilitiesKt;
+import com.t20worldcup.states.T20CricketTicket;
+import com.r3.corda.lib.accounts.contracts.states.AccountInfo;
+import com.r3.corda.lib.accounts.workflows.UtilitiesKt;
+import com.r3.corda.lib.accounts.workflows.flows.RequestKeyForAccount;
+import com.r3.corda.lib.ci.workflows.SyncKeyMappingFlow;
+import com.r3.corda.lib.ci.workflows.SyncKeyMappingFlowHandler;
+import com.r3.corda.lib.tokens.contracts.states.FungibleToken;
+import com.r3.corda.lib.tokens.contracts.types.TokenPointer;
+import com.r3.corda.lib.tokens.contracts.types.TokenType;
+import com.r3.corda.lib.tokens.money.FiatCurrency;
+import com.r3.corda.lib.tokens.selection.TokenQueryBy;
+import com.r3.corda.lib.tokens.selection.database.config.DatabaseSelectionConfigKt;
+import com.r3.corda.lib.tokens.selection.database.selector.DatabaseTokenSelection;
+import com.r3.corda.lib.tokens.workflows.flows.move.MoveTokensUtilitiesKt;
+import kotlin.Pair;
+import net.corda.core.contracts.*;
+import net.corda.core.flows.*;
+import net.corda.core.identity.AbstractParty;
+import net.corda.core.identity.AnonymousParty;
+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 org.jetbrains.annotations.NotNull;
+
+import java.security.PublicKey;
+import java.util.*;
+
+
+/**
+ * This flow shows you how to perform a dvp between accounts hosted on different nodes. Buyer account is on one host and Seller account is on other node.
+ * Majority of the code which deals with building the transaction for dvp is similar to DVPAccountsOnSameNode.java.
+ * Few more things to keep in mind - when accounts hosted on different nodes want to transact with each other you need to make sure to
+ * share the keys which account on one node must created and used. This is done as the other node/account is not aware which key was used to sign
+ * a shared transaction. To verify this, Node1 needs to share the keys. This can be done by calling SyncKeyMappingFlow. This flow will have to be called from
+ * both the sides. Once we sync accounts and keys and built the transaction, we can then call CollectSignaturesFlow.
+ * Look at how I am passing the 4 th parameter to CollectSignaturesFlow which tells the counterparty which all keys were used by the initiator for signing,
+ * so the counterparty will use remaining keys to sign the transaction. There is one more tricky bit tto this. When we call MoveTokensUtilitiesKt.addMoveTokens,
+ * internally a new Anonymous key is created and assigned to the current holder. So internally as well token sdk uses Confidential Identity. We will have to
+ * explicitly sync this key as well, as the counterparty is not aware of this key.
+ */
+@StartableByRPC
+@InitiatingFlow
+public class DVPAccountsHostedOnDifferentNodes extends FlowLogic {
+
+ private final String tokenId;
+ private final String buyerAccountName;
+ private final String sellerAccountName;
+ private final String currency;
+ private final Long costOfTicket;
+
+ public DVPAccountsHostedOnDifferentNodes(String tokenId, String buyerAccountName, String sellerAccountName, Long costOfTicket, String currency) {
+ this.tokenId = tokenId;
+ this.buyerAccountName = buyerAccountName;
+ this.sellerAccountName = sellerAccountName;
+ this.costOfTicket = costOfTicket;
+ this.currency = currency;
+ }
+
+
+ //This flow will be initiated by the buyer who wishes to buy the ticket from an account hosted on different node.
+ //The buyer will call the generate move token , generate the cash token transfer states and send it to selelr.
+ @Override
+ @Suspendable
+ public String call() throws FlowException {
+
+ //Get buyers and sellers account infos
+ AccountInfo buyerAccountInfo = UtilitiesKt.getAccountService(this).accountInfo(buyerAccountName).get(0).getState().getData();
+ AccountInfo sellerAccountInfo = UtilitiesKt.getAccountService(this).accountInfo(sellerAccountName).get(0).getState().getData();
+
+ //Generate new keys for buyers and sellers
+ //make sure to sync these keys with the counterparty by calling SyncKeyMappingFlow as below
+ AnonymousParty buyerAccount = subFlow(new RequestKeyForAccount(buyerAccountInfo));//mappng saved locally
+ AnonymousParty sellerAccount = subFlow(new RequestKeyForAccount(sellerAccountInfo));//mappiing requested from counterparty. does the counterparty save i dont think so
+
+
+ //Part1 : Move non fungible token - ticket from seller to buyer
+ //establish session with seller
+ FlowSession sellerSession = initiateFlow(sellerAccountInfo.getHost());
+
+ //send uuid, buyer,seller account name to seller
+ sellerSession.send(tokenId);
+ sellerSession.send(buyerAccountName);
+ sellerSession.send(sellerAccountName);
+
+ //buyer will create generate a move tokens state and send this state with new holder(seller) to seller
+ Amount amount = new Amount(costOfTicket, FiatCurrency.Companion.getInstance(currency));
+
+ //Buyer Query for token balance.
+ QueryCriteria queryCriteria = QueryUtilitiesKt.heldTokenAmountCriteria(this.getInstance(currency), buyerAccount).and(QueryUtilitiesKt.sumTokenCriteria());
+ List