Steem Developer logo

Steem Developer Portal

Streaming blockchain transactions

Including virtual operations when streaming blockchain transactions

This recipe will take you through the process of streaming blockchain transactions, both from head_block_num and last_irreversible_block_num, and explain the presence/absence of virtual operations in the streamed transactions.

Intro

There are two points from which Steem blockchain transactions can be streamed to give a “live” view of what’s happening on the blockchain. The first is from the head block which is the most recent block created on the chain (every 3 seconds when a new block is created). The second, is from the last irreversible block which is the newest block that has been confirmed by a sufficient number of block producers so that it can no longer be invalidated. This is not a live view but it is normally not far behind the head block number.

There is already a javascript tutorial on the devportal describing how to stream blockchain transactions. This recipe will go into further detail on operations on each block and more specifically the virtual operations that are executed with every new block. We will also assume that you have already run through the basic tutorials on the Steem blockchain and will focus more on the specific functions and outputs pertinent to this topic.

Steps

  1. Blocks, transactions and operations
  2. Virtual operation streaming

1. Blocks, transactions and operations

In order to stream a block and get the information as will be shown below we use the blockchain api in the dsteem library. The below method has an option parameter mode that defaults to irreversible but can be set to latest which would then return the head block. This means that both types of blocks can be streamed.

stream = client.blockchain.getBlockStream();
    stream
        .on('data', function(block) {
            console.log(block);
            ...
            ...

Below is an example of what a block looks like:

{
  "block_id":"017fa2a9b142cd8d3607b7e7421412402bf97957",
  "extensions":[],
  "previous":"017fa2a867978140e7553bbfd65396a5a8136d53",
  "signing_key":"STM5gBt5xvdb5vhmXjBqfzQ7vwr4hFF5rjmYmZnSbzdb9eWmk9or5",
  "timestamp":"2018-08-17T08:31:48",
  "transaction_ids": [],
  "transaction_merkle_root":"4f0d61928ce9595aec6558fb53f1af1b8de06d78",
  "transactions": [],
  "witness":"smooth.witness",
  "witness_signature":"204e00e747ce75b24fc26b5d18f12992197c61de0bf27c830416761bd25648238239c5eb26a5e392d474e27c601842e2ccf105ffb47f5a5712727412a18f106dbb"
}

Each block contains transactions:

{
  "block_num": 25141929,
  "expiration": "2018-08-17T08:41:42",
  "extensions": [],
  "operations": [],
  "ref_block_num": 41616,
  "ref_block_prefix": 3838737669,
  "signatures": ["1f261ccf59131dcd10334a40b8b76bd2e80b05eee1c8deaedb…ebb7e4a4d6e22f7823940248f1488978d4ec8ecbd8abbd88e"],
  "transaction_id": "a972aef3388908f8a4b4a8d889fb89c83d2b8eb3",
  "transaction_num": 0
}

And each transaction contains operations:

[
  "vote", 
  {
    "author":"skmedia",
    "permlink":"buynearn-new-mlm-plan-launched-4th-june-2018-new-mlm-plan-2018-10inr-4-buynearn-online",
    "voter":"nazann",
    "weight":4700  
  }
]

2. Virtual operation streaming

Virtual operations (curation rewards, etc) are derived from blockchain activity, but aren’t actually stored as operations themselves. They happen based on consensus from the blockchain based on other user initiated operations. These virtual operations are NOT available on the head block, so a 100% live feed of this information would not be possible. In order then to follow these operations you would have to stream the last_irreversible_block. To get a feed of virtual operations, each of the block transactions needs to be investigated for the type of the operations.

steem-python provides a very simple method to stream virtual or any other operations directly:

from steem import Steem
from steem.blockchain import Blockchain
import pprint
s = Steem()
b = Blockchain(s)

for op in b.stream('author_reward'):
    pprint.pprint(op)
    # break

With result:

{
  "_id": "11cb40b9283c8a89ed5d8c348cbc68d76a9d8bd3",
  "author": "hopehash",
  "block_num": 25145619,
  "permlink": "hopehash-btc-1-057",
  "sbd_payout": "0.000 SBD",
  "steem_payout": "2.341 STEEM",
  "timestamp": "2018-08-17T17:11:36.18",
  "trx_id": "0000000000000000000000000000000000000000",
  "type": "author_reward",
  "vesting_payout": "4740.455508 VESTS"
}

From the above example all operations of type “author_reward” will be printed on the console/terminal. You can change the type to which ever operation you want to stream or remove the parameter and stream all operations. The same logic can be followed when using steem-js by isolating the operations of each transaction and looking for the required operation type. Below example is again a modification of the tutorial initially referenced.

stream = client.blockchain.getBlockStream();
    stream
        .on('data', function(block) {
            let x = 0
            while (x < block.transactions.length) {
                if (block.transactions[x].operations[0][0] = 'author_reward') {
                    console.log(block.transactions[x].operations[0]);
                }
                x += 1
            }
        });

That’s all there is to it.