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