Dummies Guide to Querying a Hyperledger Fabric Blockchain Network with ExpressJS | Skcript

(S//Bot) #1

At the heart of a blockchain network is a distributed ledger that records all the transactions that take place on the network. A blockchain ledger is often described as decentralized because it is replicated across many network participants, each of whom collaborate in its maintenance.

Queries are how you read data from the ledger. This data is stored as a series of key-value pairs, and you can query for the value of a single key, multiple keys, or – if the ledger is written in a rich data storage format like JSON – perform complex searches against it (looking for all assets that contain certain keywords, for example).

This is a representation of how a query works:

Querying a ledger (Source: Hyperledger Fabric)

Pre Requisites

We will be using the official fabcar chaincode of the Hyperledger Fabric Samples in this article. Before proceeding with the article, I will assume that you have set up the Dev Environment, downloaded the fabric-samples, and a network is running on your machine.

After downloading the fabric samples, navigate to the fabcar subdirectory within the fabric-samples directory. Run npm install to install the required fabric dependencies and launch the network by running the shell script against the chaincode written in NodeJS (./startFabric.sh node)

Setting up the project

As the first step in any project, we will be creating the folder and the file structures.

mkdir myapp cd myapp touch index.js npm install express fabric-ca-client fabric-client --save

The packages fabric-ca-client & fabric-client are the ones which help us to interact with the Fabric network and express is to create the web server for RESTFul API .

Since we will be mainly dealing with querying the ledger. I recommend you to refer Varun’s article. To make it to work with our fabcar chaincode, make sure that you edit the model class file and add the following function,

invoke() { let tx_id = this.connection.newTransactionID(); let requestData = { chaincodeId: 'fabcar', fcn: 'initLedger', args: [], txId: tx_id, chainId: 'mychannel', }; return this.connection.submitTransaction(requestData); }

The above function will call the initLedger fuction in the chaincode. This function will insert a set of record into the Ledger which contains the details about cars.

Now, set up the server in index.js file and write the following end point:

app.post('/api/invoke', function(req, res) { let exampleNetwork = new ExampleNetwork("admin"); exampleNetwork.init().then(function(data) { return exampleNetwork.invoke() }).then(function (data) { res.status(200).json({response : data}) }).catch(function(err) { res.status(500).json({error: err.toString()}) }) })

The above endpoint will make a call to the invoke function which will insert the record into the ledger.

Querying the Ledger

Set up the endpoint in order to query the Ledger:

app.post('/api/query', function(req, res) { let exampleNetwork = new ExampleNetwork("admin"); exampleNetwork.init().then(function(data) { return exampleNetwork.query() }).then(function (data) { res.status(200).json({response : data}) }).catch(function(err) { res.status(500).json({error: err.toString()}) }) })

After setting up the endpoint in the index.js file, let’s make a call to the Ledger by invoking the function in the chaincode. Thus the endpoint will call the query method in the model class which will in turn call the function of the chaincode to query data. Add the following function in the model class file,

query() { let requestData = { chaincodeId: 'fabcar', fcn: 'queryAllCars', args: [''] }; return this.connection.query(requestData); }

In the Config/FabricClient.js file, we have written a function to clean the data that were retrieved from the Ledger. The above function will call the following function which resides in the FabricClient.js file,

query(requestData) { let channel = this.getChannel(); return channel.queryByChaincode(requestData).then((response_payloads) => { let resultData = JSON.parse(response_payloads.toString('utf8')); return resultData; }).then(function(resultData) { if (resultData.constructor === Array) { resultData = resultData.map(function (item, index) { if (item.data) { return item.data } else { return item; } }) } return resultData; }); }

The above function will first get the corresponding channel and makes a call to the chaincode function. The function will return the payload. The payload is the list of all the cars that are available in the ledger. Since the payload will be in the form of a string, we will parse it using JSON.parse to convert it to a javascript object. If the payload is an array, we retrieve the data and store it in the resultData variable. If it is not an array, we directly return the retrieved payload instead.

And that’s all there is to it! While there are many JS clients you can use to expose Hyperledger Fabric’s APIs, I felt ExpressJS was the most straightforward option. If you’ve used anything else, let me know in the comments section below!

This is a companion discussion topic for the original entry at https://www.skcript.com/svr/querying-hyperledger-fabric-blockchain-network-expressjs/

(Anushaath) #2

Don’t you think that using Hyperledger Composer to generate REST APIs are much easier? By interacting directly with Fabric, you have to first write the chaincode and then write code to create the Express.js server.

(Naveen Honest Raj) #3

Hey @Anushaath,
With Composer’s REST API, you have some restrictions to the generated API endpoint. And comparing Composer with Fabric, Fabric’s performance is really outstanding. Writing a Chaincode in Golang has it’s own Pros which you cannot expect in a Composer’s output. Overall, Yes, if time is your concern you can go with Composer. But Fabric helps you to build a high-performing scalable application overtime.