Koinos: How to create a microservice in Typescript

rect6350.png

In the last months I've been working in Koinos Types in order to add support to Typescript. I'm glad to say it is almost finished and I already published a version in npm to start testing it. In this post I want to explain how to create a simple microservice in Nodejs and how to connect it to other microservices in the cluster.

Koinos developer preview

Koinos Group has already released a developer preview, which consists in a cluster of 7 microservices: p2p, block_producer, chain, jsonrpc, mempool, block_store, and amqp. All of these microservices are packaged in a docker compose.

Clone the repo

git clone https://github.com/koinos/koinos.git

Launch services

cd koinos
docker-compose up

You need docker and docker-compose installed

Microservice in Typescript

The next steps will show you how to use koinos-types, how to communicate with other microservices, and how to verify signatures from block producer. The complete code can be downloaded from https://github.com/joticajulian/koinos-tutorial-microservice-typescript

Create a new project in Typescript and install the following packages:

  • koinos-types2: Library to create/parse blockchain messages. This is a temporary package while the official is published (koinos-types).
  • amqplib: AMQP library that permits the communication between microservices in the node.
  • secp256k1: Library to sign and verify signatures.

Create the file app.ts with the following content:

import {
  VariableBlob,
  SubmitBlockRequest,
  SubmitBlockRequestLike,
  Multihash
} from "koinos-types2";
import * as secp256k1 from "secp256k1";
import * as amqp from "amqplib/callback_api";

function recover(signatureRec: VariableBlob, hash: Multihash): Uint8Array {
  const recid = signatureRec.buffer[0] >> 5;
  const signature = signatureRec.buffer.slice(1);
  return secp256k1.ecdsaRecover(signature, recid, hash.digest.buffer, true);
}

amqp.connect("amqp://guest:guest@localhost:5672/", function(error0, connection) {
  if(error0) throw error0;

  connection.createChannel(function(error1, channel) {
    const queue = "koinos.rpc.chain";
    channel.assertQueue(queue, {
      durable: true
    });

    console.log(`Waiting for messages in ${queue}. To exit press CTRL+C`);
    channel.consume(queue, function(msg) {
      const { type, value } = JSON.parse(msg.content.toString()) as { type: string; value: unknown };
      if (type === "koinos::rpc::chain::submit_block_request") {
        const { block } = new SubmitBlockRequest(value as SubmitBlockRequestLike);
        const signer = recover(block.signatureData, block.id);
        console.log(`\nBlock height: ${block.header.height.toString()}`);
        console.log(`Number of transactions: ${block.transactions.items.length}`);
        console.log(`Signed by: ${Buffer.from(signer).toString("hex")}`);
      }
    },{
      noAck: true
    });
  });
});

The url for the amqp ("amqp://guest:guest@localhost:5672/") must correspond with the one configured in the cluster (see the configuration here). On the other hand, take a look to this line: queue = "koinos.rpc.chain". AMQP permits the creation of several channels, each service has a channel and it is broadcasted to all microservices in different queues. In this case we are connecting to the channel of the chain service in order to get the blocks.

The channel.consume function is used to read the messages in the queue. It is received as string and we parse it to JSON. That JSON contains the "type" and "value". At this point we use the Koinos Types package to parse the content. The service chain uses 2 types but the principal one is "submit_block_request".

Finally I've added a function to recover the public key from the signature, which corresponds to block producer's public key. This function most probably will be included in another package in the future as part of a Wallet library.

Now launch your microservice with npm run start. If everything is ok you should see the following in the output:

Block height: 53453
Number of transactions: 0
Signed by: 0264e8e4c5cd774c2a746a21d35c8f00e43cf72121820cd1fae930db5a2479e8fc

Block height: 53454
Number of transactions: 0
Signed by: 0264e8e4c5cd774c2a746a21d35c8f00e43cf72121820cd1fae930db5a2479e8fc

Block height: 53455
Number of transactions: 0
Signed by: 0264e8e4c5cd774c2a746a21d35c8f00e43cf72121820cd1fae930db5a2479e8fc

Go to https://github.com/joticajulian/koinos-tutorial-microservice-typescript to download the code and start testing it.

H2
H3
H4
3 columns
2 columns
1 column
3 Comments