Repository
https://github.com/jnordberg/dsteem
You will learn how to:
- Set up a block/operation stream without the complications of Node.JS
- Filter content of interest.
- Take a look at games on the Steem blockchain (custom JSON operations)
Requirements
- HTML
- JavaScript
Difficulty
- Basic
Curriculum
Lesson 0: Steem Tutorials Are Severely Lacking
Lesson 1: Filtering Tabs
Lesson 2: Hello World
Lesson 3: Dissecting Discussions
Lesson 4: Steem Stake Sterilizer
Lesson 5: Inspecting Block Operations
Proof-of-Brain:
https://gist.github.com/edict3d/2ee3f858d42b9d478c1cab6422e9443d

Here is the easiest way to set up a blockchain data stream from Steemit Inc:
<script src="https://unpkg.com/dsteem@^0.10.0/dist/dsteem.js"></script>
<button id="on"> On </button>
<script>
var client = new dsteem.Client('https://api.steemit.com')
var stream = client.blockchain.getOperationsStream()
function filter(operation){
console.log(operation);
}
function on(){
stream.on('data', (operation) => filter(operation))
}
document.getElementById("on").onclick = on
</script>
Use client.blockchain.getBlockStream() to get the full block instead of just operations
And there you have it! A real time stream of all the data being logged to the blockchain.
It really is that easy.
Now we can filter this information into something useful.

Personally I think the most interesting thing to look at is custom JSON operations.
<script src="https://unpkg.com/dsteem@^0.10.0/dist/dsteem.js"></script>
<br><button id="on"> On </button><br>
<br><button id="pause"> Pause </button><br>
<br><button id="resume"> Resume </button><br>
<h1>Output:</h1>
<p id='output'></p>
<script>
var client = new dsteem.Client('https://api.steemit.com')
var stream = client.blockchain.getOperationsStream()
function filter(operation){
let op = operation.op
if(op[0] === 'custom_json'){
let data = op[1]
document.getElementById("output").innerHTML += data.id + '<br>'
document.getElementById("output").innerHTML += data.json + '<br>'
}
}
function on(){
stream.on('data', (operation) => filter(operation))
}
function pause(){
stream.pause()
}
function resume(){
stream.resume()
}
document.getElementById("on").onclick = on
document.getElementById("pause").onclick = pause
document.getElementById("resume").onclick = resume
</script>
It becomes obviously apparent that the vast majority of activity is eclipsed by @drugwars and @steemmonsters.
Let's say we wanted to filter this even further to see only @drugwars accounts attacking other @drugwars accounts. No problem:
function filter(operation){
let op = operation.op
let data = op[1]
if(op[0] === 'custom_json' && data.id === 'drugwars'){
document.getElementById("output").innerHTML += data.id + '<br>'
+ data.json + '<br><br>'
}
}
We could then use this information to find weak/undefended accounts.
We could also use this information to capitalize on two users fighting each other resulting in a draw, which would then allow us to swoop in and take the reward for ourselves.
It would be even easier to set up alerts that would play a sound anytime someone attacked your account or any other accounts on your whitelist. Considering the lag and delay of the @drugwars servers, you would get tipped off much faster by simply streaming the block operations manually like this. All you'd have to do is set an alert if the "target": was your account.
It also wouldn't be that difficult to set up a script that detected an attack against your account and in response dumped all your drugs into the heist, purchased units with the rest of your available resources, and then attacked a dummy account with no defense so that you wouldn't lose any units.
However, all of these suggestions are far beyond the scope of this tutorial.

Operation object
Now let's take a look at the actual object given to us by Steemit's API. We can see that they give us an object with several attributes. The most important attribute is op
. op
is an array with two values in it.
- The type of operation (in this case
custom_json
) - The data structure of the operation
The data structure, in turn, is an object containing the attributes id
and json
, which is the bulk of the information we are looking for. It also contains required_posting_auths
, letting us know who posted this JSON to the blockchain in the first place.
Seems a little convoluted to me personally, but I'm sure Steemit has their reasons. It is what it is.

The contents of other operations is a little different, but they all seem to use op
with an array of length two.

Conclusion
While the concept of block streaming is simple and the code provided here is sparse, the utility of being able to see everything happening on the blockchain in real time is quite invaluable. Also, the documentation on block streaming is quite poor. I was not able to find the information I needed from the Steemit API docs or from the dsteem repository itself.
I believe we can create dapps where we don't have to run our own servers. Instead, we can rely on witnesses to create the blocks and full-nodes to distribute the information. Hopefully in the future we see a scaling solution using a torrent-like block distribution that takes the load off of full-nodes.
As we continue to grind forward in our journey, it becomes obvious that a scalable way to distribute blocks will be pinnacle to the expansion of the Steem blockchain.