Advanced Steem Blockchain Monitoring With Only 12 Lines of Code!
Introduction
This is the first tutorial in a series that will explore helper code for the steem-js library.
Steem-js is a great example of one of the projects out there that lower the barrier to steem blockchain interaction, but unfortunately documentation in the form of examples is still a bit lax. This blog series is meant to provide examples of tricky procedures for developers with at least a basic to intermediate understanding of NodeJS development.
If you've never heard of steem-js before, you can learn more about it on the GitHub page for the project:
https://github.com/steemit/steem-js/tree/master/doc
Monitoring
The inspiration for this piece of code came out of a need to monitor and isolate blockchain operations that meet specific criteria.
With this function, one can monitor all operations on the steem blockchain in realtime and take action on only the ones they are interested in. The use case that inspired this code was user monitoring in order to generate a notification as soon as one of my friends has made post.
Let's take a look at the 12 magic lines of code. Please note that this is just an example and does not include error handling:
steem.api.streamOperations((err, result) => {
let valid = false;
let resultBody = result[1];
criteria.map((c)=>{
let rules = Object.keys(c);
rules.map((r)=>{
resultBody[r] == c[r] ? valid = true : valid = false;
});
if (valid){
// do something
}
});
});
Breaking it down
So, what exactly is happening here? First we've used the streamOperations() method to invoke a live stream of the Steem blockchain. The method takes a callback function that we use to evaluate each result.
The callback function we've written expects the presence of an array called 'criteria'. For every operation that the streamOperations() method returns, our callback function will loop through the rules objects in our criteria array and evaluate the operation against the rule. If the rule is met, we can then "do something."
Here's an example of how I've built the criteria array to monitor posts made by some of my imaginary friends:
let criteria = [];
criteria.push({ author: 'imaginary_username' });
criteria.push({ author: 'imaginary_username_2' });
criteria.push({ author: 'imaginary_username_3' });
But the beauty of the callback function that we've written is that our criteria array can have any combination of different types of rules. In fact, we can create some pretty advanced combinations. Suppose we want to get notified any time imaginary_username votes at a weight of 10000 AND imaginary_username_2 makes a comment on a post authored by imaginary_username_3.
No problem:
let criteria = [];
criteria.push({
voter: 'imaginary_username',
weight: 10000
});
criteria.push({
author: 'imaginary_username_2',
parent_author: 'imaginary_username_3'
});
In fact, we can reference any paramater that can ever appear in a result returned by streamOperations. Unfortunately these are not well documented, but can easily be discovered by letting this run for a little bit and exploring the results:
steem.api.streamOperations((err, result) => {
console.log(result[1]);
});
Putting it all together
To connect all the dots, let's see how this would look in a working example. I'm going to go back to my original use case of triggering an alert every time one of my imaginary friends makes a post. The alert will be a post to a Slack a channel.
First we need to create a Slack webhook. Here's how:
- Point your browser to http://[example].slack.com/apps/manage
- Click on Custom Integrations -> Incoming WebHooks -> Add Configuration
- Fill in your preferences and save the WebHook URL
See Screenshots:
Now for the complete code:
let steem = require('steem');
var Slack = require('slack-node');
steem.api.setOptions({ url: 'https://api.steemit.com' });
webhook = '[WebHook URL]';
let criteria = [];
criteria.push({ author: 'sha256md5' });
criteria.push({ author: 'imaginary_username_2' });
criteria.push({ author: 'imaginary_username_3' });
let slack = new Slack();
slack.setWebhook(webhook);
function slackpost(post){
slack.webhook({
channel: "#test",
username: "test",
text: post
}, (err, response) => {
//console.log(response);
});
}
steem.api.streamOperations((err, result) => {
console.log(result[1]);
let valid = false;
let resultBody = result[1];
criteria.map((c)=>{
let rules = Object.keys(c);
rules.map((r)=>{
resultBody[r] == c[r] ? valid = true : valid = false;
});
if (valid){
let post = result[1].author + " made a post on Steemit!";
slackpost(post);
}
});
});
GitHub Gist URL:
https://gist.github.com/eliyastein/434cd9334f6aa75cfe789f5c562647d1
Final breakdown
The final script adds a slack integration to our streamOperations() callback. We have setup our criteria with a list of authors that we want to monitor and we have written a function called slackpost that takes an argument and posts it tour Slack channel via the slack-node library. Everything is driven by a conditional statement in our callback that builds our post string and calls the slackpost() function.
The script can now be deployed with a tool like pm2 for persistence or simply run from the command line!
Posted on Utopian.io - Rewarding Open Source Contributors
Thank you for the contribution. It has been approved.
You can contact us on Discord.
[utopian-moderator]
Thanks @scipio - nice avatar :)
You're welcome Elliot, and tell Darlene my Python is still in tiptop condition!
@scipio
After rechecking this post, it cannot be approved as is.
Please check my comment below.
Although - as a Utopian moderator - I've also considered the possibility of re-filing this as a tutorial, I think it also has characteristics of a blog. The article contents are not exactly step-by-step tutorial-style, as @sha256md5 is setting up a code boilerplate for the streamOperations() method and criteria list. But if you feel, as a Utopian supervisor, this should be -refiled as a tutorial before getting the Utopian upvote, that's your conclusion, and as we are a team: fine.
@sha256md5: Please edit this post as "tutorial", fill-out the tutorial template parts, and respond to @mcfarhat afterwards. Do this this ASAP, please.
And in my role as Utopian Advisor, regarding platform strategy, I strongly disagree with approving, rejecting, approving, and having loads of discussions. That's, to my perception, ineffective, counter-productive and unprofessional. I will discuss that mechanism with my fellow Utopian Advisors @jedigeiss and @littleboy and @transisto and @elear - regarding the mechanism of supervisors rejecting contributions after moderator approval for category / administrative reasons only (it's clear that the quality of this contribution on its own is fine as it is according to perceived quality).
Thanks @scipio, I've updated my post (see my reply to @mcfarhat below). I appreciate the feedback and I'm definitely treating this as a learning experience toward future contributions.
Good, good! We live and we learn! Steem on!
Your contribution cannot be approved because it does not follow the Utopian Rules.
While this is a cool tutorial, this is what it is, a tutorial not a blog post.
It needs to be submitted under the proper tutorial category.
Please edit your post accordingly and promptly, then we can proceed approving it
You can contact us on Discord.
[utopian-moderator]
Hi @mcfarhat - Thanks for reading my post. I've updated to categorize as a tutorial. Please let me know if the format is lacking. I've not yet developed a curriculum, but hope to include one in the next one that I write for this series. I think there's a lot I can share with the community as I continue my exploration of steem-js. I do have to ask though, can you please provide some more clarity on what constitutes a blog post vs tutorial?
Perfect, thank you..
Your contribution has been approved now.
In a nutshell tutorial are how-tos, just like you laid out above. The more detailed you are the better.
Blog posts are targeted at describing open source projects in a very unique, repeatable, and consistent format and they should "provide detailed content and overviews related to the open-source projects"
Great! All Great! Next! :-)
Hey @sha256md5 I am @utopian-io. I have just upvoted you!
Achievements
Suggestions
Get Noticed!
Community-Driven Witness!
I am the first and only Steem Community-Driven Witness. Participate on Discord. Lets GROW TOGETHER!
Up-vote this comment to grow my power and help Open Source contributions like this one. Want to chat? Join me on Discord https://discord.gg/Pc8HG9x
Great post! It was an informative read!