Hey everyone 👋, you might have noticed I’ve been learning about the Steem-js library and building a couple of projects. I wanted to create my first tutorial to show you how to create a simple Steem bot in Javascript. There is a lot we could do with a bot but for the purpose of this tutorial and to keep it beginner friendly our bot will be fairly simple.
The completed bot code is here - I know some people find it easier to see everything in one block and follow along that way. ⬅️
Outline
We will create an auto-voting bot, our bot will automatically upvote posts from our selected list of usernames. Imagine you have new friends joining the platform, and you want to encourage them with upvotes but you’re too busy to check Steemit regularly.
What you need
- A plain text editor (I use atom.io )
- Your private posting key - This is found in your wallet on the permissions tab on steemit.com, click ‘show private key’ (remember to keep this safe). This is what allows the bot to vote for you
Goals
- specify a list of usernames (our friends)
- connect to the Steem-js API
- check when a new post is posted to the Steem network
- check if the post belongs to any of our friends
- send a vote to that post
Step 1 - setup 💻
For this tutorial our bot will run in the web browser, a more effective way to use this bot would be on the command-line but we’ll save that for another post.
We’re going to set up a blank HTML file and link to the steem.js library. The library does most of the work, talking to the Steem network and means we have to write very little code ourselves.
<html>
<head>
<script src="https://cdn.steemjs.com/lib/latest/steem.min.js"></script>
<script></script>
</head>
<body></body>
</html>
Go ahead and save this file as bot-tutorial.html. You can open this up in your browser although you’ll just see a white screen for now. Looking at the code you can see we have added the basic structure of a html page. All pages are made up on the , and tags. We’ve linked to the steemjs library file with a script tag. We also have our own tags to work with. This is where our javascript code will go.
Let's try testing everything is good to go. Add a console message to your script tag like so.
<script>
console.log(‘hello, is this working’)
</script>
Now open up the developer tools in your browser and move to the console.
- Chrome - View > Developer > Javascript Console
- FireFox - Tools > Web Developer > Browser Console
- Safari - Develop (turn on in advanced options - Safari prefrences) > Show Javascript Console
- IE/Edge/Windows 🤷♂️
If you’ve got the message above, let's keep moving.
Step 2 - create friends list 👫
We’ll store a list of friends in our code to start, we can use these names later to decide if to vote or not.
In javascript lists of information are called an Array, they are specified with the square brackets. Text needs to be represented with single or double quotes around it and it’s a list so we separate the names with commas.
Add this line below our console.log from above.
const FRIEND_LIST = ['sam', 'fred', 'sarah', 'lucy']
const
Is a store of information that is constant, so our list of friends can’t/won’t change once our bot is running.
Step 3 - Connect to the Steem-js API 🙌
Here comes the fun part. We want to connect to the steem network and check all new transactions. Each block on the steem blockchain holds transactions, these can be anything transfers, votes, comments, profile updates to name just a few. Once we connect every couple of seconds we’ll be sent new data from the blockchain.
First, we need to set the URL where we receive information (currently the CDN hosted teemA-js tries to connect to an out of date URL *as of 6th Jan)
Whenever we interact with the Ateem-js library we’ll specify steem.api.
and then the action we’re taking, most actions also need some extra information (these are called arguments), in this case, it’s the URL we want to connect to.
steem.api.setOptions({ url: 'wss://rpc.buildteam.io' });
The real magic is this next line.
steem.api.streamTransactions('head’,(error, result) => {});
This time we’re using the streamTransactions action to request the transactions from each block as they’re processed. we’re then taking the data (the error and the result and sending them into our own action. Between those curly baskets {}
we can check for an error or see the result. Let's try that.
steem.api.streamTransactions('head’,(error, result) => {
console.log(error, result)
});
as new transactions come In we’ll see each one in the browser console. It might look a bit funky, you also might get a lot, don’t worry we’ll narrow it down in just a second.
{ref_block_num: 60613, ref_block_prefix: 233123265, expiration: "2018-01-08T17:34:44", operations: Array(1), extensions: Array(0), …}
Okay looking at above we have, Block Number, Operations, extensions etc. What we’re looking at is a Javascript Object, it’s a way to store a group of information together. We’re interested in the Operations part. To make life easier for ourselves lets store the relevant information with better names. Click the little down arrows to see inside to the information we want.
steem.api.streamTransactions('head’,(error, result) => {
let txType = result.operations[0][0]
let txData = result.operations[0][1]
console.log(txType)
});
We creating two variables here to store our information. transaction type eg vote, comment etc and transaction data this is everything else relevant so for a comment it might be who commented and on what post etc. We first take the result then specify we want just the operations part then because operations is an Array we select the parts we want with square brackets.
Now instead of seeing all of the information coming through, we’ll just see the type. Try it out. For our bot we’re interested in ‘comments’, this is because there is actually not a type of post or blog, all blogs are classified as comments on the Steem network, its just that blog posts aren’t replying to anyone.
step 4 - checking friends names 📝
we need to create a way to check if the names we get from the blockchain match those in our list of friends. Let’s make a function. Functions allow us to create blocks of code we can reuse over and over.
function isFriend(name){
return (FRIEND_LIST.indexOf(name) > -1);
}
Out function takes one piece of data ‘name’ and it’s going to return us a yes/no or really a true/false answer. What’s happening here is we are taking our FRIEND_LIST
and looking for the index( the position ) of the name we entered. if our friend is is the list it will say 1 or 3 for example if not it says -1. checking if the answer is > -1
gives us our true/false for friends. Try it out.
function isFriend(name){
return (FRIEND_LIST.indexOf(name) > -1);
}
isFriend(‘sam’)
// yes
isFriend(‘lucy’)
// yes
isFriend(‘bob’)
// no
next, we’ll create another function to check the transaction data. We’re looking to see if the author
is our friend (with the function above), but we also need to check that the parent_author
is empty, if it’s empty we know this is a blog post and not a comment on someone else post.
function checkAuthor(txData){
if (txData.parent_author == '' && isFriend(txData.author)){
console.log(‘our friend posted a blog post!!!’)
}
}
This one is a little more involved. we are checking the transaction data which looks like this.
author: “namehere”
body: "That is a blast. It has an amazing potential!↵I will definitely participate in it!"
json_metadata : "{"tags":["crypto"],"app":"steemit/0.1"}"
parent_author: ""
parent_permlink: ""
permlink : “long—name-like-thisproject-20180108t173707137z"
title: “awesome post title”
you access this information with dot notation so if we want the author it is txData.author
it’s called txData because that’s what we specified in our function it could be called anything.
this time we’re checking that this is a blog post and not just a comment with txData.parent_author == ''
that’s checking the parent_author is empty and using our function to check if the txData.author
is in our friend's list.
Going back to out Steem transaction function we can combine these together. We’ll check the transaction type is equal to comment and then we’ll check the author.
steem.api.streamTransactions('head', (err, result) => {
console.log(result)
let txType = result.operations[0][0]
let txData = result.operations[0][1]
if(txType == 'comment') {
checkAuthor(txData)
} });
Looking good. With all this together we’ll get a message in the browser console every time any of our friend's posts!
Step 5 - Sending Votes 👍
Okay, we’re super close! Final Steps!
First up let's make a couple more constants to store information. You can do this at the top of your script, right by your friend's list.
const ACCOUNT_NAME = ‘yourusernamehere’
const ACCOUNT_POSTING_KEY = ‘yourprivatepostingkeyhere’
Fill in this information with your username and private posting key.
function sendVote(author, permlink){}
Let's create another function, this time the data we need is the author and the permlink, this is going to be which author and what post we’re voting on.
function sendVote(author, permlink){
steem.broadcast.vote(ACCOUNT_POSTING_KEY, ACCOUNT_NAME, author, permlink, 10000, function(err, result) {
console.log(result);
});
}
Here you can see we’re doing a ‘steem.broadcast’ the data we need to send is the posting key, account name, the author, the link and a voting weight. Note the voting weight does not use percentages so 10000 is the same as 100%.
All that’s left to do is using this function inside our check author function. let’s edit that now.
function checkAuthor(txData){
if (txData.parent_author == '' && isFriend(txData.author)){
sendVote(txData.author, txData.permlink)
}
}
Update the function to add our sendVote function instead of just a message. We’re taking the data from the transaction and using it in our send vote function.
that’s it - run this code in your browser and whenever your friend post’s it will automatically upvote their post. 👍
There’s a lot more we can do with bots and the Steem API but I hope this has been an interesting look at a simple bot.
post note - are bots a good idea? do bots devalue the Steemit platform? really interested to hear your thoughts on this. My take is that any ‘bad guys’ already know how to do this so showing you isn’t such a big deal. Remember to consider we’re hear to talk to humans, not robots. Use your new skills wisely
Posted on Utopian.io - Rewarding Open Source Contributors