FGJ-4 commercial paper client sample

commercial paper sample for Java Gateway SDK (client app)

Change-Id: I80c6b9dbc36631004903244a20e6a492138c7751
Signed-off-by: andrew-coleman <andrew_coleman@uk.ibm.com>
This commit is contained in:
andrew-coleman 2019-07-24 10:17:55 +01:00
parent 8f92861104
commit c57f10f5f6
14 changed files with 554 additions and 0 deletions

View file

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" output="target/classes" path="organization/digibank/application-java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" path="organization/magnetocorp/application-java"/>
<classpathentry kind="src" path="ledger-java-api"/>
<classpathentry kind="src" path="organization/shared/lib-java"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="output" path="target/classes"/>
</classpath>

View file

@ -6,3 +6,5 @@ organization/digibank/contract/node_modules/
organization/digibank/identity/user/
package-lock.json
.vscode
/target/
bin/

View file

@ -0,0 +1,5 @@
package org.example.ledger.api;
public @interface Field {
public String name() default "";
}

View file

@ -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;
}

View file

@ -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<String, String> properties;
protected final Supplier<String> keyBuilder(String[] parts) {
return () -> Arrays.asList(parts).stream().map(part -> getProperty(part)).collect(Collectors.joining(":"));
};
public State(byte[] buffer) {
this.properties = deserialize(buffer);
List<String> keyParts = new ArrayList<String>();
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<String, String> deserialize(byte[] buffer) {
JsonObject json = toJSON(buffer);
Map<String, String> 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<Field> 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();
}
}

View file

@ -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();
}
}
}

View file

@ -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();
}
}
}

View file

@ -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();
}
}
}

View file

@ -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

View file

@ -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();
}
}
}

View file

@ -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();
}
}
}

View file

@ -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

View file

@ -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;
}
}

33
commercial-paper/pom.xml Normal file
View file

@ -0,0 +1,33 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>commercial-paper</groupId>
<artifactId>commercial-paper</artifactId>
<version>0.0.1-SNAPSHOT</version>
<build>
<sourceDirectory>organization/digibank/application-java</sourceDirectory>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>hyperledger</id>
<name>Hyperledger Nexus</name>
<url>https://nexus.hyperledger.org/content/repositories/snapshots</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>org.hyperledger.fabric</groupId>
<artifactId>fabric-gateway-java</artifactId>
<version>1.4.0-SNAPSHOT</version>
</dependency>
</dependencies>
</project>