Communicating to a Lisk node via RPC

The open Lisk communication architecture is based on three different RPC (Remote-Procedure-Call) API modes: Inter-Process Communication (IPC), WebSocket (WS), and Hypertext Transfer Protocol (HTTP).

The blockchain node can be configured to expose either IPC, WS, or HTTP APIs, as described in the Node configuration reference.

These APIs can be used by internal components such as modules and plugins. External services such as other scripts in JS, a tool in Rust, or a Python daemon can also use these APIs.

communication architecture

The API client

The API client simplifies sending API requests to a blockchain node. A Lisk application communicates to the blockchain by requesting the RPC endpoints of a blockchain node. RPC-based interfaces i.e. IPC, WS, or HTTP allow applications to invoke and subscribe (WS and IPC only) to RPC endpoints and events.

An API client can be imported into a JS client application as shown in the following snippets.

To conveniently communicate with a Lisk application, use the apiClient included in the @liskhq/lisk-client and the lisk-sdk packages.
  • WS API client example

  • IPC API client example

  • HTTP cURL

const { apiClient } = require('@liskhq/lisk-client');
let clientCache;
const nodeAPIURL = 'ws://localhost:7887/rpc-ws';

const getClient = async () => {
    if (!clientCache) {
        clientCache = await apiClient.createWSClient(nodeAPIURL);
    }
    return clientCache;
};


const blockId = "0f4ea1c3cfb61b99d387b26aaadf57936a528e5c713c6e55aa06f4d621b7e6f0";

getClient().then((client) => {
    client.invoke("chain_getBlockByID", {
        id: blockId
    }).then(res => {
        console.log("Result: ", res);
    });
});
const { apiClient } = require('@liskhq/lisk-client');
let clientCache;

const getClient = async () => {
    if (!clientCache) {
        clientCache = await apiClient.createIPCClient('~/.lisk/my-app');
    }
    return clientCache;
};

const blockId = "0f4ea1c3cfb61b99d387b26aaadf57936a528e5c713c6e55aa06f4d621b7e6f0";

getClient().then((client) => {
    client.invoke("chain_getBlockByID", {
        id: blockId
    }).then(res => {
        console.log("Result: ", res);
    });
});

Apart from the WS and IPC method, Lisk endpoints also support HTTP requests and response mechanisms. With a JSON RPC 2.0 based format, any endpoint can be invoked using a cURL request.

For example:

curl --location --request POST 'http://localhost:7887/rpc' \
--header 'Content-Type: application/json' \
--data-raw '{
    "jsonrpc": "2.0",
    "id": "1",
    "method": "chain_getBlockByHeight",
    "params": {
        "height": 2291
    }
}'

IPC vs WS vs HTTP

The three modes of communication i.e. IPC, WS, and HTTP allow Lisk applications to communicate with Lisk nodes.

IPC in general is the preferred method for local connections:

  • It is slightly faster.

  • It supports synchronous data exchange.

  • It does not use the system ports, so it mitigates any risk of collision when the ports are already in use by another application.

  • It can invoke and subscribe to endpoints and events, respectively.

WS on the contrary should be used if the node API has to communicate with services on remote servers.

  • It is a bidirectional communication protocol that allows sending and receiving of data between a client and a server.

  • A WS connection is kept alive until terminated by either the client or the server.

  • A WS connection is usually necessary if real-time data acquisition is required.

  • A WS connection can also invoke and subscribe to endpoints and events, respectively.

HTTP is stateless, so it can only be used for fetching data from an endpoint.

  • HTTP requests establish a uni-directional connection to the server and close it once a response is received.

  • Since an event emits data in real time, a subscription can only work if the receiver’s connection is persistent. This is not possible with an HTTP connection, hence it cannot be used to subscribe to events.

Enabling IPC, WebSocket, and HTTP APIs

Below are examples of the different options that can be used to enable certain client modes. There are two methods that can be used to expose the node APIs via IPC, WS, and HTTP.

  1. Use the following command line flags when starting the application:

    • --api-ipc: Enable API over IPC

    • --api-ws: Enable API over WS

    • --api-http: Enable API over HTTP

    • --api-host=127.0.0.1: IP over which the API is exposed. Use 0.0.0.0 to expose the API on all available ethernet IP instances

    • --api-port=7887: Port on which the API is exposed

  2. This can also be achieved by adding the RPC configuration option to your Lisk node’s configuration file as shown below. To enforce the config changes --overwrite-config flag must be passed when starting the application. To supply a custom config file, use the --config=</path/to/custom/config> flag:

    {
     "rpc": {
       "modes": ["ipc", "ws", "http"], // Only specify the modes you need to enable
       "port": 7887,
       "host": "127.0.0.1" // Use `0.0.0.0` to expose them on all available ethernet IP instances
     },
    }
Please note that when the WS mode is enabled, the API can be accessed via the /rpc-ws path. Furthermore, when the HTTP mode is enabled the API can be accessed via the /rpc path.

Aliases

Events and Endpoints are identified by their aliases.

Example alias:

"system_getNodeInfo"

An alias always consists of the following parts:

  1. Prefix: A namespace from which an event or an endpoint belongs to. The prefix system in this example is referring to the System namespace.

  2. Separator: The prefix and suffix are always separated by an underscore _.

  3. Suffix: A suffix is a name of the event or an endpoint e.g. getNodeInfo is the name of an endpoint that exists inside the system namespace.

Interfaces

A Lisk application communicates via interfaces i.e. Endpoints and Events. Endpoints are invoked and events are subscribed to.

Within an application, different interfaces are exposed to different components. This is summarized in the following diagram.

sdk interfaces

For each endpoint and event displayed above, the following statements apply:

  • …​ reply means, the component can reply to this kind of RPC request.

  • …​ invoke means, the component can invoke this kind of RPC request.

  • …​ subscribe means, the component can subscribe to RPC events.

Endpoints

Endpoints are invoked to receive specific data from the blockchain. Endpoints are part of the request/response mechanism and are invoked via RPCs.

The following components can expose endpoints:

The following components can invoke endpoints:

  • Plugins

  • External services/applications

How to invoke endpoints

Whilst invoking an endpoint, the first argument is always the alias.

If input data is required, it is provided as a second argument.

All endpoints can be invoked via either The API client or an HTTP request.

The following example shows the invocation of an endpoint with and without additional arguments.

How to invoke different kinds of endpoints with the API client
// How to invoke an endpoint.
const data = await client.invoke('system_getSchema');
console.log(data);

// How to invoke an endpoint that needs some data input.
const data = await client.invoke('namespace_endpointName', input);
console.log(data);

Events

The Lisk apps emit RPC events and Blockchain events, whereby each follows very different concepts.

Details of both event types are discussed below:

RPC Events

RPC events allow other applications to subscribe to Lisk Blockchain events. By default, Lisk exposes various events that can be subscribed to get the latest information regarding network, chain, and transactions.

These events can be subscribed to, by the following:

  • Plugins

  • External services/applications

For more information about the default events exposed by the Lisk Framework, check out the Events reference page.

How to subscribe to events

Each event as described in the Events reference page can be subscribed to, by using the convention mentioned in the Aliases section.

The following snippet describes how an event can be subscribed by using The API client:

Subscribing to an event
client.subscribe('network_newBlock', ( data ) => {
  console.log('new block: ',data);
});

Blockchain events

Blockchain events emit data about events occurring on chain. For details, see the Blockchain Events section.