In order to create an Todo List app that is backed by Blockchain on Mac OSX, you need to install certain prerequisites for Hyperledger Composer.
On any system, before proceeding any further, make sure that you have the following dependencies installed:
- OSX Only -- Install Xcode
- Docker version 17.03 or later
- Docker-compose version 1.11.2 or later
- Node.js version 8.9 or higher
- npm v5.x
- Python 2.7.x
- Hyperledger Composer version 0.19.0 or later
- Yeoman Generator version 2.0 or later
Once you have Docker and Docker-compose installed, you can download and and start Hyperledger Fabric v1.1 as shown below:
$ cd ~/Workdir
$ git clone https://github.com/sanjay-saxena/todolist-network
$ cd ~/Workdir/todolist-network
$ export FABRIC_VERSION=hlfv11 // Add it the ~/.bash_profile
$ npm install
$ ./fabric-tools/downloadFabric.sh
$ ./fabric-tools/startFabric.sh
$ ./fabric-tools/createPeerAdminCard.sh
The aforementioned steps download Hyperledger Fabric v1.1 docker images and start an instance of Hyperledger Fabric on your machine. Furthermore, a network card for PeerAdmin
identity is created for the instance and the card is imported to the Certificate Authority that is part of the running instance.
Hyperledger Composer provides higher-level abstractions to hide the complexity of the blockchain technologies that are implemented as part of Hyperledger Fabric. A Blockchain app that is built by Hyperledger Composer relies on a Business Network
as an abstraction that helps orchestrate the transfer of assets. A Business Network
comprises of Business Model
, Business Logic
, and Access Control Lists
.
The following sections provide the steps for creating the Todo List app backed by Blockchain. The Todo List Business Network is extremely simple and does not have support for authentication or authorization and so it will only contain the Business Model
and Business Logic
and there is no Access Control Lists
defined in the network. The repo includes some scripts for creating a Business Network Archive(.bna), deploying the archive to Hyperledger Fabric, etc. for convenience.
Business Model consists of Participants
, Assets
, and Transactions
. It is expressed using a Domain Specific Language called Concerto. A very simple business model for Todo List is defined in models/todo.cto.
The model consists of Task
type representing an Asset
. A Task
is uniquely identified using it's id
. It also has state
, description
, assignee
, and creator
attributes.
asset Task identified by id {
o String taskId
o String name
o String tags
o TaskState state
--> User assignee optional
--> User createdBy
--> User lastUpdatedBy optional
...
}
The model also contains Admin
and Superhero
types representing Participants
in the network:
participant User identified by email {
o String email
o String firstName
o String lastName
o String password
...
}
A participant is uniquely identified by his/her email
.
The model also defines Transaction
types and some of them are shown below:
transaction Bootstrap {
}
transaction AssignTask {
--> Task task
--> User assignee
...
}
transaction CreateTask {
....
--> Task task
}
transaction CompleteTask {
--> Task task
...
}
....
The transactions are used to trigger the Business Logic.
Hyperledger Composer allows Business Logic to be implemented using Javascript and provides a rich set of APIs to update and query the world state.
The business logic for the Todo List Business Network is implemented in lib/logic.js. For each of the three transaction types that are defined in the model, there is a corresponding transaction processor function that implements the business logic for that transaction.
For example, when the Bootstrap
transaction is submitted, Hyperledger Composer runtime will eventually invoke the following onBootstrap()
function:
/**
* Bootstrap items for convenience.
* @param {org.example.todolist.Bootstrap} txn -- Bootstrap transaction
* @transaction
*/
function onBootstrap(txn) {
....
var factory = getFactory();
// Admin
var bossman = factory.newResource('org.example.todolist',
'User',
'bobby.da.boss@example.com');
bossman.firstName = "Bobby";
bossman.lastName = "Da Boss";
admins.push(bossman);
var catwoman = factory.newResource('org.example.todolist',
'User',
'catwoman@example.com');
catwoman.firstName = "Selina";
catwoman.lastName = "Kyle";
superheroes.push(catwoman);
var batman = factory.newResource('org.example.todolist',
'User',
'batman@example.com');
batman.firstName = "Bruce";
batman.lastName = "Wayne";
superheroes.push(batman);
....
var task1 = factory.newResource('org.example.todolist',
'Task',
'T1');
task1.description = "Build a Bat Mobile!";
task1.state = 'ACTIVE';
task1.creator = bossmanForeignKey;
tasks.push(task1);
....
return getParticipantRegistry('org.example.todolist.User')
.then(function(participantRegistry) {
userRegistry = participantRegistry;
return userRegistry.addAll(users);
})
.then(function() {
return getAssetRegistry('org.example.todolist.Task');
})
.then(function(assetRegistry) {
taskRegistry = assetRegistry;
return taskRegistry.addAll(tasks);
})
.catch(function (error) {
console.log(error);
throw error;
})
;
}
which implements the business logic for Bootstrap
transaction. The onBootstrap()
function creates an Admin
instance for bobby.da.boss
and Superhero
instances for batman
, catwoman
, spiderman
, and superman
as participants. It also creates some Task
instances to represent assets. The world state is populated using the assets and the participants and the Bootstrap
transaction is added to the immutable ledger.
So, bobby.da.boss
(our admin) can assign a task to a specific superhero by submitting the AssignTask
transaction. As a result, Hyperledger Composer runtime will invoke the following onAssignTask()
function:
/**
* Assigns the item/task to a user.
* @param {org.example.todolist.AssignTask} txn -- AssignTask transaction
* @transaction
*/
function onAssignTask(txn) {
....
task.assignee = txn.taskAssignee;
task.state = 'ACTIVE';
....
return getAssetRegistry('org.example.todolist.Task')
.then(function(assetRegistry) {
assetRegistry.update(txn.task);
}
);
}
which updates the task's assignee field and updates the world state appropriately and the AssignTask
transaction gets added to the immutable ledger.
And, when a superhero completes a task, he/she can submit the CompleteTask
transaction. This will result in Hyperledger Composer invoking the following onCompleteTask()
function:
/**
* Marks the item/task as COMPLETED once it has been successfully dealt with.
* @param {org.example.todolist.CompleteTask} txn -- CompleteTask transaction
* @transaction
*/
function onCompleteTask(txn) {
....
task.state = 'COMPLETED';
....
return getAssetRegistry('org.example.todolist.Task')
.then(function(assetRegistry) {
assetRegistry.update(txn.task);
}
);
}
where the task is updated, world state reflects the change, and the CompleteTask
transaction gets added to the immutable ledger.
So, the changes to the world state are triggered in response to transactions being submitted and validated. And, eventually the transaction gets added to the immutable ledger.
Once the Business Model and Business Logic is ready, they can be packaged up in a Business Network Archive(.bna) as shown below:
$ cd ~/Workdir/todolist-network
$ ./scripts/createArchive.sh
This will result in the creation of todolist-network@1.0.0.bna
.
Assuming that Hyperledger Fabric is running, here are the steps to install and start todolist-network@1.0.0.bna
to it:
$ cd ~/Workdir/todolist-network
$ ./scripts/installNetwork.sh
$ ./scripts/startNetwork.sh
$ ./scripts/importNetworkAdminCard.sh
The above steps also create a network administrator for the newly installed business network and then import the corresponding card for the administrator.
In order to populate the world state for convenience, the Bootstrap
transaction can be submitted as shown below:
$ cd ~/Workdir/todolist-network
$ ./scripts/bootstrapTransaction.sh
You can use ./scripts/list.sh
to look at the assets that were created by the Bootstrap
transaction.
Using the todolist-network that is deployed to the local Hyperledger Fabric instance, you can create REST APIs that can be exercised from a mobile or web application. To be able to generate the REST APIs, first you should install composer-rest-server
as shown below:
$ npm install -g composer-rest-server
Then, you can generate the REST APIs for the todolist-network as shown below:
$ cd ~/Workdir/todolist-network
$ composer-rest-server
? Enter the name of the business network card to use: admin@todolist-network
? Specify if you want namespaces in the generated REST API: never use namespaces
? Specify if you want to enable authentication for the REST API using Passport: No
? Specify if you want to enable event publication over WebSockets: Yes
? Specify if you want to enable TLS security for the REST API: No
To restart the REST server using the same options, issue the following command:
composer-rest-server -c admin@todolist-network -n never -w true
Discovering types from business network definition ...
Discovered types from business network definition
Generating schemas for all types in business network definition ...
Generated schemas for all types in business network definition
Adding schemas for all types to Loopback ...
Added schemas for all types to Loopback
Web server listening at: http://localhost:3000
Browse your REST API at http://localhost:3000/explorer
REST APIs can be explored by loading http://localhost:3000/explorer
in your browser.
First, install the generator as shown below:
$ npm install -g generator-hyperledger-composer
$ npm install -g yo
Here is the step to generate the Angular2 app for Todo List using Yeoman:
$ cd ~/Workdir/todolist-network
$ yo hyperledger-composer:angular
Welcome to the Hyperledger Composer project generator
? Please select the type of project: Angular
You can run this generator using: 'yo hyperledger-composer:angular'
Welcome to the Hyperledger Composer Angular project generator
? Do you want to connect to a running Business Network? Yes
? Project name: angular-app
? Description: Hyperledger Composer Angular project
? Author name: foo
? Author email: foo@gmail.com
? License: Apache-2.0
? Name of the Business Network card: admin@todolist-network
? Do you want to generate a new REST API or connect to an existing REST API? Connect to an
existing REST API
angular-app
? REST server address: http://localhost
? REST server port: 3000
? Should namespaces be used in the generated REST API? Namespaces are not used
Created application!
....
This will result in the generation of Todo List app in the angular-app
sub-folder.
You can run the app as shown below:
$ cd ~/Workdir/todolist-network
$ cd angular-app
$ npm start
The app will be compiled and you can eventually interact with it by pointing your browser to http://localhost:4200
. Also, you can look and play with the generated REST APIs or endpoints by
pointing your browser to the Loopback Explorer at http://localhost:3000/explorer
. You can
also exercise the REST API to retrieve all the Tasks that were created by the
Bootstrap
transaction by pointing your browser to http://localhost:3000/api/Task
to
receive JSON response containing all the tasks in the world state.