Hyperledger Composer is an application development framework which simplifies and expedites the creation of Hyperledger fabric blockchain applications.
What we are going to develop is a payment system where a bank can issue asset / currency to a user. And user can transfer from his/her account to another account.
- Open Chrome Browser (Download and Install chrome by visiting https://www.google.com/chrome/)
- Visit https://composer-playground.mybluemix.net/ to start developing blockchain application using Hyperledger Composer.
We have to define a business network (nodes) and it's policies to start with the development process.
- Click on Deploy a New Business Network
- Give the informations as follows. Here we are defining the network parameters.
- Business Network Name - payment-system
- Description - Any random Description
- Network Admin Card - Leave it blank
- Model Network Starter Template - Select empty-business-network
Now you can see a screen with your business network in it.
Click Connect Now
to start the business network.
You will get a screen as follows.
The Hyperledger Composer is mainly consist of 4 building blocs.
CTO File
- Here we defines, Assets, Participants and various Transactions associated with the application.ACL File
- It's an access control file where we define various access permissions and policies to operate on the network.JS File
- It's a script file, Used to operate various functionalities on the ledger.QRY File
- Used to implement querying for ledger.
First we are going to do is defining Asset, Participants and Transaction models in the model.cto
file.
- Define the namespace as
com.netobjex.payment
- Defining Currency as asset.
asset Currency identified by currencySymbol {
o String currencyName
o String currencySymbol
o String currencyDescription
o Integer liquidity
}
Generic Structure for Asset Definition - Do not Use in code
// String, Integer, Double, State, DateTime, Boolean
asset AssetName identified by keyword {
o dataType fieldName
}
- Defining Participants model
participant User identified by userID {
o String userID
o String firstName
o String lastName
o Integer balance
}
Generic Structure for Participant Definition - Do not Use in code
// String, Integer, Double, State, DateTime, Boolean
participant ParticipantModel identified by keyword {
o dataType fieldName
}
- Defining Transaction
transaction Issue {
--> Currency currency // Inheriting the model of Currency to currency
--> User recipientUser // Inherting the model of User to recipientUser
o Integer amount
}
Generic Structure for Transaction Definition - Do not Use in code
// String, Integer, Double, State, DateTime, Boolean
transaction TransactionName {
o dataType fieldName
}
- Click on Add a file to Include a script file. Name it as
issue.js
- Here we are going to define the definition for Issue. (The transaction we defined above)
/**
* Issue money from bank to a user
* @param {com.netobjex.payment.Issue} issue - issue of money to user
* @transaction
*/
async function issueMoney(issue) {
issue.recipientUser.balance = issue.amount // Updating the Balance with Input Amount.
let participantRegistry = await getParticipantRegistry('com.netobjex.payment.User'); // Retrieving Participant Registry
await participantRegistry.update(issue.recipientUser);
}
Currently the problem is, balance is overwriting rather than adding it into the existing balance.
Let's modify the issueMoney
function in issue.js
file slightly to add more functionality.
async function issueMoney(issue) {
const currentBalance = issue.recipientUser.balance
issue.recipientUser.balance = issue.amount + currentBalance
let participantRegistry = await getParticipantRegistry('com.netobjex.payment.User');
await participantRegistry.update(issue.recipientUser);
}
Let's do a validation now, to check whether the issuer have enough fund before issuing the amount.
async function issueMoney(issue) {
const liquidity = issue.currency.liquidity
const currentBalance = issue.recipientUser.balance
if(liquidity >= issue.amount) {
issue.recipientUser.balance = issue.amount + currentBalance
issue.currency.liquidity = liquidity - issue.amount
} else {
alert("Insufficient fund in Bank")
}
let participantRegistry = await getParticipantRegistry('com.netobjex.payment.User');
let assetRegistry = await getAssetRegistry('com.netobjex.payment.Currency');
await participantRegistry.update(issue.recipientUser);
await assetRegistry.update(issue.currency);
}
First we have to define the transaction model. For that open model.cto and add following code.
- Model definition
transaction Transfer {
--> User sender
--> User receiver
o Integer amount
}
- Defining the transaction
Now we have to define the transaction based on the model defined.
Add a new script file. Name it as
transfer.js
/**
* Transfer of fund from one user to another
* @param {com.netobjex.payment.Transfer} transfer - fund transfer between users
* @transaction
*/
async function fundTransfer(transfer) {
const senderBalance = transfer.sender.balance
const receiverBalance = transfer.receiver.balance
if(senderBalance >= transfer.amount) {
transfer.receiver.balance = recieverBalance + transfer.amount
transfer.sender.balance = senderBalance - transfer.amount
} else {
alert("Insufficient fund")
}
let participantRegistry = await getParticipantRegistry("com.netobjex.payment.User")
await participantRegistry.update(transfer.receiver)
await participantRegistry.update(transfer.sender)
}
- Deploy and Test like we did before.