Tutorial - Back end

Beware that this tutorial is in case you'd like to build a whole back end API from scratch. If you'd like an auto-generated back end you can checkout the convector-rest-api project, currently on BETA.
This guide will walk you through the process of building a back end API for a Convector Smart Contract from 0 to hero.
Components from this tutorial can be imported into your existing back end, nothing prevents you from altering the order or structure of this project.
Are you looking for a guide on how to build the smart contract used here? Check the part one of this tutorial.
high-levelevel steps on this guide are:
- Bootstrap a web server
- Build your connections to the Blockchain
- Expose your endpoints
This part of the tutorial will stop before getting into advanced features like mango queries, sending queries to CouchDB directly, adding an auth layer for front ends, and adding Swagger, to continue in a next part tutorial.
The general architecture we will build goes as follows:
Bootstrap your web server
For the server itself we will be using:
Let's go to the project you generated in the previous step of this tutorial or access this Github repo and clone it.
If you didn't follow the previous step of this tutorial (like getting the code from the Github repo) then you may not have a blockchain running locally with the right configurations. Please follow these README instructions before running this server.
Once you have the source code, let's create a basic structure with these commands:
Then copy this files inside of ./packages/server (one tip is to download them and drag the files to the corresponding folder):
Then let's resolve dependencies by running Lerna bootstrap (this will install dependencies from the internet but also resolve the local ones - like pointing to person-cc and participant-cc):
app.ts
Head to the ./packages/server/app.ts and add this code (this is the almost minimum to start a web server):
You can start the server by running on your console:
Pro tip: Lerna's goal is to allow you to manage multiple packages, so instead of having to move into and outside of folders you can simple add the --scope
flag with the name of the project you target for the command.
Now that we have the server and its dependencies ready let's move to connect with the blockchain.
Build your connections to the Blockchain
We will need some logic to connect to the network and we will depend on some files and configurations. To centralize configurations, we will create a file inside of ./packages/server/src/env.ts this fill will read environment variables and parse them for our application in a centralized way.
Inside of that file let's paste the following content to extract values from the ./packages/server/.env
in your package's root directory.
Some properties are pretty self-explanatory. Some others are not, we'll explain them better here:
- chaincode: the name of the smart contract. This is given when you installed it with
hurl install <name> <language></language> </name>
- channel: by default a channel (ledger) is created for you with Hurley. Its name is
ch1
and each subsequent channel will follow that pattern (ch2, ch3, ch4) check more on channels here. - identityName: Its the name of the user that will be used to run the server (wallet). In this case Hurley also handles an standard (like user1, user2, user3) depending on how many to told it to create.
- identityOrg: Just like identityName this property refers to the organization of the identity which will be used to run, query, and submit transactions to the network.
- keyStore: The key store is a path where cryptographic objects are stored (for example the private key/wallet). This folder can be located anywhere and this property fallbacks to Hurley defaults.
- networkProfile: The network profile is a file with the addresses and certificates to communicate with the blockchain network. This coordinates are used by Fabric's official SDK.
- port: This is simply the port that will be used for the server. We previously set it in the app.ts file, but we will relocate it to this central configurations repository.
- couchDB*: This properties will define the coordinates to communicate with the CouchDB server of one of the peers. This is because we want to query some data directly and not through the peers - which is another way to do queries.
If you'd like to change a value instead of using the default in the app.ts file you can create a ./packages/server/.env
with the values. However, that is not required for this project to start.
This is an example of a .env file:
PORT=9292 IDENTITY=user2
You can now import the values from the env.ts file and use them in your application. Anytime you need to tweak or check a config you can refer to this file. Modify the app.ts with this:
Files we need to connect
We will need some configurations and keys to connect to the blockchain network. These files will be resolved from the address set in the properties keyStore and networkProfile.
- Network Profile (also known as a connection profile): this file is a yaml or json that maps all the addresses of the components of the network. With Hurley these files are located in
~/hyperledger-fabric-network/network-profiles
. Hurley also creates yaml files by default. There's one per identity. - Cryptographic objects: these are the private and public keys for your identities/wallets (the ones used to connect and authenticate with the network). These files are located by default in
~/hyperledger-fabric-network/.hfc-*
, there's one folder per organization you created and are usually hidden from your files explorer.
Let's connect to the blockchain
To connect to a Hyperledger Fabric network you will need an adapter - that adapter is an object of type FabricControllerAdapter
initialized with the configuration loaded from the key store and the network profile fields we saw earlier.
The minimal steps required are:
- Initialize the adapter - this will also query one channel to get the configuration of the network.
- Initialize with a
ClientFactory
the code you created for your chaincode (importing it) and passing the adapter we initialized before.
For this example we will perform some extra tasks to make the server more explicit when misconfigurations are found (but take note that this is not always mandatory).
- Check that the folder with the keystore and the files for that identity actually exist. If not, throw an error with the explanation.
- Check that the identity which was used to run the server has been provisioned in the chaincode. If not, throw an error with the explanation.
We recommend you read and understand this explanation to better follow the dynamics between a certificate generated from a Certificate Authority (wallet) and the smart contract representation of that identity.
How does the code look? Let's find out!
Create a file here ./packages/server/src/convector.ts and paste the following contents:
From line #1 to line #22 is where the mandatory tasks occur. The rest are healthy checks for preventing uncontrolled errors, we advise you include them, otherwise, you will get weird errors from components that were expecting some configurations that were not provided and throw generic or not so clear error messages.
It looks nice so far but there's no actual way to test if this code works yet. So, let's proceed to create some endpoints in Express.
Expose your endpoints
If you are not familiar with Express it would be nice to read a little bit about it here.
Basically, Express can expose API endpoints through controllers (yeah, same name as Convector, since we follow a similar pattern).
Let's create a few files inside of a new folder ./packages/server/src/ called controllers. Create the following files there.
Pay special attention to the line#12 in participant.controller.ts. That's all that's needed to make a request to the Blockchain! Yeah, the adapter makes sure to configure your controller to have it make web grpc calls instead of calling the ledger (as the original code of your controller did). You could even position your mouse on ParticipantControllerBackEnd.
and see how it resolves the functions we coded before (like register
, the difference is that it is smart enough to now that the logic of where the data is located is different.
In a nutshell we are creating the base to expose an endpoint at http://localhost:8000/participant/. Also we created the base to have the controller for data related to the person.
This is almost all you need to have your first API endpoint, but we will need to tell the server to consider this file, so head back to app.ts and add these two lines:
import { ParticipantExpressController } from './controllers'; app.use('/participant', ParticipantExpressController);
With this, we are almost ready to test our API!
Test it out!
Before calling it, you need your Blockchain up and running. We will also need some data to make the query. Seed some data to be able to test the API.
After seeding some data, and starting the network and the server. We can proceed to make a web call!
We are almost done with our server. We will need to add some more functions to our controllers. You can remember that we had some extra functions such as create and addAttribute in the person-cc package. We won't be adding the rest of the functions from the participant-cc package as these are for administrative purposes and should be handled on a different way (like an administrative UI, automated scripts, or console apps).
Before we jump into adding more functions for the API controllers, let's add an extra function to be able to query people from our smart contract. Replace the contents of ./packages/person-cc/src/person.controller.ts with:
Now that we have the new get function ready, we will need to upgrade our smart contract.
Add the pending API functions
Stop your server running, and replace the contents of these files:
Once this is ready start your web server again and run these commands to add a person and a "birth-year" attribute.
That's pretty much all that it takes to build your API connected to Convector.
You know have an API with the following endpoints:
- GET http://localhost:8000/participant/:id
- GET http://localhost:8000/person/:id
- POST http://localhost:8000/person/
- POST http://localhost:8000/person/:id/add-attribute
You could use a visual tool to play with the server such as Postman.
Wrap up
Convector works natively with Fabric which means that even though we used Convector tools for NodeJS backend you could connect to it with any other Fabric SDK. This is really important, you could use Convector with Go, Java, Python, and any other language but the seamless experience is achieved with NodeJS to have JavaScript in the full stack.
If you decide to use another SDK make sure to use the files referenced here as these are Fabric specific and Convector doesn't add extra layers to them.
Overall the process of setting up Convector is fairly straight forward from the developer perspective. We will explore more advanced capabilities in the second part of this tutorial.