diff --git a/commercial-paper/.classpath b/commercial-paper/.classpath
new file mode 100644
index 00000000..a27a7889
--- /dev/null
+++ b/commercial-paper/.classpath
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/commercial-paper/.gitignore b/commercial-paper/.gitignore
index 14c40052..3ed60ea0 100644
--- a/commercial-paper/.gitignore
+++ b/commercial-paper/.gitignore
@@ -6,3 +6,5 @@ organization/digibank/contract/node_modules/
organization/digibank/identity/user/
package-lock.json
.vscode
+/target/
+bin/
diff --git a/commercial-paper/ledger-java-api/org/example/ledger/api/Field.java b/commercial-paper/ledger-java-api/org/example/ledger/api/Field.java
new file mode 100644
index 00000000..25d81f67
--- /dev/null
+++ b/commercial-paper/ledger-java-api/org/example/ledger/api/Field.java
@@ -0,0 +1,5 @@
+package org.example.ledger.api;
+
+public @interface Field {
+ public String name() default "";
+}
diff --git a/commercial-paper/ledger-java-api/org/example/ledger/api/Property.java b/commercial-paper/ledger-java-api/org/example/ledger/api/Property.java
new file mode 100644
index 00000000..5453d4f4
--- /dev/null
+++ b/commercial-paper/ledger-java-api/org/example/ledger/api/Property.java
@@ -0,0 +1,10 @@
+package org.example.ledger.api;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+@Retention(value=RetentionPolicy.RUNTIME)
+public @interface Property {
+ public String name() default "";
+ public boolean key() default false;
+}
diff --git a/commercial-paper/ledger-java-api/org/example/ledger/api/State.java b/commercial-paper/ledger-java-api/org/example/ledger/api/State.java
new file mode 100644
index 00000000..5b43ab3c
--- /dev/null
+++ b/commercial-paper/ledger-java-api/org/example/ledger/api/State.java
@@ -0,0 +1,125 @@
+/*
+SPDX-License-Identifier: Apache-2.0
+*/
+
+package org.example.ledger.api;
+
+import java.io.StringReader;
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Supplier;
+import java.util.stream.Collectors;
+
+import javax.json.Json;
+import javax.json.JsonArray;
+import javax.json.JsonNumber;
+import javax.json.JsonObject;
+import javax.json.JsonReader;
+import javax.json.JsonString;
+import javax.json.JsonValue;
+
+public class State {
+ private final String key;
+ private final Map properties;
+
+ protected final Supplier keyBuilder(String[] parts) {
+ return () -> Arrays.asList(parts).stream().map(part -> getProperty(part)).collect(Collectors.joining(":"));
+ };
+
+ public State(byte[] buffer) {
+ this.properties = deserialize(buffer);
+ List keyParts = new ArrayList();
+ for (Field field: getStateFields()) {
+ field.setAccessible(true);
+ try {
+ String value = properties.get(getPropertyName(field));
+ field.set(this, value);
+ boolean isKey = field.getAnnotation(Property.class).key();
+ if(isKey) {
+ keyParts.add(value);
+ }
+ } catch (IllegalArgumentException | IllegalAccessException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+ key = String.join(":", keyParts);
+ System.out.println(key);
+ }
+
+ private static Map deserialize(byte[] buffer) {
+ JsonObject json = toJSON(buffer);
+ Map result = json.entrySet().stream().collect(
+ Collectors.toMap(e -> e.getKey(), e -> jsonString(e.getValue())));
+ return result;
+ }
+
+ private static String jsonString(JsonValue value) {
+ if(value.getValueType() == JsonValue.ValueType.STRING) {
+ return ((JsonString)value).getString();
+ }
+ return value.toString();
+ }
+
+ private static JsonObject toJSON(byte[] buffer) {
+ String payload = new String(buffer);
+ String payloadData;
+ try (JsonReader reader = Json.createReader(new StringReader(payload))) {
+ JsonObject json = reader.readObject();
+ JsonArray arr = json.getJsonArray("data");
+ byte[] codepoints = new byte[arr.size()];
+ for(int i = 0; i < arr.size(); i++) {
+ codepoints[i] = (byte) ((JsonNumber)arr.get(i)).intValue();
+ }
+ payloadData = new String(codepoints);
+ }
+ try (JsonReader reader = Json.createReader(new StringReader(payloadData))) {
+ JsonObject json = reader.readObject();
+ return json;
+ }
+ }
+
+ private static String getPropertyName(java.lang.reflect.Field field) {
+ String name = field.getAnnotation(Property.class).name();
+ if (name.isEmpty()) {
+ name = field.getName();
+ }
+ return name;
+ }
+
+ private String getProperty(String key) {
+ return properties.get(key);
+ }
+
+ private List getStateFields() {
+ Class extends State> clazz = this.getClass().asSubclass(this.getClass());
+ return Arrays.asList(clazz.getDeclaredFields())
+ .stream()
+ .filter(field -> field.isAnnotationPresent(Property.class))
+ .collect(Collectors.toList());
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append(this.getClass().getName());
+ builder.append(" [");
+ for (Field field: getStateFields()) {
+ field.setAccessible(true);
+ builder.append(field.getName());
+ builder.append("=");
+ try {
+ builder.append(field.get(this));
+ } catch (IllegalArgumentException | IllegalAccessException e) {
+ // ignore for now
+ }
+ builder.append(", ");
+ }
+ builder.setCharAt(builder.length() - 2, ']');
+ return builder.toString();
+ }
+
+}
diff --git a/commercial-paper/organization/digibank/application-java/org/digibank/AddToWallet.java b/commercial-paper/organization/digibank/application-java/org/digibank/AddToWallet.java
new file mode 100644
index 00000000..702ed058
--- /dev/null
+++ b/commercial-paper/organization/digibank/application-java/org/digibank/AddToWallet.java
@@ -0,0 +1,44 @@
+/*
+SPDX-License-Identifier: Apache-2.0
+*/
+
+package org.digibank;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import org.hyperledger.fabric.gateway.GatewayException;
+import org.hyperledger.fabric.gateway.Wallet;
+import org.hyperledger.fabric.gateway.Wallet.Identity;
+
+public class AddToWallet {
+
+ public static void main(String[] args) {
+ try {
+ // A wallet stores a collection of identities
+ Path walletPath = Paths.get("organization", "digibank", "identity", "user", "balaji", "wallet");
+ Wallet wallet = Wallet.createFileSystemWallet(walletPath);
+
+ // Location of credentials to be stored in the wallet
+ Path credentialPath = Paths.get("..", "basic-network", "crypto-config",
+ "peerOrganizations", "org1.example.com", "users", "Admin@org1.example.com", "msp");
+ Path certificatePem = credentialPath.resolve(Paths.get("signcerts",
+ "Admin@org1.example.com-cert.pem"));
+ Path privateKey = credentialPath.resolve(Paths.get("keystore",
+ "cd96d5260ad4757551ed4a5a991e62130f8008a0bf996e4e4b84cd097a747fec_sk"));
+
+ // Load credentials into wallet
+ String identityLabel = "Admin@org1.example.com";
+ Identity identity = Identity.createIdentity("Org1MSP", Files.newBufferedReader(certificatePem), Files.newBufferedReader(privateKey));
+
+ wallet.put(identityLabel, identity);
+
+ } catch (IOException | GatewayException e) {
+ System.err.println("Error adding to wallet");
+ e.printStackTrace();
+ }
+ }
+
+}
diff --git a/commercial-paper/organization/digibank/application-java/org/digibank/Buy.java b/commercial-paper/organization/digibank/application-java/org/digibank/Buy.java
new file mode 100644
index 00000000..0dc0a306
--- /dev/null
+++ b/commercial-paper/organization/digibank/application-java/org/digibank/Buy.java
@@ -0,0 +1,62 @@
+/*
+SPDX-License-Identifier: Apache-2.0
+*/
+
+package org.digibank;
+
+import java.io.IOException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.concurrent.TimeoutException;
+
+import org.hyperledger.fabric.gateway.Contract;
+import org.hyperledger.fabric.gateway.Gateway;
+import org.hyperledger.fabric.gateway.GatewayException;
+import org.hyperledger.fabric.gateway.Network;
+import org.hyperledger.fabric.gateway.Wallet;
+import org.papernet.CommercialPaper;
+
+public class Buy {
+
+ public static void main(String[] args) {
+ Gateway.Builder builder = Gateway.createBuilder();
+
+ try {
+ // A wallet stores a collection of identities
+ Path walletPath = Paths.get("organization", "digibank", "identity", "user", "balaji", "wallet");
+ Wallet wallet = Wallet.createFileSystemWallet(walletPath);
+
+ String userName = "Admin@org1.example.com";
+
+ Path connectionProfile = Paths.get("organization", "digibank", "gateway", "networkConnection.yaml");
+
+ // Set connection options on the gateway builder
+ builder.identity(wallet, userName).networkConfig(connectionProfile).discovery(false);
+
+ // Connect to gateway using application specified parameters
+ try(Gateway gateway = builder.connect()) {
+
+ // Access PaperNet network
+ System.out.println("Use network channel: mychannel.");
+ Network network = gateway.getNetwork("mychannel");
+
+ // Get addressability to commercial paper contract
+ System.out.println("Use org.papernet.commercialpaper smart contract.");
+ Contract contract = network.getContract("papercontract", "org.papernet.commercialpaper");
+
+ // Buy commercial paper
+ System.out.println("Submit commercial paper buy transaction.");
+ byte[] response = contract.submitTransaction("buy", "MagnetoCorp", "00001", "MagnetoCorp", "DigiBank", "4900000", "2020-05-31");
+
+ // Process response
+ System.out.println("Process buy transaction response.");
+ CommercialPaper paper = CommercialPaper.create(response);
+ System.out.println(paper);
+ }
+ } catch (GatewayException | IOException | TimeoutException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+}
diff --git a/commercial-paper/organization/digibank/application-java/org/digibank/Redeem.java b/commercial-paper/organization/digibank/application-java/org/digibank/Redeem.java
new file mode 100644
index 00000000..b96876d6
--- /dev/null
+++ b/commercial-paper/organization/digibank/application-java/org/digibank/Redeem.java
@@ -0,0 +1,62 @@
+/*
+SPDX-License-Identifier: Apache-2.0
+*/
+
+package org.digibank;
+
+import java.io.IOException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.concurrent.TimeoutException;
+
+import org.hyperledger.fabric.gateway.Contract;
+import org.hyperledger.fabric.gateway.Gateway;
+import org.hyperledger.fabric.gateway.GatewayException;
+import org.hyperledger.fabric.gateway.Network;
+import org.hyperledger.fabric.gateway.Wallet;
+import org.papernet.CommercialPaper;
+
+public class Redeem {
+
+ public static void main(String[] args) {
+ Gateway.Builder builder = Gateway.createBuilder();
+
+ try {
+ // A wallet stores a collection of identities
+ Path walletPath = Paths.get("organization", "digibank", "identity", "user", "balaji", "wallet");
+ Wallet wallet = Wallet.createFileSystemWallet(walletPath);
+
+ String userName = "Admin@org1.example.com";
+
+ Path connectionProfile = Paths.get("organization", "digibank", "gateway", "networkConnection.yaml");
+
+ // Set connection options on the gateway builder
+ builder.identity(wallet, userName).networkConfig(connectionProfile).discovery(false);
+
+ // Connect to gateway using application specified parameters
+ try(Gateway gateway = builder.connect()) {
+
+ // Access PaperNet network
+ System.out.println("Use network channel: mychannel.");
+ Network network = gateway.getNetwork("mychannel");
+
+ // Get addressability to commercial paper contract
+ System.out.println("Use org.papernet.commercialpaper smart contract.");
+ Contract contract = network.getContract("papercontract", "org.papernet.commercialpaper");
+
+ // Redeem commercial paper
+ System.out.println("Submit commercial paper redeem transaction.");
+ byte[] response = contract.submitTransaction("redeem", "MagnetoCorp", "00001", "DigiBank", "2020-11-30");
+
+ // Process response
+ System.out.println("Process redeem transaction response.");
+ CommercialPaper paper = CommercialPaper.create(response);
+ System.out.println(paper);
+ }
+ } catch (GatewayException | IOException | TimeoutException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+}
diff --git a/commercial-paper/organization/digibank/gateway/networkConnection.yaml b/commercial-paper/organization/digibank/gateway/networkConnection.yaml
index db50f318..8da20358 100644
--- a/commercial-paper/organization/digibank/gateway/networkConnection.yaml
+++ b/commercial-paper/organization/digibank/gateway/networkConnection.yaml
@@ -26,6 +26,9 @@ description: "The basic network"
#
version: "1.0"
+client:
+ organization: Org1
+
#
# [Optional]. But most apps would have this section so that channel objects can be constructed
# based on the content below. If an app is creating channels, then it likely will not need this
diff --git a/commercial-paper/organization/magnetocorp/application-java/org/magnetocorp/AddToWallet.java b/commercial-paper/organization/magnetocorp/application-java/org/magnetocorp/AddToWallet.java
new file mode 100644
index 00000000..dba3e5e3
--- /dev/null
+++ b/commercial-paper/organization/magnetocorp/application-java/org/magnetocorp/AddToWallet.java
@@ -0,0 +1,44 @@
+/*
+SPDX-License-Identifier: Apache-2.0
+*/
+
+package org.magnetocorp;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import org.hyperledger.fabric.gateway.GatewayException;
+import org.hyperledger.fabric.gateway.Wallet;
+import org.hyperledger.fabric.gateway.Wallet.Identity;
+
+public class AddToWallet {
+
+ public static void main(String[] args) {
+ try {
+ // A wallet stores a collection of identities
+ Path walletPath = Paths.get("organization", "magnetocorp", "identity", "user", "isabella", "wallet");
+ Wallet wallet = Wallet.createFileSystemWallet(walletPath);
+
+ // Location of credentials to be stored in the wallet
+ Path credentialPath = Paths.get("..", "basic-network", "crypto-config",
+ "peerOrganizations", "org1.example.com", "users", "User1@org1.example.com", "msp");
+ Path certificatePem = credentialPath.resolve(Paths.get("signcerts",
+ "User1@org1.example.com-cert.pem"));
+ Path privateKey = credentialPath.resolve(Paths.get("keystore",
+ "c75bd6911aca808941c3557ee7c97e90f3952e379497dc55eb903f31b50abc83_sk"));
+
+ // Load credentials into wallet
+ String identityLabel = "User1@org1.example.com";
+ Identity identity = Identity.createIdentity("Org1MSP", Files.newBufferedReader(certificatePem), Files.newBufferedReader(privateKey));
+
+ wallet.put(identityLabel, identity);
+
+ } catch (IOException | GatewayException e) {
+ System.err.println("Error adding to wallet");
+ e.printStackTrace();
+ }
+ }
+
+}
diff --git a/commercial-paper/organization/magnetocorp/application-java/org/magnetocorp/Issue.java b/commercial-paper/organization/magnetocorp/application-java/org/magnetocorp/Issue.java
new file mode 100644
index 00000000..e196b782
--- /dev/null
+++ b/commercial-paper/organization/magnetocorp/application-java/org/magnetocorp/Issue.java
@@ -0,0 +1,62 @@
+/*
+SPDX-License-Identifier: Apache-2.0
+*/
+
+package org.magnetocorp;
+
+import java.io.IOException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.concurrent.TimeoutException;
+
+import org.hyperledger.fabric.gateway.Contract;
+import org.hyperledger.fabric.gateway.Gateway;
+import org.hyperledger.fabric.gateway.GatewayException;
+import org.hyperledger.fabric.gateway.Network;
+import org.hyperledger.fabric.gateway.Wallet;
+import org.papernet.CommercialPaper;
+
+public class Issue {
+
+ public static void main(String[] args) {
+ Gateway.Builder builder = Gateway.createBuilder();
+
+ try {
+ // A wallet stores a collection of identities
+ Path walletPath = Paths.get("organization", "magnetocorp", "identity", "user", "isabella", "wallet");
+ Wallet wallet = Wallet.createFileSystemWallet(walletPath);
+
+ String userName = "User1@org1.example.com";
+
+ Path connectionProfile = Paths.get("organization", "magnetocorp", "gateway", "networkConnection.yaml");
+
+ // Set connection options on the gateway builder
+ builder.identity(wallet, userName).networkConfig(connectionProfile).discovery(false);
+
+ // Connect to gateway using application specified parameters
+ try(Gateway gateway = builder.connect()) {
+
+ // Access PaperNet network
+ System.out.println("Use network channel: mychannel.");
+ Network network = gateway.getNetwork("mychannel");
+
+ // Get addressability to commercial paper contract
+ System.out.println("Use org.papernet.commercialpaper smart contract.");
+ Contract contract = network.getContract("papercontract", "org.papernet.commercialpaper");
+
+ // Issue commercial paper
+ System.out.println("Submit commercial paper issue transaction.");
+ byte[] response = contract.submitTransaction("issue", "MagnetoCorp", "00001", "2020-05-31", "2020-11-30", "5000000");
+
+ // Process response
+ System.out.println("Process issue transaction response.");
+ CommercialPaper paper = CommercialPaper.create(response);
+ System.out.println(paper);
+ }
+ } catch (GatewayException | IOException | TimeoutException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+}
diff --git a/commercial-paper/organization/magnetocorp/gateway/networkConnection.yaml b/commercial-paper/organization/magnetocorp/gateway/networkConnection.yaml
index db50f318..8da20358 100644
--- a/commercial-paper/organization/magnetocorp/gateway/networkConnection.yaml
+++ b/commercial-paper/organization/magnetocorp/gateway/networkConnection.yaml
@@ -26,6 +26,9 @@ description: "The basic network"
#
version: "1.0"
+client:
+ organization: Org1
+
#
# [Optional]. But most apps would have this section so that channel objects can be constructed
# based on the content below. If an app is creating channels, then it likely will not need this
diff --git a/commercial-paper/organization/shared/lib-java/org/papernet/CommercialPaper.java b/commercial-paper/organization/shared/lib-java/org/papernet/CommercialPaper.java
new file mode 100644
index 00000000..7fb3016c
--- /dev/null
+++ b/commercial-paper/organization/shared/lib-java/org/papernet/CommercialPaper.java
@@ -0,0 +1,76 @@
+package org.papernet;
+
+import org.example.ledger.api.Property;
+import org.example.ledger.api.State;
+
+public class CommercialPaper extends State {
+ private static final String ISSUED = "1";
+ private static final String TRADING = "2";
+ private static final String REDEEMED = "3";
+
+ @Property(key=true)
+ private String issuer;
+
+ @Property
+ private String owner;
+
+ @Property(key=true)
+ private String paperNumber;
+
+ @Property
+ private String issueDateTime;
+
+ @Property
+ private String maturityDateTime;
+
+ @Property
+ private String faceValue;
+
+ @Property(name="currentState")
+ private String status;
+
+ private CommercialPaper(byte[] buffer) {
+ super(buffer);
+ }
+
+ public static CommercialPaper create(byte[] buffer) {
+ return new CommercialPaper(buffer);
+ }
+
+ public String getOwner() {
+ return owner;
+ }
+
+ public void setOwner(String owner) {
+ this.owner = owner;
+ }
+
+ public String getIssuer() {
+ return issuer;
+ }
+
+ public void setIssued() {
+ status = ISSUED;
+ }
+
+ public void setTrading() {
+ status = TRADING;
+ }
+
+ public void setRedeemed() {
+ status = REDEEMED;
+ }
+
+ public boolean isIssued() {
+ return status == ISSUED;
+ }
+
+ public boolean isTrading() {
+ return status == TRADING;
+ }
+
+ public boolean isRedeemed() {
+ return status == REDEEMED;
+ }
+
+}
diff --git a/commercial-paper/pom.xml b/commercial-paper/pom.xml
new file mode 100644
index 00000000..f67d8f6c
--- /dev/null
+++ b/commercial-paper/pom.xml
@@ -0,0 +1,33 @@
+
+ 4.0.0
+ commercial-paper
+ commercial-paper
+ 0.0.1-SNAPSHOT
+
+ organization/digibank/application-java
+
+
+ maven-compiler-plugin
+ 3.8.0
+
+ 1.8
+ 1.8
+
+
+
+
+
+
+ hyperledger
+ Hyperledger Nexus
+ https://nexus.hyperledger.org/content/repositories/snapshots
+
+
+
+
+ org.hyperledger.fabric
+ fabric-gateway-java
+ 1.4.0-SNAPSHOT
+
+
+
\ No newline at end of file