Private Blockchains: Hyperledger Composer Javascript API
Tags: blockchain, showdev, javascript
Published: 2018-03-26 09:03:53

---
title: Private Blockchains: Hyperledger Composer Javascript API
published: true
description: Building a little command line app with the Hyperledger Composer's Javascript API
tags: blockchain, showdev, javascript
cover_image: https://thepracticaldev.s3.amazonaws.com/i/h78las99wxj3o6thi3d4.png
canonical_url: https://www.damiencosset.com/private-blockchains-hyperledger-composer-javascript-api/
---

## Introduction

In my [last article](https://dev.to/damcosset/getting-started-with-hyperledger-composer-and-private-blockchains--36ab), I gave a quick overview of the Hyperledger Composer framework to build a business network with a private blockchain technology. I used a land registry network to show how the framework works. We then used a React application to use the REST API provided. 

This time, instead of using the REST API, I made a little command line application using the Javascript API. The concept is simple. You enter commands in your terminal to trigger actions ( retrieve data, create assets and/or transactions ). We will re-use the same land registry network I used in the previous article.


## Connecting to the composer runtime

First, we need to have our private blockchain running. If you haven't gone through my [last article](https://dev.to/damcosset/getting-started-with-hyperledger-composer-and-private-blockchains--36ab) to set up your environment, you need to do it right now.

If you went through the article, you need to run a few commands to launch the runtime:

- First, you need to launch the `./startFabric.sh` command from the folder I called *fabric-tools* in the last article.

- Next, from the *land-registry* folder, you need to install the composer runtime: `composer network install --card PeerAdmin@hlfv1 --archiveFile land-registry@0.0.1.bna`

- Finally, still from the *land-registry* folder, deploy the business network: `composer network start --networkName land-registry --networkVersion 0.0.1 --networkAdmin admin --networkAdminEnrollSecret adminpw --card PeerAdmin@hlfv1 --file networkadmin.card`

And that's all you need, assuming you've done all the steps in the previous article before. If you only do those three commands without setting a proper environment, it will obviously not work.

## The code

*Note:* I will link to the Github repository at the end of this article. 

The application is rather simple. There is an *index.js* file.

```javascript
const shell = require('shelljs')
const args = process.argv.slice(2)
const getREregistry = require('./getREregistry')
const getPIregistry = require('./getPIregistry')
const getPI = require('./getPI')
const contractLoan = require('./contractLoan')
const getLoans = require('./getLoans')
const getBanks = require('./getBanks')
const createPI = require('./createPI')
const createRE = require('./createRE')
const contractInsurance = require('./contractInsurance')
const getInsurances = require('./getInsurances')
const buyRealEstate = require('./buyRealEstate')
const getREAgents = require('./getREAgents')
const getNotaries = require('./getNotaries')

// get first argument
let arg = args.shift()
let realEstateId, duration, bankId, privateId, address, insuranceId

switch( arg ){
	case 'getAllRE':
		shell.exec('node getREregistry.js')
		process.exit()
		break
	case 'getAllPI': 
		shell.exec('node getPIregistry.js')
		process.exit()
		break
	case 'getREAgents':
		shell.exec('node getREAgents.js')
		process.exit()
		break
	case 'getInsurances':
		shell.exec('node getInsurances.js')
		process.exit()
		break
	case 'getNotaries': 
		shell.exec('node getNotaries.js')
		process.exit()
		break
	case 'getPI':
		const id = args.shift()
		shell.exec(`node getPI.js ${id}`)
		process.exit()
		break
	case 'getLoans':
		shell.exec('node getLoans.js')
		process.exit()
		break
	case 'getBanks':
		shell.exec('node getBanks.js')
		process.exit()
		break
	case 'createPI':
		privateId = args.shift()
		let name = args.shift()
		address = args.shift()
		let balance = args.shift()
		shell.exec(`node createPI.js ${privateId} ${name} ${address} ${balance}`)
		process.exit()
		break
	case 'createRE':
		let reId = args.shift()
		address = args.shift()
		let reSquareMeters = args.shift()
		let price = args.shift()
		let ownerId = args.shift()
		shell.exec(`node createRE.js ${reId} ${reAddress} ${reSquareMeters} ${price} ${ownerId}`)
		process.exit()
		break
	case 'contractLoan':
		let debtorId = args.shift()
		let bankId = args.shift()
		realEstateId = args.shift()
		let insterestRate = args.shift()
		duration = args.shift()
		shell.exec(`node contractLoan.js ${debtorId} ${bankId} ${realEstateId} ${insterestRate} ${duration}`)
		process.exit()
		break
	case 'contractInsurance':
		let insuredId = args.shift()
		insuranceId = args.shift()
		realEstateId = args.shift()
		cost = args.shift()
		duration = args.shift()
		shell.exec(`node contractInsurance.js ${insuredId} ${insuranceId} ${realEstateId} ${cost} ${duration}`)
		process.exit()
		break
	case 'buyRealEstate':
		let buyer = args.shift()
		let seller = args.shift()
		realEstateId = args.shift()
		let loan = args.shift()
		let realEstateAgent = args.shift()
		let notary = args.shift()
		insuranceId = args.shift()
		shell.exec(`node buyRealEstate.js ${buyer} ${seller} ${realEstateId} ${loan} ${realEstateAgent} ${notary} ${insuranceId}`)
		process.exit()
		break
	default:
		console.log('Wrong argument')
		process.exit()
		break
}

shell.exec('node index.js')
```

### A GET route

We use *shelljs* to interact with the terminal. Depending on the argument you provide, we will execute a certain action. Some actions, when creating an asset or a participant, require additional arguments. Let's look at the *getAllPI* argument. *PI* stands for Private Individual, a participant in our network. When we provide this argument, we are going to retrieve every single Private Individual participant in the network. The action is described in the *getPIRegistry.js* file:

```javascript
const BusinessNetworkConnection = require('composer-client').BusinessNetworkConnection
const Table = require('cli-table2')

const getPIregistry = (async function(){
	
	try {
		this.bizNetworkConnection = new BusinessNetworkConnection()
		let connection = await this.bizNetworkConnection.connect('admin@land-registry')
		let registry = await this.bizNetworkConnection.getParticipantRegistry('org.acme.landregistry.PrivateIndividual')
		let resources = await registry.getAll()
		let table = new Table({
			head: ['ID', 'Name', 'Address', 'Balance']
		})
		let arrayLength = resources.length
		for(let i = 0; i < arrayLength; i++) {
			let tableLine = []
			tableLine.push(resources[i].id)
			tableLine.push(resources[i].name)
			tableLine.push(resources[i].address)
			tableLine.push(resources[i].balance)
			table.push(tableLine)
		}
		console.log(table.toString())
		process.exit()
			
	} catch(error) {
		console.log(error)
		process.exit()
	}
}())

module.exports = getPIregistry
```

In order to interact with the Javascript API, we need only one package: `composer-client`. The structure is the same in every file. We connect to the private blockchain using the *admin@land-registry* admin card. I've put everything inside a IIFE ( Immediately Invoked Function Expression ) and I used the async/await keywords to make it clearer. The Javascript API uses promises, so you can chain the .then methods if you wish.

In our *getPIRegistry* file, we get the participant registry and call the *getAll* method on it. This will retrieve all the Private Individual participants. We then used the *cli-table2* package to display the data in a nice table in our terminal.


### A POST route

##### Create a Real Estate asset

To create a real estate asset, we use a command like this:

`node index.js createRE id address squareMeters price ownerId`

We need 5 parameters to create such an asset. The code is in the *createRE.js* file:

```javascript
const BusinessNetworkConnection = require('composer-client').BusinessNetworkConnection

const createRE = (async function(){
	try {
		this.bizNetworkConnection = new BusinessNetworkConnection()
		let connection = await this.bizNetworkConnection.connect('admin@land-registry')
		const args = process.argv.slice(2)
		const reId = args.shift()
		const address = args.shift()
		const squareMeters = args.shift()
		const price = args.shift()
		const ownerId = args.shift()
		let factory = connection.getFactory()
		let re = factory.newResource('org.acme.landregistry', 'RealEstate', reId)
		re.address = address
		re.squareMeters = parseFloat(squareMeters)
		re.price = parseFloat(price)

		this.reRegistry = await this.bizNetworkConnection.getAssetRegistry('org.acme.landregistry.RealEstate')

		let ownerRelationship = factory.newRelationship('org.acme.landregistry', 'PrivateIndividual', ownerId)
		re.owner = ownerRelationship

		await this.reRegistry.add(re)
		console.log('Real Estate asset created!')
		process.exit()

	}catch( err ){
		console.log(err)
		process.exit()
	}
})()

module.exports = createRE

```

After the initial connection to the blockchain network, we retrieve the arguments we need. Then, we create a *factory* to create a new resource, in this case a RealEstate asset. We specify the relationship between the PrivateIndividual participant and this new RealEstate asset. Finally, after retrieving the RealEstate registry, we call the add method.

*Note:* You can add several assets or participants at once with the *addAll* method. This methods takes an array of the resources you want to add to the blockchain.

#### Submit a transaction

Last but not least, I will show you how to submit a transaction. The transaction will be triggered by this command:

`node index.js buyRealEstate buyerId sellerId realEstateId loanId realEstateAgentId notaryId insuranceId`

We need a few more arguments to complete this transaction, because there are quite a few relationships. You can go back to the [previous article](https://dev.to/damcosset/getting-started-with-hyperledger-composer-and-private-blockchains--36ab) if you want to take a look at the business model we are using.

*buyRealEstate.js*

```javascript
const BusinessNetworkConnection = require('composer-client').BusinessNetworkConnection

const contractInsurance = (async function(){
	try{
		this.bizNetworkConnection = new BusinessNetworkConnection()
		let connection = await this.bizNetworkConnection.connect('admin@land-registry')
		const args = process.argv.slice(2)
		const pIdBuyer = args.shift()
		const pIdSeller = args.shift()
		const realEstateId = args.shift()
		const loanId = args.shift()
		const realEstateAgentId = args.shift()
		const notaryId = args.shift()
		const insuranceId = args.shift()
		let transaction = {
			"$class": "org.acme.landregistry.BuyingRealEstate"
		}
		transaction.buyer = pIdBuyer
		transaction.seller = pIdSeller
		transaction.realEstate = realEstateId
		transaction.loan = loanId
		transaction.realEstateAgent = realEstateAgentId
		transaction.notary = notaryId
		transaction.insurance = insuranceId
		transaction.isNewOwnerMainResidence = false

		let serializer = connection.getSerializer()
		let resource = serializer.fromJSON(transaction)
		await this.bizNetworkConnection.submitTransaction(resource)
		console.log('Transaction Completed!')
		process.exit()
	}catch( err ){
		console.log(err)
		process.exit()
	}
})()

module.exports = contractInsurance
```

We start off the same, connecting to the blockchain and retrieving arguments. We then create a transaction object. Notice the *$class* key in the object. We get the serializer to transform our JSON into a resource Composer can understand. Finally we call the *submitTransaction* method.

Of course, before doing this transaction, you would need to contract a loan and an insurance. Both transactions can be created via the command line and you will find the code in the Github repository. To keep things short, I only show a few actions here.

*Note:* You could ( should ) add some validations in some actions ( make sure a Participant exists for example before specifying it in a transaction... ). I'll let you do that ;)

## Repository

The code can be found [here](https://github.com/Tagada85/Land-Registry-HyperledgerComposer). Feedbacks welcome :)

Have fun!