In this Code Pattern, we'll demonstrate how to simulate a securitization process using React.js, Hyperledger Fabric Node SDK, and an IBM Blockchain service instance.
Securitization is a financial process that can be used to consolidate a set of illiquid assets into a set of tradable securities. A common example of an illiquid asset would be a home mortgage, as they cannot be readily bought and sold. An example of a tradable asset can be a stock or bond. This process can be useful for financial institutions that are looking to increase the liquidity of their assets and free up capital. This application provides a dashboard that will allow users to create and view the relationship between Assets, Pools, Investors, and Securities.
When the reader has completed this Code Pattern, they will understand how to:
- Deploy a Hyperledger Blockchain network on IBM Cloud
- Create and enroll a administrative client using the Hyperledger Node SDK
- Deploy and Instantiate a set of smart contracts to handle transactions and pool assets
-
A homebuyer leverages the services of a Loan Originator to secure financing for a home mortgage
-
The Loan Originator loads the application, and submits requests to update the Blockchain ledger state with a new Asset
This request is handled by the node.js Express backend formats CRUD request into a jsonrpc object like below, and submits it to a Hyperledger peer as a transaction proposal. The request below would register a mortgage with a value of $540000, an interest rate of 3.3%, and a credit score of 720. The credit score is used to calculate risk for potential investors.
{
"jsonrpc": "2.0",
"method": "invoke",
"params": {
"type": "1",
"chaincodeID": {
"name": "securitization_contracts"
},
"ctorMsg": {
"function": 'init_asset',
"args": '["asset1" , "540000", "0.033", "720"]'
},
"secureContext": "[email protected]"
},
"id": "5"
}
-
Peer uses an "endorsement" service to simulate the proposed transaction against the relevant smart contracts. This endorsement service is used to confirm that the transaction is possible given the current state of the ledger. Examples of invalid proposals might be creating an asset that already exists, querying the state of an asset that does not exist, etc.
-
If the simulation is successful, the proposal is then "signed" by the peer's endorser.
-
The signed transaction is forwarded to an ordering service, which executes the transaction. In this case, the newly created "Asset" would be placed in an "Asset Pool"
-
The updated state is committed to the blockchain ledger
-
The Securitization UI queries the updated ledger state and renders tables with the updated information
-
If the Asset Pool has been split up into "Securities", an investor has the ability to buy and sell them. The security price should be updated every time there is a change to the ledger state
-
A creditor checks the ledger state to determine the risk of losses by late payments or mortgages going into default. If a significant change is found, the security credit rating will be recalculated by the creditor and updated in the ledger.
To interact with the hosted offerings, the IBM Cloud CLI will need to be installed beforehand. The latest CLI releases can be found at the link here. An install script is maintained at the mentioned link, which can be executed with one of the following commands
# Mac OSX
curl -fsSL https://clis.ng.bluemix.net/install/osx | sh
# Linux
curl -fsSL https://clis.ng.bluemix.net/install/linux | sh
# Powershell
iex(New-Object Net.WebClient).DownloadString('https://clis.ng.bluemix.net/install/powershell')
After installation is complete, confirm the CLI is working by printing the version like so
ibmcloud -v
# Log in
ibmcloud login
Finally, install the container service plugin, which is required to interact with IBM Kubernetes deployments
ibmcloud plugin install container-service -r Bluemix
# OS X
curl https://storage.googleapis.com/kubernetes-release/release/v1.11.7/bin/darwin/amd64/kubectl -P /usr/local/bin/
# Linux
curl https://storage.googleapis.com/kubernetes-release/release/v1.11.7/bin/linux/amd64/kubectl -P /usr/local/bin/
chmod +x /usr/local/bin/kubectl
kubectl -v
If expecting to run this application locally, please install Node.js and NPM. Currently the Hyperledger Fabric SDK only appears to work with node v8.9.0+, but is not yet supported on node v9.0+. If your system requires newer versions of node for other projects, we'd suggest using nvm to easily switch between node versions. We did so with the following commands
curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.11/install.sh | bash
# Place next three lines in ~/.bash_profile
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" # This loads nvm bash_completion
nvm install v8.9.0
nvm use 8.9.0
To run the Securitization UI locally, we'll need to install a few node libraries which are listed in our package.json
file.
- React.js: Used to simplify the generation of front-end components
- MQTT: Client package to subscribe to Watson IoT Platform and handle incoming messages
- Hyperledger Fabric SDK: Enables backend to connect to IBM Blockchain service
There are two methods we can use to deploy the application, either run everything locally on your development machine, OR initialize a hosted blockchain service and run in IBM Cloud. These separate steps are labeled as local or hosted, respectively
- Provision Blockchain+Kubernetes services in IBM Cloud Platform
- Configure IBM Cloud Services
- Clone repository
- Configure and Deploy application locally OR On IBM Cloud
- Import Service Credentials
- Configure Application
Next, we'll need to deploy our service instances using the IBM Cloud dashboard. This step is only required if you're not deploying the application locally. If you will be running the app and blockchain cluster locally, please skip ahead to the "Clone Repository" section
The IBM Blockchain service can be found by logging in to the IBM Cloud dashboard, selecting the Catalog
button, searching for Blockchain
, and clicking on the resulting icon. Or click this link.
After selecting the blockchain icon, a form will be presented for configuring the service name, region, and pricing plan. The default values for these fields can be left as is. Also, be sure that the free pricing tier is selected, which is titled Starter Membership Plan
. If you are using an IBM Cloud Lite account, this plan can be used for free for up to 30 days. After validating that the information in the form is correct, scroll down and click the Create
button in the lower right corner
Create a Kubernetes cluster here. The free offering will suffice for this demo app. Kubernetes will be used to host a container running the express and react applications
Run the following command to download the configuration file for your cluster. The "mycluster" parameter is the default cluster name (as seen in above screenshot). Be sure to change this parameter if you entered a custom cluster name.
ibmcloud cs cluster-config mycluster
The result of the previous command will download a configuration file which will be used to connect to the Container service. The output will contain an export command like so
export KUBECONFIG=/Users/$USER/.bluemix/plugins/container-service/clusters/mycluster/kube-config-hou02-mycluster.yml
After running the command above, confirm that the kubernetes cli can communicate with the container service by running the following
kubectl get nodes
In this section, we'll be uploading our securitization logic to the Blockchain service.
"Smart contracts", commonly referred to as "Chaincode", can be used to execute business logic and validate incoming requests. In this context, the contracts are used to initialize all participants of the securitization process, define their relationships, and verify transactions. These contracts can be hosted either on IBM Cloud or on a local Hyperledger network managed by Docker.
To begin the process of uploading the smart contracts to the hosted blockchain service, we can start by opening the IBM Cloud dashboard, selecting your provisioned Blockchain service, and accessing the blockchain network monitor by clicking Enter Monitor
Next, click the Install code
option on the left hand menu, and then the Install Chaincode
button on the right of the page
Enter an id and a version (here we'll use "sec" and "v1"). Then, select the Choose Files
button to upload the smart contracts, which are titled lib.go, read_ledger.go, write_ledger.go, and securitization.go. These files are located in the chaincode/src
directory of this project
Finally, we'll need to Instantiate the chaincode. This can be done by opening the chaincode Actions
menu and selecting Instantiate
. This will present a form where arguments can be provided to the chaincode init
function. In this case, we'll just need to provide an integer (we used "101"
) to the Arguments section, then click Next
and then Submit
As an alternative to the hosted IBM Blockchain service, we can deploy a local Hyperledger network using docker-compose like so
git clone https://github.com/hyperledger/fabric-samples.git
cd fabric-samples/chaincode-docker-devmode
# clear your previous network if it exists
docker-compose -f docker-compose-simple.yaml down
# start up a new local hyperledger network
docker-compose -f docker-compose-simple.yaml up
By default, this will stay open and aggregate the logs from the container. If you'd prefer it to run in headless mode, please add the -d
flag to the command
In a separate tab, run the following commands from the root directory of this project to copy the chaincode files into the "chaincode" container, build the binary, and start the chaincode service. The last command will run as a daemon, and will not exit
docker exec -it chaincode mkdir -p securitization
docker cp ./chaincode/src/. chaincode:/opt/gopath/src/chaincode/securitization/
docker exec -it chaincode bash -c 'cd securitization && go build'
docker exec -it chaincode bash -c 'CORE_PEER_ADDRESS=peer:7052 CORE_CHAINCODE_ID_NAME=sec:0 ./securitization/securitization'
In a third tab, run the following commands to install and instantiate the chaincode
docker exec cli peer chaincode install -p chaincodedev/chaincode/securitization -n sec -v 0
docker exec cli peer chaincode instantiate -n sec -v 0 -c '{"Args":["101"]}' -C myc
Finally, run an invoke command to ensure the chaincode was installed successfully
docker exec cli peer chaincode invoke -n sec -c '{"Args":["read_everything"]}' -C myc
Clone the securitization_blockchain
project locally. In a terminal, run:
git clone https://github.com/IBM/securitization_blockchain.git
Deploy the kubernetes application with the following command
kubectl apply -f kubernetes/kube-config.yml
If successful, you should get the following output
Kalonjis-MacBook-Pro:securitization_blockchain [email protected]$ kubectl apply -f kubernetes/kube-config.yml
service/api-service created
pod/securitization-pod created
This may take a few minutes. In a different tab, following along by running the logs
command like so.
kubectl logs -f securitization-pod
We should get output saying the backend and react servers have started. Continue on to access the application
Find the public ip address of the Kubernetes cluster
# Get id of cluster (if it's not the default "mycluster")
ibmcloud ks clusters
# Print workers associated with cluster, take note of public ip
ibmcloud ks workers mycluster
Confirm that the Node.js application is up and running by opening the following
<worker_public_ip>:30000
Install the Securitization UI node packages by running npm install
in the project root directory and in the react-backend directory. Both python
and build-essential
are required for these dependencies to install properly:
# install react dependencies
cd sc-ui
npm install
npm run build
# install express/hyperledger dependencies
cd react-backend
npm install
# return to the root project directory
cd ../../
As an alternative to installing these additional dependencies on your system, you can build the application and dependencies in a docker container like so
docker build -t securitization_blockchain .
NOTE: These steps are only needed when running locally instead of using the
Deploy to IBM Cloud
button.
Make sure the correct version of node is equipped
nvm use 8.9.0
Start the app locally
cd sc-ui
npm start | PORT=3001 node react-backend/bin/www
If you built the application using docker, then simply run
docker run -it -p 30000:30000 -p 30001:30001 -v /var/run/docker.sock:/var/run/docker.sock -v /usr/local/bin/docker:/usr/local/bin/docker securitization_blockchain bash -c 'cd /root/securitization_blockchain/sc-ui ; npm start | PORT=30001 node react-backend/bin/www'
To access the local Securitization application, open the following URL in a browser: http://localhost:30000/
This section is only necessary for working on the hosted IBM Cloud blockchain offering. If deploying locally, you can skip to step #7. The credentials for IBM Cloud Blockchain service can be found in the Services
menu in IBM Cloud by selecting the Service Credentials
option for each service. If using the local network,
The Blockchain credentials consist of the key
, secret
, and network_id
parameters.
We'll also need to provide the Chaincode Id and Version, which is "sec" and "v1" in this example
The credentials will need to be entered in the configuration form, which can be opened by clicking the button in the upper right of the UI
After submitting this form, the UI will fetch a "connection profile" json file, which contains all information needed by our hyperledger client to connect to the blockchain ledger.
Once the connection profile has been retrieved, a certificate will be generated to allow the application to make administrative requests. These elevated privileges are required to make calls to the chaincode service. This PEM encoded certificate will be output in the terminal logs like so. If deploying on IBM Cloud, this certificate can be found parsing the logs using kubectl logs -f securitization-pod
, or by opening the developer console in your browser
Once the PEM certificate is generated, it can be copied and uploaded by visiting the printed url, or by revisiting the Blockchain Monitor, navigating to Members on the left hand menu, and then clicking "Certificates" and "Add Certificate"
The securitization flow generally occurs in the following format
-
A homebuyer will apply for financing of an asset via a loan "originator". The loan will have a balance, interest rate, monthly payment, and expected time period for payback (many mortgages are roughly 30 years). A total expected payoff amount will be generated based off this information as well.
-
Once the loan has been approved and processed, the loan originator then finances the asset, and transfers the debt to a "Special Purpose Vehicle", which is a entity that protects the assets even if the originator goes bankrupt.
-
The Asset is then placed into a "Pool" along with other assets. Once Assets have been placed into a pool, a set of "securities" can be generated to allow the pool to become tradable. Each Security can be bought and sold by investors, and has a "Yield" which determines the return each security holder will receive on their investment.
-
The Homebuyer submits payments towards their mortgage.
-
Each payment is split up and distributed amongst investors who own "securities" associated with the pool. When all mortgages in the pool are paid off, each investor should have received their original investment back plus the agreed "Yield" amount. Each payment will also have a processing fee which will be dispersed to the originator
This securitization process can be replicated with this application by visiting the dashboard and creating Originators, Assets, Pools, Securities, and Investors using the provided forms. Each form requests an unique id format with the name of the object type followed by an integer asset1, pool123, security15
First, we'll need to create a loan "Originator", which will require an ID, Processing Fee (percentage), and (optional) Company Name. This form can be loaded by selecting the Create Originator
button. (Note: There is a known intermittent issue with this Originator creation process, so the initial submission may fail. If this occurs, please try submitting again)
Note that the Balance and Assets fields in the table are initially blank, but will be filled in as we associate assets with the originator. And as the originator receives processing fees and security sale proceeds, their Balance will increase as well
Next, we'll create an Asset, which will require an outstanding balance, interest rate, and a payment period, which defines how many monthly payments they'll need to pay off their entire balance. This can be done by scrolling directly down to the Assets
Table, clicking the Create New Asset
button.
Once the Asset has been created, we can also link it to an originator using the Transfer Asset
button
The resulting table should then reflect the following
Create an Asset Pool via the Create Pool
form by providing an ID. We can also transfer our asset(s) to the pool using the Transfer Asset
button in the Assets table
Create one or more "Securities". The create security form will require a ID, associated Asset Pool, and "Coupon Rate". The Coupon Rate defines the return on investment.
Finally, we can create our Investors, which have the ability to buy and sell securities. This can be done by clicking the Create Investor
button and providing a unique id. Once the investor is created, we can then buy and sell securities using the respective buttons. So in this example, we'll do so by clicking the Buy Security
button and providing the Security and Investor Id.
Now we can simulate a mortgage payment and view the corresponding payment distributions. We can do so by scrolling back up to the Assets table selecting the "Process Payment" view, and entering an Asset Id and Payment Amount.
Submitting the payment will then:
- Calculate the payment amount allocated to interest and principal
- Adjust the remaining balance
- Calculate and disperse payment amount owed to security holders and originator
Once these calculations are complete, the dashboard tables will then be updated with the latest ledger state
sendPeersProposal - Promise is rejected: Error: 2 UNKNOWN: chaincode error (status: 500, message: Authorization for GETINSTALLEDCHAINCODES on channel getinstalledchaincodes has been denied with error Failed verifying that proposal's creator satisfies local MSP principal during channelless check policy with policy [Admins]: [This identity is not an admin]
This error occurs if the certificate generated by the SDK user has not been uploaded to the peer
Error: The gRPC binary module was not installed. This may be fixed by running "npm rebuild"
grpc
is a requirement for the fabric-client SDK. Confirm that it has been installed in thereact_backend
directory withnpm install [email protected]
error: [client-utils.js]: sendPeersProposal - Promise is rejected: Error: 2 UNKNOWN: chaincode error (status: 500, message: Authorization for GETINSTALLEDCHAINCODES on channel getinstalledchaincodes has been denied with error Failed verifying that proposal's creator satisfies local MSP principal during channelless check policy with policy [Admins]: [This identity is not an admin])
This error occurs if the admin certificate for the hosted IBM Blockchain service has not been uploaded.
Objects are not valid as a React child
This error occurs if one of the Golang structs defined in the chaincode are invalid. These may not have nested objects. To fix this, clear cookies or open a different browser
- Blockchain Patterns: Enjoyed this Code Pattern? Check out our other Blockchain Patterns
This code pattern is licensed under the Apache Software License, Version 2. Separate third party code objects invoked within this code pattern are licensed by their respective providers pursuant to their own separate licenses. Contributions are subject to the Developer Certificate of Origin, Version 1.1 (DCO) and the Apache Software License, Version 2.