diff --git a/java-samples/corda5-obligation-cordapp/README.md b/java-samples/corda5-obligation-cordapp/README.md new file mode 100644 index 0000000..24a030c --- /dev/null +++ b/java-samples/corda5-obligation-cordapp/README.md @@ -0,0 +1,89 @@ +# C5-Obligation-CorDapp + +This app is our signature CorDapp that we use to show the main functionalities of Corda, which are creating a digital asset, +updating the digital asset, and transferring the digital asset. This app depicts a simple use +case of money borrowing between two parties. In the app, the borrowed asset is called the `IOUState` (I-owe-you) +and it is quantifiable. + +In this app you can: +1. Create a new IOUState with a counterparty. `IOUIssueFlow` +2. List out the IOU entries you had. `ListIOUFlow` +3. Settle(pau back) the IOUState `IOUSettleFlow` +4. Lender transfer the debt to a different person `IOUTransferFlow` + +### Setting up + +1. We will begin our test deployment with clicking the `startCorda`. This task will load up the combined Corda workers in docker. + A successful deployment will allow you to open the REST APIs at: https://localhost:8888/api/v1/swagger#. You can test out some + functions to check connectivity. (GET /cpi function call should return an empty list as for now.) +2. We will now deploy the cordapp with a click of `5-vNodeSetup` task. Upon successful deployment of the CPI, the GET /cpi function call should now return the meta data of the cpi you just upload + + + +### Running the app + +In Corda 5, flows will be triggered via `POST /flow/{holdingidentityshorthash}` and flow result will need to be view at `GET /flow/{holdingidentityshorthash}/{clientrequestid}` +* holdingidentityshorthash: the id of the network participants, ie Bob, Alice, Charlie. You can view all the short hashes of the network member with another gradle task called `ListVNodes` +* clientrequestid: the id you specify in the flow requestBody when you trigger a flow. + +#### Step 1: Create IOUState between two parties +Pick a VNode identity to initiate the IOU creation, and get its short hash. (Let's pick Alice. Don't pick Bob because Bob is the person who alice will borrow from). + +Go to `POST /flow/{holdingidentityshorthash}`, enter the identity short hash(Alice's hash) and request body: +``` +{ + "clientRequestId": "createiou-1", + "flowClassName": "com.r3.developers.samples.obligation.workflows.IOUIssueFlow", + "requestBody": { + "amount":"20", + "lender":"CN=Bob, OU=Test Dept, O=R3, L=London, C=GB" + } +} +``` + +After trigger the create-IOUflow, hop to `GET /flow/{holdingidentityshorthash}/{clientrequestid}` and enter the short hash(Alice's hash) and client request id to view the flow result + +#### Step 2: List created IOU state +In order to continue the app logics, we would need the IOU ID. This step will bring out all the IOU entries this entity (Alice) has. +Go to `POST /flow/{holdingidentityshorthash}`, enter the identity short hash(Alice's hash) and request body: +``` +{ + "clientRequestId": "list-1", + "flowClassName": "com.r3.developers.samples.obligation.workflows.ListIOUFlow", + "requestBody": {} +} +``` +After trigger the list-IOUs flow, again, we need to hop to `GET /flow/{holdingidentityshorthash}/{clientrequestid}` and check the result. Let's record that id. + + +#### Step 3: Partially settle the IOU with `IOUSettleFlow` +In this step, we will partially settle the IOU with some amount. +Goto `POST /flow/{holdingidentityshorthash}`, enter the identity short hash and request body. Note that the settle action can only be initiated by the borrower of the IOU +``` +{ + "clientRequestId": "settleiou-1", + "flowClassName": "com.r3.developers.samples.obligation.workflows.IOUSettleFlow", + "requestBody": { + "amountSettle":"10", + "iouID":" ** fill in id **" + } +} +``` +And as for the result of this flow, go to `GET /flow/{holdingidentityshorthash}/{clientrequestid}` and enter the required fields. + +#### Step 4: Lastly, the lender of the IOU can transfer the IOU to a different owner. +Note this transfer action can only be initiated by the lender of the IOU. We will have Bob transfer his IOU to Charlie. +We will now take Bob's shorthash and enter the following request Body. +``` +{ + "clientRequestId": "transferiou-1", + "flowClassName": "com.r3.developers.samples.obligation.workflows.IOUTransferFlow", + "requestBody": { + "newLender":"CN=Charlie, OU=Test Dept, O=R3, L=London, C=GB", + "iouID":" ** fill in id **" + } +} +``` +And as for the result, you need to go to the Get API again and enter the short hash and client request ID. + +Thus, we have concluded a full run through of the obligation app. diff --git a/java-samples/encumbrance-pawn-shop/workflows/src/main/java/com/r3/developers/samples/encumbrance/workflows/CreateAssetFlow.java b/java-samples/encumbrance-pawn-shop/workflows/src/main/java/com/r3/developers/samples/encumbrance/workflows/CreateAssetFlow.java new file mode 100644 index 0000000..5fe3b91 --- /dev/null +++ b/java-samples/encumbrance-pawn-shop/workflows/src/main/java/com/r3/developers/samples/encumbrance/workflows/CreateAssetFlow.java @@ -0,0 +1,81 @@ +package com.r3.developers.samples.encumbrance.workflows; + +import com.r3.developers.samples.encumbrance.contracts.AssetContract; +import com.r3.developers.samples.encumbrance.states.Asset; +import com.r3.developers.samples.encumbrance.states.Member; +import net.corda.v5.application.flows.ClientRequestBody; +import net.corda.v5.application.flows.ClientStartableFlow; +import net.corda.v5.application.flows.CordaInject; +import net.corda.v5.application.marshalling.JsonMarshallingService; +import net.corda.v5.application.membership.MemberLookup; +import net.corda.v5.application.messaging.FlowMessaging; +import net.corda.v5.base.annotations.Suspendable; +import net.corda.v5.base.exceptions.CordaRuntimeException; +import net.corda.v5.ledger.common.NotaryLookup; +import net.corda.v5.ledger.utxo.UtxoLedgerService; +import net.corda.v5.ledger.utxo.transaction.UtxoSignedTransaction; +import net.corda.v5.ledger.utxo.transaction.UtxoTransactionBuilder; +import net.corda.v5.membership.MemberInfo; +import net.corda.v5.membership.NotaryInfo; +import org.jetbrains.annotations.NotNull; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.time.Duration; +import java.time.Instant; +import java.util.Collections; +import java.util.UUID; + +public class CreateAssetFlow implements ClientStartableFlow { + private final static Logger log = LoggerFactory.getLogger(CreateAssetFlow.class); + @CordaInject + private JsonMarshallingService jsonMarshallingService; + @CordaInject + private MemberLookup memberLookup; + @CordaInject + private NotaryLookup notaryLookup; + @CordaInject + private UtxoLedgerService ledgerService; + + @NotNull + @Override + @Suspendable + public String call(@NotNull ClientRequestBody requestBody) { + try{ + CreateAssetFlowArgs flowArgs = requestBody.getRequestBodyAs(jsonMarshallingService, CreateAssetFlowArgs.class); + MemberInfo myInfo = memberLookup.myInfo(); + NotaryInfo notary = notaryLookup.getNotaryServices().iterator().next(); + + Asset asset = new Asset( + new Member(myInfo.getName(), myInfo.getLedgerKeys().get(0)), + flowArgs.getAssetName(), + UUID.randomUUID().toString(), + Collections.singletonList(myInfo.getLedgerKeys().get(0)) + ); + UtxoTransactionBuilder transactionBuilder = ledgerService.createTransactionBuilder() + .setNotary(notary.getName()) + .setTimeWindowBetween(Instant.now(), Instant.now().plusMillis(Duration.ofMinutes(5).toMillis())) + .addOutputState(asset) + .addCommand(new AssetContract.Create()) + .addSignatories(asset.getOwner().getLedgerKey()); + UtxoSignedTransaction signedTransaction = transactionBuilder.toSignedTransaction(); + UtxoSignedTransaction finalizedTransaction = + ledgerService.finalize(signedTransaction, Collections.emptyList()).getTransaction(); + + return finalizedTransaction.getId().toString(); + }catch (Exception e){ + log.warn("Failed to process flow for request body " + requestBody + " because: " + e.getMessage()); + throw new CordaRuntimeException(e.getMessage()); + } + } +} + +/* Example JSON to put into REST-API POST requestBody +{ + "clientRequestId": "create-asset", + "flowClassName": "com.r3.developers.samples.encumbrance.workflows.CreateAssetFlow", + "requestBody": { + "assetName": "My Asset" + } +} +*/ \ No newline at end of file